diff options
Diffstat (limited to 'lib/Driver/ToolChains/CommonArgs.cpp')
-rw-r--r-- | lib/Driver/ToolChains/CommonArgs.cpp | 356 |
1 files changed, 180 insertions, 176 deletions
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 99691cb43dc42..10743559e0481 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -11,8 +11,12 @@ #include "Arch/ARM.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/RISCV.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "AMDGPU.h" +#include "MSP430.h" #include "HIP.h" #include "Hexagon.h" #include "InputInfo.h" @@ -145,6 +149,11 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, // (constructed via -Xarch_). Args.AddAllArgValues(CmdArgs, options::OPT_Zlinker_input); + // LIBRARY_PATH are included before user inputs and only supported on native + // toolchains. + if (!TC.isCrossCompiling()) + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + for (const auto &II : Inputs) { // If the current tool chain refers to an OpenMP or HIP offloading host, we // should ignore inputs that refer to OpenMP or HIP offloading devices - @@ -182,12 +191,6 @@ void tools::AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, A.renderAsInput(Args, CmdArgs); } } - - // LIBRARY_PATH - included following the user specified library paths. - // and only supported on native toolchains. - if (!TC.isCrossCompiling()) { - addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); - } } void tools::AddTargetFeature(const ArgList &Args, @@ -485,6 +488,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, if (!StatsFile.empty()) CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); + + getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs, + /* ForAS= */ false, /* ForLTOPlugin= */ true); + + StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple()); + if (!ABIName.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName)); } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -501,30 +512,41 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args, bool IsOffloadingHost, - bool GompNeedsRT) { + const ArgList &Args, bool ForceStaticHostRuntime, + bool IsOffloadingHost, bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) return false; - switch (TC.getDriver().getOpenMPRuntime(Args)) { + Driver::OpenMPRuntimeKind RTKind = TC.getDriver().getOpenMPRuntime(Args); + + if (RTKind == Driver::OMPRT_Unknown) + // Already diagnosed. + return false; + + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bstatic"); + + switch (RTKind) { case Driver::OMPRT_OMP: CmdArgs.push_back("-lomp"); break; case Driver::OMPRT_GOMP: CmdArgs.push_back("-lgomp"); - - if (GompNeedsRT) - CmdArgs.push_back("-lrt"); break; case Driver::OMPRT_IOMP5: CmdArgs.push_back("-liomp5"); break; case Driver::OMPRT_Unknown: - // Already diagnosed. - return false; + break; } + if (ForceStaticHostRuntime) + CmdArgs.push_back("-Bdynamic"); + + if (RTKind == Driver::OMPRT_GOMP && GompNeedsRT) + CmdArgs.push_back("-lrt"); + if (IsOffloadingHost) CmdArgs.push_back("-lomptarget"); @@ -605,29 +627,29 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Collect shared runtimes. if (SanArgs.needsSharedRt()) { - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { SharedRuntimes.push_back("asan"); if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("asan-preinit"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("ubsan_minimal"); else SharedRuntimes.push_back("ubsan_standalone"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) SharedRuntimes.push_back("scudo_minimal"); else SharedRuntimes.push_back("scudo"); } - if (SanArgs.needsHwasanRt()) + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) SharedRuntimes.push_back("hwasan"); } // The stats_client library is also statically linked into DSOs. - if (SanArgs.needsStatsRt()) + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("stats_client"); // Collect static runtimes. @@ -635,32 +657,32 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, // Don't link static runtimes into DSOs or if -shared-libasan. return; } - if (SanArgs.needsAsanRt()) { + if (SanArgs.needsAsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("asan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("asan_cxx"); } - if (SanArgs.needsHwasanRt()) { + if (SanArgs.needsHwasanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("hwasan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("hwasan_cxx"); } - if (SanArgs.needsDfsanRt()) + if (SanArgs.needsDfsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("dfsan"); - if (SanArgs.needsLsanRt()) + if (SanArgs.needsLsanRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("lsan"); - if (SanArgs.needsMsanRt()) { + if (SanArgs.needsMsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("msan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("msan_cxx"); } - if (SanArgs.needsTsanRt()) { + if (SanArgs.needsTsanRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("tsan"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("tsan_cxx"); } - if (SanArgs.needsUbsanRt()) { + if (SanArgs.needsUbsanRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("ubsan_minimal"); } else { @@ -669,22 +691,22 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("ubsan_standalone_cxx"); } } - if (SanArgs.needsSafeStackRt()) { + if (SanArgs.needsSafeStackRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("safestack"); RequiredSymbols.push_back("__safestack_init"); } - if (SanArgs.needsCfiRt()) + if (SanArgs.needsCfiRt() && SanArgs.linkRuntimes()) StaticRuntimes.push_back("cfi"); - if (SanArgs.needsCfiDiagRt()) { + if (SanArgs.needsCfiDiagRt() && SanArgs.linkRuntimes()) { StaticRuntimes.push_back("cfi_diag"); if (SanArgs.linkCXXRuntimes()) StaticRuntimes.push_back("ubsan_standalone_cxx"); } - if (SanArgs.needsStatsRt()) { + if (SanArgs.needsStatsRt() && SanArgs.linkRuntimes()) { NonWholeStaticRuntimes.push_back("stats"); RequiredSymbols.push_back("__sanitizer_stats_register"); } - if (SanArgs.needsScudoRt()) { + if (SanArgs.needsScudoRt() && SanArgs.linkRuntimes()) { if (SanArgs.requiresMinimalRuntime()) { StaticRuntimes.push_back("scudo_minimal"); if (SanArgs.linkCXXRuntimes()) @@ -707,9 +729,10 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); + const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Inject libfuzzer dependencies. - if (TC.getSanitizerArgs().needsFuzzer() - && !Args.hasArg(options::OPT_shared)) { + if (SanArgs.needsFuzzer() && SanArgs.linkRuntimes() && + !Args.hasArg(options::OPT_shared)) { addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) @@ -738,7 +761,6 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (AddExportDynamic) CmdArgs.push_back("--export-dynamic"); - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); if (SanArgs.hasCrossDsoCfi() && !AddExportDynamic) CmdArgs.push_back("-export-dynamic-symbol=__cfi_check"); @@ -823,10 +845,10 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, ExtractArgs, II)); // Then remove them from the original .o file. - C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II)); + C.addCommand(std::make_unique<Command>(JA, T, Exec, StripArgs, II)); } // Claim options we don't want to warn if they are unused. We do this for @@ -1176,7 +1198,6 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, case ToolChain::UNW_None: return; case ToolChain::UNW_Libgcc: { - LibGccType LGT = getLibGccType(D, Args); if (LGT == LibGccType::StaticLibGcc) CmdArgs.push_back("-lgcc_eh"); else @@ -1235,131 +1256,6 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, } } -/// Add OpenMP linker script arguments at the end of the argument list so that -/// the fat binary is built by embedding each of the device images into the -/// host. The linker script also defines a few symbols required by the code -/// generation so that the images can be easily retrieved at runtime by the -/// offloading library. This should be used only in tool chains that support -/// linker scripts. -void tools::AddOpenMPLinkerScript(const ToolChain &TC, Compilation &C, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, ArgStringList &CmdArgs, - const JobAction &JA) { - - // If this is not an OpenMP host toolchain, we don't need to do anything. - if (!JA.isHostOffloading(Action::OFK_OpenMP)) - return; - - // Create temporary linker script. Keep it if save-temps is enabled. - const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); - if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); - } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); - } - - // Add linker script option to the command. - CmdArgs.push_back("-T"); - CmdArgs.push_back(LKS); - - // Create a buffer to write the contents of the linker script. - std::string LksBuffer; - llvm::raw_string_ostream LksStream(LksBuffer); - - // Get the OpenMP offload tool chains so that we can extract the triple - // associated with each device input. - auto OpenMPToolChains = C.getOffloadToolChains<Action::OFK_OpenMP>(); - assert(OpenMPToolChains.first != OpenMPToolChains.second && - "No OpenMP toolchains??"); - - // Track the input file name and device triple in order to build the script, - // inserting binaries in the designated sections. - SmallVector<std::pair<std::string, const char *>, 8> InputBinaryInfo; - - // Add commands to embed target binaries. We ensure that each section and - // image is 16-byte aligned. This is not mandatory, but increases the - // likelihood of data to be aligned with a cache block in several main host - // machines. - LksStream << "/*\n"; - LksStream << " OpenMP Offload Linker Script\n"; - LksStream << " *** Automatically generated by Clang ***\n"; - LksStream << "*/\n"; - LksStream << "TARGET(binary)\n"; - auto DTC = OpenMPToolChains.first; - for (auto &II : Inputs) { - const Action *A = II.getAction(); - // Is this a device linking action? - if (A && isa<LinkJobAction>(A) && - A->isDeviceOffloading(Action::OFK_OpenMP)) { - assert(DTC != OpenMPToolChains.second && - "More device inputs than device toolchains??"); - InputBinaryInfo.push_back(std::make_pair( - DTC->second->getTriple().normalize(), II.getFilename())); - ++DTC; - LksStream << "INPUT(" << II.getFilename() << ")\n"; - } - } - - assert(DTC == OpenMPToolChains.second && - "Less device inputs than device toolchains??"); - - LksStream << "SECTIONS\n"; - LksStream << "{\n"; - - // Put each target binary into a separate section. - for (const auto &BI : InputBinaryInfo) { - LksStream << " .omp_offloading." << BI.first << " :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_start." << BI.first - << " = .);\n"; - LksStream << " " << BI.second << "\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.img_end." << BI.first - << " = .);\n"; - LksStream << " }\n"; - } - - // Add commands to define host entries begin and end. We use 1-byte subalign - // so that the linker does not add any padding and the elements in this - // section form an array. - LksStream << " .omp_offloading.entries :\n"; - LksStream << " ALIGN(0x10)\n"; - LksStream << " SUBALIGN(0x01)\n"; - LksStream << " {\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_begin = .);\n"; - LksStream << " *(.omp_offloading.entries)\n"; - LksStream << " PROVIDE_HIDDEN(.omp_offloading.entries_end = .);\n"; - LksStream << " }\n"; - LksStream << "}\n"; - LksStream << "INSERT BEFORE .data\n"; - LksStream.flush(); - - // Dump the contents of the linker script if the user requested that. We - // support this option to enable testing of behavior with -###. - if (C.getArgs().hasArg(options::OPT_fopenmp_dump_offload_linker_script)) - llvm::errs() << LksBuffer; - - // If this is a dry run, do not create the linker script file. - if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) - return; - - // Open script file and write the contents. - std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); - - if (EC) { - C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); - return; - } - - Lksf << LksBuffer; -} - /// Add HIP linker script arguments at the end of the argument list so that /// the fat binary is built by embedding the device images into the host. The /// linker script also defines a symbol required by the code generation so that @@ -1389,14 +1285,12 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Create temporary linker script. Keep it if save-temps is enabled. const char *LKS; - SmallString<256> Name = llvm::sys::path::filename(Output.getFilename()); + std::string Name = llvm::sys::path::filename(Output.getFilename()); if (C.getDriver().isSaveTempsEnabled()) { - llvm::sys::path::replace_extension(Name, "lk"); - LKS = C.getArgs().MakeArgString(Name.c_str()); + LKS = C.getArgs().MakeArgString(Name + ".lk"); } else { - llvm::sys::path::replace_extension(Name, ""); - Name = C.getDriver().GetTemporaryPath(Name, "lk"); - LKS = C.addTempFile(C.getArgs().MakeArgString(Name.c_str())); + auto TmpName = C.getDriver().GetTemporaryPath(Name, "lk"); + LKS = C.addTempFile(C.getArgs().MakeArgString(TmpName)); } // Add linker script option to the command. @@ -1414,11 +1308,13 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, "Wrong platform"); (void)HIPTC; - // The output file name needs to persist through the compilation, therefore - // it needs to be created through MakeArgString. - std::string BundleFileName = C.getDriver().GetTemporaryPath("BUNDLE", "hipfb"); - const char *BundleFile = - C.addTempFile(C.getArgs().MakeArgString(BundleFileName.c_str())); + const char *BundleFile; + if (C.getDriver().isSaveTempsEnabled()) { + BundleFile = C.getArgs().MakeArgString(Name + ".hipfb"); + } else { + auto TmpName = C.getDriver().GetTemporaryPath(Name, "hipfb"); + BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpName)); + } AMDGCN::constructHIPFatbinCommand(C, JA, BundleFile, DeviceInputs, Args, T); // Add commands to embed target binaries. We ensure that each section and @@ -1430,14 +1326,14 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, LksStream << " *** Automatically generated by Clang ***\n"; LksStream << "*/\n"; LksStream << "TARGET(binary)\n"; - LksStream << "INPUT(" << BundleFileName << ")\n"; + LksStream << "INPUT(" << BundleFile << ")\n"; LksStream << "SECTIONS\n"; LksStream << "{\n"; LksStream << " .hip_fatbin :\n"; LksStream << " ALIGN(0x10)\n"; LksStream << " {\n"; LksStream << " PROVIDE_HIDDEN(__hip_fatbin = .);\n"; - LksStream << " " << BundleFileName << "\n"; + LksStream << " " << BundleFile << "\n"; LksStream << " }\n"; LksStream << " /DISCARD/ :\n"; LksStream << " {\n"; @@ -1458,7 +1354,7 @@ void tools::AddHIPLinkerScript(const ToolChain &TC, Compilation &C, // Open script file and write the contents. std::error_code EC; - llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::F_None); + llvm::raw_fd_ostream Lksf(LKS, EC, llvm::sys::fs::OF_None); if (EC) { C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message(); @@ -1496,3 +1392,111 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags) { Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); } + +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector<StringRef> &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin) { + + const Driver &D = TC.getDriver(); + std::vector<StringRef> Features; + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + mips::getMIPSTargetFeatures(D, Triple, Args, Features); + break; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + ppc::getPPCTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::systemz: + systemz::getSystemZTargetFeatures(Args, Features); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + x86::getX86TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::hexagon: + hexagon::getHexagonTargetFeatures(D, Args, Features); + break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + sparc::getSparcTargetFeatures(D, Args, Features); + break; + case llvm::Triple::r600: + case llvm::Triple::amdgcn: + amdgpu::getAMDGPUTargetFeatures(D, Args, Features); + break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); + } + + // Find the last of each feature. + llvm::StringMap<unsigned> LastOpt; + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + assert(Name[0] == '-' || Name[0] == '+'); + LastOpt[Name.drop_front(1)] = I; + } + + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + // If this feature was overridden, ignore it. + StringRef Name = Features[I]; + llvm::StringMap<unsigned>::iterator LastI = + LastOpt.find(Name.drop_front(1)); + assert(LastI != LastOpt.end()); + unsigned Last = LastI->second; + if (Last != I) + continue; + if (!ForLTOPlugin) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Name.data()); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name)); + } + } +} + +StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) { + // TODO: Support the other target ABI + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + return tools::riscv::getRISCVABI(Args, Triple); + break; + } + return StringRef(); +} |