aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/ToolChains/CommonArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/ToolChains/CommonArgs.cpp')
-rw-r--r--lib/Driver/ToolChains/CommonArgs.cpp238
1 files changed, 199 insertions, 39 deletions
diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp
index 00bd60bc24bb..ab51a8c3cc90 100644
--- a/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/lib/Driver/ToolChains/CommonArgs.cpp
@@ -320,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:
@@ -376,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
@@ -440,6 +454,14 @@ 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,
@@ -522,7 +544,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC,
CmdArgs.push_back("-lrt");
}
CmdArgs.push_back("-lm");
- // There's no libdl on FreeBSD or RTEMS.
+ // There's no libdl on all OSes.
if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
TC.getTriple().getOS() != llvm::Triple::NetBSD &&
TC.getTriple().getOS() != llvm::Triple::RTEMS)
@@ -538,26 +560,44 @@ 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");
+ }
+ }
+ if (SanArgs.needsScudoRt())
+ SharedRuntimes.push_back("scudo");
+ if (SanArgs.needsHwasanRt())
+ SharedRuntimes.push_back("hwasan");
}
+
// 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.needsHwasanRt()) {
+ StaticRuntimes.push_back("hwasan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("hwasan_cxx");
}
if (SanArgs.needsDfsanRt())
StaticRuntimes.push_back("dfsan");
@@ -574,9 +614,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");
@@ -595,19 +639,13 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
}
if (SanArgs.needsEsanRt())
StaticRuntimes.push_back("esan");
+ if (SanArgs.needsScudoRt()) {
+ StaticRuntimes.push_back("scudo");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("scudo_cxx");
+ }
}
-static void addLibFuzzerRuntime(const ToolChain &TC,
- const ArgList &Args,
- ArgStringList &CmdArgs) {
- StringRef ParentDir = llvm::sys::path::parent_path(TC.getDriver().InstalledDir);
- SmallString<128> P(ParentDir);
- llvm::sys::path::append(P, "lib", "libLLVMFuzzer.a");
- CmdArgs.push_back(Args.MakeArgString(P));
- TC.AddCXXStdlibLibArgs(Args, CmdArgs);
-}
-
-
// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
bool tools::addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
@@ -617,10 +655,14 @@ 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)) {
- addLibFuzzerRuntime(TC, Args, CmdArgs);
+
+ addSanitizerRuntime(TC, Args, CmdArgs, "fuzzer", false, true);
+ if (!Args.hasArg(clang::driver::options::OPT_nostdlibxx))
+ TC.AddCXXStdlibLibArgs(Args, CmdArgs);
}
for (auto RT : SharedRuntimes)
@@ -691,7 +733,8 @@ void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T,
ExtractArgs.push_back(Output.getFilename());
ExtractArgs.push_back(OutFile);
- const char *Exec = Args.MakeArgString(TC.GetProgramPath("objcopy"));
+ const char *Exec =
+ Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY));
InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename());
// First extract the dwo sections.
@@ -999,15 +1042,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
@@ -1023,3 +1058,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;
+}