10b57cec5SDimitry Andric //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
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 "CrossWindows.h"
100b57cec5SDimitry Andric #include "CommonArgs.h"
110b57cec5SDimitry Andric #include "clang/Driver/Compilation.h"
120b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
130b57cec5SDimitry Andric #include "clang/Driver/Options.h"
140b57cec5SDimitry Andric #include "clang/Driver/SanitizerArgs.h"
150b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
160b57cec5SDimitry Andric #include "llvm/Support/Path.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace clang::driver;
190b57cec5SDimitry Andric using namespace clang::driver::toolchains;
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric using llvm::opt::ArgList;
220b57cec5SDimitry Andric using llvm::opt::ArgStringList;
230b57cec5SDimitry Andric
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const240b57cec5SDimitry Andric void tools::CrossWindows::Assembler::ConstructJob(
250b57cec5SDimitry Andric Compilation &C, const JobAction &JA, const InputInfo &Output,
260b57cec5SDimitry Andric const InputInfoList &Inputs, const ArgList &Args,
270b57cec5SDimitry Andric const char *LinkingOutput) const {
280b57cec5SDimitry Andric claimNoWarnArgs(Args);
290b57cec5SDimitry Andric const auto &TC =
300b57cec5SDimitry Andric static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
310b57cec5SDimitry Andric ArgStringList CmdArgs;
320b57cec5SDimitry Andric const char *Exec;
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric switch (TC.getArch()) {
350b57cec5SDimitry Andric default:
360b57cec5SDimitry Andric llvm_unreachable("unsupported architecture");
370b57cec5SDimitry Andric case llvm::Triple::arm:
380b57cec5SDimitry Andric case llvm::Triple::thumb:
390b57cec5SDimitry Andric case llvm::Triple::aarch64:
400b57cec5SDimitry Andric break;
410b57cec5SDimitry Andric case llvm::Triple::x86:
420b57cec5SDimitry Andric CmdArgs.push_back("--32");
430b57cec5SDimitry Andric break;
440b57cec5SDimitry Andric case llvm::Triple::x86_64:
450b57cec5SDimitry Andric CmdArgs.push_back("--64");
460b57cec5SDimitry Andric break;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric CmdArgs.push_back("-o");
520b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename());
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric for (const auto &Input : Inputs)
550b57cec5SDimitry Andric CmdArgs.push_back(Input.getFilename());
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric const std::string Assembler = TC.GetProgramPath("as");
580b57cec5SDimitry Andric Exec = Args.MakeArgString(Assembler);
590b57cec5SDimitry Andric
605ffd83dbSDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
61e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output));
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const640b57cec5SDimitry Andric void tools::CrossWindows::Linker::ConstructJob(
650b57cec5SDimitry Andric Compilation &C, const JobAction &JA, const InputInfo &Output,
660b57cec5SDimitry Andric const InputInfoList &Inputs, const ArgList &Args,
670b57cec5SDimitry Andric const char *LinkingOutput) const {
680b57cec5SDimitry Andric const auto &TC =
690b57cec5SDimitry Andric static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
700b57cec5SDimitry Andric const llvm::Triple &T = TC.getTriple();
710b57cec5SDimitry Andric const Driver &D = TC.getDriver();
720b57cec5SDimitry Andric SmallString<128> EntryPoint;
730b57cec5SDimitry Andric ArgStringList CmdArgs;
740b57cec5SDimitry Andric const char *Exec;
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric // Silence warning for "clang -g foo.o -o foo"
770b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_g_Group);
780b57cec5SDimitry Andric // and "clang -emit-llvm foo.o -o foo"
790b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_emit_llvm);
800b57cec5SDimitry Andric // and for "clang -w foo.o -o foo"
810b57cec5SDimitry Andric Args.ClaimAllArgs(options::OPT_w);
820b57cec5SDimitry Andric // Other warning options are already handled somewhere else.
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric if (!D.SysRoot.empty())
850b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric if (Args.hasArg(options::OPT_pie))
880b57cec5SDimitry Andric CmdArgs.push_back("-pie");
890b57cec5SDimitry Andric if (Args.hasArg(options::OPT_rdynamic))
900b57cec5SDimitry Andric CmdArgs.push_back("-export-dynamic");
910b57cec5SDimitry Andric if (Args.hasArg(options::OPT_s))
920b57cec5SDimitry Andric CmdArgs.push_back("--strip-all");
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric CmdArgs.push_back("-m");
950b57cec5SDimitry Andric switch (TC.getArch()) {
960b57cec5SDimitry Andric default:
97*06c3fb27SDimitry Andric D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
98*06c3fb27SDimitry Andric break;
990b57cec5SDimitry Andric case llvm::Triple::arm:
1000b57cec5SDimitry Andric case llvm::Triple::thumb:
1010b57cec5SDimitry Andric // FIXME: this is incorrect for WinCE
1020b57cec5SDimitry Andric CmdArgs.push_back("thumb2pe");
1030b57cec5SDimitry Andric break;
1040b57cec5SDimitry Andric case llvm::Triple::aarch64:
1050b57cec5SDimitry Andric CmdArgs.push_back("arm64pe");
1060b57cec5SDimitry Andric break;
1070b57cec5SDimitry Andric case llvm::Triple::x86:
1080b57cec5SDimitry Andric CmdArgs.push_back("i386pe");
1090b57cec5SDimitry Andric EntryPoint.append("_");
1100b57cec5SDimitry Andric break;
1110b57cec5SDimitry Andric case llvm::Triple::x86_64:
1120b57cec5SDimitry Andric CmdArgs.push_back("i386pep");
1130b57cec5SDimitry Andric break;
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric
1160b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) {
1170b57cec5SDimitry Andric switch (T.getArch()) {
1180b57cec5SDimitry Andric default:
1190b57cec5SDimitry Andric llvm_unreachable("unsupported architecture");
1200b57cec5SDimitry Andric case llvm::Triple::aarch64:
1210b57cec5SDimitry Andric case llvm::Triple::arm:
1220b57cec5SDimitry Andric case llvm::Triple::thumb:
1230b57cec5SDimitry Andric case llvm::Triple::x86_64:
1240b57cec5SDimitry Andric EntryPoint.append("_DllMainCRTStartup");
1250b57cec5SDimitry Andric break;
1260b57cec5SDimitry Andric case llvm::Triple::x86:
1270b57cec5SDimitry Andric EntryPoint.append("_DllMainCRTStartup@12");
1280b57cec5SDimitry Andric break;
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric CmdArgs.push_back("-shared");
1320b57cec5SDimitry Andric CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
1330b57cec5SDimitry Andric : "-Bdynamic");
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric CmdArgs.push_back("--enable-auto-image-base");
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric CmdArgs.push_back("--entry");
1380b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(EntryPoint));
1390b57cec5SDimitry Andric } else {
1400b57cec5SDimitry Andric EntryPoint.append("mainCRTStartup");
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
1430b57cec5SDimitry Andric : "-Bdynamic");
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
1460b57cec5SDimitry Andric CmdArgs.push_back("--entry");
1470b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(EntryPoint));
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric // FIXME: handle subsystem
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
1540b57cec5SDimitry Andric CmdArgs.push_back("--allow-multiple-definition");
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric CmdArgs.push_back("-o");
1570b57cec5SDimitry Andric CmdArgs.push_back(Output.getFilename());
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
1600b57cec5SDimitry Andric SmallString<261> ImpLib(Output.getFilename());
1610b57cec5SDimitry Andric llvm::sys::path::replace_extension(ImpLib, ".lib");
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric CmdArgs.push_back("--out-implib");
1640b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(ImpLib));
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric Args.AddAllArgs(CmdArgs, options::OPT_L);
1680b57cec5SDimitry Andric TC.AddFilePathLibArgs(Args, CmdArgs);
1690b57cec5SDimitry Andric AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric if (TC.ShouldLinkCXXStdlib(Args)) {
1720b57cec5SDimitry Andric bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
1730b57cec5SDimitry Andric !Args.hasArg(options::OPT_static);
1740b57cec5SDimitry Andric if (StaticCXX)
1750b57cec5SDimitry Andric CmdArgs.push_back("-Bstatic");
1760b57cec5SDimitry Andric TC.AddCXXStdlibLibArgs(Args, CmdArgs);
1770b57cec5SDimitry Andric if (StaticCXX)
1780b57cec5SDimitry Andric CmdArgs.push_back("-Bdynamic");
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nostdlib)) {
1820b57cec5SDimitry Andric if (!Args.hasArg(options::OPT_nodefaultlibs)) {
1830b57cec5SDimitry Andric // TODO handle /MT[d] /MD[d]
1840b57cec5SDimitry Andric CmdArgs.push_back("-lmsvcrt");
1850b57cec5SDimitry Andric AddRunTimeLibs(TC, D, CmdArgs, Args);
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
189349cc55cSDimitry Andric if (TC.getSanitizerArgs(Args).needsAsanRt()) {
1900b57cec5SDimitry Andric // TODO handle /MT[d] /MD[d]
1910b57cec5SDimitry Andric if (Args.hasArg(options::OPT_shared)) {
1920b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
1930b57cec5SDimitry Andric } else {
1940b57cec5SDimitry Andric for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
1950b57cec5SDimitry Andric CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
1960b57cec5SDimitry Andric // Make sure the dynamic runtime thunk is not optimized out at link time
1970b57cec5SDimitry Andric // to ensure proper SEH handling.
1980b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString("--undefined"));
1990b57cec5SDimitry Andric CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
2000b57cec5SDimitry Andric ? "___asan_seh_interceptor"
2010b57cec5SDimitry Andric : "__asan_seh_interceptor"));
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric Exec = Args.MakeArgString(TC.GetLinkerPath());
2060b57cec5SDimitry Andric
207e8d8bef9SDimitry Andric C.addCommand(std::make_unique<Command>(JA, *this,
208e8d8bef9SDimitry Andric ResponseFileSupport::AtFileUTF8(),
209e8d8bef9SDimitry Andric Exec, CmdArgs, Inputs, Output));
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
CrossWindowsToolChain(const Driver & D,const llvm::Triple & T,const llvm::opt::ArgList & Args)2120b57cec5SDimitry Andric CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
2130b57cec5SDimitry Andric const llvm::Triple &T,
2140b57cec5SDimitry Andric const llvm::opt::ArgList &Args)
2150b57cec5SDimitry Andric : Generic_GCC(D, T, Args) {}
2160b57cec5SDimitry Andric
217bdd1243dSDimitry Andric ToolChain::UnwindTableLevel
getDefaultUnwindTableLevel(const ArgList & Args) const218bdd1243dSDimitry Andric CrossWindowsToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
2190b57cec5SDimitry Andric // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
2200b57cec5SDimitry Andric // not know how to emit them.
221bdd1243dSDimitry Andric return getArch() == llvm::Triple::x86_64 ? UnwindTableLevel::Asynchronous : UnwindTableLevel::None;
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
isPICDefault() const2240b57cec5SDimitry Andric bool CrossWindowsToolChain::isPICDefault() const {
2250b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64;
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
isPIEDefault(const llvm::opt::ArgList & Args) const228349cc55cSDimitry Andric bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
2290b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric
isPICDefaultForced() const2320b57cec5SDimitry Andric bool CrossWindowsToolChain::isPICDefaultForced() const {
2330b57cec5SDimitry Andric return getArch() == llvm::Triple::x86_64;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric void CrossWindowsToolChain::
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const2370b57cec5SDimitry Andric AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2380b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args) const {
2390b57cec5SDimitry Andric const Driver &D = getDriver();
2400b57cec5SDimitry Andric const std::string &SysRoot = D.SysRoot;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric auto AddSystemAfterIncludes = [&]() {
2430b57cec5SDimitry Andric for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
2440b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, P);
2450b57cec5SDimitry Andric };
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc)) {
2480b57cec5SDimitry Andric AddSystemAfterIncludes();
2490b57cec5SDimitry Andric return;
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
2530b57cec5SDimitry Andric if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
2540b57cec5SDimitry Andric SmallString<128> ResourceDir(D.ResourceDir);
2550b57cec5SDimitry Andric llvm::sys::path::append(ResourceDir, "include");
2560b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, ResourceDir);
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric AddSystemAfterIncludes();
2590b57cec5SDimitry Andric addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric void CrossWindowsToolChain::
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const2630b57cec5SDimitry Andric AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
2640b57cec5SDimitry Andric llvm::opt::ArgStringList &CC1Args) const {
2650b57cec5SDimitry Andric const std::string &SysRoot = getDriver().SysRoot;
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric if (DriverArgs.hasArg(options::OPT_nostdinc) ||
2680b57cec5SDimitry Andric DriverArgs.hasArg(options::OPT_nostdincxx))
2690b57cec5SDimitry Andric return;
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
2720b57cec5SDimitry Andric addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const276e8d8bef9SDimitry Andric AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
277e8d8bef9SDimitry Andric llvm::opt::ArgStringList &CmdArgs) const {
278fcaf7f86SDimitry Andric if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
279e8d8bef9SDimitry Andric CmdArgs.push_back("-lc++");
280fcaf7f86SDimitry Andric if (Args.hasArg(options::OPT_fexperimental_library))
281fcaf7f86SDimitry Andric CmdArgs.push_back("-lc++experimental");
282fcaf7f86SDimitry Andric }
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric
getSupportedSanitizers() const2850b57cec5SDimitry Andric clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
2860b57cec5SDimitry Andric SanitizerMask Res = ToolChain::getSupportedSanitizers();
2870b57cec5SDimitry Andric Res |= SanitizerKind::Address;
2880b57cec5SDimitry Andric Res |= SanitizerKind::PointerCompare;
2890b57cec5SDimitry Andric Res |= SanitizerKind::PointerSubtract;
2900b57cec5SDimitry Andric return Res;
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
buildLinker() const2930b57cec5SDimitry Andric Tool *CrossWindowsToolChain::buildLinker() const {
2940b57cec5SDimitry Andric return new tools::CrossWindows::Linker(*this);
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
buildAssembler() const2970b57cec5SDimitry Andric Tool *CrossWindowsToolChain::buildAssembler() const {
2980b57cec5SDimitry Andric return new tools::CrossWindows::Assembler(*this);
2990b57cec5SDimitry Andric }
300