From 07b5cfc7a0cc1948e0c7eba12970b13075e8177b Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Wed, 26 Feb 2020 10:08:18 -0800 Subject: [PATCH 1/7] [SYCL][Driver] Improve fat static library support When processing libraries on the command line, take into account any thusly named static archive (*.a) file and consider that for offloading. We will also scan the appropriate linker options passed in so we can determine if the library should be considered as whole-archive. The static libraries found on the command line will be 'sniffed' to determine if the static library is fat. This effectively negates the need to use -foffload-static-lib and -foffload-whole-static-lib which we should consider deprecated now. Add a deprecated diagnostic when -foffload-static-lib is used Refactor to bring along common code for the device check. Narrows the focus of what is considered to be processed from the linker only arguments. Pulls in objects from -Wl, instead of only archives, but is only part of a potential partial link step and is not fully processed. Signed-off-by: Michael D Toguchi --- .../clang/Basic/DiagnosticDriverKinds.td | 2 + clang/include/clang/Driver/Action.h | 13 + clang/include/clang/Driver/Driver.h | 15 + clang/include/clang/Driver/ToolChain.h | 2 + clang/lib/Driver/Action.cpp | 10 + clang/lib/Driver/Driver.cpp | 342 +++++++++++++----- clang/lib/Driver/ToolChain.cpp | 9 + clang/lib/Driver/ToolChains/Clang.cpp | 108 +++--- clang/lib/Driver/ToolChains/Clang.h | 14 + clang/test/Driver/sycl-offload-intelfpga.cpp | 78 ++-- .../test/Driver/sycl-offload-static-lib-2.cpp | 102 ++++++ clang/test/Driver/sycl-offload-static-lib.cpp | 24 +- clang/test/Driver/sycl-offload-win.c | 10 +- 13 files changed, 558 insertions(+), 171 deletions(-) create mode 100644 clang/test/Driver/sycl-offload-static-lib-2.cpp diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 6ac9e94f7c330..58f7c07fb18ad 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -340,6 +340,8 @@ def warn_drv_object_size_disabled_O0 : Warning< InGroup, DefaultWarnNoWerror; def err_invalid_branch_protection: Error < "invalid branch protection option '%0' in '%1'">; +def warn_drv_deprecated_option : Warning< + "option '%0' is deprecated, use '%1' directly instead">, InGroup; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h index fe991b971b73f..88e20a965c690 100644 --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -76,6 +76,7 @@ class Action { SPIRVTranslatorJobClass, SPIRCheckJobClass, SYCLPostLinkJobClass, + PartialLinkJobClass, BackendCompileJobClass, JobClassFirst = PreprocessJobClass, @@ -680,6 +681,18 @@ class SYCLPostLinkJobAction : public JobAction { } }; +class PartialLinkJobAction : public JobAction { + void anchor() override; + +public: + PartialLinkJobAction(Action *Input, types::ID OutputType); + PartialLinkJobAction(ActionList &Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == PartialLinkJobClass; + } +}; + class BackendCompileJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 4867f48b53005..04076addaa2a0 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -621,6 +621,15 @@ class Driver { &CachedResults, Action::OffloadKind TargetDeviceOffloadKind) const; + /// Static offload library seen. + bool OffloadStaticLibSeen = false; + + void setOffloadStaticLibSeen() { OffloadStaticLibSeen = true; } + + /// Returns true if an offload static library is found. + bool checkForOffloadStaticLib(Compilation &C, + llvm::opt::DerivedArgList &Args) const; + public: /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and /// return the grouped values as integers. Numbers which are not @@ -642,6 +651,9 @@ class Driver { MutableArrayRef Digits); /// Compute the default -fmodule-cache-path. static void getDefaultModuleCachePath(SmallVectorImpl &Result); + + bool getOffloadStaticLibSeen() const { return OffloadStaticLibSeen; }; + }; /// \return True if the last defined optimization level is -Ofast. @@ -651,6 +663,9 @@ bool isOptimizationLevelFast(const llvm::opt::ArgList &Args); /// \return True if the filename has a valid object file extension. bool isObjectFile(std::string FileName); +/// \return True if the filename has a static archive/lib extension. +bool isStaticArchiveFile(const std::string &FileName); + /// \return True if the argument combination will end up generating remarks. bool willEmitRemarks(const llvm::opt::ArgList &Args); diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 8436bdef71541..7c05cb219639a 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -145,6 +145,7 @@ class ToolChain { mutable std::unique_ptr SPIRVTranslator; mutable std::unique_ptr SPIRCheck; mutable std::unique_ptr SYCLPostLink; + mutable std::unique_ptr PartialLink; mutable std::unique_ptr BackendCompiler; Tool *getClang() const; @@ -158,6 +159,7 @@ class ToolChain { Tool *getSPIRVTranslator() const; Tool *getSPIRCheck() const; Tool *getSYCLPostLink() const; + Tool *getPartialLink() const; Tool *getBackendCompiler() const; mutable std::unique_ptr SanitizerArguments; diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp index e83094374a04c..f2973da2322e1 100644 --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -49,6 +49,8 @@ const char *Action::getClassName(ActionClass AC) { return "llvm-no-spir-kernel"; case SYCLPostLinkJobClass: return "sycl-post-link"; + case PartialLinkJobClass: + return "partial-link"; case BackendCompileJobClass: return "backend-compiler"; } @@ -454,6 +456,14 @@ void SYCLPostLinkJobAction::anchor() {} SYCLPostLinkJobAction::SYCLPostLinkJobAction(Action *Input, types::ID Type) : JobAction(SYCLPostLinkJobClass, Input, Type) {} +void PartialLinkJobAction::anchor() {} + +PartialLinkJobAction::PartialLinkJobAction(Action *Input, types::ID Type) + : JobAction(PartialLinkJobClass, Input, Type) {} + +PartialLinkJobAction::PartialLinkJobAction(ActionList &Inputs, types::ID Type) + : JobAction(PartialLinkJobClass, Inputs, Type) {} + void BackendCompileJobAction::anchor() {} BackendCompileJobAction::BackendCompileJobAction(ActionList &Inputs, diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 512b92010f1d3..62b843820d3b0 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1301,6 +1301,10 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { InputList Inputs; BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); + // Determine if there are any offload static libraries. + if (checkForOffloadStaticLib(*C, *TranslatedArgs)) + setOffloadStaticLibSeen(); + // Populate the tool chains for the offloading devices, if any. CreateOffloadingDeviceToolChains(*C, Inputs); @@ -2479,6 +2483,10 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); Inputs.push_back(std::make_pair(types::TY_Object, InputArg)); A->claim(); + // Use of -foffload-static-lib and -foffload-whole-static-lib are + // deprecated with the updated functionality to scan the static libs. + Diag(clang::diag::warn_drv_deprecated_option) << A->getAsString(Args) << + A->getValue(); } } if (CCCIsCPP() && Inputs.empty()) { @@ -2489,6 +2497,187 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } +static bool runBundler(const std::vector &BundlerArgs, + Compilation &C) { + // Find bundler. + StringRef ExecPath(C.getArgs().MakeArgString(C.getDriver().Dir)); + llvm::ErrorOr BundlerBinary = llvm::sys::findProgramByName( + "clang-offload-bundler", ExecPath); + // Since this is run in real time and not in the toolchain, output the + // command line if requested. + bool OutputOnly = C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); + if (C.getArgs().hasArg(options::OPT_v) || OutputOnly) { + for (StringRef A : BundlerArgs) + if (OutputOnly) + llvm::errs() << "\"" << A << "\" "; + else + llvm::errs() << A << " "; + llvm::errs() << '\n'; + } + if (BundlerBinary.getError()) + return false; + + return !llvm::sys::ExecuteAndWait(BundlerBinary.get(), BundlerArgs); +} + +bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) { + assert(types::isFPGA(Type) && "unexpected Type for FPGA binary check"); + // Temporary names for the output. + llvm::Triple TT; + TT.setArchName(types::getTypeName(Type)); + TT.setVendorName("intel"); + TT.setOS(llvm::Triple::UnknownOS); + TT.setEnvironment(llvm::Triple::SYCLDevice); + + // Checking uses -check-section option with the input file, no output + // file and the target triple being looked for. + const char *Targets = + C.getArgs().MakeArgString(Twine("-targets=sycl-") + TT.str()); + const char *Inputs = C.getArgs().MakeArgString(Twine("-inputs=") + + Object); + // Always use -type=ao for aocx/aocr bundle checking. The 'bundles' are + // actually archives. + std::vector BundlerArgs = { "clang-offload-bundler", + "-type=ao", + Targets, + Inputs, + "-check-section" }; + return runBundler(BundlerArgs, C); +} + +static bool hasOffloadSections(Compilation &C, const std::string Archive, + DerivedArgList &Args) { + // Do not do the check if the file doesn't exist + if (!llvm::sys::fs::exists(Archive)) + return false; + + llvm::Triple TT(C.getDefaultToolChain().getTriple()); + // Checking uses -check-section option with the input file, no output + // file and the target triple being looked for. + // TODO - Improve checking to check for explicit offload target instead + // of the generic host availability. + const char *Targets = + Args.MakeArgString(Twine("-targets=host-") + TT.str()); + const char *Inputs = Args.MakeArgString(Twine("-inputs=") + Archive); + // Always use -type=ao for bundle checking. The 'bundles' are + // actually archives. + std::vector BundlerArgs = { "clang-offload-bundler", + "-type=ao", + Targets, + Inputs, + "-check-section" }; + return runBundler(BundlerArgs, C); +} + +// Simple helper function for Linker options, where the option is valid if +// it has '-' or '--' as the designator. +static bool optionMatches(const std::string &Option, + const std::string &OptCheck) { + return (Option == OptCheck || ("-" + Option) == OptCheck); +} + +// Process linker inputs for use with offload static libraries. We are only +// handling options and explicitly named static archives as these need to be +// partially linked. +static void getLinkerArgs(Compilation &C, DerivedArgList &Args, + SmallVector &LibArgs) { + for (const auto *A : Args) { + std::string FileName = A->getAsString(Args); + if (A->getOption().getKind() == Option::InputClass) { + std::string Value(A->getValue()); + if (isStaticArchiveFile(Value)) { + LibArgs.push_back(Args.MakeArgString(FileName)); + continue; + } + } + if (A->getOption().hasFlag(options::LinkerInput)) { + // Do not add any libraries that are not fully named static libs + if (A->getOption().matches(options::OPT_l) || + A->getOption().matches(options::OPT_reserved_lib_Group) || + A->getOption().hasFlag(options::NoArgumentUnused)) + continue; + for (const std::string &Value : A->getValues()) { + static std::string PrevArg; + auto addKnownValues = [&](const std::string &V) { + // Only add named static libs objects and --whole-archive options. + if (optionMatches("-whole-archive", V) || + optionMatches("-no-whole-archive", V) || isStaticArchiveFile(V)) { + LibArgs.push_back(Args.MakeArgString(V)); + return; + } + // Probably not the best way to handle this, but there are options + // that take arguments which we should not add to the known values. + // Handle -z for now - can be expanded if/when usage shows the need + if (PrevArg != "-z" && V[0] != '-' && isObjectFile(V)) { + LibArgs.push_back(Args.MakeArgString(V)); + return; + } + }; + if (Value[0] == '@') { + // Found a response file, we want to expand contents to try and + // discover more libraries and options. + SmallVector ExpandArgs; + ExpandArgs.push_back(Value.c_str()); + + llvm::BumpPtrAllocator A; + llvm::StringSaver S(A); + llvm::cl::ExpandResponseFiles(S, + C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() ? + llvm::cl::TokenizeWindowsCommandLine : + llvm::cl::TokenizeGNUCommandLine, ExpandArgs); + for (std::string MA : ExpandArgs) + addKnownValues(MA); + } else + addKnownValues(Value); + PrevArg = Value; + } + continue; + } + // Use of -foffload-static-lib and -foffload-whole-static-lib is + // considered deprecated. Usage should move to passing in the static + // library name on the command line, encapsulating with + // -Wl,--whole-archive -Wl,--no-whole-archive as needed. + if (A->getOption().matches(options::OPT_foffload_static_lib_EQ)) { + LibArgs.push_back(Args.MakeArgString(A->getValue())); + continue; + } + if (A->getOption().matches(options::OPT_foffload_whole_static_lib_EQ)) { + // For -foffload-whole-static-lib, we add the --whole-archive wrap + // around the library which will be used during the partial link step. + LibArgs.push_back("--whole-archive"); + LibArgs.push_back(Args.MakeArgString(A->getValue())); + LibArgs.push_back("--no-whole-archive"); + continue; + } + } +} + +// Goes through all of the arguments, including inputs expected for the +// linker directly, to determine if we need to perform additional work for +// static offload libraries. +bool Driver::checkForOffloadStaticLib(Compilation &C, + DerivedArgList &Args) const { + // Check only if enabled with -fsycl + if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) + return false; + // Right off the bat, assume the presense of -foffload-static-lib means + // to perform the needed linking steps for offload fat archives. + if (Args.hasArg(options::OPT_offload_lib_Group)) + return true; + SmallVector OffloadLibArgs; + getLinkerArgs(C, Args, OffloadLibArgs); + for (std::string MA : OffloadLibArgs) + if (isStaticArchiveFile(MA) && hasOffloadSections(C, MA, Args)) { + // For FPGA binaries with AOCX or AOCR sections are not + // considered fat static archives + if (Args.hasArg(options::OPT_fintelfpga)) + return !(hasFPGABinary(C, MA, types::TY_FPGA_AOCR) || + hasFPGABinary(C, MA, types::TY_FPGA_AOCX)); + return true; + } + return false; +} + namespace { /// Provides a convenient interface for different programming models to generate /// the required device actions. @@ -3392,8 +3581,9 @@ class OffloadingActionBuilder final { return ABRT_Inactive; std::string InputName = IA->getInputArg().getAsString(Args); - // Objects should already be consumed with -foffload-static-lib - if (Args.hasArg(options::OPT_offload_lib_Group) && + // Objects will be consumed as part of the partial link step when + // dealing with offload static libraries + if (C.getDriver().getOffloadStaticLibSeen() && IA->getType() == types::TY_Object && isObjectFile(InputName)) return ABRT_Inactive; @@ -3898,57 +4088,6 @@ class OffloadingActionBuilder final { return C.MakeAction(HDep, DDeps); } - bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) { - assert(types::isFPGA(Type) && "unexpected Type for FPGA binary check"); - // Temporary names for the output. - const ToolChain *OTC = C.getSingleOffloadToolChain(); - llvm::Triple TT; - TT.setArchName(types::getTypeName(Type)); - TT.setVendorName("intel"); - TT.setOS(llvm::Triple(OTC->getTriple()).getOS()); - TT.setEnvironment(llvm::Triple::SYCLDevice); - - // Checking uses -check-section option with the input file, no output - // file and the target triple being looked for. - const char *Targets = - C.getArgs().MakeArgString(Twine("-targets=sycl-") + TT.str()); - const char *Inputs = C.getArgs().MakeArgString(Twine("-inputs=") + - Object); - // Always use -type=ao for aocx/aocr bundle checking. The 'bundles' are - // actually archives. - std::vector BundlerArgs = { "clang-offload-bundler", - "-type=ao", - Targets, - Inputs, - "-check-section" }; - // Find bundler. - StringRef ExecPath(C.getArgs().MakeArgString(C.getDriver().Dir)); - auto BundlerBinary = llvm::sys::findProgramByName("clang-offload-bundler", - ExecPath); - if (C.getArgs().hasArg(options::OPT_ccc_print_phases, - options::OPT_ccc_print_bindings)) - return false; - // Since this is run in real time and not in the toolchain, output the - // command line if requested. - bool OutputOnly = C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); - if (C.getArgs().hasArg(options::OPT_v) || OutputOnly) { - for (StringRef A : BundlerArgs) - if (OutputOnly) - llvm::errs() << "\"" << A << "\" "; - else - llvm::errs() << A << " "; - llvm::errs() << '\n'; - } - if (BundlerBinary.getError()) - return false; - - // Run the bundler. - bool Failed = llvm::sys::ExecuteAndWait(BundlerBinary.get(), BundlerArgs); - if (!Failed) - return true; - return false; - } - /// Generate an action that adds a host dependence to a device action. The /// results will be kept in this action builder. Return true if an error was /// found. @@ -3985,7 +4124,7 @@ class OffloadingActionBuilder final { if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() || !(HostAction->getType() == types::TY_Object && isObjectFile(InputName) && - Args.hasArg(options::OPT_offload_lib_Group))) { + C.getDriver().getOffloadStaticLibSeen())) { ActionList HostActionList; Action *A(HostAction); // Only check for FPGA device information when using fpga SubArch. @@ -4468,7 +4607,7 @@ 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_offload_lib_Group)) { + C.getDriver().getOffloadStaticLibSeen()) { ActionList UnbundlerInputs; for (const auto &LI : LinkerInputs) { // Unbundler only handles objects. @@ -4482,55 +4621,82 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, UnbundlerInputs.push_back(LI); } const Arg *LastArg; - auto addUnbundlerInput = [&](types::ID T, const Arg *A) { + auto addUnbundlerInput = [&](types::ID T, const char *A) { const llvm::opt::OptTable &Opts = getOpts(); - Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); + Arg *InputArg = MakeInputArg(Args, Opts, C.getArgs().MakeArgString(A)); LastArg = InputArg; Action *Current = C.MakeAction(*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); + // Go through all of the args, and create a Linker specific argument list. + // This is fed into the partial link step. + SmallVector LinkArgs; + getLinkerArgs(C, Args, LinkArgs); + bool IsWholeArchive = false; + for (std::string MA : LinkArgs) { + if (isStaticArchiveFile(MA)) { + addUnbundlerInput(IsWholeArchive ? types::TY_WholeArchive : + types::TY_Archive, MA.c_str()); + continue; + } + if (optionMatches("-no-whole-archive", MA)) { + IsWholeArchive = false; + continue; + } + if (optionMatches("-whole-archive", MA)) { + IsWholeArchive = true; + continue; + } + if (isObjectFile(MA)) { + // Add any objects to the unbundler step. These objects are passed + // directly to the linker, so the driver does not know about them. + // FIXME - Better process objects passed to the linker process them + // like regular objects that need to be potentially unbundled. + addUnbundlerInput(types::TY_Object, MA.c_str()); + continue; + } + } + if (!UnbundlerInputs.empty()) { - Action *Current = C.MakeAction(*LastArg, types::TY_Archive); - OffloadBuilder.addHostDependenceToUnbundlingAction(Current, - UnbundlerInputs, LastArg); + Action *PartialLink = C.MakeAction( + UnbundlerInputs, types::TY_Object); + Action *Current = C.MakeAction(*LastArg, types::TY_Object); + ActionList AL; + AL.push_back(PartialLink); + OffloadBuilder.addHostDependenceToUnbundlingAction(Current, AL, LastArg); Current = OffloadBuilder.addDeviceDependencesToHostAction(Current, LastArg, phases::Link, PL.back(), PL); } } const llvm::opt::OptTable &Opts = getOpts(); - auto unbundleStaticLib = [&](types::ID T, const Arg *A) { - Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); + auto unbundleStaticLib = [&](types::ID T, const std::string &A) { + Arg *InputArg = MakeInputArg(Args, Opts, Args.MakeArgString(A)); Action *Current = C.MakeAction(*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)) { + SmallVector LinkArgs; + getLinkerArgs(C, Args, LinkArgs); + for (std::string MA : LinkArgs) { + // At this point, we will process the archives for FPGA AOCO and individual + // archive unbundling for Windows. + if (!isStaticArchiveFile(MA)) + continue; // 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, 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, 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 (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() && + hasOffloadSections(C, MA, Args)) + unbundleStaticLib(types::TY_Archive, MA); + // Pass along the static libraries 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, A); + unbundleStaticLib(types::TY_FPGA_AOCO, MA); } // For an FPGA archive, we add the unbundling step above to take care of @@ -5408,8 +5574,8 @@ 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_offload_lib_Group) && - ((JA->getType() == types::TY_Archive && IsMSVCEnv) || + if (C.getDriver().getOffloadStaticLibSeen() && + (JA->getType() == types::TY_Archive || (JA->getType() == types::TY_Object && !IsMSVCEnv))) { // Host part of the unbundled static archive is not used. if (UI.DependentOffloadKind == Action::OFK_Host) @@ -6311,6 +6477,16 @@ bool clang::driver::isObjectFile(std::string FileName) { types::lookupTypeForExtension(Ext) == types::TY_Object); } +bool clang::driver::isStaticArchiveFile(const std::string &FileName) { + if (!llvm::sys::path::has_extension(FileName)) + // Any file with no extension should be considered an Object. Take into + // account -lsomelib library filenames. + return false; + StringRef Ext(llvm::sys::path::extension(FileName).drop_front()); + // Only .lib and .a files are to be considered. + return (Ext == "lib" || Ext == "a"); +} + bool clang::driver::willEmitRemarks(const ArgList &Args) { // -fsave-optimization-record enables it. if (Args.hasFlag(options::OPT_fsave_optimization_record, diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 51be68bbe1212..1abb81a8019c2 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -330,6 +330,12 @@ Tool *ToolChain::getSYCLPostLink() const { return SYCLPostLink.get(); } +Tool *ToolChain::getPartialLink() const { + if (!PartialLink) + PartialLink.reset(new tools::PartialLink(*this)); + return PartialLink.get(); +} + Tool *ToolChain::getBackendCompiler() const { if (!BackendCompiler) BackendCompiler.reset(buildBackendCompiler()); @@ -381,6 +387,9 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const { case Action::SYCLPostLinkJobClass: return getSYCLPostLink(); + case Action::PartialLinkJobClass: + return getPartialLink(); + case Action::BackendCompileJobClass: return getBackendCompiler(); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c7006cb04229b..7ab7005306dcc 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7181,55 +7181,15 @@ void OffloadBundler::ConstructJobMultipleOutputs( C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); types::ID InputType(Input.getType()); bool IsFPGADepUnbundle = (JA.getType() == types::TY_FPGA_Dependencies); + bool IsArchiveUnbundle = (!IsMSVCEnv && + C.getDriver().getOffloadStaticLibSeen() && + (types::isArchive(InputType) || InputType == types::TY_Object) && + !(InputType == types::TY_FPGA_AOCX || InputType == types::TY_FPGA_AOCR)); - // For Linux, we have initial support for fat archives (archives which - // contain bundled objects). We will perform partial linking against the - // 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)) { + if (IsArchiveUnbundle) TypeArg = "oo"; - ArgStringList LinkArgs; - LinkArgs.push_back("-r"); - LinkArgs.push_back("-o"); - std::string TmpName = - C.getDriver().GetTemporaryPath( - llvm::sys::path::stem(Input.getFilename()).str() + "-prelink", "o"); - InputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName)); - LinkArgs.push_back(InputFileName); - const ToolChain *HTC = C.getSingleOffloadToolChain(); - // Add crt objects - LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crt1.o"))); - LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crti.o"))); - // Add -L search directories. - TCArgs.AddAllArgs(LinkArgs, options::OPT_L); - - // 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= -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(JA, *this, Exec, LinkArgs, Inputs)); - } else if (InputType == types::TY_FPGA_AOCX || - InputType == 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) @@ -7274,10 +7234,9 @@ void OffloadBundler::ConstructJobMultipleOutputs( Triples += Dep.DependentToolChain->getTriple().normalize(); } continue; - } 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))))) { + } else if (InputType == types::TY_Archive || IsArchiveUnbundle || + (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 @@ -7702,3 +7661,50 @@ void SYCLPostLink::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs, None)); } +// For Linux, we have initial support for fat archives (archives which +// contain bundled objects). We will perform partial linking against the +// specific offload target archives which will be sent to the unbundler to +// produce a list of target objects. +void PartialLink::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const { + // Construct simple partial link command. + assert(isa(JA) && "Expecting Partial Link job!"); + + // The partial linking command resembles this: + // ld -r -o + ArgStringList LinkArgs; + LinkArgs.push_back("-r"); + LinkArgs.push_back("-o"); + LinkArgs.push_back(Output.getFilename()); + + const ToolChain *HTC = C.getSingleOffloadToolChain(); + // Add crt objects + LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crt1.o"))); + LinkArgs.push_back(TCArgs.MakeArgString(HTC->GetFilePath("crti.o"))); + // Add -L search directories. + TCArgs.AddAllArgs(LinkArgs, options::OPT_L); + HTC->AddFilePathLibArgs(TCArgs, LinkArgs); + + // Input files consist of fat libraries and the object(s) to be unbundled. + // We add the needed --whole-archive/--no-whole-archive when appropriate. + 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(JA, *this, Exec, LinkArgs, Inputs)); +} diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 0cd0e16ad7784..02c34af659b7d 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -205,6 +205,20 @@ class LLVM_LIBRARY_VISIBILITY SYCLPostLink final : public Tool { const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override; }; + +/// Partially link objects and archives. +class LLVM_LIBRARY_VISIBILITY PartialLink final : public Tool { +public: + PartialLink(const ToolChain &TC) + : Tool("partial link", "partial-link", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool hasGoodDiagnostics() const override { return true; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; } // end namespace tools } // end namespace driver diff --git a/clang/test/Driver/sycl-offload-intelfpga.cpp b/clang/test/Driver/sycl-offload-intelfpga.cpp index 33fd08f64091e..88ba93c94921f 100644 --- a/clang/test/Driver/sycl-offload-intelfpga.cpp +++ b/clang/test/Driver/sycl-offload-intelfpga.cpp @@ -59,7 +59,7 @@ // Create the dummy archive // RUN: echo "Dummy AOCR image" > %t.aocr // RUN: echo "void foo() {}" > %t.c -// RUN: %clang -c %t.c +// RUN: %clang -c -o %t.o %t.c // RUN: clang-offload-wrapper -o %t-aocr.bc -host=x86_64-unknown-linux-gnu -kind=sycl -target=fpga_aocr-intel-unknown-sycldevice %t.aocr // RUN: llc -filetype=obj -o %t-aocr.o %t-aocr.bc // RUN: llvm-ar crv %t.a %t.o %t-aocr.o @@ -115,7 +115,7 @@ // Create the dummy archive // RUN: echo "Dummy AOCX image" > %t.aocx // RUN: echo "void foo() {}" > %t.c -// RUN: %clang -c %t.c +// RUN: %clang -c -o %t.o %t.c // RUN: clang-offload-wrapper -o %t-aocx.bc -host=x86_64-unknown-linux-gnu -kind=sycl -target=fpga_aocx-intel-unknown-sycldevice %t.aocx // RUN: llc -filetype=obj -o %t-aocx.o %t-aocx.bc // RUN: llvm-ar crv %t_aocx.a %t.o %t-aocx.o @@ -123,8 +123,11 @@ // RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCX-PHASES %s // RUN: %clang_cl -fsycl -fintelfpga %t_aocx.a -ccc-print-phases 2>&1 \ // RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCX-PHASES %s -// CHK-FPGA-AOCX-PHASES: 0: input, "{{.*}}", object, (host-sycl) +// CHK-FPGA-AOCX-PHASES: 0: input, "{{.*}}", fpga_aocx, (host-sycl) // CHK-FPGA-AOCX-PHASES: 1: linker, {0}, image, (host-sycl) +// CHK-FPGA-AOCX-PHASES: 2: clang-offload-unbundler, {0}, fpga_aocx +// CHK-FPGA-AOCX-PHASES: 3: clang-offload-wrapper, {2}, object, (device-sycl) +// CHK-FPGA-AOCX-PHASES: 4: offload, "host-sycl ({{.*}}x86_64{{.*}})" {1}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice{{(-coff)?}})" {3}, image // RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga %t_aocx.a -### 2>&1 \ // RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCX,CHK-FPGA-AOCX-LIN %s @@ -255,47 +258,78 @@ /// -fintelfpga static lib (aoco) // RUN: echo "Dummy AOCO image" > %t.aoco // RUN: echo "void foo() {}" > %t.c -// RUN: %clang -c %t.c +// RUN: echo "void foo2() {}" > %t2.c +// RUN: %clang -c -o %t.o %t.c +// RUN: %clang -fsycl -c -o %t2.o %t2.c +// RUN: %clang_cl -fsycl -c -o %t2_cl.o %t2.c // RUN: clang-offload-wrapper -o %t-aoco.bc -host=x86_64-unknown-linux-gnu -kind=sycl -target=fpga_aoco-intel-unknown-sycldevice %t.aoco // RUN: llc -filetype=obj -o %t-aoco.o %t-aoco.bc -// RUN: llvm-ar crv %t_aoco.a %t.o %t-aoco.o -// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga -foffload-static-lib=%t_aocx.a %s -### -ccc-print-phases 2>&1 \ -// RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO-PHASES,CHK-FPGA-AOCO-PHASES-LIN %s -// RUN: %clang_cl -fsycl -fintelfpga -foffload-static-lib=%t_aoco.a %s -### -ccc-print-phases 2>&1 \ -// RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO-PHASES,CHK-FPGA-AOCO-PHASES-WIN %s +// RUN: llvm-ar crv %t_aoco.a %t.o %t2.o %t-aoco.o +// RUN: llvm-ar crv %t_aoco_cl.a %t.o %t2_cl.o %t-aoco.o +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga -foffload-static-lib=%t_aoco.a %s -### -ccc-print-phases 2>&1 \ +// RUN: | FileCheck -check-prefix=CHK-FPGA-AOCO-PHASES %s // CHK-FPGA-AOCO-PHASES: 0: input, "[[INPUTA:.+\.a]]", object, (host-sycl) // CHK-FPGA-AOCO-PHASES: 1: input, "[[INPUTCPP:.+\.cpp]]", c++, (host-sycl) // CHK-FPGA-AOCO-PHASES: 2: preprocessor, {1}, c++-cpp-output, (host-sycl) // CHK-FPGA-AOCO-PHASES: 3: input, "[[INPUTCPP]]", c++, (device-sycl) // CHK-FPGA-AOCO-PHASES: 4: preprocessor, {3}, c++-cpp-output, (device-sycl) // CHK-FPGA-AOCO-PHASES: 5: compiler, {4}, sycl-header, (device-sycl) -// CHK-FPGA-AOCO-PHASES-LIN: 6: offload, "host-sycl (x86_64-unknown-linux-gnu)" {2}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {5}, c++-cpp-output -// CHK-FPGA-AOCO-PHASES-WIN: 6: offload, "host-sycl (x86_64-pc-windows-msvc)" {2}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {5}, c++-cpp-output +// CHK-FPGA-AOCO-PHASES: 6: offload, "host-sycl (x86_64-unknown-linux-gnu)" {2}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {5}, c++-cpp-output // CHK-FPGA-AOCO-PHASES: 7: compiler, {6}, ir, (host-sycl) // CHK-FPGA-AOCO-PHASES: 8: backend, {7}, assembler, (host-sycl) // CHK-FPGA-AOCO-PHASES: 9: assembler, {8}, object, (host-sycl) // CHK-FPGA-AOCO-PHASES: 10: linker, {0, 9}, image, (host-sycl) // CHK-FPGA-AOCO-PHASES: 11: compiler, {4}, ir, (device-sycl) // CHK-FPGA-AOCO-PHASES: 12: input, "[[INPUTA]]", archive -// CHK-FPGA-AOCO-PHASES-LIN: 13: clang-offload-unbundler, {9, 12}, object +// CHK-FPGA-AOCO-PHASES: 13: partial-link, {9, 12}, object +// CHK-FPGA-AOCO-PHASES: 14: clang-offload-unbundler, {13}, object +// CHK-FPGA-AOCO-PHASES: 15: linker, {11, 14}, ir, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 16: llvm-spirv, {15}, spirv, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 17: input, "[[INPUTA]]", fpga_aoco +// CHK-FPGA-AOCO-PHASES: 18: clang-offload-unbundler, {17}, fpga_aoco +// CHK-FPGA-AOCO-PHASES: 19: backend-compiler, {16, 18}, fpga_aocx, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 20: clang-offload-wrapper, {19}, object, (device-sycl) +// CHK-FPGA-AOCO-PHASES: 21: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {20}, image + +/// FPGA AOCO Windows phases check +// RUN: %clang_cl -fsycl -fintelfpga -foffload-static-lib=%t_aoco_cl.a %s -### -ccc-print-phases 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO-PHASES-WIN %s +// CHK-FPGA-AOCO-PHASES-WIN: 0: input, "{{.*}}", object, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 1: input, "[[INPUTSRC:.+\.cpp]]", c++, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 2: preprocessor, {1}, c++-cpp-output, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 3: input, "[[INPUTSRC]]", c++, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 4: preprocessor, {3}, c++-cpp-output, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 5: compiler, {4}, sycl-header, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 6: offload, "host-sycl (x86_64-pc-windows-msvc)" {2}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {5}, c++-cpp-output +// CHK-FPGA-AOCO-PHASES-WIN: 7: compiler, {6}, ir, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 8: backend, {7}, assembler, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 9: assembler, {8}, object, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 10: linker, {0, 9}, image, (host-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 11: compiler, {4}, ir, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 12: input, "[[INPUTA:.+\.a]]", archive // CHK-FPGA-AOCO-PHASES-WIN: 13: clang-offload-unbundler, {12}, archive -// CHK-FPGA-AOCO-PHASES: 14: linker, {11, 13}, ir, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 15: llvm-spirv, {14}, spirv, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 16: backend-compiler, {15}, fpga_aocx, (device-sycl) -// CHK-FPGA-AOCO-PHASES: 17: clang-offload-wrapper, {16}, object, (device-sycl) -// CHK-FPGA-AOCO-PHASES-LIN: 18: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice)" {17}, image -// CHK-FPGA-AOCO-PHASES-WIN: 18: offload, "host-sycl (x86_64-pc-windows-msvc)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {17}, image +// CHK-FPGA-AOCO-PHASES-WIN: 14: linker, {11, 13}, ir, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 15: llvm-spirv, {14}, spirv, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 16: input, "[[INPUTA]]", fpga_aoco +// CHK-FPGA-AOCO-PHASES-WIN: 17: clang-offload-unbundler, {16}, fpga_aoco +// CHK-FPGA-AOCO-PHASES-WIN: 18: backend-compiler, {15, 17}, fpga_aocx, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 19: clang-offload-wrapper, {18}, object, (device-sycl) +// CHK-FPGA-AOCO-PHASES-WIN: 20: offload, "host-sycl (x86_64-pc-windows-msvc)" {10}, "device-sycl (spir64_fpga-unknown-unknown-sycldevice-coff)" {19}, image /// aoco test, checking tools // RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga -foffload-static-lib=%t_aoco.a -### %s 2>&1 \ // RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO,CHK-FPGA-AOCO-LIN %s -// RUN: %clang_cl -fsycl -fintelfpga -foffload-static-lib=%t_aoco.a -### %s 2>&1 \ +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fintelfpga %t_aoco.a -### %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO,CHK-FPGA-AOCO-LIN %s +// RUN: %clang_cl -fsycl -fintelfpga -foffload-static-lib=%t_aoco_cl.a -### %s 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO,CHK-FPGA-AOCO-WIN %s +// RUN: %clang_cl -fsycl -fintelfpga %t_aoco_cl.a -### %s 2>&1 \ // RUN: | FileCheck -check-prefixes=CHK-FPGA-AOCO,CHK-FPGA-AOCO-WIN %s // CHK-FPGA-AOCO-LIN: clang-offload-bundler{{.*}} "-type=ao" "-targets=sycl-fpga_aoco-intel-unknown-sycldevice" "-inputs=[[INPUTLIB:.+\.a]]" "-check-section" // CHK-FPGA-AOCO-LIN: clang{{.*}} "-emit-obj" {{.*}} "-o" "[[HOSTOBJ:.+\.o]]" -// CHK-FPGA-AOCO-LIN: ld{{.*}} "-r" "-o" "[[PARTLINKOBJ:.+\.o]]" "{{.*}}crt1.o" "{{.*}}crti.o" "[[HOSTOBJ]]" "[[INPUTLIB]]" "{{.*}}crtn.o" +// CHK-FPGA-AOCO-LIN: ld{{.*}} "-r" "-o" "[[PARTLINKOBJ:.+\.o]]" "{{.*}}crt1.o" "{{.*}}crti.o" {{.*}} "[[HOSTOBJ]]" "[[INPUTLIB]]" "{{.*}}crtn.o" // CHK-FPGA-AOCO-LIN: clang-offload-bundler{{.*}} "-type=oo" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice" "-inputs=[[PARTLINKOBJ]]" "-outputs={{.*}}" "-unbundle" -// CHK-FPGA-AOCO-WIN: clang-offload-bundler{{.*}} "-type=aoo" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice-coff" "-inputs=[[INPUTLIB:.+\.a]]" "-outputs={{.*}}" "-unbundle" +// CHK-FPGA-AOCO-WIN: clang-offload-bundler{{.*}} "-type=aoo" "-targets=sycl-spir64_fpga-unknown-unknown-sycldevice{{(-coff)?}}" "-inputs=[[INPUTLIB:.+\.a]]" "-outputs={{.*}}" "-unbundle" // CHK-FPGA-AOCO: llvm-link{{.*}} "@{{.*}}" "-o" "[[LINKEDBC:.+\.bc]]" // CHK-FPGA-AOCO: llvm-spirv{{.*}} "-o" "[[TARGSPV:.+\.spv]]" {{.*}} "[[LINKEDBC]]" // CHK-FPGA-AOCO: clang-offload-bundler{{.*}} "-type=aoo" "-targets=sycl-fpga_aoco-intel-unknown-sycldevice" "-inputs=[[INPUTLIB]]" "-outputs=[[AOCOLIST:.+\.txt]]" "-unbundle" @@ -304,7 +338,7 @@ // CHK-FPGA-AOCO-LIN: llc{{.*}} "-filetype=obj" "-o" "[[FINALOBJL:.+\.o]]" "[[FINALBC]]" // CHK-FPGA-AOCO-WIN: llc{{.*}} "-filetype=obj" "-o" "[[FINALOBJW:.+\.obj]]" "[[FINALBC]]" // CHK-FPGA-AOCO-LIN: ld{{.*}} "[[INPUTLIB]]" {{.*}} "[[FINALOBJL]]" -// CHK-FPGA-AOCO-WIN: link.exe{{.*}} "-defaultlib:[[INPUTLIB]]" {{.*}} "[[FINALOBJW]]" +// CHK-FPGA-AOCO-WIN: link.exe{{.*}} "{{.*}}[[INPUTLIB]]" {{.*}} "[[FINALOBJW]]" // TODO: SYCL specific fail - analyze and enable // XFAIL: windows-msvc diff --git a/clang/test/Driver/sycl-offload-static-lib-2.cpp b/clang/test/Driver/sycl-offload-static-lib-2.cpp new file mode 100644 index 0000000000000..0c1a8709594b7 --- /dev/null +++ b/clang/test/Driver/sycl-offload-static-lib-2.cpp @@ -0,0 +1,102 @@ +/// +/// Perform several driver tests for SYCL offloading involving static libs +/// +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target + +/// ########################################################################### + +/// test behaviors of passing a fat static lib +// Build a fat static lib that will be used for all tests +// RUN: echo "void foo(void) {}" > %t1.cpp +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl %t1.cpp -c -o %t1_bundle.o +// RUN: llvm-ar crv %t.a %t1_bundle.o +// +// RUN: touch %t.a +// RUN: touch %t.o +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir %t.a -### %t.o 2>&1 \ +// RUN: | FileCheck %s -check-prefix=STATIC_LIB +// STATIC_LIB: ld{{(.exe)?}}" "-r" "-o" {{.*}} "[[INPUT:.+\.o]]" "-L/dummy/dir"{{.*}} "[[INPUT:.+\.a]]" +// STATIC_LIB: clang-offload-bundler{{.*}} "-type=oo" +// STATIC_LIB: llvm-link{{.*}} "@{{.*}}" + +/// ########################################################################### + +/// test behaviors of fat static lib with multiple objects +// RUN: touch %t.a +// RUN: touch %t-1.o +// RUN: touch %t-2.o +// RUN: touch %t-3.o +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl %t.a -### %t-1.o %t-2.o %t-3.o 2>&1 \ +// RUN: | FileCheck %s -check-prefix=STATIC_LIB_MULTI_O +// STATIC_LIB_MULTI_O: ld{{(.exe)?}}" "-r" "-o" {{.*}} "[[INPUT:.+\-1.o]]" "[[INPUT:.+\-2.o]]" "[[INPUT:.+\-3.o]]" "[[INPUT:.+\.a]]" +// STATIC_LIB_MULTI_O: clang-offload-bundler{{.*}} "-type=oo" +// STATIC_LIB_MULTI_O: llvm-link{{.*}} "@{{.*}}" + +/// ########################################################################### + +/// test behaviors of fat static lib from source +// RUN: touch %t.a +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl %t.a -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=STATIC_LIB_SRC +// STATIC_LIB_SRC: ld{{(.exe)?}}" "-r" "-o" {{.*}} "[[INPUT:.+\.a]]" +// STATIC_LIB_SRC: clang-offload-bundler{{.*}} "-type=oo" +// STATIC_LIB_SRC: llvm-link{{.*}} "@{{.*}}" + +/// ########################################################################### + +// RUN: touch %t.a +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl %t.a -o output_name -lOpenCL -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=STATIC_LIB_SRC2 +// STATIC_LIB_SRC2: ld{{(.exe)?}}" "-r" "-o" {{.*}} "[[INPUT:.+\.a]]" +// STATIC_LIB_SRC2: clang-offload-bundler{{.*}} "-type=oo" +// STATIC_LIB_SRC2: llvm-link{{.*}} "@{{.*}}" +// STATIC_LIB_SRC2: ld{{(.exe)?}}" {{.*}} "-o" "output_name" {{.*}} "-lOpenCL" + +/// ########################################################################### + +// RUN: touch %t.a +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl %t.a -o output_name -lstdc++ -z relro -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix=STATIC_LIB_SRC3 +// STATIC_LIB_SRC3: ld{{(.exe)?}}" "-r" "-o" {{.*}} "[[INPUT:.+\.a]]" +// STATIC_LIB_SRC3: clang-offload-bundler{{.*}} "-type=oo" +// STATIC_LIB_SRC3: llvm-link{{.*}} "@{{.*}}" +// STATIC_LIB_SRC3: ld{{(.exe)?}}" {{.*}} "-o" "output_name" {{.*}} "-lstdc++" "-z" "relro" + +/// ########################################################################### + +/// test behaviors of -Wl,--whole-archive staticlib.a -Wl,--no-whole-archive +/// also test behaviors of -Wl,@arg with the above arguments +// RUN: touch %t.a +// RUN: touch %t_2.a +// RUN: touch %t.o +// RUN: echo "--whole-archive %t.a %t_2.a --no-whole-archive" > %t.arg +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir %t.o -Wl,--whole-archive %t.a %t_2.a -Wl,--no-whole-archive -### 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=WHOLE_STATIC_LIB,WHOLE_STATIC_LIB_1 +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir %t.o -Wl,@%t.arg -### 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=WHOLE_STATIC_LIB,WHOLE_STATIC_LIB_2 -DARGFILE=%t.arg +// WHOLE_STATIC_LIB: ld{{(.exe)?}}" "-r" "-o" "[[INPUT:.+\.o]]" "{{.*}}crt1.o" "{{.*}}crti.o" "-L/dummy/dir" {{.*}} "[[INPUTO:.+\.o]]" "--whole-archive" "[[INPUTA:.+\.a]]" "[[INPUTB:.+\.a]]" "--no-whole-archive" "{{.*}}crtn.o" +// WHOLE_STATIC_LIB: clang-offload-bundler{{.*}} "-type=oo" {{.*}} "-inputs=[[INPUT]]" +// WHOLE_STATIC_LIB: llvm-link{{.*}} "@{{.*}}" +// WHOLE_STATIC_LIB: llvm-spirv{{.*}} +// WHOLE_STATIC_LIB: clang-offload-wrapper{{.*}} +// WHOLE_STATIC_LIB: llc{{.*}} +// WHOLE_STATIC_LIB_1: ld{{.*}} "[[INPUTO]]" "--whole-archive" "[[INPUTA]]" "[[INPUTB]]" "--no-whole-archive" +// WHOLE_STATIC_LIB_2: ld{{.*}} "[[INPUTO]]" "@[[ARGFILE]]" + +/// ########################################################################### + +/// test behaviors of static lib with no source/object +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir %t.a -### 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=STATIC_LIB_NOSRC +// STATIC_LIB_NOSRC: clang-offload-bundler{{.*}} "-type=ao" "-targets=host-x86_64-unknown-linux-gnu" "-inputs=[[INPUTLIB:.+\.a]]" "-check-section" +// STATIC_LIB_NOSRC: ld{{.*}} "-r" "-o" "[[PARTIALOBJ:.+\.o]]" "{{.*}}crt1.o" {{.*}} "-L/dummy/dir" {{.*}} "[[INPUTLIB]]" +// STATIC_LIB_NOSRC: clang-offload-bundler{{.*}} "-type=oo" "-targets=sycl-spir64-unknown-unknown-sycldevice" "-inputs=[[PARTIALOBJ]]" "-outputs=[[DEVICELIST:.+\.txt]]" "-unbundle" +// STATIC_LIB_NOSRC: llvm-link{{.*}} "@[[DEVICELIST]]" "-o" "[[BCFILE:.+\.bc]]" +// STATIC_LIB_NOSRC: llvm-spirv{{.*}} "-o" "[[SPVFILE:.+\.spv]]" {{.*}} "[[BCFILE]]" +// STATIC_LIB_NOSRC: clang-offload-wrapper{{.*}} "-o=[[BCFILE2:.+\.bc]]" "-host=x86_64-unknown-linux-gnu" "-target=spir64" "-kind=sycl" "[[SPVFILE]]" +// STATIC_LIB_NOSRC: llc{{.*}} "-filetype=obj" "-o" "[[FINALOBJ:.+\.o]]" "[[BCFILE2]]" +// STATIC_LIB_NOSRC: ld{{.*}} "-L/dummy/dir" {{.*}} "[[INPUTLIB]]" "[[FINALOBJ]]" + +// fails on Windows due to the argument file to -Wl and directory separators +// XFAIL: windows-msvc diff --git a/clang/test/Driver/sycl-offload-static-lib.cpp b/clang/test/Driver/sycl-offload-static-lib.cpp index 897c34cf2bef2..4ab248a109e99 100644 --- a/clang/test/Driver/sycl-offload-static-lib.cpp +++ b/clang/test/Driver/sycl-offload-static-lib.cpp @@ -48,11 +48,12 @@ // FOFFLOAD_STATIC_LIB_SRC: 10: linker, {0, 9}, image, (host-sycl) // FOFFLOAD_STATIC_LIB_SRC: 11: compiler, {4}, ir, (device-sycl) // FOFFLOAD_STATIC_LIB_SRC: 12: input, "[[INPUTA]]", archive -// FOFFLOAD_STATIC_LIB_SRC: 13: clang-offload-unbundler, {9, 12}, object -// FOFFLOAD_STATIC_LIB_SRC: 14: linker, {11, 13}, ir, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 15: llvm-spirv, {14}, spirv, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 16: clang-offload-wrapper, {15}, object, (device-sycl) -// FOFFLOAD_STATIC_LIB_SRC: 17: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {16}, image +// FOFFLOAD_STATIC_LIB_SRC: 13: partial-link, {9, 12}, object +// FOFFLOAD_STATIC_LIB_SRC: 14: clang-offload-unbundler, {13}, object +// FOFFLOAD_STATIC_LIB_SRC: 15: linker, {11, 14}, ir, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 16: llvm-spirv, {15}, spirv, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 17: clang-offload-wrapper, {16}, object, (device-sycl) +// FOFFLOAD_STATIC_LIB_SRC: 18: offload, "host-sycl (x86_64-unknown-linux-gnu)" {10}, "device-sycl (spir64-unknown-unknown-sycldevice)" {17}, image /// ########################################################################### @@ -92,7 +93,7 @@ // RUN: touch %t.o // RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir -foffload-whole-static-lib=%t.a -foffload-whole-static-lib=%t_2.a -### %t.o 2>&1 \ // RUN: | FileCheck %s -check-prefix=FOFFLOAD_WHOLE_STATIC_LIB -// FOFFLOAD_WHOLE_STATIC_LIB: ld{{(.exe)?}}" "-r" "-o" "[[INPUT:.+\.o]]" "{{.*}}crt1.o" "{{.*}}crti.o" "-L/dummy/dir" "[[INPUTO:.+\.o]]" "--whole-archive" "[[INPUTA:.+\.a]]" "[[INPUTB:.+\.a]]" "--no-whole-archive" "{{.*}}crtn.o" +// FOFFLOAD_WHOLE_STATIC_LIB: ld{{(.exe)?}}" "-r" "-o" "[[INPUT:.+\.o]]" "{{.*}}crt1.o" "{{.*}}crti.o" "-L/dummy/dir" {{.*}} "[[INPUTO:.+\.o]]" "--whole-archive" "[[INPUTA:.+\.a]]" "[[INPUTB:.+\.a]]" "--no-whole-archive" "{{.*}}crtn.o" // FOFFLOAD_WHOLE_STATIC_LIB: clang-offload-bundler{{.*}} "-type=oo" {{.*}} "-inputs=[[INPUT]]" // FOFFLOAD_WHOLE_STATIC_LIB: llvm-link{{.*}} "@{{.*}}" // FOFFLOAD_WHOLE_STATIC_LIB: llvm-spirv{{.*}} @@ -111,8 +112,9 @@ // FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 1: linker, {0}, image, (host-sycl) // FOFFLOAD_STATIC_LIB_NOSRC_PHASES_1: 2: input, "[[INPUTA]]", archive // FOFFLOAD_STATIC_LIB_NOSRC_PHASES_2: 2: input, "[[INPUTA]]", wholearchive -// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 3: clang-offload-unbundler, {2}, object -// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 4: linker, {3}, ir, (device-sycl) -// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 5: llvm-spirv, {4}, spirv, (device-sycl) -// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 6: clang-offload-wrapper, {5}, object, (device-sycl) -// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 7: offload, "host-sycl (x86_64-unknown-linux-gnu)" {1}, "device-sycl (spir64-unknown-unknown-sycldevice)" {6}, image +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 3: partial-link, {2}, object +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 4: clang-offload-unbundler, {3}, object +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 5: linker, {4}, ir, (device-sycl) +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 6: llvm-spirv, {5}, spirv, (device-sycl) +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 7: clang-offload-wrapper, {6}, object, (device-sycl) +// FOFFLOAD_STATIC_LIB_NOSRC_PHASES: 8: offload, "host-sycl (x86_64-unknown-linux-gnu)" {1}, "device-sycl (spir64-unknown-unknown-sycldevice)" {7}, image diff --git a/clang/test/Driver/sycl-offload-win.c b/clang/test/Driver/sycl-offload-win.c index 5192e12f45d1e..db65b5d70c113 100644 --- a/clang/test/Driver/sycl-offload-win.c +++ b/clang/test/Driver/sycl-offload-win.c @@ -6,8 +6,10 @@ // REQUIRES: x86-registered-target /// Test behaviors of -foffload-static-lib= with single object. -// RUN: touch %t.lib -// RUN: touch %t.obj +// Build the offload library that is used for the tests. +// RUN: echo "void foo() {}" > %t.c +// RUN: %clang_cl -fsycl -c -Fo%t.obj %t.c +// RUN: llvm-ar cr %t.lib %t.obj // RUN: %clang --target=x86_64-pc-windows-msvc -fsycl -foffload-static-lib=%t.lib %t.obj -### 2>&1 \ // RUN: | FileCheck -DOBJ=%t.obj -DLIB=%t.lib %s -check-prefixes=FOFFLOAD_STATIC_LIB,FOFFLOAD_STATIC_LIB_DEFAULT // RUN: %clang_cl --target=x86_64-pc-windows-msvc -fsycl -foffload-static-lib=%t.lib %t.obj -### 2>&1 \ @@ -40,8 +42,8 @@ /// ########################################################################### /// Test behaviors with multiple -foffload-static-lib= options. -// RUN: touch %t1.lib -// RUN: touch %t2.lib +// RUN: cp %t.lib %t1.lib +// RUN: cp %t.lib %t2.lib // RUN: touch %t.obj // RUN: %clang --target=x86_64-pc-windows-msvc -fsycl -foffload-static-lib=%t1.lib -foffload-static-lib=%t2.lib %t.obj -### 2>&1 \ // RUN: | FileCheck -DOBJ=%t.obj -DLIB1=%t1.lib -DLIB2=%t2.lib %s -check-prefixes=FOFFLOAD_STATIC_MULTI_LIB,FOFFLOAD_STATIC_MULTI_LIB_DEFAULT From 2b1460657b42ae38ba0423fd6ca0c628c1a89feb Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Sat, 14 Mar 2020 09:11:09 -0700 Subject: [PATCH 2/7] [NFC] clang-format patch Signed-off-by: Michael D Toguchi --- clang/include/clang/Driver/Driver.h | 1 - clang/lib/Driver/Driver.cpp | 55 ++++++++++++--------------- clang/lib/Driver/ToolChains/Clang.cpp | 14 ++++--- clang/lib/Driver/ToolChains/Clang.h | 3 +- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 04076addaa2a0..80d03ef2aa1ed 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -653,7 +653,6 @@ class Driver { static void getDefaultModuleCachePath(SmallVectorImpl &Result); bool getOffloadStaticLibSeen() const { return OffloadStaticLibSeen; }; - }; /// \return True if the last defined optimization level is -Ofast. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 62b843820d3b0..5fb33b49f5b17 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2485,8 +2485,8 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, A->claim(); // Use of -foffload-static-lib and -foffload-whole-static-lib are // deprecated with the updated functionality to scan the static libs. - Diag(clang::diag::warn_drv_deprecated_option) << A->getAsString(Args) << - A->getValue(); + Diag(clang::diag::warn_drv_deprecated_option) + << A->getAsString(Args) << A->getValue(); } } if (CCCIsCPP() && Inputs.empty()) { @@ -2498,11 +2498,11 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } static bool runBundler(const std::vector &BundlerArgs, - Compilation &C) { + Compilation &C) { // Find bundler. StringRef ExecPath(C.getArgs().MakeArgString(C.getDriver().Dir)); - llvm::ErrorOr BundlerBinary = llvm::sys::findProgramByName( - "clang-offload-bundler", ExecPath); + llvm::ErrorOr BundlerBinary = + llvm::sys::findProgramByName("clang-offload-bundler", ExecPath); // Since this is run in real time and not in the toolchain, output the // command line if requested. bool OutputOnly = C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); @@ -2533,15 +2533,11 @@ bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) { // file and the target triple being looked for. const char *Targets = C.getArgs().MakeArgString(Twine("-targets=sycl-") + TT.str()); - const char *Inputs = C.getArgs().MakeArgString(Twine("-inputs=") + - Object); + const char *Inputs = C.getArgs().MakeArgString(Twine("-inputs=") + Object); // Always use -type=ao for aocx/aocr bundle checking. The 'bundles' are // actually archives. - std::vector BundlerArgs = { "clang-offload-bundler", - "-type=ao", - Targets, - Inputs, - "-check-section" }; + std::vector BundlerArgs = {"clang-offload-bundler", "-type=ao", + Targets, Inputs, "-check-section"}; return runBundler(BundlerArgs, C); } @@ -2556,23 +2552,19 @@ static bool hasOffloadSections(Compilation &C, const std::string Archive, // file and the target triple being looked for. // TODO - Improve checking to check for explicit offload target instead // of the generic host availability. - const char *Targets = - Args.MakeArgString(Twine("-targets=host-") + TT.str()); + const char *Targets = Args.MakeArgString(Twine("-targets=host-") + TT.str()); const char *Inputs = Args.MakeArgString(Twine("-inputs=") + Archive); // Always use -type=ao for bundle checking. The 'bundles' are // actually archives. - std::vector BundlerArgs = { "clang-offload-bundler", - "-type=ao", - Targets, - Inputs, - "-check-section" }; + std::vector BundlerArgs = {"clang-offload-bundler", "-type=ao", + Targets, Inputs, "-check-section"}; return runBundler(BundlerArgs, C); } // Simple helper function for Linker options, where the option is valid if // it has '-' or '--' as the designator. static bool optionMatches(const std::string &Option, - const std::string &OptCheck) { + const std::string &OptCheck) { return (Option == OptCheck || ("-" + Option) == OptCheck); } @@ -2580,7 +2572,7 @@ static bool optionMatches(const std::string &Option, // handling options and explicitly named static archives as these need to be // partially linked. static void getLinkerArgs(Compilation &C, DerivedArgList &Args, - SmallVector &LibArgs) { + SmallVector &LibArgs) { for (const auto *A : Args) { std::string FileName = A->getAsString(Args); if (A->getOption().getKind() == Option::InputClass) { @@ -2621,10 +2613,12 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, llvm::BumpPtrAllocator A; llvm::StringSaver S(A); - llvm::cl::ExpandResponseFiles(S, - C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() ? - llvm::cl::TokenizeWindowsCommandLine : - llvm::cl::TokenizeGNUCommandLine, ExpandArgs); + llvm::cl::ExpandResponseFiles( + S, + C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() + ? llvm::cl::TokenizeWindowsCommandLine + : llvm::cl::TokenizeGNUCommandLine, + ExpandArgs); for (std::string MA : ExpandArgs) addKnownValues(MA); } else @@ -2656,7 +2650,7 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, // linker directly, to determine if we need to perform additional work for // static offload libraries. bool Driver::checkForOffloadStaticLib(Compilation &C, - DerivedArgList &Args) const { + DerivedArgList &Args) const { // Check only if enabled with -fsycl if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) return false; @@ -4635,8 +4629,9 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, bool IsWholeArchive = false; for (std::string MA : LinkArgs) { if (isStaticArchiveFile(MA)) { - addUnbundlerInput(IsWholeArchive ? types::TY_WholeArchive : - types::TY_Archive, MA.c_str()); + addUnbundlerInput(IsWholeArchive ? types::TY_WholeArchive + : types::TY_Archive, + MA.c_str()); continue; } if (optionMatches("-no-whole-archive", MA)) { @@ -4658,8 +4653,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, } if (!UnbundlerInputs.empty()) { - Action *PartialLink = C.MakeAction( - UnbundlerInputs, types::TY_Object); + Action *PartialLink = + C.MakeAction(UnbundlerInputs, types::TY_Object); Action *Current = C.MakeAction(*LastArg, types::TY_Object); ActionList AL; AL.push_back(PartialLink); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 7ab7005306dcc..c31c725f44967 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7181,10 +7181,10 @@ void OffloadBundler::ConstructJobMultipleOutputs( C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); types::ID InputType(Input.getType()); bool IsFPGADepUnbundle = (JA.getType() == types::TY_FPGA_Dependencies); - bool IsArchiveUnbundle = (!IsMSVCEnv && - C.getDriver().getOffloadStaticLibSeen() && - (types::isArchive(InputType) || InputType == types::TY_Object) && - !(InputType == types::TY_FPGA_AOCX || InputType == types::TY_FPGA_AOCR)); + bool IsArchiveUnbundle = + (!IsMSVCEnv && C.getDriver().getOffloadStaticLibSeen() && + (types::isArchive(InputType) || InputType == types::TY_Object) && + !(InputType == types::TY_FPGA_AOCX || InputType == types::TY_FPGA_AOCR)); if (IsArchiveUnbundle) TypeArg = "oo"; @@ -7666,8 +7666,10 @@ void SYCLPostLink::ConstructJob(Compilation &C, const JobAction &JA, // specific offload target archives which will be sent to the unbundler to // produce a list of target objects. void PartialLink::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, const InputInfoList &Inputs, - const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const { + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const { // Construct simple partial link command. assert(isa(JA) && "Expecting Partial Link job!"); diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 02c34af659b7d..f1467e40746e1 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -209,8 +209,7 @@ class LLVM_LIBRARY_VISIBILITY SYCLPostLink final : public Tool { /// Partially link objects and archives. class LLVM_LIBRARY_VISIBILITY PartialLink final : public Tool { public: - PartialLink(const ToolChain &TC) - : Tool("partial link", "partial-link", TC) {} + PartialLink(const ToolChain &TC) : Tool("partial link", "partial-link", TC) {} bool hasIntegratedCPP() const override { return false; } bool hasGoodDiagnostics() const override { return true; } From 95bac018250b5940c75e6fef3af74e221b92fbb8 Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Mon, 16 Mar 2020 18:49:11 -0700 Subject: [PATCH 3/7] [NFC] Address review comments Signed-off-by: Michael D Toguchi --- clang/lib/Driver/Driver.cpp | 15 +++++++-------- clang/lib/Driver/ToolChains/Clang.cpp | 3 +-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 5fb33b49f5b17..1c98b5a2d4a68 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2662,8 +2662,8 @@ bool Driver::checkForOffloadStaticLib(Compilation &C, getLinkerArgs(C, Args, OffloadLibArgs); for (std::string MA : OffloadLibArgs) if (isStaticArchiveFile(MA) && hasOffloadSections(C, MA, Args)) { - // For FPGA binaries with AOCX or AOCR sections are not - // considered fat static archives + // FPGA binaries with AOCX or AOCR sections are not considered fat + // static archives. if (Args.hasArg(options::OPT_fintelfpga)) return !(hasFPGABinary(C, MA, types::TY_FPGA_AOCR) || hasFPGABinary(C, MA, types::TY_FPGA_AOCX)); @@ -4598,6 +4598,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, OffloadBuilder.appendTopLevelLinkAction(Actions); + // Go through all of the args, and create a Linker specific argument list. + // When dealing with fat static archives, this is fed into the partial link + // step on Linux or each archive is individually addressed on Windows. + SmallVector LinkArgs; + getLinkerArgs(C, Args, LinkArgs); // When a static fat archive is provided, create a new unbundling step // for all of the objects. if (!C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() && @@ -4622,10 +4627,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, Action *Current = C.MakeAction(*InputArg, T); UnbundlerInputs.push_back(Current); }; - // Go through all of the args, and create a Linker specific argument list. - // This is fed into the partial link step. - SmallVector LinkArgs; - getLinkerArgs(C, Args, LinkArgs); bool IsWholeArchive = false; for (std::string MA : LinkArgs) { if (isStaticArchiveFile(MA)) { @@ -4671,8 +4672,6 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, OffloadBuilder.addDeviceDependencesToHostAction( Current, InputArg, phases::Link, PL.back(), PL); }; - SmallVector LinkArgs; - getLinkerArgs(C, Args, LinkArgs); for (std::string MA : LinkArgs) { // At this point, we will process the archives for FPGA AOCO and individual // archive unbundling for Windows. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c31c725f44967..bb71afa371f28 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7183,8 +7183,7 @@ void OffloadBundler::ConstructJobMultipleOutputs( bool IsFPGADepUnbundle = (JA.getType() == types::TY_FPGA_Dependencies); bool IsArchiveUnbundle = (!IsMSVCEnv && C.getDriver().getOffloadStaticLibSeen() && - (types::isArchive(InputType) || InputType == types::TY_Object) && - !(InputType == types::TY_FPGA_AOCX || InputType == types::TY_FPGA_AOCR)); + (types::isArchive(InputType) || InputType == types::TY_Object)); if (IsArchiveUnbundle) TypeArg = "oo"; From da235dacd596144494148920e863367951f86ab3 Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Tue, 17 Mar 2020 11:27:56 -0700 Subject: [PATCH 4/7] [Driver][SYCL] Additional review adjustments and test/checks Make adjustments according to recent reviews, also add -rpath as an additional -Wl check, adding a test for that as well. Signed-off-by: Michael D Toguchi --- clang/include/clang/Driver/Driver.h | 2 +- clang/lib/Driver/Driver.cpp | 92 ++++++++++--------- .../test/Driver/sycl-offload-static-lib-2.cpp | 6 ++ 3 files changed, 56 insertions(+), 44 deletions(-) diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 80d03ef2aa1ed..6679fae41f436 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -663,7 +663,7 @@ bool isOptimizationLevelFast(const llvm::opt::ArgList &Args); bool isObjectFile(std::string FileName); /// \return True if the filename has a static archive/lib extension. -bool isStaticArchiveFile(const std::string &FileName); +bool isStaticArchiveFile(const StringRef &FileName); /// \return True if the argument combination will end up generating remarks. bool willEmitRemarks(const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 1c98b5a2d4a68..47ffbdf9ce135 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2541,7 +2541,7 @@ bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) { return runBundler(BundlerArgs, C); } -static bool hasOffloadSections(Compilation &C, const std::string Archive, +static bool hasOffloadSections(Compilation &C, const StringRef &Archive, DerivedArgList &Args) { // Do not do the check if the file doesn't exist if (!llvm::sys::fs::exists(Archive)) @@ -2553,7 +2553,7 @@ static bool hasOffloadSections(Compilation &C, const std::string Archive, // TODO - Improve checking to check for explicit offload target instead // of the generic host availability. const char *Targets = Args.MakeArgString(Twine("-targets=host-") + TT.str()); - const char *Inputs = Args.MakeArgString(Twine("-inputs=") + Archive); + const char *Inputs = Args.MakeArgString(Twine("-inputs=") + Archive.str()); // Always use -type=ao for bundle checking. The 'bundles' are // actually archives. std::vector BundlerArgs = {"clang-offload-bundler", "-type=ao", @@ -2571,12 +2571,13 @@ static bool optionMatches(const std::string &Option, // Process linker inputs for use with offload static libraries. We are only // handling options and explicitly named static archives as these need to be // partially linked. -static void getLinkerArgs(Compilation &C, DerivedArgList &Args, - SmallVector &LibArgs) { +static SmallVector getLinkerArgs(Compilation &C, + DerivedArgList &Args) { + SmallVector LibArgs; for (const auto *A : Args) { std::string FileName = A->getAsString(Args); if (A->getOption().getKind() == Option::InputClass) { - std::string Value(A->getValue()); + StringRef Value(A->getValue()); if (isStaticArchiveFile(Value)) { LibArgs.push_back(Args.MakeArgString(FileName)); continue; @@ -2588,19 +2589,22 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, A->getOption().matches(options::OPT_reserved_lib_Group) || A->getOption().hasFlag(options::NoArgumentUnused)) continue; + std::string PrevArg; for (const std::string &Value : A->getValues()) { - static std::string PrevArg; - auto addKnownValues = [&](const std::string &V) { + auto addKnownValues = [&](const StringRef &V) { // Only add named static libs objects and --whole-archive options. - if (optionMatches("-whole-archive", V) || - optionMatches("-no-whole-archive", V) || isStaticArchiveFile(V)) { + if (optionMatches("-whole-archive", V.str()) || + optionMatches("-no-whole-archive", V.str()) || + isStaticArchiveFile(V)) { LibArgs.push_back(Args.MakeArgString(V)); return; } // Probably not the best way to handle this, but there are options // that take arguments which we should not add to the known values. - // Handle -z for now - can be expanded if/when usage shows the need - if (PrevArg != "-z" && V[0] != '-' && isObjectFile(V)) { + // Handle -z and -rpath for now - can be expanded if/when usage shows + // the need. + if (PrevArg != "-z" && PrevArg != "-rpath" && + V[0] != '-' && isObjectFile(V.str())) { LibArgs.push_back(Args.MakeArgString(V)); return; } @@ -2619,8 +2623,8 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, ? llvm::cl::TokenizeWindowsCommandLine : llvm::cl::TokenizeGNUCommandLine, ExpandArgs); - for (std::string MA : ExpandArgs) - addKnownValues(MA); + for (StringRef EA : ExpandArgs) + addKnownValues(EA); } else addKnownValues(Value); PrevArg = Value; @@ -2644,6 +2648,7 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, continue; } } + return LibArgs; } // Goes through all of the arguments, including inputs expected for the @@ -2651,22 +2656,24 @@ static void getLinkerArgs(Compilation &C, DerivedArgList &Args, // static offload libraries. bool Driver::checkForOffloadStaticLib(Compilation &C, DerivedArgList &Args) const { - // Check only if enabled with -fsycl - if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) + // Check only if enabled with -fsycl or -fopenmp-targets + if (!Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false) && + !Args.hasArg(options::OPT_fopenmp_targets_EQ)) return false; + // Right off the bat, assume the presense of -foffload-static-lib means - // to perform the needed linking steps for offload fat archives. + // the need to perform linking steps for fat static archive offloading. if (Args.hasArg(options::OPT_offload_lib_Group)) return true; - SmallVector OffloadLibArgs; - getLinkerArgs(C, Args, OffloadLibArgs); - for (std::string MA : OffloadLibArgs) - if (isStaticArchiveFile(MA) && hasOffloadSections(C, MA, Args)) { + SmallVector OffloadLibArgs(getLinkerArgs(C, Args)); + for (const StringRef &OLArg : OffloadLibArgs) + if (isStaticArchiveFile(OLArg) && + hasOffloadSections(C, OLArg, Args)) { // FPGA binaries with AOCX or AOCR sections are not considered fat // static archives. if (Args.hasArg(options::OPT_fintelfpga)) - return !(hasFPGABinary(C, MA, types::TY_FPGA_AOCR) || - hasFPGABinary(C, MA, types::TY_FPGA_AOCX)); + return !(hasFPGABinary(C, OLArg.str(), types::TY_FPGA_AOCR) || + hasFPGABinary(C, OLArg.str(), types::TY_FPGA_AOCX)); return true; } return false; @@ -4601,8 +4608,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // Go through all of the args, and create a Linker specific argument list. // When dealing with fat static archives, this is fed into the partial link // step on Linux or each archive is individually addressed on Windows. - SmallVector LinkArgs; - getLinkerArgs(C, Args, LinkArgs); + SmallVector LinkArgs(getLinkerArgs(C, Args)); // When a static fat archive is provided, create a new unbundling step // for all of the objects. if (!C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() && @@ -4620,7 +4626,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, UnbundlerInputs.push_back(LI); } const Arg *LastArg; - auto addUnbundlerInput = [&](types::ID T, const char *A) { + auto addUnbundlerInput = [&](types::ID T, const StringRef &A) { const llvm::opt::OptTable &Opts = getOpts(); Arg *InputArg = MakeInputArg(Args, Opts, C.getArgs().MakeArgString(A)); LastArg = InputArg; @@ -4628,27 +4634,28 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, UnbundlerInputs.push_back(Current); }; bool IsWholeArchive = false; - for (std::string MA : LinkArgs) { - if (isStaticArchiveFile(MA)) { + for (const StringRef &LA : LinkArgs) { + if (isStaticArchiveFile(LA)) { addUnbundlerInput(IsWholeArchive ? types::TY_WholeArchive : types::TY_Archive, - MA.c_str()); + LA); continue; } - if (optionMatches("-no-whole-archive", MA)) { + if (optionMatches("-no-whole-archive", LA.str())) { IsWholeArchive = false; continue; } - if (optionMatches("-whole-archive", MA)) { + if (optionMatches("-whole-archive", LA.str())) { IsWholeArchive = true; continue; } - if (isObjectFile(MA)) { + if (isObjectFile(LA.str())) { // Add any objects to the unbundler step. These objects are passed // directly to the linker, so the driver does not know about them. - // FIXME - Better process objects passed to the linker process them - // like regular objects that need to be potentially unbundled. - addUnbundlerInput(types::TY_Object, MA.c_str()); + // FIXME - Better process objects passed to the linker. We are only + // adding these objects to the unbundler step, but these objects can + // potentially be fat objects that should be processed by the driver. + addUnbundlerInput(types::TY_Object, LA); continue; } } @@ -4665,17 +4672,17 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, } } const llvm::opt::OptTable &Opts = getOpts(); - auto unbundleStaticLib = [&](types::ID T, const std::string &A) { + auto unbundleStaticLib = [&](types::ID T, const StringRef &A) { Arg *InputArg = MakeInputArg(Args, Opts, Args.MakeArgString(A)); Action *Current = C.MakeAction(*InputArg, T); OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg, Args); OffloadBuilder.addDeviceDependencesToHostAction( Current, InputArg, phases::Link, PL.back(), PL); }; - for (std::string MA : LinkArgs) { + for (const StringRef &LA : LinkArgs) { // At this point, we will process the archives for FPGA AOCO and individual // archive unbundling for Windows. - if (!isStaticArchiveFile(MA)) + if (!isStaticArchiveFile(LA)) continue; // In MSVC environment offload-static-libs are handled slightly different // because of missing support for partial linking in the linker. We add an @@ -4684,13 +4691,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, // 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() && - hasOffloadSections(C, MA, Args)) - unbundleStaticLib(types::TY_Archive, MA); + hasOffloadSections(C, LA, Args)) + unbundleStaticLib(types::TY_Archive, LA); // Pass along the static libraries 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, MA); + unbundleStaticLib(types::TY_FPGA_AOCO, LA); } // For an FPGA archive, we add the unbundling step above to take care of @@ -6471,10 +6478,9 @@ bool clang::driver::isObjectFile(std::string FileName) { types::lookupTypeForExtension(Ext) == types::TY_Object); } -bool clang::driver::isStaticArchiveFile(const std::string &FileName) { +bool clang::driver::isStaticArchiveFile(const StringRef &FileName) { if (!llvm::sys::path::has_extension(FileName)) - // Any file with no extension should be considered an Object. Take into - // account -lsomelib library filenames. + // Any file with no extension should not be considered an Archive. return false; StringRef Ext(llvm::sys::path::extension(FileName).drop_front()); // Only .lib and .a files are to be considered. diff --git a/clang/test/Driver/sycl-offload-static-lib-2.cpp b/clang/test/Driver/sycl-offload-static-lib-2.cpp index 0c1a8709594b7..0fd43773dec6a 100644 --- a/clang/test/Driver/sycl-offload-static-lib-2.cpp +++ b/clang/test/Driver/sycl-offload-static-lib-2.cpp @@ -84,6 +84,12 @@ // WHOLE_STATIC_LIB_1: ld{{.*}} "[[INPUTO]]" "--whole-archive" "[[INPUTA]]" "[[INPUTB]]" "--no-whole-archive" // WHOLE_STATIC_LIB_2: ld{{.*}} "[[INPUTO]]" "@[[ARGFILE]]" +/// test -Wl, behaviors for special case handling of -z and -rpath +// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L/dummy/dir %t.o -Wl,-rpath,nopass -Wl,-z,nopass %t.a %t_2.a -### 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=WL_CHECK +// WL_CHECK-NOT: ld{{(.exe)?}}" "-r" {{.*}} "{{.*}}crt1.o" "{{.*}}crti.o" "-L/dummy/dir" {{.*}} "nopass" {{.*}} "{{.*}}crtn.o" +// WL_CHECK: ld{{.*}}" "-rpath" "nopass" "-z" "nopass" + /// ########################################################################### /// test behaviors of static lib with no source/object From 5223faa2f72f08d00cb602fb0a3f41618fd3f34a Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Tue, 17 Mar 2020 11:33:53 -0700 Subject: [PATCH 5/7] [NFC] another clang-format patch Signed-off-by: Michael D Toguchi --- clang/lib/Driver/Driver.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 47ffbdf9ce135..a3248206ed02f 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2572,7 +2572,7 @@ static bool optionMatches(const std::string &Option, // handling options and explicitly named static archives as these need to be // partially linked. static SmallVector getLinkerArgs(Compilation &C, - DerivedArgList &Args) { + DerivedArgList &Args) { SmallVector LibArgs; for (const auto *A : Args) { std::string FileName = A->getAsString(Args); @@ -2603,8 +2603,8 @@ static SmallVector getLinkerArgs(Compilation &C, // that take arguments which we should not add to the known values. // Handle -z and -rpath for now - can be expanded if/when usage shows // the need. - if (PrevArg != "-z" && PrevArg != "-rpath" && - V[0] != '-' && isObjectFile(V.str())) { + if (PrevArg != "-z" && PrevArg != "-rpath" && V[0] != '-' && + isObjectFile(V.str())) { LibArgs.push_back(Args.MakeArgString(V)); return; } @@ -2667,8 +2667,7 @@ bool Driver::checkForOffloadStaticLib(Compilation &C, return true; SmallVector OffloadLibArgs(getLinkerArgs(C, Args)); for (const StringRef &OLArg : OffloadLibArgs) - if (isStaticArchiveFile(OLArg) && - hasOffloadSections(C, OLArg, Args)) { + if (isStaticArchiveFile(OLArg) && hasOffloadSections(C, OLArg, Args)) { // FPGA binaries with AOCX or AOCR sections are not considered fat // static archives. if (Args.hasArg(options::OPT_fintelfpga)) @@ -4636,9 +4635,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args, bool IsWholeArchive = false; for (const StringRef &LA : LinkArgs) { if (isStaticArchiveFile(LA)) { - addUnbundlerInput(IsWholeArchive ? types::TY_WholeArchive - : types::TY_Archive, - LA); + addUnbundlerInput( + IsWholeArchive ? types::TY_WholeArchive : types::TY_Archive, LA); continue; } if (optionMatches("-no-whole-archive", LA.str())) { From 36447ceac860b8e7a0adba5b888d2adde6578676 Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Wed, 18 Mar 2020 13:43:21 -0700 Subject: [PATCH 6/7] [NFC] Add test for deprecated -foffload-static-lib option Signed-off-by: Michael D Toguchi --- clang/test/Driver/sycl-offload-static-lib.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clang/test/Driver/sycl-offload-static-lib.cpp b/clang/test/Driver/sycl-offload-static-lib.cpp index 4ab248a109e99..3239170f9ab59 100644 --- a/clang/test/Driver/sycl-offload-static-lib.cpp +++ b/clang/test/Driver/sycl-offload-static-lib.cpp @@ -15,6 +15,14 @@ // FOFFLOAD_STATIC_LIB: clang-offload-bundler{{.*}} "-type=oo" // FOFFLOAD_STATIC_LIB: llvm-link{{.*}} "@{{.*}}" +/// Use of -foffload-static-lib and -foffload-whole-static-lib are deprecated +// RUN: touch dummy.a +// RUN: %clangxx -fsycl -foffload-static-lib=dummy.a -foffload-whole-static-lib=dummy.a -### 2>&1 \ +// RUN: | FileCheck %s -check-prefix=FOFFLOAD_STATIC_LIB_DEPRECATED +// RUN: %clang_cl -fsycl -foffload-static-lib=dummy.a -foffload-whole-static-lib=dummy.a -### 2>&1 \ +// RUN: | FileCheck %s -check-prefix=FOFFLOAD_STATIC_LIB_DEPRECATED +// FOFFLOAD_STATIC_LIB_DEPRECATED: option '-foffload-whole-static-lib=dummy.a' is deprecated, use 'dummy.a' directly instead + /// ########################################################################### /// test behaviors of -foffload-static-lib= with multiple objects From cab9855ba99246eb91ab8484299245bbcc6b0414 Mon Sep 17 00:00:00 2001 From: Michael D Toguchi Date: Wed, 18 Mar 2020 14:07:47 -0700 Subject: [PATCH 7/7] [NFC] Address review comments Use SmallVector for bundler args, add TODOs for -foffload-static-lib removal Signed-off-by: Michael D Toguchi --- clang/lib/Driver/Driver.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index a3248206ed02f..95a733994c6d5 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2476,6 +2476,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, Diag(diag::note_use_dashdash); } } + // TODO: remove when -foffload-static-lib support is dropped. 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 @@ -2497,7 +2498,7 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, } } -static bool runBundler(const std::vector &BundlerArgs, +static bool runBundler(const SmallVectorImpl &BundlerArgs, Compilation &C) { // Find bundler. StringRef ExecPath(C.getArgs().MakeArgString(C.getDriver().Dir)); @@ -2536,8 +2537,8 @@ bool hasFPGABinary(Compilation &C, std::string Object, types::ID Type) { const char *Inputs = C.getArgs().MakeArgString(Twine("-inputs=") + Object); // Always use -type=ao for aocx/aocr bundle checking. The 'bundles' are // actually archives. - std::vector BundlerArgs = {"clang-offload-bundler", "-type=ao", - Targets, Inputs, "-check-section"}; + SmallVector BundlerArgs = {"clang-offload-bundler", "-type=ao", + Targets, Inputs, "-check-section"}; return runBundler(BundlerArgs, C); } @@ -2556,8 +2557,8 @@ static bool hasOffloadSections(Compilation &C, const StringRef &Archive, const char *Inputs = Args.MakeArgString(Twine("-inputs=") + Archive.str()); // Always use -type=ao for bundle checking. The 'bundles' are // actually archives. - std::vector BundlerArgs = {"clang-offload-bundler", "-type=ao", - Targets, Inputs, "-check-section"}; + SmallVector BundlerArgs = {"clang-offload-bundler", "-type=ao", + Targets, Inputs, "-check-section"}; return runBundler(BundlerArgs, C); } @@ -2663,6 +2664,7 @@ bool Driver::checkForOffloadStaticLib(Compilation &C, // Right off the bat, assume the presense of -foffload-static-lib means // the need to perform linking steps for fat static archive offloading. + // TODO: remove when -foffload-static-lib support is dropped. if (Args.hasArg(options::OPT_offload_lib_Group)) return true; SmallVector OffloadLibArgs(getLinkerArgs(C, Args));