void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; auto &TC = static_cast<const toolchains::BareMetal&>(getToolChain()); AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); CmdArgs.push_back("-Bstatic"); CmdArgs.push_back(Args.MakeArgString("-L" + TC.getRuntimesDir())); Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); if (TC.ShouldLinkCXXStdlib(Args)) TC.AddCXXStdlibLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lm"); TC.AddLinkRuntimeLib(Args, CmdArgs); } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs)); }
void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); // Ananas only supports static linkage for now. CmdArgs.push_back("-Bstatic"); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); } Args.AddAllArgs(CmdArgs, options::OPT_L); ToolChain.AddFilePathLibArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); if (D.isUsingLTO()) AddGoldPlugin(ToolChain, Args, CmdArgs, D.getLTOMode() == LTOK_Thin, D); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) CmdArgs.push_back("-lc"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; assert(Inputs.size() == 1); const InputInfo &II = Inputs[0]; assert(II.getType() == types::TY_PP_Asm); // Require preprocessed asm input. assert(Output.getType() == types::TY_Object); CmdArgs.push_back("-no6thSlotCompression"); const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); if (CPUArg) CmdArgs.push_back( Args.MakeArgString("-cv:" + StringRef(CPUArg->getValue()))); CmdArgs.push_back("-noSPrefixing"); CmdArgs.push_back("-a"); // Mystery option. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); for (const Arg *A : Args.filtered(options::OPT_I, options::OPT_isystem)) { A->claim(); CmdArgs.push_back( Args.MakeArgString(std::string("-i:") + A->getValue(0))); } CmdArgs.push_back("-elf"); // Output format. CmdArgs.push_back(II.getFilename()); CmdArgs.push_back( Args.MakeArgString(std::string("-o:") + Output.getFilename())); std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviAsm")); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); }
void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; assert(Inputs.size() == 1); const InputInfo &II = Inputs[0]; assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX || II.getType() == types::TY_PP_CXX); if (JA.getKind() == Action::PreprocessJobClass) { Args.ClaimAllArgs(); CmdArgs.push_back("-E"); } else { assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm. CmdArgs.push_back("-S"); CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified. } CmdArgs.push_back("-DMYRIAD2"); // Append all -I, -iquote, -isystem paths, defines/undefines, 'f' // flags, 'g' flags, 'M' flags, optimize flags, warning options, // mcpu flags, mllvm flags, and Xclang flags. // These are spelled the same way in clang and moviCompile. Args.AddAllArgsExcept( CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ, options::OPT_D, options::OPT_U, options::OPT_f_Group, options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group, options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ, options::OPT_mllvm, options::OPT_Xclang}, {options::OPT_fno_split_dwarf_inlining}); Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present. // If we're producing a dependency file, and assembly is the final action, // then the name of the target in the dependency file should be the '.o' // file, not the '.s' file produced by this step. For example, instead of // /tmp/mumble.s: mumble.c .../someheader.h // the filename on the lefthand side should be "mumble.o" if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) && C.getActions().size() == 1 && C.getActions()[0]->getKind() == Action::AssembleJobClass) { Arg *A = Args.getLastArg(options::OPT_o); if (A) { CmdArgs.push_back("-MT"); CmdArgs.push_back(Args.MakeArgString(A->getValue())); } } CmdArgs.push_back(II.getFilename()); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); }
void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); const Driver &D = ToolChain.getDriver(); std::string Linker = ToolChain.GetProgramPath(getShortName()); ArgStringList CmdArgs; if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); Args.AddAllArgs(CmdArgs, options::OPT_L); ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_T)) { if (const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ)) CmdArgs.push_back( Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld")); } else { Args.AddAllArgs(CmdArgs, options::OPT_T); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); CmdArgs.push_back("--start-group"); CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args))); CmdArgs.push_back("-lgcc"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lcrt"); CmdArgs.push_back("-lnosys"); } CmdArgs.push_back("--end-group"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker), CmdArgs, Inputs)); }
void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA, const InputInfoList &Inputs, const InputInfo &Output, const llvm::opt::ArgList &Args, const char *InputFileName) const { // Construct lld command. // The output from ld.lld is an HSA code object file. ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined", "-shared", "-o", Output.getFilename(), InputFileName}; SmallString<128> LldPath(C.getDriver().Dir); llvm::sys::path::append(LldPath, "lld"); const char *Lld = Args.MakeArgString(LldPath); C.addCommand(llvm::make_unique<Command>(JA, *this, Lld, LldArgs, Inputs)); }
void tools::SplitDebugInfo(const ToolChain &TC, Compilation &C, const Tool &T, const JobAction &JA, const ArgList &Args, const InputInfo &Output, const char *OutFile) { ArgStringList ExtractArgs; ExtractArgs.push_back("--extract-dwo"); ArgStringList StripArgs; StripArgs.push_back("--strip-dwo"); // Grabbing the output of the earlier compile step. StripArgs.push_back(Output.getFilename()); ExtractArgs.push_back(Output.getFilename()); ExtractArgs.push_back(OutFile); const char *Exec = Args.MakeArgString(TC.GetProgramPath(CLANG_DEFAULT_OBJCOPY)); 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)); // Then remove them from the original .o file. C.addCommand(llvm::make_unique<Command>(JA, T, Exec, StripArgs, II)); }
// All inputs to this linker must be from CudaDeviceActions, as we need to look // at the Inputs' Actions in order to figure out which GPU architecture they // correspond to. void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const auto &TC = static_cast<const toolchains::CudaToolChain &>(getToolChain()); assert(TC.getTriple().isNVPTX() && "Wrong platform"); ArgStringList CmdArgs; CmdArgs.push_back("--cuda"); CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-64" : "-32"); CmdArgs.push_back(Args.MakeArgString("--create")); CmdArgs.push_back(Args.MakeArgString(Output.getFilename())); if (mustEmitDebugInfo(Args) == FullDebug) CmdArgs.push_back("-g"); for (const auto& II : Inputs) { auto *A = II.getAction(); assert(A->getInputs().size() == 1 && "Device offload action is expected to have a single input"); const char *gpu_arch_str = A->getOffloadingArch(); assert(gpu_arch_str && "Device action expected to have associated a GPU architecture!"); CudaArch gpu_arch = StringToCudaArch(gpu_arch_str); if (II.getType() == types::TY_PP_Asm && !shouldIncludePTX(Args, gpu_arch_str)) continue; // We need to pass an Arch of the form "sm_XX" for cubin files and // "compute_XX" for ptx. const char *Arch = (II.getType() == types::TY_PP_Asm) ? CudaVirtualArchToString(VirtualArchForCudaArch(gpu_arch)) : gpu_arch_str; CmdArgs.push_back(Args.MakeArgString(llvm::Twine("--image=profile=") + Arch + ",file=" + II.getFilename())); } for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_fatbinary)) CmdArgs.push_back(Args.MakeArgString(A)); const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void solaris::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { claimNoWarnArgs(Args); ArgStringList CmdArgs; Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); ArgStringList CmdArgs; if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("--strip-all"); Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args); } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); }
void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::FreeBSD &ToolChain = static_cast<const toolchains::FreeBSD &>(getToolChain()); const Driver &D = ToolChain.getDriver(); const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool IsPIE = !Args.hasArg(options::OPT_shared) && (Args.hasArg(options::OPT_pie) || ToolChain.isPIEDefault()); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (IsPIE) CmdArgs.push_back("-pie"); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/libexec/ld-elf.so.1"); } if (ToolChain.getTriple().getOSMajorVersion() >= 9) { if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64) { CmdArgs.push_back("--hash-style=both"); } } CmdArgs.push_back("--enable-new-dtags"); } // Explicitly set the linker emulation for platforms that might not // be the default emulation for the linker. switch (Arch) { case llvm::Triple::x86: CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386_fbsd"); break; case llvm::Triple::ppc: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_fbsd"); break; case llvm::Triple::mips: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32btsmip_fbsd"); break; case llvm::Triple::mipsel: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ltsmip_fbsd"); break; case llvm::Triple::mips64: CmdArgs.push_back("-m"); if (tools::mips::hasMipsAbiArg(Args, "n32")) CmdArgs.push_back("elf32btsmipn32_fbsd"); else CmdArgs.push_back("elf64btsmip_fbsd"); break; case llvm::Triple::mips64el: CmdArgs.push_back("-m"); if (tools::mips::hasMipsAbiArg(Args, "n32")) CmdArgs.push_back("elf32ltsmipn32_fbsd"); else CmdArgs.push_back("elf64ltsmip_fbsd"); break; default: break; } if (Arg *A = Args.getLastArg(options::OPT_G)) { if (ToolChain.getTriple().isMIPS()) { StringRef v = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-G" + v)); A->claim(); } } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { const char *crt1 = nullptr; if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) crt1 = "gcrt1.o"; else if (IsPIE) crt1 = "Scrt1.o"; else crt1 = "crt1.o"; } if (crt1) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); const char *crtbegin = nullptr; if (Args.hasArg(options::OPT_static)) crtbegin = "crtbeginT.o"; else if (Args.hasArg(options::OPT_shared) || IsPIE) crtbegin = "crtbeginS.o"; else crtbegin = "crtbegin.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); } Args.AddAllArgs(CmdArgs, options::OPT_L); ToolChain.AddFilePathLibArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); if (D.isUsingLTO()) { assert(!Inputs.empty() && "Must have at least one input."); AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], D.getLTOMode() == LTOK_Thin); } bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { addOpenMPRuntime(CmdArgs, ToolChain, Args); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else CmdArgs.push_back("-lm"); } if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(ToolChain, CmdArgs); if (NeedsXRayDeps) linkXRayRuntimeDeps(ToolChain, CmdArgs); // FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding // the default system libraries. Just mimic this for now. if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lgcc_p"); else CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else if (Args.hasArg(options::OPT_pg)) { CmdArgs.push_back("-lgcc_eh_p"); } else { CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } if (Args.hasArg(options::OPT_pthread)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lpthread_p"); else CmdArgs.push_back("-lpthread"); } if (Args.hasArg(options::OPT_pg)) { if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-lc"); else CmdArgs.push_back("-lc_p"); CmdArgs.push_back("-lgcc_p"); } else { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-lgcc_eh"); } else if (Args.hasArg(options::OPT_pg)) { CmdArgs.push_back("-lgcc_eh_p"); } else { CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || IsPIE) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); else CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; // Demangle C++ names in errors CmdArgs.push_back("-C"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { CmdArgs.push_back("-e"); CmdArgs.push_back("_start"); } if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("-dn"); } else { CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("--dynamic-linker"); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("ld.so.1"))); } } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("values-Xa.o"))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); } getToolChain().AddFilePathLibArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e, options::OPT_r}); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("-lc"); if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("-lm"); } } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); const Driver &D = ToolChain.getDriver(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); ArgStringList CmdArgs; CmdArgs.push_back("-flavor"); CmdArgs.push_back("ld"); // Enable garbage collection of unused input sections by default, since code // size is of particular importance. This is significantly facilitated by // the enabling of -ffunction-sections and -fdata-sections in // Clang::ConstructJob. if (areOptimizationsEnabled(Args)) CmdArgs.push_back("--gc-sections"); if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("--strip-all"); if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-shared"); if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-Bstatic"); Args.AddAllArgs(CmdArgs, options::OPT_L); ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("rcrt1.o"))); else if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o"))); else CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lcompiler_rt"); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique<Command>(JA, *this, Linker, CmdArgs, Inputs)); }
void cloudabi::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); // CloudABI only supports static linkage. CmdArgs.push_back("-Bstatic"); CmdArgs.push_back("--no-dynamic-linker"); // Provide PIE linker flags in case PIE is default for the architecture. if (ToolChain.isPIEDefault()) { CmdArgs.push_back("-pie"); CmdArgs.push_back("-zrelro"); } CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("--gc-sections"); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o"))); } Args.AddAllArgs(CmdArgs, options::OPT_L); ToolChain.AddFilePathLibArgs(Args, CmdArgs); Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); if (D.isUsingLTO()) { assert(!Inputs.empty() && "Must have at least one input."); AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], D.getLTOMode() == LTOK_Thin); } AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lcompiler_rt"); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::OpenBSD &ToolChain = static_cast<const toolchains::OpenBSD &>(getToolChain()); const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else if (getToolChain().getArch() == llvm::Triple::mips64el) CmdArgs.push_back("-EL"); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) { CmdArgs.push_back("-e"); CmdArgs.push_back("__start"); } CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); } else { CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/usr/libexec/ld.so"); } } if (Args.hasArg(options::OPT_pie)) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_nopie)) CmdArgs.push_back("-nopie"); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("gcrt0.o"))); else if (Args.hasArg(options::OPT_static) && !Args.hasArg(options::OPT_nopie)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("rcrt0.o"))); else CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); } else { CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o"))); } } std::string Triple = getToolChain().getTripleString(); if (Triple.substr(0, 6) == "x86_64") Triple.replace(0, 6, "amd64"); CmdArgs.push_back( Args.MakeArgString("-L/usr/lib/gcc-lib/" + Triple + "/4.2.1")); CmdArgs.push_back(Args.MakeArgString("-L/usr/lib")); Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs); bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (D.CCCIsCXX()) { if (getToolChain().ShouldLinkCXXStdlib(Args)) getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lm_p"); else CmdArgs.push_back("-lm"); } if (NeedsSanitizerDeps) { CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false)); linkSanitizerRuntimeDeps(ToolChain, CmdArgs); } if (NeedsXRayDeps) { CmdArgs.push_back(ToolChain.getCompilerRTArgString(Args, "builtins", false)); linkXRayRuntimeDeps(ToolChain, CmdArgs); } // FIXME: For some reason GCC passes -lgcc before adding // the default system libraries. Just mimic this for now. CmdArgs.push_back("-lgcc"); if (Args.hasArg(options::OPT_pthread)) { if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lpthread_p"); else CmdArgs.push_back("-lpthread"); } if (!Args.hasArg(options::OPT_shared)) { if (Args.hasArg(options::OPT_pg)) CmdArgs.push_back("-lc_p"); else CmdArgs.push_back("-lc"); } CmdArgs.push_back("-lgcc"); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); else CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const auto &TC = static_cast<const toolchains::CudaToolChain &>(getToolChain()); assert(TC.getTriple().isNVPTX() && "Wrong platform"); // Obtain architecture from the action. CudaArch gpu_arch = StringToCudaArch(JA.getOffloadingArch()); assert(gpu_arch != CudaArch::UNKNOWN && "Device action expected to have an architecture."); // Check that our installation's ptxas supports gpu_arch. if (!Args.hasArg(options::OPT_no_cuda_version_check)) { TC.CudaInstallation.CheckCudaVersionSupportsArch(gpu_arch); } ArgStringList CmdArgs; CmdArgs.push_back(TC.getTriple().isArch64Bit() ? "-m64" : "-m32"); if (Args.hasFlag(options::OPT_cuda_noopt_device_debug, options::OPT_no_cuda_noopt_device_debug, false)) { // ptxas does not accept -g option if optimization is enabled, so // we ignore the compiler's -O* options if we want debug info. CmdArgs.push_back("-g"); CmdArgs.push_back("--dont-merge-basicblocks"); CmdArgs.push_back("--return-at-end"); } else if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { // Map the -O we received to -O{0,1,2,3}. // // TODO: Perhaps we should map host -O2 to ptxas -O3. -O3 is ptxas's // default, so it may correspond more closely to the spirit of clang -O2. // -O3 seems like the least-bad option when -Osomething is specified to // clang but it isn't handled below. StringRef OOpt = "3"; if (A->getOption().matches(options::OPT_O4) || A->getOption().matches(options::OPT_Ofast)) OOpt = "3"; else if (A->getOption().matches(options::OPT_O0)) OOpt = "0"; else if (A->getOption().matches(options::OPT_O)) { // -Os, -Oz, and -O(anything else) map to -O2, for lack of better options. OOpt = llvm::StringSwitch<const char *>(A->getValue()) .Case("1", "1") .Case("2", "2") .Case("3", "3") .Case("s", "2") .Case("z", "2") .Default("2"); } CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt)); } else { // If no -O was passed, pass -O0 to ptxas -- no opt flag should correspond // to no optimizations, but ptxas's default is -O3. CmdArgs.push_back("-O0"); } CmdArgs.push_back("--gpu-name"); CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch))); CmdArgs.push_back("--output-file"); CmdArgs.push_back(Args.MakeArgString(Output.getFilename())); for (const auto& II : Inputs) CmdArgs.push_back(Args.MakeArgString(II.getFilename())); for (const auto& A : Args.getAllArgValues(options::OPT_Xcuda_ptxas)) CmdArgs.push_back(Args.MakeArgString(A)); const char *Exec; if (Arg *A = Args.getLastArg(options::OPT_ptxas_path_EQ)) Exec = A->getValue(); else Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { claimNoWarnArgs(Args); ArgStringList CmdArgs; // GNU as needs different flags for creating the correct output format // on architectures with different ABIs or optional feature sets. switch (getToolChain().getArch()) { case llvm::Triple::x86: CmdArgs.push_back("--32"); break; case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: { StringRef MArch, MCPU; arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true); std::string Arch = arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple()); CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch)); break; } case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips || getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::sparc: case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } default: break; } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
static void constructHexagonLinkArgs(Compilation &C, const JobAction &JA, const toolchains::HexagonToolChain &HTC, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs, const char *LinkingOutput) { const Driver &D = HTC.getDriver(); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- bool IsStatic = Args.hasArg(options::OPT_static); bool IsShared = Args.hasArg(options::OPT_shared); bool IsPIE = Args.hasArg(options::OPT_pie); bool IncStdLib = !Args.hasArg(options::OPT_nostdlib); bool IncStartFiles = !Args.hasArg(options::OPT_nostartfiles); bool IncDefLibs = !Args.hasArg(options::OPT_nodefaultlibs); bool UseG0 = false; bool UseShared = IsShared && !IsStatic; //---------------------------------------------------------------------------- // Silence warnings for various options //---------------------------------------------------------------------------- Args.ClaimAllArgs(options::OPT_g_Group); Args.ClaimAllArgs(options::OPT_emit_llvm); Args.ClaimAllArgs(options::OPT_w); // Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_static_libgcc); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); if (Args.hasArg(options::OPT_r)) CmdArgs.push_back("-r"); for (const auto &Opt : HTC.ExtraOpts) CmdArgs.push_back(Opt.c_str()); CmdArgs.push_back("-march=hexagon"); std::string CpuVer = toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str(); std::string MCpuString = "-mcpu=hexagon" + CpuVer; CmdArgs.push_back(Args.MakeArgString(MCpuString)); if (IsShared) { CmdArgs.push_back("-shared"); // The following should be the default, but doing as hexagon-gcc does. CmdArgs.push_back("-call_shared"); } if (IsStatic) CmdArgs.push_back("-static"); if (IsPIE && !IsShared) CmdArgs.push_back("-pie"); if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { std::string N = llvm::utostr(G.getValue()); CmdArgs.push_back(Args.MakeArgString(std::string("-G") + N)); UseG0 = G.getValue() == 0; } //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); //---------------------------------------------------------------------------- // moslib //---------------------------------------------------------------------------- std::vector<std::string> OsLibs; bool HasStandalone = false; for (const Arg *A : Args.filtered(options::OPT_moslib_EQ)) { A->claim(); OsLibs.emplace_back(A->getValue()); HasStandalone = HasStandalone || (OsLibs.back() == "standalone"); } if (OsLibs.empty()) { OsLibs.push_back("standalone"); HasStandalone = true; } //---------------------------------------------------------------------------- // Start Files //---------------------------------------------------------------------------- const std::string MCpuSuffix = "/" + CpuVer; const std::string MCpuG0Suffix = MCpuSuffix + "/G0"; const std::string RootDir = HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/"; const std::string StartSubDir = "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix); auto Find = [&HTC] (const std::string &RootDir, const std::string &SubDir, const char *Name) -> std::string { std::string RelName = SubDir + Name; std::string P = HTC.GetFilePath(RelName.c_str()); if (llvm::sys::fs::exists(P)) return P; return RootDir + RelName; }; if (IncStdLib && IncStartFiles) { if (!IsShared) { if (HasStandalone) { std::string Crt0SA = Find(RootDir, StartSubDir, "/crt0_standalone.o"); CmdArgs.push_back(Args.MakeArgString(Crt0SA)); } std::string Crt0 = Find(RootDir, StartSubDir, "/crt0.o"); CmdArgs.push_back(Args.MakeArgString(Crt0)); } std::string Init = UseShared ? Find(RootDir, StartSubDir + "/pic", "/initS.o") : Find(RootDir, StartSubDir, "/init.o"); CmdArgs.push_back(Args.MakeArgString(Init)); } //---------------------------------------------------------------------------- // Library Search Paths //---------------------------------------------------------------------------- const ToolChain::path_list &LibPaths = HTC.getFilePaths(); for (const auto &LibPath : LibPaths) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + LibPath)); //---------------------------------------------------------------------------- // //---------------------------------------------------------------------------- Args.AddAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_u_Group}); AddLinkerInputs(HTC, Inputs, Args, CmdArgs, JA); //---------------------------------------------------------------------------- // Libraries //---------------------------------------------------------------------------- if (IncStdLib && IncDefLibs) { if (D.CCCIsCXX()) { if (HTC.ShouldLinkCXXStdlib(Args)) HTC.AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } CmdArgs.push_back("--start-group"); if (!IsShared) { for (const std::string &Lib : OsLibs) CmdArgs.push_back(Args.MakeArgString("-l" + Lib)); CmdArgs.push_back("-lc"); } CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--end-group"); } //---------------------------------------------------------------------------- // End files //---------------------------------------------------------------------------- if (IncStdLib && IncStartFiles) { std::string Fini = UseShared ? Find(RootDir, StartSubDir + "/pic", "/finiS.o") : Find(RootDir, StartSubDir, "/fini.o"); CmdArgs.push_back(Args.MakeArgString(Fini)); } }
void hexagon::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { claimNoWarnArgs(Args); auto &HTC = static_cast<const toolchains::HexagonToolChain&>(getToolChain()); const Driver &D = HTC.getDriver(); ArgStringList CmdArgs; std::string MArchString = "-march=hexagon"; CmdArgs.push_back(Args.MakeArgString(MArchString)); RenderExtraToolArgs(JA, CmdArgs); std::string AsName = "hexagon-llvm-mc"; std::string MCpuString = "-mcpu=hexagon" + toolchains::HexagonToolChain::GetTargetCPUVersion(Args).str(); CmdArgs.push_back("-filetype=obj"); CmdArgs.push_back(Args.MakeArgString(MCpuString)); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Unexpected output"); CmdArgs.push_back("-fsyntax-only"); } if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) { std::string N = llvm::utostr(G.getValue()); CmdArgs.push_back(Args.MakeArgString(std::string("-gpsize=") + N)); } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go // wrong in is for linker inputs if they happened to have an odd // suffix; really the only way to get this to happen is a command // like '-x foobar a.c' which will treat a.c like a linker input. // // FIXME: For the linker case specifically, can we safely convert // inputs into '-Wl,' options? for (const auto &II : Inputs) { // Don't try to pass LLVM or AST inputs to a generic gcc. if (types::isLLVMIR(II.getType())) D.Diag(clang::diag::err_drv_no_linker_llvm_support) << HTC.getTripleString(); else if (II.getType() == types::TY_AST) D.Diag(clang::diag::err_drv_no_ast_support) << HTC.getTripleString(); else if (II.getType() == types::TY_ModuleFile) D.Diag(diag::err_drv_no_module_support) << HTC.getTripleString(); if (II.isFilename()) CmdArgs.push_back(II.getFilename()); else // Don't render as input, we need gcc to do the translations. // FIXME: What is this? II.getInputArg().render(Args, CmdArgs); } auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName.c_str())); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
std::string ToolChain::getInputFilename(const InputInfo &Input) const { return Input.getFilename(); }
void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const auto &TC = static_cast<const toolchains::CudaToolChain &>(getToolChain()); assert(TC.getTriple().isNVPTX() && "Wrong platform"); ArgStringList CmdArgs; // OpenMP uses nvlink to link cubin files. The result will be embedded in the // host binary by the host linker. assert(!JA.isHostOffloading(Action::OFK_OpenMP) && "CUDA toolchain not expected for an OpenMP host device."); if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else assert(Output.isNothing() && "Invalid output."); if (Args.hasArg(options::OPT_g_Flag)) CmdArgs.push_back("-g"); if (Args.hasArg(options::OPT_v)) CmdArgs.push_back("-v"); StringRef GPUArch = Args.getLastArgValue(options::OPT_march_EQ); assert(!GPUArch.empty() && "At least one GPU Arch required for ptxas."); CmdArgs.push_back("-arch"); CmdArgs.push_back(Args.MakeArgString(GPUArch)); // Add paths specified in LIBRARY_PATH environment variable as -L options. addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); // Add paths for the default clang library path. SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(TC.getDriver().Dir); llvm::sys::path::append(DefaultLibPath, "lib" CLANG_LIBDIR_SUFFIX); CmdArgs.push_back(Args.MakeArgString(Twine("-L") + DefaultLibPath)); // Add linking against library implementing OpenMP calls on NVPTX target. CmdArgs.push_back("-lomptarget-nvptx"); for (const auto &II : Inputs) { if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || II.getType() == types::TY_LTO_BC || II.getType() == types::TY_LLVM_BC) { C.getDriver().Diag(diag::err_drv_no_linker_llvm_support) << getToolChain().getTripleString(); continue; } // Currently, we only pass the input files to the linker, we do not pass // any libraries that may be valid only for the host. if (!II.isFilename()) continue; const char *CubinF = C.addTempFile( C.getArgs().MakeArgString(getToolChain().getInputFilename(II))); CmdArgs.push_back(CubinF); } AddOpenMPLinkerScript(getToolChain(), C, Output, Inputs, Args, CmdArgs, JA); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("nvlink")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { claimNoWarnArgs(Args); ArgStringList CmdArgs; switch (getToolChain().getArch()) { case llvm::Triple::x86: // When building 32-bit code on OpenBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. CmdArgs.push_back("--32"); break; case llvm::Triple::ppc: CmdArgs.push_back("-mppc"); CmdArgs.push_back("-many"); break; case llvm::Triple::sparc: case llvm::Triple::sparcel: { CmdArgs.push_back("-32"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::sparcv9: { CmdArgs.push_back("-64"); std::string CPU = getCPUName(Args, getToolChain().getTriple()); CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::mips64: case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("-EB"); else CmdArgs.push_back("-EL"); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } default: break; } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::Fuchsia &ToolChain = static_cast<const toolchains::Fuchsia &>(getToolChain()); const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); if (llvm::sys::path::stem(Exec).equals_lower("lld")) { CmdArgs.push_back("-flavor"); CmdArgs.push_back("gnu"); CmdArgs.push_back("-z"); CmdArgs.push_back("rodynamic"); } if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (!Args.hasArg(options::OPT_shared) && !Args.hasArg(options::OPT_r)) CmdArgs.push_back("-pie"); if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); if (Args.hasArg(options::OPT_r)) { CmdArgs.push_back("-r"); } else { CmdArgs.push_back("--build-id"); CmdArgs.push_back("--hash-style=gnu"); } CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-Bstatic"); else if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-shared"); if (!Args.hasArg(options::OPT_shared)) { std::string Dyld = D.DyldPrefix; if (ToolChain.getSanitizerArgs().needsAsanRt() && ToolChain.getSanitizerArgs().needsSharedAsanRt()) Dyld += "asan/"; Dyld += "ld.so.1"; CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back(Args.MakeArgString(Dyld)); } CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("Scrt1.o"))); } } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); addSanitizerRuntimes(ToolChain, Args, CmdArgs); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-Bdynamic"); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } AddRunTimeLibs(ToolChain, D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads)) CmdArgs.push_back("-lpthread"); if (Args.hasArg(options::OPT_fsplit_stack)) CmdArgs.push_back("--wrap=pthread_create"); CmdArgs.push_back("-lc"); } C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const auto &TC = static_cast<const toolchains::MyriadToolChain &>(getToolChain()); const llvm::Triple &T = TC.getTriple(); ArgStringList CmdArgs; bool UseStartfiles = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); bool UseDefaultLibs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs); // Silence warning if the args contain both -nostdlib and -stdlib=. Args.getLastArg(options::OPT_stdlib_EQ); if (T.getArch() == llvm::Triple::sparc) CmdArgs.push_back("-EB"); else // SHAVE assumes little-endian, and sparcel is expressly so. CmdArgs.push_back("-EL"); // The remaining logic is mostly like gnutools::Linker::ConstructJob, // but we never pass through a --sysroot option and various other bits. // For example, there are no sanitizers (yet) nor gold linker. // Eat some arguments that may be present but have no effect. Args.ClaimAllArgs(options::OPT_g_Group); Args.ClaimAllArgs(options::OPT_w); Args.ClaimAllArgs(options::OPT_static_libgcc); if (Args.hasArg(options::OPT_s)) // Pass the 'strip' option. CmdArgs.push_back("-s"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); if (UseStartfiles) { // If you want startfiles, it means you want the builtin crti and crtbegin, // but not crt0. Myriad link commands provide their own crt0.o as needed. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crti.o"))); CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); } Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group, options::OPT_e, options::OPT_s, options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); TC.AddFilePathLibArgs(Args, CmdArgs); bool NeedsSanitizerDeps = addSanitizerRuntimes(TC, Args, CmdArgs); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); if (UseDefaultLibs) { if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(TC, CmdArgs); if (C.getDriver().CCCIsCXX()) { if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) { CmdArgs.push_back("-lc++"); CmdArgs.push_back("-lc++abi"); } else CmdArgs.push_back("-lstdc++"); } if (T.getOS() == llvm::Triple::RTEMS) { CmdArgs.push_back("--start-group"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); // circularly dependent on rtems // You must provide your own "-L" option to enable finding these. CmdArgs.push_back("-lrtemscpu"); CmdArgs.push_back("-lrtemsbsp"); CmdArgs.push_back("--end-group"); } else { CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } } if (UseStartfiles) { CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtn.o"))); } std::string Exec = Args.MakeArgString(TC.GetProgramPath("sparc-myriad-elf-ld")); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); }
void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { claimNoWarnArgs(Args); ArgStringList CmdArgs; // When building 32-bit code on FreeBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. switch (getToolChain().getArch()) { default: break; case llvm::Triple::x86: CmdArgs.push_back("--32"); break; case llvm::Triple::ppc: CmdArgs.push_back("-a32"); break; case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: case llvm::Triple::mips64el: { StringRef CPUName; StringRef ABIName; mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName); CmdArgs.push_back("-march"); CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-mabi"); CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data()); if (getToolChain().getTriple().isLittleEndian()) CmdArgs.push_back("-EL"); else CmdArgs.push_back("-EB"); if (Arg *A = Args.getLastArg(options::OPT_G)) { StringRef v = A->getValue(); CmdArgs.push_back(Args.MakeArgString("-G" + v)); A->claim(); } AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: { arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args); if (ABI == arm::FloatABI::Hard) CmdArgs.push_back("-mfpu=vfp"); else CmdArgs.push_back("-mfpu=softvfp"); switch (getToolChain().getTriple().getEnvironment()) { case llvm::Triple::GNUEABIHF: case llvm::Triple::GNUEABI: case llvm::Triple::EABI: CmdArgs.push_back("-meabi=5"); break; default: CmdArgs.push_back("-matpcs"); } break; } case llvm::Triple::sparc: case llvm::Triple::sparcel: case llvm::Triple::sparcv9: { std::string CPU = getCPUName(Args, getToolChain().getTriple()); CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple())); AddAssemblerKPIC(getToolChain(), Args, CmdArgs); break; } } Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); for (const auto &II : Inputs) CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const Driver &D = getToolChain().getDriver(); ArgStringList CmdArgs; if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); CmdArgs.push_back("--eh-frame-hdr"); if (Args.hasArg(options::OPT_static)) { CmdArgs.push_back("-Bstatic"); } else { if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-Bshareable"); } else { Args.AddAllArgs(CmdArgs, options::OPT_pie); CmdArgs.push_back("-dynamic-linker"); CmdArgs.push_back("/libexec/ld.elf_so"); } } // Many NetBSD architectures support more than one ABI. // Determine the correct emulation for ld. switch (getToolChain().getArch()) { case llvm::Triple::x86: CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); break; case llvm::Triple::arm: case llvm::Triple::thumb: CmdArgs.push_back("-m"); switch (getToolChain().getTriple().getEnvironment()) { case llvm::Triple::EABI: case llvm::Triple::GNUEABI: CmdArgs.push_back("armelf_nbsd_eabi"); break; case llvm::Triple::EABIHF: case llvm::Triple::GNUEABIHF: CmdArgs.push_back("armelf_nbsd_eabihf"); break; default: CmdArgs.push_back("armelf_nbsd"); break; } break; case llvm::Triple::armeb: case llvm::Triple::thumbeb: arm::appendEBLinkFlags(Args, CmdArgs, getToolChain().getEffectiveTriple()); CmdArgs.push_back("-m"); switch (getToolChain().getTriple().getEnvironment()) { case llvm::Triple::EABI: case llvm::Triple::GNUEABI: CmdArgs.push_back("armelfb_nbsd_eabi"); break; case llvm::Triple::EABIHF: case llvm::Triple::GNUEABIHF: CmdArgs.push_back("armelfb_nbsd_eabihf"); break; default: CmdArgs.push_back("armelfb_nbsd"); break; } break; case llvm::Triple::mips64: case llvm::Triple::mips64el: if (mips::hasMipsAbiArg(Args, "32")) { CmdArgs.push_back("-m"); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("elf32btsmip"); else CmdArgs.push_back("elf32ltsmip"); } else if (mips::hasMipsAbiArg(Args, "64")) { CmdArgs.push_back("-m"); if (getToolChain().getArch() == llvm::Triple::mips64) CmdArgs.push_back("elf64btsmip"); else CmdArgs.push_back("elf64ltsmip"); } break; case llvm::Triple::ppc: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32ppc_nbsd"); break; case llvm::Triple::ppc64: case llvm::Triple::ppc64le: CmdArgs.push_back("-m"); CmdArgs.push_back("elf64ppc"); break; case llvm::Triple::sparc: CmdArgs.push_back("-m"); CmdArgs.push_back("elf32_sparc"); break; case llvm::Triple::sparcv9: CmdArgs.push_back("-m"); CmdArgs.push_back("elf64_sparc"); break; default: break; } if (Output.isFilename()) { CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); } else { assert(Output.isNothing() && "Invalid output."); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crt0.o"))); } CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) { CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbeginS.o"))); } else { CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); } } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_e); Args.AddAllArgs(CmdArgs, options::OPT_s); Args.AddAllArgs(CmdArgs, options::OPT_t); Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag); Args.AddAllArgs(CmdArgs, options::OPT_r); bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs); AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); unsigned Major, Minor, Micro; getToolChain().getTriple().getOSVersion(Major, Minor, Micro); bool useLibgcc = true; if (Major >= 7 || Major == 0) { switch (getToolChain().getArch()) { case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: case llvm::Triple::thumbeb: case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: case llvm::Triple::sparc: case llvm::Triple::sparcv9: case llvm::Triple::x86: case llvm::Triple::x86_64: useLibgcc = false; break; default: break; } } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { addOpenMPRuntime(CmdArgs, getToolChain(), Args); if (D.CCCIsCXX()) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } if (NeedsSanitizerDeps) linkSanitizerRuntimeDeps(getToolChain(), CmdArgs); if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); CmdArgs.push_back("-lc"); if (useLibgcc) { if (Args.hasArg(options::OPT_static)) { // libgcc_eh depends on libc, so resolve as much as possible, // pull in any new requirements from libc and then get the rest // of libgcc. CmdArgs.push_back("-lgcc_eh"); CmdArgs.push_back("-lc"); CmdArgs.push_back("-lgcc"); } else { CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--as-needed"); CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); } } } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtendS.o"))); else CmdArgs.push_back( Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); } getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
// This is quite similar to gnutools::Linker::ConstructJob with changes that // we use static by default, do not yet support sanitizers or LTO, and a few // others. Eventually we can support more of that and hopefully migrate back // to gnutools::Linker. void nacltools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { const toolchains::NaClToolChain &ToolChain = static_cast<const toolchains::NaClToolChain &>(getToolChain()); const Driver &D = ToolChain.getDriver(); const llvm::Triple::ArchType Arch = ToolChain.getArch(); const bool IsStatic = !Args.hasArg(options::OPT_dynamic) && !Args.hasArg(options::OPT_shared); ArgStringList CmdArgs; // Silence warning for "clang -g foo.o -o foo" Args.ClaimAllArgs(options::OPT_g_Group); // and "clang -emit-llvm foo.o -o foo" Args.ClaimAllArgs(options::OPT_emit_llvm); // and for "clang -w foo.o -o foo". Other warning options are already // handled somewhere else. Args.ClaimAllArgs(options::OPT_w); if (!D.SysRoot.empty()) CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); if (Args.hasArg(options::OPT_rdynamic)) CmdArgs.push_back("-export-dynamic"); if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("-s"); // NaClToolChain doesn't have ExtraOpts like Linux; the only relevant flag // from there is --build-id, which we do want. CmdArgs.push_back("--build-id"); if (!IsStatic) CmdArgs.push_back("--eh-frame-hdr"); CmdArgs.push_back("-m"); if (Arch == llvm::Triple::x86) CmdArgs.push_back("elf_i386_nacl"); else if (Arch == llvm::Triple::arm) CmdArgs.push_back("armelf_nacl"); else if (Arch == llvm::Triple::x86_64) CmdArgs.push_back("elf_x86_64_nacl"); else if (Arch == llvm::Triple::mipsel) CmdArgs.push_back("mipselelf_nacl"); else D.Diag(diag::err_target_unsupported_arch) << ToolChain.getArchName() << "Native Client"; if (IsStatic) CmdArgs.push_back("-static"); else if (Args.hasArg(options::OPT_shared)) CmdArgs.push_back("-shared"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt1.o"))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); const char *crtbegin; if (IsStatic) crtbegin = "crtbeginT.o"; else if (Args.hasArg(options::OPT_shared)) crtbegin = "crtbeginS.o"; else crtbegin = "crtbegin.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin))); } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_u); ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) CmdArgs.push_back("--no-demangle"); AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { if (ToolChain.ShouldLinkCXXStdlib(Args)) { bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && !IsStatic; if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); if (OnlyLibstdcxxStatic) CmdArgs.push_back("-Bdynamic"); } CmdArgs.push_back("-lm"); } if (!Args.hasArg(options::OPT_nostdlib)) { if (!Args.hasArg(options::OPT_nodefaultlibs)) { // Always use groups, since it has no effect on dynamic libraries. CmdArgs.push_back("--start-group"); CmdArgs.push_back("-lc"); // NaCl's libc++ currently requires libpthread, so just always include it // in the group for C++. if (Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads) || D.CCCIsCXX()) { // Gold, used by Mips, handles nested groups differently than ld, and // without '-lnacl' it prefers symbols from libpthread.a over libnacl.a, // which is not a desired behaviour here. // See https://sourceware.org/ml/binutils/2015-03/msg00034.html if (getToolChain().getArch() == llvm::Triple::mipsel) CmdArgs.push_back("-lnacl"); CmdArgs.push_back("-lpthread"); } CmdArgs.push_back("-lgcc"); CmdArgs.push_back("--as-needed"); if (IsStatic) CmdArgs.push_back("-lgcc_eh"); else CmdArgs.push_back("-lgcc_s"); CmdArgs.push_back("--no-as-needed"); // Mips needs to create and use pnacl_legacy library that contains // definitions from bitcode/pnaclmm.c and definitions for // __nacl_tp_tls_offset() and __nacl_tp_tdb_offset(). if (getToolChain().getArch() == llvm::Triple::mipsel) CmdArgs.push_back("-lpnacl_legacy"); CmdArgs.push_back("--end-group"); } if (!Args.hasArg(options::OPT_nostartfiles)) { const char *crtend; if (Args.hasArg(options::OPT_shared)) crtend = "crtendS.o"; else crtend = "crtend.o"; CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend))); CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); }
/// 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; }