10b57cec5SDimitry Andric //===--- MSP430.cpp - MSP430 Helpers for Tools ------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MSP430.h"
100b57cec5SDimitry Andric #include "CommonArgs.h"
110b57cec5SDimitry Andric #include "Gnu.h"
120b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
13fe6060f1SDimitry Andric #include "clang/Driver/InputInfo.h"
140b57cec5SDimitry Andric #include "clang/Driver/Multilib.h"
150b57cec5SDimitry Andric #include "clang/Driver/Options.h"
160b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
170b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
180b57cec5SDimitry Andric #include "llvm/Support/Path.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace clang::driver;
210b57cec5SDimitry Andric using namespace clang::driver::toolchains;
220b57cec5SDimitry Andric using namespace clang::driver::tools;
230b57cec5SDimitry Andric using namespace clang;
240b57cec5SDimitry Andric using namespace llvm::opt;
250b57cec5SDimitry Andric 
isSupportedMCU(const StringRef MCU)260b57cec5SDimitry Andric static bool isSupportedMCU(const StringRef MCU) {
270b57cec5SDimitry Andric   return llvm::StringSwitch<bool>(MCU)
280b57cec5SDimitry Andric #define MSP430_MCU(NAME) .Case(NAME, true)
290b57cec5SDimitry Andric #include "clang/Basic/MSP430Target.def"
300b57cec5SDimitry Andric       .Default(false);
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric 
getSupportedHWMult(const Arg * MCU)330b57cec5SDimitry Andric static StringRef getSupportedHWMult(const Arg *MCU) {
340b57cec5SDimitry Andric   if (!MCU)
350b57cec5SDimitry Andric     return "none";
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   return llvm::StringSwitch<StringRef>(MCU->getValue())
380b57cec5SDimitry Andric #define MSP430_MCU_FEAT(NAME, HWMULT) .Case(NAME, HWMULT)
390b57cec5SDimitry Andric #include "clang/Basic/MSP430Target.def"
400b57cec5SDimitry Andric       .Default("none");
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
getHWMultLib(const ArgList & Args)430b57cec5SDimitry Andric static StringRef getHWMultLib(const ArgList &Args) {
440b57cec5SDimitry Andric   StringRef HWMult = Args.getLastArgValue(options::OPT_mhwmult_EQ, "auto");
450b57cec5SDimitry Andric   if (HWMult == "auto") {
460b57cec5SDimitry Andric     HWMult = getSupportedHWMult(Args.getLastArg(options::OPT_mmcu_EQ));
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   return llvm::StringSwitch<StringRef>(HWMult)
500b57cec5SDimitry Andric       .Case("16bit", "-lmul_16")
510b57cec5SDimitry Andric       .Case("32bit", "-lmul_32")
520b57cec5SDimitry Andric       .Case("f5series", "-lmul_f5")
530b57cec5SDimitry Andric       .Default("-lmul_none");
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
getMSP430TargetFeatures(const Driver & D,const ArgList & Args,std::vector<StringRef> & Features)560b57cec5SDimitry Andric void msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
570b57cec5SDimitry Andric                                      std::vector<StringRef> &Features) {
580b57cec5SDimitry Andric   const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ);
590b57cec5SDimitry Andric   if (MCU && !isSupportedMCU(MCU->getValue())) {
600b57cec5SDimitry Andric     D.Diag(diag::err_drv_clang_unsupported) << MCU->getValue();
610b57cec5SDimitry Andric     return;
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   const Arg *HWMultArg = Args.getLastArg(options::OPT_mhwmult_EQ);
650b57cec5SDimitry Andric   if (!MCU && !HWMultArg)
660b57cec5SDimitry Andric     return;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   StringRef HWMult = HWMultArg ? HWMultArg->getValue() : "auto";
690b57cec5SDimitry Andric   StringRef SupportedHWMult = getSupportedHWMult(MCU);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   if (HWMult == "auto") {
720b57cec5SDimitry Andric     // 'auto' - deduce hw multiplier support based on mcu name provided.
730b57cec5SDimitry Andric     // If no mcu name is provided, assume no hw multiplier is supported.
740b57cec5SDimitry Andric     if (!MCU)
750b57cec5SDimitry Andric       D.Diag(clang::diag::warn_drv_msp430_hwmult_no_device);
760b57cec5SDimitry Andric     HWMult = SupportedHWMult;
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   if (HWMult == "none") {
800b57cec5SDimitry Andric     // 'none' - disable hw multiplier.
810b57cec5SDimitry Andric     Features.push_back("-hwmult16");
820b57cec5SDimitry Andric     Features.push_back("-hwmult32");
830b57cec5SDimitry Andric     Features.push_back("-hwmultf5");
840b57cec5SDimitry Andric     return;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   if (MCU && SupportedHWMult == "none")
880b57cec5SDimitry Andric     D.Diag(clang::diag::warn_drv_msp430_hwmult_unsupported) << HWMult;
890b57cec5SDimitry Andric   if (MCU && HWMult != SupportedHWMult)
900b57cec5SDimitry Andric     D.Diag(clang::diag::warn_drv_msp430_hwmult_mismatch)
910b57cec5SDimitry Andric         << SupportedHWMult << HWMult;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   if (HWMult == "16bit") {
940b57cec5SDimitry Andric     // '16bit' - for 16-bit only hw multiplier.
950b57cec5SDimitry Andric     Features.push_back("+hwmult16");
960b57cec5SDimitry Andric   } else if (HWMult == "32bit") {
970b57cec5SDimitry Andric     // '32bit' - for 16/32-bit hw multiplier.
980b57cec5SDimitry Andric     Features.push_back("+hwmult32");
990b57cec5SDimitry Andric   } else if (HWMult == "f5series") {
1000b57cec5SDimitry Andric     // 'f5series' - for 16/32-bit hw multiplier supported by F5 series mcus.
1010b57cec5SDimitry Andric     Features.push_back("+hwmultf5");
1020b57cec5SDimitry Andric   } else {
1030b57cec5SDimitry Andric     D.Diag(clang::diag::err_drv_unsupported_option_argument)
104bdd1243dSDimitry Andric         << HWMultArg->getSpelling() << HWMult;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric /// MSP430 Toolchain
MSP430ToolChain(const Driver & D,const llvm::Triple & Triple,const ArgList & Args)1090b57cec5SDimitry Andric MSP430ToolChain::MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
1100b57cec5SDimitry Andric                                  const ArgList &Args)
1110b57cec5SDimitry Andric     : Generic_ELF(D, Triple, Args) {
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   StringRef MultilibSuf = "";
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   GCCInstallation.init(Triple, Args);
1160b57cec5SDimitry Andric   if (GCCInstallation.isValid()) {
1170b57cec5SDimitry Andric     MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     SmallString<128> GCCBinPath;
1200b57cec5SDimitry Andric     llvm::sys::path::append(GCCBinPath,
1210b57cec5SDimitry Andric                             GCCInstallation.getParentLibPath(), "..", "bin");
1220b57cec5SDimitry Andric     addPathIfExists(D, GCCBinPath, getProgramPaths());
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     SmallString<128> GCCRtPath;
1250b57cec5SDimitry Andric     llvm::sys::path::append(GCCRtPath,
1260b57cec5SDimitry Andric                             GCCInstallation.getInstallPath(), MultilibSuf);
1270b57cec5SDimitry Andric     addPathIfExists(D, GCCRtPath, getFilePaths());
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   SmallString<128> SysRootDir(computeSysRoot());
131e8d8bef9SDimitry Andric   llvm::sys::path::append(SysRootDir, "msp430-elf", "lib", MultilibSuf);
1320b57cec5SDimitry Andric   addPathIfExists(D, SysRootDir, getFilePaths());
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric 
computeSysRoot() const1350b57cec5SDimitry Andric std::string MSP430ToolChain::computeSysRoot() const {
1360b57cec5SDimitry Andric   if (!getDriver().SysRoot.empty())
1370b57cec5SDimitry Andric     return getDriver().SysRoot;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   SmallString<128> Dir;
1400b57cec5SDimitry Andric   if (GCCInstallation.isValid())
141e8d8bef9SDimitry Andric     llvm::sys::path::append(Dir, GCCInstallation.getParentLibPath(), "..");
1420b57cec5SDimitry Andric   else
143e8d8bef9SDimitry Andric     llvm::sys::path::append(Dir, getDriver().Dir, "..");
1440b57cec5SDimitry Andric 
1457a6dacacSDimitry Andric   return std::string(Dir);
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
AddClangSystemIncludeArgs(const ArgList & DriverArgs,ArgStringList & CC1Args) const1480b57cec5SDimitry Andric void MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
1490b57cec5SDimitry Andric                                                 ArgStringList &CC1Args) const {
1500b57cec5SDimitry Andric   if (DriverArgs.hasArg(options::OPT_nostdinc) ||
1510b57cec5SDimitry Andric       DriverArgs.hasArg(options::OPT_nostdlibinc))
1520b57cec5SDimitry Andric     return;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   SmallString<128> Dir(computeSysRoot());
155e8d8bef9SDimitry Andric   llvm::sys::path::append(Dir, "msp430-elf", "include");
1560b57cec5SDimitry Andric   addSystemInclude(DriverArgs, CC1Args, Dir.str());
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
addClangTargetOptions(const ArgList & DriverArgs,ArgStringList & CC1Args,Action::OffloadKind) const1590b57cec5SDimitry Andric void MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
1600b57cec5SDimitry Andric                                             ArgStringList &CC1Args,
1610b57cec5SDimitry Andric                                             Action::OffloadKind) const {
1620b57cec5SDimitry Andric   CC1Args.push_back("-nostdsysteminc");
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   const auto *MCUArg = DriverArgs.getLastArg(options::OPT_mmcu_EQ);
1650b57cec5SDimitry Andric   if (!MCUArg)
1660b57cec5SDimitry Andric     return;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   const StringRef MCU = MCUArg->getValue();
1695f757f3fSDimitry Andric   if (MCU.starts_with("msp430i")) {
1700b57cec5SDimitry Andric     // 'i' should be in lower case as it's defined in TI MSP430-GCC headers
1710b57cec5SDimitry Andric     CC1Args.push_back(DriverArgs.MakeArgString(
1720b57cec5SDimitry Andric         "-D__MSP430i" + MCU.drop_front(7).upper() + "__"));
1730b57cec5SDimitry Andric   } else {
1740b57cec5SDimitry Andric     CC1Args.push_back(DriverArgs.MakeArgString("-D__" + MCU.upper() + "__"));
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
buildLinker() const1780b57cec5SDimitry Andric Tool *MSP430ToolChain::buildLinker() const {
1790b57cec5SDimitry Andric   return new tools::msp430::Linker(*this);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
AddStartFiles(bool UseExceptions,const ArgList & Args,ArgStringList & CmdArgs) const182e8d8bef9SDimitry Andric void msp430::Linker::AddStartFiles(bool UseExceptions, const ArgList &Args,
183e8d8bef9SDimitry Andric                                    ArgStringList &CmdArgs) const {
184e8d8bef9SDimitry Andric   const ToolChain &ToolChain = getToolChain();
185e8d8bef9SDimitry Andric 
186e8d8bef9SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
187e8d8bef9SDimitry Andric   const char *crtbegin = UseExceptions ? "crtbegin.o" : "crtbegin_no_eh.o";
188e8d8bef9SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
189e8d8bef9SDimitry Andric }
190e8d8bef9SDimitry Andric 
AddDefaultLibs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const191e8d8bef9SDimitry Andric void msp430::Linker::AddDefaultLibs(const llvm::opt::ArgList &Args,
192e8d8bef9SDimitry Andric                                     llvm::opt::ArgStringList &CmdArgs) const {
193e8d8bef9SDimitry Andric   const ToolChain &ToolChain = getToolChain();
194e8d8bef9SDimitry Andric   const Driver &D = ToolChain.getDriver();
195e8d8bef9SDimitry Andric 
196e8d8bef9SDimitry Andric   CmdArgs.push_back("--start-group");
197e8d8bef9SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args)));
198e8d8bef9SDimitry Andric   CmdArgs.push_back("-lc");
199e8d8bef9SDimitry Andric   AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
200e8d8bef9SDimitry Andric   CmdArgs.push_back("-lcrt");
201e8d8bef9SDimitry Andric 
202e8d8bef9SDimitry Andric   if (Args.hasArg(options::OPT_msim)) {
203e8d8bef9SDimitry Andric     CmdArgs.push_back("-lsim");
204e8d8bef9SDimitry Andric 
205e8d8bef9SDimitry Andric     // msp430-sim.ld relies on __crt0_call_exit being implicitly .refsym-ed
206e8d8bef9SDimitry Andric     // in main() by msp430-gcc.
207e8d8bef9SDimitry Andric     // This workaround should work seamlessly unless the compilation unit that
208e8d8bef9SDimitry Andric     // contains main() is compiled by clang and then passed to
209e8d8bef9SDimitry Andric     // gcc compiler driver for linkage.
210e8d8bef9SDimitry Andric     CmdArgs.push_back("--undefined=__crt0_call_exit");
211e8d8bef9SDimitry Andric   } else
212e8d8bef9SDimitry Andric     CmdArgs.push_back("-lnosys");
213e8d8bef9SDimitry Andric 
214e8d8bef9SDimitry Andric   CmdArgs.push_back("--end-group");
215e8d8bef9SDimitry Andric   AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
216e8d8bef9SDimitry Andric }
217e8d8bef9SDimitry Andric 
AddEndFiles(bool UseExceptions,const ArgList & Args,ArgStringList & CmdArgs) const218e8d8bef9SDimitry Andric void msp430::Linker::AddEndFiles(bool UseExceptions, const ArgList &Args,
219e8d8bef9SDimitry Andric                                  ArgStringList &CmdArgs) const {
220e8d8bef9SDimitry Andric   const ToolChain &ToolChain = getToolChain();
221e8d8bef9SDimitry Andric   const Driver &D = ToolChain.getDriver();
222e8d8bef9SDimitry Andric 
223e8d8bef9SDimitry Andric   const char *crtend = UseExceptions ? "crtend.o" : "crtend_no_eh.o";
224e8d8bef9SDimitry Andric   CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
225e8d8bef9SDimitry Andric   AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
226e8d8bef9SDimitry Andric }
227e8d8bef9SDimitry Andric 
AddSspArgs(const ArgList & Args,ArgStringList & CmdArgs)228e8d8bef9SDimitry Andric static void AddSspArgs(const ArgList &Args, ArgStringList &CmdArgs) {
229e8d8bef9SDimitry Andric   Arg *SspFlag = Args.getLastArg(
230e8d8bef9SDimitry Andric       options::OPT_fno_stack_protector, options::OPT_fstack_protector,
231e8d8bef9SDimitry Andric       options::OPT_fstack_protector_all, options::OPT_fstack_protector_strong);
232e8d8bef9SDimitry Andric 
233e8d8bef9SDimitry Andric   if (SspFlag &&
234e8d8bef9SDimitry Andric       !SspFlag->getOption().matches(options::OPT_fno_stack_protector)) {
235e8d8bef9SDimitry Andric     CmdArgs.push_back("-lssp_nonshared");
236e8d8bef9SDimitry Andric     CmdArgs.push_back("-lssp");
237e8d8bef9SDimitry Andric   }
238e8d8bef9SDimitry Andric }
239e8d8bef9SDimitry Andric 
AddImplicitLinkerScript(const std::string SysRoot,const ArgList & Args,ArgStringList & CmdArgs)240e8d8bef9SDimitry Andric static void AddImplicitLinkerScript(const std::string SysRoot,
241e8d8bef9SDimitry Andric                                     const ArgList &Args,
242e8d8bef9SDimitry Andric                                     ArgStringList &CmdArgs) {
243e8d8bef9SDimitry Andric   if (Args.hasArg(options::OPT_T))
244e8d8bef9SDimitry Andric     return;
245e8d8bef9SDimitry Andric 
246e8d8bef9SDimitry Andric   if (Args.hasArg(options::OPT_msim)) {
247e8d8bef9SDimitry Andric     CmdArgs.push_back("-Tmsp430-sim.ld");
248e8d8bef9SDimitry Andric     return;
249e8d8bef9SDimitry Andric   }
250e8d8bef9SDimitry Andric 
251e8d8bef9SDimitry Andric   const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ);
252e8d8bef9SDimitry Andric   if (!MCUArg)
253e8d8bef9SDimitry Andric     return;
254e8d8bef9SDimitry Andric 
255e8d8bef9SDimitry Andric   SmallString<128> MCULinkerScriptPath(SysRoot);
256e8d8bef9SDimitry Andric   llvm::sys::path::append(MCULinkerScriptPath, "include");
257e8d8bef9SDimitry Andric   // -L because <mcu>.ld INCLUDEs <mcu>_symbols.ld
258e8d8bef9SDimitry Andric   CmdArgs.push_back(Args.MakeArgString("-L" + MCULinkerScriptPath));
259e8d8bef9SDimitry Andric   CmdArgs.push_back(
260e8d8bef9SDimitry Andric       Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld"));
261e8d8bef9SDimitry Andric }
262e8d8bef9SDimitry Andric 
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const2630b57cec5SDimitry Andric void msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
2640b57cec5SDimitry Andric                                   const InputInfo &Output,
2650b57cec5SDimitry Andric                                   const InputInfoList &Inputs,
2660b57cec5SDimitry Andric                                   const ArgList &Args,
2670b57cec5SDimitry Andric                                   const char *LinkingOutput) const {
2680b57cec5SDimitry Andric   const ToolChain &ToolChain = getToolChain();
2690b57cec5SDimitry Andric   const Driver &D = ToolChain.getDriver();
2700b57cec5SDimitry Andric   std::string Linker = ToolChain.GetProgramPath(getShortName());
2710b57cec5SDimitry Andric   ArgStringList CmdArgs;
272e8d8bef9SDimitry Andric   bool UseExceptions = Args.hasFlag(options::OPT_fexceptions,
273e8d8bef9SDimitry Andric                                     options::OPT_fno_exceptions, false);
274e8d8bef9SDimitry Andric   bool UseStartAndEndFiles = !Args.hasArg(options::OPT_nostdlib, options::OPT_r,
275e8d8bef9SDimitry Andric                                           options::OPT_nostartfiles);
2760b57cec5SDimitry Andric 
277e8d8bef9SDimitry Andric   if (Args.hasArg(options::OPT_mrelax))
278e8d8bef9SDimitry Andric     CmdArgs.push_back("--relax");
279e8d8bef9SDimitry Andric   if (!Args.hasArg(options::OPT_r, options::OPT_g_Group))
280e8d8bef9SDimitry Andric     CmdArgs.push_back("--gc-sections");
281e8d8bef9SDimitry Andric 
2825f757f3fSDimitry Andric   Args.addAllArgs(CmdArgs, {
283e8d8bef9SDimitry Andric                                options::OPT_n,
284e8d8bef9SDimitry Andric                                options::OPT_s,
285e8d8bef9SDimitry Andric                                options::OPT_t,
286e8d8bef9SDimitry Andric                                options::OPT_u,
287e8d8bef9SDimitry Andric                            });
288e8d8bef9SDimitry Andric 
289e8d8bef9SDimitry Andric   if (UseStartAndEndFiles)
290e8d8bef9SDimitry Andric     AddStartFiles(UseExceptions, Args, CmdArgs);
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_L);
2930b57cec5SDimitry Andric   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
2940b57cec5SDimitry Andric   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
2950b57cec5SDimitry Andric 
296e8d8bef9SDimitry Andric   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r,
297e8d8bef9SDimitry Andric                    options::OPT_nodefaultlibs)) {
298e8d8bef9SDimitry Andric     AddSspArgs(Args, CmdArgs);
299e8d8bef9SDimitry Andric     AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
300e8d8bef9SDimitry Andric     if (!Args.hasArg(options::OPT_nolibc)) {
301e8d8bef9SDimitry Andric       AddDefaultLibs(Args, CmdArgs);
302e8d8bef9SDimitry Andric       AddImplicitLinkerScript(D.SysRoot, Args, CmdArgs);
3030b57cec5SDimitry Andric     }
304e8d8bef9SDimitry Andric   }
3050b57cec5SDimitry Andric 
306e8d8bef9SDimitry Andric   if (UseStartAndEndFiles)
307e8d8bef9SDimitry Andric     AddEndFiles(UseExceptions, Args, CmdArgs);
308e8d8bef9SDimitry Andric 
3090b57cec5SDimitry Andric   CmdArgs.push_back("-o");
3100b57cec5SDimitry Andric   CmdArgs.push_back(Output.getFilename());
311e8d8bef9SDimitry Andric 
312e8d8bef9SDimitry Andric   Args.AddAllArgs(CmdArgs, options::OPT_T);
313e8d8bef9SDimitry Andric 
314e8d8bef9SDimitry Andric   C.addCommand(std::make_unique<Command>(
315e8d8bef9SDimitry Andric       JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
316e8d8bef9SDimitry Andric       CmdArgs, Inputs, Output));
3170b57cec5SDimitry Andric }
318