106f32e7eSjoerg //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg
906f32e7eSjoerg #include "CrossWindows.h"
1006f32e7eSjoerg #include "CommonArgs.h"
1106f32e7eSjoerg #include "clang/Driver/Compilation.h"
1206f32e7eSjoerg #include "clang/Driver/Driver.h"
1306f32e7eSjoerg #include "clang/Driver/Options.h"
1406f32e7eSjoerg #include "clang/Driver/SanitizerArgs.h"
1506f32e7eSjoerg #include "llvm/Option/ArgList.h"
1606f32e7eSjoerg #include "llvm/Support/Path.h"
1706f32e7eSjoerg
1806f32e7eSjoerg using namespace clang::driver;
1906f32e7eSjoerg using namespace clang::driver::toolchains;
2006f32e7eSjoerg
2106f32e7eSjoerg using llvm::opt::ArgList;
2206f32e7eSjoerg using llvm::opt::ArgStringList;
2306f32e7eSjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const2406f32e7eSjoerg void tools::CrossWindows::Assembler::ConstructJob(
2506f32e7eSjoerg Compilation &C, const JobAction &JA, const InputInfo &Output,
2606f32e7eSjoerg const InputInfoList &Inputs, const ArgList &Args,
2706f32e7eSjoerg const char *LinkingOutput) const {
2806f32e7eSjoerg claimNoWarnArgs(Args);
2906f32e7eSjoerg const auto &TC =
3006f32e7eSjoerg static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
3106f32e7eSjoerg ArgStringList CmdArgs;
3206f32e7eSjoerg const char *Exec;
3306f32e7eSjoerg
3406f32e7eSjoerg switch (TC.getArch()) {
3506f32e7eSjoerg default:
3606f32e7eSjoerg llvm_unreachable("unsupported architecture");
3706f32e7eSjoerg case llvm::Triple::arm:
3806f32e7eSjoerg case llvm::Triple::thumb:
3906f32e7eSjoerg case llvm::Triple::aarch64:
4006f32e7eSjoerg break;
4106f32e7eSjoerg case llvm::Triple::x86:
4206f32e7eSjoerg CmdArgs.push_back("--32");
4306f32e7eSjoerg break;
4406f32e7eSjoerg case llvm::Triple::x86_64:
4506f32e7eSjoerg CmdArgs.push_back("--64");
4606f32e7eSjoerg break;
4706f32e7eSjoerg }
4806f32e7eSjoerg
4906f32e7eSjoerg Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
5006f32e7eSjoerg
5106f32e7eSjoerg CmdArgs.push_back("-o");
5206f32e7eSjoerg CmdArgs.push_back(Output.getFilename());
5306f32e7eSjoerg
5406f32e7eSjoerg for (const auto &Input : Inputs)
5506f32e7eSjoerg CmdArgs.push_back(Input.getFilename());
5606f32e7eSjoerg
5706f32e7eSjoerg const std::string Assembler = TC.GetProgramPath("as");
5806f32e7eSjoerg Exec = Args.MakeArgString(Assembler);
5906f32e7eSjoerg
60*13fbcb42Sjoerg C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
61*13fbcb42Sjoerg Exec, CmdArgs, Inputs, Output));
6206f32e7eSjoerg }
6306f32e7eSjoerg
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const6406f32e7eSjoerg void tools::CrossWindows::Linker::ConstructJob(
6506f32e7eSjoerg Compilation &C, const JobAction &JA, const InputInfo &Output,
6606f32e7eSjoerg const InputInfoList &Inputs, const ArgList &Args,
6706f32e7eSjoerg const char *LinkingOutput) const {
6806f32e7eSjoerg const auto &TC =
6906f32e7eSjoerg static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
7006f32e7eSjoerg const llvm::Triple &T = TC.getTriple();
7106f32e7eSjoerg const Driver &D = TC.getDriver();
7206f32e7eSjoerg SmallString<128> EntryPoint;
7306f32e7eSjoerg ArgStringList CmdArgs;
7406f32e7eSjoerg const char *Exec;
7506f32e7eSjoerg
7606f32e7eSjoerg // Silence warning for "clang -g foo.o -o foo"
7706f32e7eSjoerg Args.ClaimAllArgs(options::OPT_g_Group);
7806f32e7eSjoerg // and "clang -emit-llvm foo.o -o foo"
7906f32e7eSjoerg Args.ClaimAllArgs(options::OPT_emit_llvm);
8006f32e7eSjoerg // and for "clang -w foo.o -o foo"
8106f32e7eSjoerg Args.ClaimAllArgs(options::OPT_w);
8206f32e7eSjoerg // Other warning options are already handled somewhere else.
8306f32e7eSjoerg
8406f32e7eSjoerg if (!D.SysRoot.empty())
8506f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
8606f32e7eSjoerg
8706f32e7eSjoerg if (Args.hasArg(options::OPT_pie))
8806f32e7eSjoerg CmdArgs.push_back("-pie");
8906f32e7eSjoerg if (Args.hasArg(options::OPT_rdynamic))
9006f32e7eSjoerg CmdArgs.push_back("-export-dynamic");
9106f32e7eSjoerg if (Args.hasArg(options::OPT_s))
9206f32e7eSjoerg CmdArgs.push_back("--strip-all");
9306f32e7eSjoerg
9406f32e7eSjoerg CmdArgs.push_back("-m");
9506f32e7eSjoerg switch (TC.getArch()) {
9606f32e7eSjoerg default:
9706f32e7eSjoerg llvm_unreachable("unsupported architecture");
9806f32e7eSjoerg case llvm::Triple::arm:
9906f32e7eSjoerg case llvm::Triple::thumb:
10006f32e7eSjoerg // FIXME: this is incorrect for WinCE
10106f32e7eSjoerg CmdArgs.push_back("thumb2pe");
10206f32e7eSjoerg break;
10306f32e7eSjoerg case llvm::Triple::aarch64:
10406f32e7eSjoerg CmdArgs.push_back("arm64pe");
10506f32e7eSjoerg break;
10606f32e7eSjoerg case llvm::Triple::x86:
10706f32e7eSjoerg CmdArgs.push_back("i386pe");
10806f32e7eSjoerg EntryPoint.append("_");
10906f32e7eSjoerg break;
11006f32e7eSjoerg case llvm::Triple::x86_64:
11106f32e7eSjoerg CmdArgs.push_back("i386pep");
11206f32e7eSjoerg break;
11306f32e7eSjoerg }
11406f32e7eSjoerg
11506f32e7eSjoerg if (Args.hasArg(options::OPT_shared)) {
11606f32e7eSjoerg switch (T.getArch()) {
11706f32e7eSjoerg default:
11806f32e7eSjoerg llvm_unreachable("unsupported architecture");
11906f32e7eSjoerg case llvm::Triple::aarch64:
12006f32e7eSjoerg case llvm::Triple::arm:
12106f32e7eSjoerg case llvm::Triple::thumb:
12206f32e7eSjoerg case llvm::Triple::x86_64:
12306f32e7eSjoerg EntryPoint.append("_DllMainCRTStartup");
12406f32e7eSjoerg break;
12506f32e7eSjoerg case llvm::Triple::x86:
12606f32e7eSjoerg EntryPoint.append("_DllMainCRTStartup@12");
12706f32e7eSjoerg break;
12806f32e7eSjoerg }
12906f32e7eSjoerg
13006f32e7eSjoerg CmdArgs.push_back("-shared");
13106f32e7eSjoerg CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
13206f32e7eSjoerg : "-Bdynamic");
13306f32e7eSjoerg
13406f32e7eSjoerg CmdArgs.push_back("--enable-auto-image-base");
13506f32e7eSjoerg
13606f32e7eSjoerg CmdArgs.push_back("--entry");
13706f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString(EntryPoint));
13806f32e7eSjoerg } else {
13906f32e7eSjoerg EntryPoint.append("mainCRTStartup");
14006f32e7eSjoerg
14106f32e7eSjoerg CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
14206f32e7eSjoerg : "-Bdynamic");
14306f32e7eSjoerg
14406f32e7eSjoerg if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
14506f32e7eSjoerg CmdArgs.push_back("--entry");
14606f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString(EntryPoint));
14706f32e7eSjoerg }
14806f32e7eSjoerg
14906f32e7eSjoerg // FIXME: handle subsystem
15006f32e7eSjoerg }
15106f32e7eSjoerg
15206f32e7eSjoerg // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
15306f32e7eSjoerg CmdArgs.push_back("--allow-multiple-definition");
15406f32e7eSjoerg
15506f32e7eSjoerg CmdArgs.push_back("-o");
15606f32e7eSjoerg CmdArgs.push_back(Output.getFilename());
15706f32e7eSjoerg
15806f32e7eSjoerg if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
15906f32e7eSjoerg SmallString<261> ImpLib(Output.getFilename());
16006f32e7eSjoerg llvm::sys::path::replace_extension(ImpLib, ".lib");
16106f32e7eSjoerg
16206f32e7eSjoerg CmdArgs.push_back("--out-implib");
16306f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString(ImpLib));
16406f32e7eSjoerg }
16506f32e7eSjoerg
16606f32e7eSjoerg Args.AddAllArgs(CmdArgs, options::OPT_L);
16706f32e7eSjoerg TC.AddFilePathLibArgs(Args, CmdArgs);
16806f32e7eSjoerg AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
16906f32e7eSjoerg
17006f32e7eSjoerg if (TC.ShouldLinkCXXStdlib(Args)) {
17106f32e7eSjoerg bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
17206f32e7eSjoerg !Args.hasArg(options::OPT_static);
17306f32e7eSjoerg if (StaticCXX)
17406f32e7eSjoerg CmdArgs.push_back("-Bstatic");
17506f32e7eSjoerg TC.AddCXXStdlibLibArgs(Args, CmdArgs);
17606f32e7eSjoerg if (StaticCXX)
17706f32e7eSjoerg CmdArgs.push_back("-Bdynamic");
17806f32e7eSjoerg }
17906f32e7eSjoerg
18006f32e7eSjoerg if (!Args.hasArg(options::OPT_nostdlib)) {
18106f32e7eSjoerg if (!Args.hasArg(options::OPT_nodefaultlibs)) {
18206f32e7eSjoerg // TODO handle /MT[d] /MD[d]
18306f32e7eSjoerg CmdArgs.push_back("-lmsvcrt");
18406f32e7eSjoerg AddRunTimeLibs(TC, D, CmdArgs, Args);
18506f32e7eSjoerg }
18606f32e7eSjoerg }
18706f32e7eSjoerg
18806f32e7eSjoerg if (TC.getSanitizerArgs().needsAsanRt()) {
18906f32e7eSjoerg // TODO handle /MT[d] /MD[d]
19006f32e7eSjoerg if (Args.hasArg(options::OPT_shared)) {
19106f32e7eSjoerg CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
19206f32e7eSjoerg } else {
19306f32e7eSjoerg for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
19406f32e7eSjoerg CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
19506f32e7eSjoerg // Make sure the dynamic runtime thunk is not optimized out at link time
19606f32e7eSjoerg // to ensure proper SEH handling.
19706f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString("--undefined"));
19806f32e7eSjoerg CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
19906f32e7eSjoerg ? "___asan_seh_interceptor"
20006f32e7eSjoerg : "__asan_seh_interceptor"));
20106f32e7eSjoerg }
20206f32e7eSjoerg }
20306f32e7eSjoerg
20406f32e7eSjoerg Exec = Args.MakeArgString(TC.GetLinkerPath());
20506f32e7eSjoerg
206*13fbcb42Sjoerg C.addCommand(std::make_unique<Command>(JA, *this,
207*13fbcb42Sjoerg ResponseFileSupport::AtFileUTF8(),
208*13fbcb42Sjoerg Exec, CmdArgs, Inputs, Output));
20906f32e7eSjoerg }
21006f32e7eSjoerg
CrossWindowsToolChain(const Driver & D,const llvm::Triple & T,const llvm::opt::ArgList & Args)21106f32e7eSjoerg CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
21206f32e7eSjoerg const llvm::Triple &T,
21306f32e7eSjoerg const llvm::opt::ArgList &Args)
21406f32e7eSjoerg : Generic_GCC(D, T, Args) {}
21506f32e7eSjoerg
IsUnwindTablesDefault(const ArgList & Args) const21606f32e7eSjoerg bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
21706f32e7eSjoerg // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
21806f32e7eSjoerg // not know how to emit them.
21906f32e7eSjoerg return getArch() == llvm::Triple::x86_64;
22006f32e7eSjoerg }
22106f32e7eSjoerg
isPICDefault() const22206f32e7eSjoerg bool CrossWindowsToolChain::isPICDefault() const {
22306f32e7eSjoerg return getArch() == llvm::Triple::x86_64;
22406f32e7eSjoerg }
22506f32e7eSjoerg
isPIEDefault() const22606f32e7eSjoerg bool CrossWindowsToolChain::isPIEDefault() const {
22706f32e7eSjoerg return getArch() == llvm::Triple::x86_64;
22806f32e7eSjoerg }
22906f32e7eSjoerg
isPICDefaultForced() const23006f32e7eSjoerg bool CrossWindowsToolChain::isPICDefaultForced() const {
23106f32e7eSjoerg return getArch() == llvm::Triple::x86_64;
23206f32e7eSjoerg }
23306f32e7eSjoerg
23406f32e7eSjoerg void CrossWindowsToolChain::
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const23506f32e7eSjoerg AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
23606f32e7eSjoerg llvm::opt::ArgStringList &CC1Args) const {
23706f32e7eSjoerg const Driver &D = getDriver();
23806f32e7eSjoerg const std::string &SysRoot = D.SysRoot;
23906f32e7eSjoerg
24006f32e7eSjoerg auto AddSystemAfterIncludes = [&]() {
24106f32e7eSjoerg for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
24206f32e7eSjoerg addSystemInclude(DriverArgs, CC1Args, P);
24306f32e7eSjoerg };
24406f32e7eSjoerg
24506f32e7eSjoerg if (DriverArgs.hasArg(options::OPT_nostdinc)) {
24606f32e7eSjoerg AddSystemAfterIncludes();
24706f32e7eSjoerg return;
24806f32e7eSjoerg }
24906f32e7eSjoerg
25006f32e7eSjoerg addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
25106f32e7eSjoerg if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
25206f32e7eSjoerg SmallString<128> ResourceDir(D.ResourceDir);
25306f32e7eSjoerg llvm::sys::path::append(ResourceDir, "include");
25406f32e7eSjoerg addSystemInclude(DriverArgs, CC1Args, ResourceDir);
25506f32e7eSjoerg }
25606f32e7eSjoerg AddSystemAfterIncludes();
25706f32e7eSjoerg addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
25806f32e7eSjoerg }
25906f32e7eSjoerg
26006f32e7eSjoerg void CrossWindowsToolChain::
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const26106f32e7eSjoerg AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
26206f32e7eSjoerg llvm::opt::ArgStringList &CC1Args) const {
26306f32e7eSjoerg const std::string &SysRoot = getDriver().SysRoot;
26406f32e7eSjoerg
26506f32e7eSjoerg if (DriverArgs.hasArg(options::OPT_nostdinc) ||
26606f32e7eSjoerg DriverArgs.hasArg(options::OPT_nostdincxx))
26706f32e7eSjoerg return;
26806f32e7eSjoerg
26906f32e7eSjoerg if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
27006f32e7eSjoerg addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
27106f32e7eSjoerg }
27206f32e7eSjoerg
27306f32e7eSjoerg void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const274*13fbcb42Sjoerg AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
275*13fbcb42Sjoerg llvm::opt::ArgStringList &CmdArgs) const {
276*13fbcb42Sjoerg if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
277*13fbcb42Sjoerg CmdArgs.push_back("-lc++");
27806f32e7eSjoerg }
27906f32e7eSjoerg
getSupportedSanitizers() const28006f32e7eSjoerg clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
28106f32e7eSjoerg SanitizerMask Res = ToolChain::getSupportedSanitizers();
28206f32e7eSjoerg Res |= SanitizerKind::Address;
28306f32e7eSjoerg Res |= SanitizerKind::PointerCompare;
28406f32e7eSjoerg Res |= SanitizerKind::PointerSubtract;
28506f32e7eSjoerg return Res;
28606f32e7eSjoerg }
28706f32e7eSjoerg
buildLinker() const28806f32e7eSjoerg Tool *CrossWindowsToolChain::buildLinker() const {
28906f32e7eSjoerg return new tools::CrossWindows::Linker(*this);
29006f32e7eSjoerg }
29106f32e7eSjoerg
buildAssembler() const29206f32e7eSjoerg Tool *CrossWindowsToolChain::buildAssembler() const {
29306f32e7eSjoerg return new tools::CrossWindows::Assembler(*this);
29406f32e7eSjoerg }
295