Skip to content

[SYCL][Driver] -foffload-static-lib improvements when no source is given #1072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,8 @@ class OffloadUnbundlingJobAction final : public JobAction {

public:
// Offloading unbundling doesn't change the type of output.
OffloadUnbundlingJobAction(ActionList &Inputs);
OffloadUnbundlingJobAction(Action *Input);
OffloadUnbundlingJobAction(ActionList &Inputs, types::ID Type);

/// Register information about a dependent action.
void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch,
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ def u_Group : OptionGroup<"<u group>">, Group<Link_Group>, DocFlatten;
def reserved_lib_Group : OptionGroup<"<reserved libs group>">,
Flags<[Unsupported]>;

def offload_lib_Group : OptionGroup<"<offload libs group>">;

// Temporary groups for clang options which we know we don't support,
// but don't want to verbosely warn the user about.
def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">,
Expand Down Expand Up @@ -1666,7 +1668,8 @@ def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, Group<f_Group>;
def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Group>;

def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
def foffload_static_lib_EQ : CommaJoined<["-"], "foffload-static-lib=">, Flags<[DriverOption, CoreOption]>;
def foffload_static_lib_EQ : CommaJoined<["-"], "foffload-static-lib=">, Flags<[DriverOption, CoreOption]>, Group<offload_lib_Group>;
def foffload_whole_static_lib_EQ : CommaJoined<["-"], "foffload-whole-static-lib=">, Flags<[DriverOption, CoreOption]>, Group<offload_lib_Group>;
def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
HelpText<"Parse OpenMP pragmas and generate parallel code.">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ TYPE("tempfilelist", Tempfilelist, INVALID, "txt", phases
TYPE("tempentriesfilelist", TempEntriesfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("tempAOCOfilelist", TempAOCOfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("archive", Archive, INVALID, "a", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("wholearchive", WholeArchive, INVALID, "a", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("fpga_aocx", FPGA_AOCX, INVALID, "aocx", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("fpga_aocr", FPGA_AOCR, INVALID, "aocr", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("fpga_aoco", FPGA_AOCO, INVALID, "aoco", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ namespace types {
/// isFPGA - Is this FPGA input.
bool isFPGA(ID Id);

/// isArchive - Is this an archive input.
bool isArchive(ID Id);

/// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
bool isObjC(ID Id);

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,12 @@ OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)

void OffloadUnbundlingJobAction::anchor() {}

OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(ActionList &Inputs)
: JobAction(OffloadUnbundlingJobClass, Inputs, Inputs.back()->getType()) {}
OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
: JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}

OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(ActionList &Inputs,
types:: ID Type)
: JobAction(OffloadUnbundlingJobClass, Inputs, Type) {}

void OffloadWrapperJobAction::anchor() {}

Expand Down
100 changes: 56 additions & 44 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2465,6 +2465,14 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
Diag(diag::note_use_dashdash);
}
}
else if (A->getOption().matches(options::OPT_offload_lib_Group)) {
// Add the foffload-static-lib library to the command line to allow
// processing when no source or object is supplied as well as proper
// host link.
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
Inputs.push_back(std::make_pair(types::TY_Object, InputArg));
A->claim();
}
}
if (CCCIsCPP() && Inputs.empty()) {
// If called as standalone preprocessor, stdin is processed
Expand Down Expand Up @@ -3332,7 +3340,7 @@ class OffloadingActionBuilder final {

std::string InputName = IA->getInputArg().getAsString(Args);
// Objects should already be consumed with -foffload-static-lib
if (Args.hasArg(options::OPT_foffload_static_lib_EQ) &&
if (Args.hasArg(options::OPT_offload_lib_Group) &&
IA->getType() == types::TY_Object && isObjectFile(InputName))
return ABRT_Inactive;

Expand Down Expand Up @@ -3866,7 +3874,7 @@ class OffloadingActionBuilder final {
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() ||
!(HostAction->getType() == types::TY_Object &&
isObjectFile(InputName) &&
Args.hasArg(options::OPT_foffload_static_lib_EQ))) {
Args.hasArg(options::OPT_offload_lib_Group))) {
ActionList HostActionList;
Action *A(HostAction);
// Only check for FPGA device information when using fpga SubArch.
Expand All @@ -3883,15 +3891,11 @@ class OffloadingActionBuilder final {
else if (hasFPGABinary(C, InputName, types::TY_FPGA_AOCR))
A = C.MakeAction<InputAction>(*InputArg, types::TY_FPGA_AOCR);
}
HostActionList.push_back(A);
if (!HostActionList.empty()) {
auto UnbundlingHostAction =
C.MakeAction<OffloadUnbundlingJobAction>(HostActionList);
UnbundlingHostAction->registerDependentActionInfo(
auto UnbundlingHostAction = C.MakeAction<OffloadUnbundlingJobAction>(A);
UnbundlingHostAction->registerDependentActionInfo(
C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/StringRef(), Action::OFK_Host);
HostAction = UnbundlingHostAction;
}
HostAction = UnbundlingHostAction;
}
}

Expand Down Expand Up @@ -3941,11 +3945,11 @@ class OffloadingActionBuilder final {
if (!IsValid || InputActionList.empty())
return true;

auto *DeviceUnbundlingAction =
C.MakeAction<OffloadUnbundlingJobAction>(InputActionList);
auto *DeviceUnbundlingAction = C.MakeAction<OffloadUnbundlingJobAction>(
InputActionList, types::TY_Object);
DeviceUnbundlingAction->registerDependentActionInfo(
C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/StringRef(), Action::OFK_Host);
C.getSingleOffloadToolChain<Action::OFK_Host>(),
/*BoundArch=*/StringRef(), Action::OFK_Host);
HostAction = DeviceUnbundlingAction;

// Register the offload kinds that are used.
Expand Down Expand Up @@ -4353,59 +4357,69 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// When a static fat archive is provided, create a new unbundling step
// for all of the objects.
if (!C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
Args.hasArg(options::OPT_foffload_static_lib_EQ) &&
!LinkerInputs.empty()) {
Args.hasArg(options::OPT_offload_lib_Group)) {
ActionList UnbundlerInputs;
ActionList TempLinkerInputs;
for (const auto &LI : LinkerInputs) {
// Unbundler only handles objects.
if (auto *IA = dyn_cast<InputAction>(LI)) {
std::string FileName = IA->getInputArg().getAsString(Args);
if ((IA->getType() == types::TY_Object && !isObjectFile(FileName)) ||
IA->getInputArg().getOption().hasFlag(options::LinkerInput))
// Pass the Input along to linker.
TempLinkerInputs.push_back(LI);
else
// Add to unbundler.
UnbundlerInputs.push_back(LI);
} else
// Pass the Input along to linker only.
continue;
UnbundlerInputs.push_back(LI);
}
}
LinkerInputs.clear();
const Arg *LastArg;
auto addUnbundlerInput = [&](types::ID T, const Arg *A) {
const llvm::opt::OptTable &Opts = getOpts();
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
LastArg = InputArg;
Action *Current = C.MakeAction<InputAction>(*InputArg, T);
UnbundlerInputs.push_back(Current);
};
for (const auto *A : Args.filtered(options::OPT_foffload_static_lib_EQ))
addUnbundlerInput(types::TY_Archive, A);
for (const auto *A :
Args.filtered(options::OPT_foffload_whole_static_lib_EQ))
addUnbundlerInput(types::TY_WholeArchive, A);
if (!UnbundlerInputs.empty()) {
Action *Current;
const Arg *LastArg = Args.getLastArg(options::OPT_foffload_static_lib_EQ);
Action *Current = C.MakeAction<InputAction>(*LastArg, types::TY_Archive);
OffloadBuilder.addHostDependenceToUnbundlingAction(Current,
UnbundlerInputs, LastArg);
UnbundlerInputs, LastArg);
Current = OffloadBuilder.addDeviceDependencesToHostAction(Current,
LastArg, phases::Link, PL.back(), PL);
LinkerInputs.push_back(Current);
LastArg, phases::Link, PL.back(), PL);
}
for (const auto &TLI : TempLinkerInputs)
LinkerInputs.push_back(TLI);
}
const llvm::opt::OptTable &Opts = getOpts();
auto unbundleStaticLib = [&](types::ID T, const Arg *A) {
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
Action *Current = C.MakeAction<InputAction>(*InputArg, T);
OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg, Args);
OffloadBuilder.addDeviceDependencesToHostAction(
Current, InputArg, phases::Link, PL.back(), PL);
};
for (const auto *A : Args.filtered(options::OPT_foffload_static_lib_EQ)) {
auto unbundleStaticLib = [&](types::ID T) {
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
Action *Current = C.MakeAction<InputAction>(*InputArg, T);
OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg, Args);
OffloadBuilder.addDeviceDependencesToHostAction(
Current, InputArg, phases::Link, PL.back(), PL);
};
// In MSVC environment offload-static-libs are handled slightly different
// because of missing support for partial linking in the linker. We add an
// unbundling action for each static archive which produces list files with
// extracted objects. Device lists are then added to the appropriate device
// link actions and host list is ignored since we are adding
// offload-static-libs as normal libraries to the host link command.
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment())
unbundleStaticLib(types::TY_Archive);
unbundleStaticLib(types::TY_Archive, A);
// Pass along the -foffload-static-lib values to check if we need to
// add them for unbundling for FPGA AOT static lib usage. Uses FPGA
// aoco type to differentiate if aoco unbundling is needed.
if (Args.hasArg(options::OPT_fintelfpga))
unbundleStaticLib(types::TY_FPGA_AOCO);
unbundleStaticLib(types::TY_FPGA_AOCO, A);
}
for (const auto *A :
Args.filtered(options::OPT_foffload_whole_static_lib_EQ)) {
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment())
unbundleStaticLib(types::TY_WholeArchive, A);
if (Args.hasArg(options::OPT_fintelfpga))
unbundleStaticLib(types::TY_FPGA_AOCO, A);
}

// For an FPGA archive, we add the unbundling step above to take care of
Expand Down Expand Up @@ -5278,13 +5292,11 @@ InputInfo Driver::BuildJobsForActionNoCache(
bool IsFPGAObjLink = (JA->getType() == types::TY_Object &&
C.getInputArgs().hasArg(options::OPT_fintelfpga) &&
C.getInputArgs().hasArg(options::OPT_fsycl_link_EQ));
if (C.getInputArgs().hasArg(options::OPT_foffload_static_lib_EQ) &&
if (C.getInputArgs().hasArg(options::OPT_offload_lib_Group) &&
((JA->getType() == types::TY_Archive && IsMSVCEnv) ||
(UI.DependentOffloadKind != Action::OFK_Host &&
(JA->getType() == types::TY_Object && !IsMSVCEnv)))) {
(JA->getType() == types::TY_Object && !IsMSVCEnv))) {
// Host part of the unbundled static archive is not used.
if (UI.DependentOffloadKind == Action::OFK_Host &&
JA->getType() == types::TY_Archive && IsMSVCEnv)
if (UI.DependentOffloadKind == Action::OFK_Host)
continue;
// Host part of the unbundled object when -fintelfpga -fsycl-link is
// enabled is not used
Expand Down
68 changes: 45 additions & 23 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6907,14 +6907,17 @@ void OffloadBundler::ConstructJobMultipleOutputs(
InputInfo Input = Inputs.front();
const char *TypeArg = types::getTypeTempSuffix(Input.getType());
const char *InputFileName = Input.getFilename();
bool IsMSVCEnv =
C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
types::ID InputType(Input.getType());

// For objects, we have initial support for fat archives (archives which
// For Linux, we have initial support for fat archives (archives which
// contain bundled objects). We will perform partial linking against the
// object and specific offload target archives which will be sent to the
// unbundler to produce a list of target objects.
if (!C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
Input.getType() == types::TY_Object &&
TCArgs.hasArg(options::OPT_foffload_static_lib_EQ)) {
// specific offload target archives which will be sent to the unbundler to
// produce a list of target objects.
// FIXME: This should be a separate job in the toolchain.
if (!IsMSVCEnv && TCArgs.hasArg(options::OPT_offload_lib_Group) &&
(types::isArchive(InputType) || InputType == types::TY_Object)) {
TypeArg = "oo";
ArgStringList LinkArgs;
LinkArgs.push_back("-r");
Expand All @@ -6924,28 +6927,47 @@ void OffloadBundler::ConstructJobMultipleOutputs(
llvm::sys::path::stem(Input.getFilename()).str() + "-prelink", "o");
InputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName));
LinkArgs.push_back(InputFileName);
// Input files consist of fat libraries and the object(s) to be unbundled.
for (const auto &I : Inputs)
LinkArgs.push_back(I.getFilename());
const ToolChain *HTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
// Add crt objects
LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crt1.o")));
LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crti.o")));
// Add -L<dir> search directories.
TCArgs.AddAllArgs(LinkArgs, options::OPT_L);
for (const auto &A :
TCArgs.getAllArgValues(options::OPT_foffload_static_lib_EQ))
LinkArgs.push_back(TCArgs.MakeArgString(A));

// TODO - We can potentially go through the args and add the known linker
// pass through args of --whole-archive and --no-whole-archive. This
// would allow to support user commands like: -Wl,--whole-archive
// -foffload-static-lib=<lib> -Wl,--no-whole-archive
// Input files consist of fat libraries and the object(s) to be unbundled.
bool IsWholeArchive = false;
for (const auto &I : Inputs) {
if (I.getType() == types::TY_WholeArchive && !IsWholeArchive) {
LinkArgs.push_back("--whole-archive");
IsWholeArchive = true;
} else if (I.getType() == types::TY_Archive && IsWholeArchive) {
LinkArgs.push_back("--no-whole-archive");
IsWholeArchive = false;
}
LinkArgs.push_back(I.getFilename());
}
// Disable whole archive if it was enabled for the previous inputs.
if (IsWholeArchive)
LinkArgs.push_back("--no-whole-archive");
// Add crt objects
LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crtn.o")));
const char *Exec = TCArgs.MakeArgString(getToolChain().GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this, Exec, LinkArgs, Inputs));
} else if (Input.getType() == types::TY_FPGA_AOCX ||
Input.getType() == types::TY_FPGA_AOCR) {
} else if (InputType == types::TY_FPGA_AOCX ||
InputType == types::TY_FPGA_AOCR) {
// Override type with archive object
if (getToolChain().getTriple().getSubArch() ==
llvm::Triple::SPIRSubArch_fpga)
TypeArg = "ao";
else
TypeArg = "aoo";
}
if (Input.getType() == types::TY_FPGA_AOCO ||
(C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
Input.getType() == types::TY_Archive))
if (InputType == types::TY_FPGA_AOCO ||
(IsMSVCEnv && types::isArchive(InputType)))
TypeArg = "aoo";

// Get the type.
Expand All @@ -6960,12 +6982,12 @@ void OffloadBundler::ConstructJobMultipleOutputs(
// FPGA device triples are 'transformed' for the bundler when creating
// aocx or aocr type bundles. Also, we only do a specific target
// unbundling, skipping the host side or device side.
if (types::isFPGA(Input.getType())) {
if (types::isFPGA(InputType)) {
if (getToolChain().getTriple().getSubArch() ==
llvm::Triple::SPIRSubArch_fpga &&
Dep.DependentOffloadKind == Action::OFK_SYCL) {
llvm::Triple TT;
TT.setArchName(types::getTypeName(Input.getType()));
TT.setArchName(types::getTypeName(InputType));
TT.setVendorName("intel");
TT.setOS(getToolChain().getTriple().getOS());
TT.setEnvironment(llvm::Triple::SYCLDevice);
Expand All @@ -6979,10 +7001,10 @@ void OffloadBundler::ConstructJobMultipleOutputs(
Triples += Dep.DependentToolChain->getTriple().normalize();
}
continue;
} else if (Input.getType() == types::TY_Archive ||
(Input.getType() == types::TY_Object &&
TCArgs.hasArg(options::OPT_fintelfpga) &&
TCArgs.hasArg(options::OPT_fsycl_link_EQ))) {
} else if (types::isArchive(InputType) || (InputType == types::TY_Object &&
((!IsMSVCEnv && TCArgs.hasArg(options::OPT_offload_lib_Group)) ||
(TCArgs.hasArg(options::OPT_fintelfpga) &&
TCArgs.hasArg(options::OPT_fsycl_link_EQ))))) {
// Do not extract host part if we are unbundling archive on Windows
// because it is not needed. Static offload libraries are added to the
// host link command just as normal libraries. Do not extract the host
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,9 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto *A : Args.filtered(options::OPT_foffload_static_lib_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-defaultlib:") + A->getValue()));
for (const auto *A : Args.filtered(options::OPT_foffload_whole_static_lib_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-wholearchive:") + A->getValue()));

if (!llvm::sys::Process::GetEnv("LIB")) {
// If the VC environment hasn't been configured (perhaps because the user
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Driver/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ bool types::isFPGA(ID Id) {
}
}

bool types::isArchive(ID Id) {
switch (Id) {
default:
return false;
case TY_Archive:
case TY_WholeArchive:
return true;
}
}

bool types::isSrcFile(ID Id) {
return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
}
Expand Down
Loading