diff options
Diffstat (limited to 'lib/Driver/ToolChains/CommonArgs.cpp')
-rw-r--r-- | lib/Driver/ToolChains/CommonArgs.cpp | 281 |
1 files changed, 246 insertions, 35 deletions
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 5afe135865..b359cbb77e 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -215,6 +215,21 @@ static std::string getR600TargetGPU(const ArgList &Args) { return ""; } +static std::string getNios2TargetCPU(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mcpu_EQ); + if (!A) + A = Args.getLastArg(options::OPT_march_EQ); + + if (!A) + return ""; + + const char *name = A->getValue(); + return llvm::StringSwitch<const char *>(name) + .Case("r1", "nios2r1") + .Case("r2", "nios2r2") + .Default(name); +} + static std::string getLanaiTargetCPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { return A->getValue(); @@ -261,6 +276,16 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs); return arm::getARMTargetCPU(MCPU, MArch, T); } + + case llvm::Triple::avr: + if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ)) + return A->getValue(); + return ""; + + case llvm::Triple::nios2: { + return getNios2TargetCPU(Args); + } + case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -295,6 +320,8 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, return TargetCPUName; } + case llvm::Triple::bpfel: + case llvm::Triple::bpfeb: case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: @@ -351,8 +378,20 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, // as gold requires -plugin to come before any -plugin-opt that -Wl might // forward. CmdArgs.push_back("-plugin"); - std::string Plugin = - ToolChain.getDriver().Dir + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold.so"; + +#if defined(LLVM_ON_WIN32) + const char *Suffix = ".dll"; +#elif defined(__APPLE__) + const char *Suffix = ".dylib"; +#else + const char *Suffix = ".so"; +#endif + + SmallString<1024> Plugin; + llvm::sys::path::native(Twine(ToolChain.getDriver().Dir) + + "/../lib" CLANG_LIBDIR_SUFFIX "/LLVMgold" + + Suffix, + Plugin); CmdArgs.push_back(Args.MakeArgString(Plugin)); // Try to pass driver level flags relevant to LTO code generation down to @@ -407,7 +446,7 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back("-plugin-opt=-data-sections"); } - if (Arg *A = Args.getLastArg(options::OPT_fprofile_sample_use_EQ)) { + if (Arg *A = getLastProfileSampleUseArg(Args)) { StringRef FName = A->getValue(); if (!llvm::sys::fs::exists(FName)) D.Diag(diag::err_drv_no_such_file) << FName; @@ -415,14 +454,18 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=sample-profile=") + FName)); } + + // Need this flag to turn on new pass manager via Gold plugin. + if (Args.hasFlag(options::OPT_fexperimental_new_pass_manager, + options::OPT_fno_experimental_new_pass_manager, + /* Default */ false)) { + CmdArgs.push_back("-plugin-opt=new-pass-manager"); + } + } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - // In the cross-compilation case, arch-specific library path is likely - // unavailable at runtime. - if (TC.isCrossCompiling()) return; - std::string CandidateRPath = TC.getArchSpecificLibPath(); if (TC.getVFS().exists(CandidateRPath)) { CmdArgs.push_back("-rpath"); @@ -430,11 +473,12 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } } -void tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args) { +bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, + const ArgList &Args, bool IsOffloadingHost, + bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) - return; + return false; switch (TC.getDriver().getOpenMPRuntime(Args)) { case Driver::OMPRT_OMP: @@ -442,16 +486,24 @@ void tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, 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. - break; + return false; } + if (IsOffloadingHost) + CmdArgs.push_back("-lomptarget"); + addArchSpecificRPath(TC, Args, CmdArgs); + + return true; } static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, @@ -494,6 +546,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, CmdArgs.push_back("-lm"); // There's no libdl on FreeBSD or RTEMS. if (TC.getTriple().getOS() != llvm::Triple::FreeBSD && + TC.getTriple().getOS() != llvm::Triple::NetBSD && TC.getTriple().getOS() != llvm::Triple::RTEMS) CmdArgs.push_back("-ldl"); } @@ -507,26 +560,35 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, SmallVectorImpl<StringRef> &RequiredSymbols) { const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); // Collect shared runtimes. - if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) { - SharedRuntimes.push_back("asan"); + if (SanArgs.needsSharedRt()) { + if (SanArgs.needsAsanRt()) { + SharedRuntimes.push_back("asan"); + if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) + HelperStaticRuntimes.push_back("asan-preinit"); + } + + if (SanArgs.needsUbsanRt()) { + if (SanArgs.requiresMinimalRuntime()) { + SharedRuntimes.push_back("ubsan_minimal"); + } else { + SharedRuntimes.push_back("ubsan_standalone"); + } + } } + // The stats_client library is also statically linked into DSOs. if (SanArgs.needsStatsRt()) StaticRuntimes.push_back("stats_client"); // Collect static runtimes. - if (Args.hasArg(options::OPT_shared) || TC.getTriple().isAndroid()) { - // Don't link static runtimes into DSOs or if compiling for Android. + if (Args.hasArg(options::OPT_shared) || SanArgs.needsSharedRt()) { + // Don't link static runtimes into DSOs or if -shared-libasan. return; } if (SanArgs.needsAsanRt()) { - if (SanArgs.needsSharedAsanRt()) { - HelperStaticRuntimes.push_back("asan-preinit"); - } else { - StaticRuntimes.push_back("asan"); - if (SanArgs.linkCXXRuntimes()) - StaticRuntimes.push_back("asan_cxx"); - } + StaticRuntimes.push_back("asan"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("asan_cxx"); } if (SanArgs.needsDfsanRt()) StaticRuntimes.push_back("dfsan"); @@ -543,9 +605,13 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, StaticRuntimes.push_back("tsan_cxx"); } if (SanArgs.needsUbsanRt()) { - StaticRuntimes.push_back("ubsan_standalone"); - if (SanArgs.linkCXXRuntimes()) - StaticRuntimes.push_back("ubsan_standalone_cxx"); + if (SanArgs.requiresMinimalRuntime()) { + StaticRuntimes.push_back("ubsan_minimal"); + } else { + StaticRuntimes.push_back("ubsan_standalone"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("ubsan_standalone_cxx"); + } } if (SanArgs.needsSafeStackRt()) { NonWholeStaticRuntimes.push_back("safestack"); @@ -575,6 +641,16 @@ bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes, NonWholeStaticRuntimes, HelperStaticRuntimes, RequiredSymbols); + + // Inject libfuzzer dependencies. + if (TC.getSanitizerArgs().needsFuzzer() + && !Args.hasArg(options::OPT_shared)) { + + addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true); + if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx)) + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + } + for (auto RT : SharedRuntimes) addSanitizerRuntime(TC, Args, CmdArgs, RT, true, false); for (auto RT : HelperStaticRuntimes) @@ -677,6 +753,22 @@ Arg *tools::getLastProfileUseArg(const ArgList &Args) { return ProfileUseArg; } +Arg *tools::getLastProfileSampleUseArg(const ArgList &Args) { + auto *ProfileSampleUseArg = Args.getLastArg( + options::OPT_fprofile_sample_use, options::OPT_fprofile_sample_use_EQ, + options::OPT_fauto_profile, options::OPT_fauto_profile_EQ, + options::OPT_fno_profile_sample_use, options::OPT_fno_auto_profile); + + if (ProfileSampleUseArg && + (ProfileSampleUseArg->getOption().matches( + options::OPT_fno_profile_sample_use) || + ProfileSampleUseArg->getOption().matches(options::OPT_fno_auto_profile))) + return nullptr; + + return Args.getLastArg(options::OPT_fprofile_sample_use_EQ, + options::OPT_fauto_profile_EQ); +} + /// Parses the various -fpic/-fPIC/-fpie/-fPIE arguments. Then, /// smooshes them together with platform defaults, to decide whether /// this compile should be using PIC mode or not. Returns a tuple of @@ -725,9 +817,10 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { // OpenBSD-specific defaults for PIE if (Triple.getOS() == llvm::Triple::OpenBSD) { switch (ToolChain.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::aarch64: case llvm::Triple::mips64: case llvm::Triple::mips64el: - case llvm::Triple::sparcel: case llvm::Triple::x86: case llvm::Triple::x86_64: IsPICLevelTwo = false; // "-fpie" @@ -735,6 +828,7 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { case llvm::Triple::ppc: case llvm::Triple::sparc: + case llvm::Triple::sparcel: case llvm::Triple::sparcv9: IsPICLevelTwo = true; // "-fPIE" break; @@ -933,15 +1027,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, switch (RLT) { case ToolChain::RLT_CompilerRT: - switch (TC.getTriple().getOS()) { - default: - llvm_unreachable("unsupported OS"); - case llvm::Triple::Win32: - case llvm::Triple::Linux: - case llvm::Triple::Fuchsia: - CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); - break; - } + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); break; case ToolChain::RLT_Libgcc: // Make sure libgcc is not used under MSVC environment by default @@ -957,3 +1043,128 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, break; } } + +/// 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; +} |