1524b3c18SFangrui Song //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
2f561ababSDavid L. Jones //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f561ababSDavid L. Jones //
7f561ababSDavid L. Jones //===----------------------------------------------------------------------===//
8f561ababSDavid L. Jones
9f561ababSDavid L. Jones #include "CrossWindows.h"
10f561ababSDavid L. Jones #include "CommonArgs.h"
11f561ababSDavid L. Jones #include "clang/Driver/Compilation.h"
12f561ababSDavid L. Jones #include "clang/Driver/Driver.h"
13f561ababSDavid L. Jones #include "clang/Driver/Options.h"
14f561ababSDavid L. Jones #include "clang/Driver/SanitizerArgs.h"
15f561ababSDavid L. Jones #include "llvm/Option/ArgList.h"
16f561ababSDavid L. Jones #include "llvm/Support/Path.h"
17f561ababSDavid L. Jones
18f561ababSDavid L. Jones using namespace clang::driver;
19f561ababSDavid L. Jones using namespace clang::driver::toolchains;
20f561ababSDavid L. Jones
21f561ababSDavid L. Jones using llvm::opt::ArgList;
220e50d4c4SSimon Pilgrim using llvm::opt::ArgStringList;
23f561ababSDavid L. Jones
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const24f561ababSDavid L. Jones void tools::CrossWindows::Assembler::ConstructJob(
25f561ababSDavid L. Jones Compilation &C, const JobAction &JA, const InputInfo &Output,
26f561ababSDavid L. Jones const InputInfoList &Inputs, const ArgList &Args,
27f561ababSDavid L. Jones const char *LinkingOutput) const {
28f561ababSDavid L. Jones claimNoWarnArgs(Args);
29f561ababSDavid L. Jones const auto &TC =
30f561ababSDavid L. Jones static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
31f561ababSDavid L. Jones ArgStringList CmdArgs;
32f561ababSDavid L. Jones const char *Exec;
33f561ababSDavid L. Jones
34f561ababSDavid L. Jones switch (TC.getArch()) {
35f561ababSDavid L. Jones default:
36f561ababSDavid L. Jones llvm_unreachable("unsupported architecture");
37f561ababSDavid L. Jones case llvm::Triple::arm:
38f561ababSDavid L. Jones case llvm::Triple::thumb:
3931cac7a6SMartin Storsjo case llvm::Triple::aarch64:
40f561ababSDavid L. Jones break;
41f561ababSDavid L. Jones case llvm::Triple::x86:
42f561ababSDavid L. Jones CmdArgs.push_back("--32");
43f561ababSDavid L. Jones break;
44f561ababSDavid L. Jones case llvm::Triple::x86_64:
45f561ababSDavid L. Jones CmdArgs.push_back("--64");
46f561ababSDavid L. Jones break;
47f561ababSDavid L. Jones }
48f561ababSDavid L. Jones
49f561ababSDavid L. Jones Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
50f561ababSDavid L. Jones
51f561ababSDavid L. Jones CmdArgs.push_back("-o");
52f561ababSDavid L. Jones CmdArgs.push_back(Output.getFilename());
53f561ababSDavid L. Jones
54f561ababSDavid L. Jones for (const auto &Input : Inputs)
55f561ababSDavid L. Jones CmdArgs.push_back(Input.getFilename());
56f561ababSDavid L. Jones
57f561ababSDavid L. Jones const std::string Assembler = TC.GetProgramPath("as");
58f561ababSDavid L. Jones Exec = Args.MakeArgString(Assembler);
59f561ababSDavid L. Jones
604772b99dSJames Y Knight C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
6170bf3507SSerge Pavlov Exec, CmdArgs, Inputs, Output));
62f561ababSDavid L. Jones }
63f561ababSDavid L. Jones
ConstructJob(Compilation & C,const JobAction & JA,const InputInfo & Output,const InputInfoList & Inputs,const ArgList & Args,const char * LinkingOutput) const64f561ababSDavid L. Jones void tools::CrossWindows::Linker::ConstructJob(
65f561ababSDavid L. Jones Compilation &C, const JobAction &JA, const InputInfo &Output,
66f561ababSDavid L. Jones const InputInfoList &Inputs, const ArgList &Args,
67f561ababSDavid L. Jones const char *LinkingOutput) const {
68f561ababSDavid L. Jones const auto &TC =
69f561ababSDavid L. Jones static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
70f561ababSDavid L. Jones const llvm::Triple &T = TC.getTriple();
71f561ababSDavid L. Jones const Driver &D = TC.getDriver();
72f561ababSDavid L. Jones SmallString<128> EntryPoint;
73f561ababSDavid L. Jones ArgStringList CmdArgs;
74f561ababSDavid L. Jones const char *Exec;
75f561ababSDavid L. Jones
76f561ababSDavid L. Jones // Silence warning for "clang -g foo.o -o foo"
77f561ababSDavid L. Jones Args.ClaimAllArgs(options::OPT_g_Group);
78f561ababSDavid L. Jones // and "clang -emit-llvm foo.o -o foo"
79f561ababSDavid L. Jones Args.ClaimAllArgs(options::OPT_emit_llvm);
80f561ababSDavid L. Jones // and for "clang -w foo.o -o foo"
81f561ababSDavid L. Jones Args.ClaimAllArgs(options::OPT_w);
82f561ababSDavid L. Jones // Other warning options are already handled somewhere else.
83f561ababSDavid L. Jones
84f561ababSDavid L. Jones if (!D.SysRoot.empty())
85f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
86f561ababSDavid L. Jones
87f561ababSDavid L. Jones if (Args.hasArg(options::OPT_pie))
88f561ababSDavid L. Jones CmdArgs.push_back("-pie");
89f561ababSDavid L. Jones if (Args.hasArg(options::OPT_rdynamic))
90f561ababSDavid L. Jones CmdArgs.push_back("-export-dynamic");
91f561ababSDavid L. Jones if (Args.hasArg(options::OPT_s))
92f561ababSDavid L. Jones CmdArgs.push_back("--strip-all");
93f561ababSDavid L. Jones
94f561ababSDavid L. Jones CmdArgs.push_back("-m");
95f561ababSDavid L. Jones switch (TC.getArch()) {
96f561ababSDavid L. Jones default:
97*ecad1210SKOMATA Manabu D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
98*ecad1210SKOMATA Manabu break;
99f561ababSDavid L. Jones case llvm::Triple::arm:
100f561ababSDavid L. Jones case llvm::Triple::thumb:
101f561ababSDavid L. Jones // FIXME: this is incorrect for WinCE
102f561ababSDavid L. Jones CmdArgs.push_back("thumb2pe");
103f561ababSDavid L. Jones break;
10431cac7a6SMartin Storsjo case llvm::Triple::aarch64:
10531cac7a6SMartin Storsjo CmdArgs.push_back("arm64pe");
10631cac7a6SMartin Storsjo break;
107f561ababSDavid L. Jones case llvm::Triple::x86:
108f561ababSDavid L. Jones CmdArgs.push_back("i386pe");
109f561ababSDavid L. Jones EntryPoint.append("_");
110f561ababSDavid L. Jones break;
111f561ababSDavid L. Jones case llvm::Triple::x86_64:
112f561ababSDavid L. Jones CmdArgs.push_back("i386pep");
113f561ababSDavid L. Jones break;
114f561ababSDavid L. Jones }
115f561ababSDavid L. Jones
116f561ababSDavid L. Jones if (Args.hasArg(options::OPT_shared)) {
117f561ababSDavid L. Jones switch (T.getArch()) {
118f561ababSDavid L. Jones default:
119f561ababSDavid L. Jones llvm_unreachable("unsupported architecture");
12031cac7a6SMartin Storsjo case llvm::Triple::aarch64:
121f561ababSDavid L. Jones case llvm::Triple::arm:
122f561ababSDavid L. Jones case llvm::Triple::thumb:
123f561ababSDavid L. Jones case llvm::Triple::x86_64:
124f561ababSDavid L. Jones EntryPoint.append("_DllMainCRTStartup");
125f561ababSDavid L. Jones break;
126f561ababSDavid L. Jones case llvm::Triple::x86:
127f561ababSDavid L. Jones EntryPoint.append("_DllMainCRTStartup@12");
128f561ababSDavid L. Jones break;
129f561ababSDavid L. Jones }
130f561ababSDavid L. Jones
131f561ababSDavid L. Jones CmdArgs.push_back("-shared");
132ca4a24ebSMartin Storsjo CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
133ca4a24ebSMartin Storsjo : "-Bdynamic");
134f561ababSDavid L. Jones
135f561ababSDavid L. Jones CmdArgs.push_back("--enable-auto-image-base");
136f561ababSDavid L. Jones
137f561ababSDavid L. Jones CmdArgs.push_back("--entry");
138f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString(EntryPoint));
139f561ababSDavid L. Jones } else {
140f561ababSDavid L. Jones EntryPoint.append("mainCRTStartup");
141f561ababSDavid L. Jones
142f561ababSDavid L. Jones CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
143f561ababSDavid L. Jones : "-Bdynamic");
144f561ababSDavid L. Jones
145f561ababSDavid L. Jones if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
146f561ababSDavid L. Jones CmdArgs.push_back("--entry");
147f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString(EntryPoint));
148f561ababSDavid L. Jones }
149f561ababSDavid L. Jones
150f561ababSDavid L. Jones // FIXME: handle subsystem
151f561ababSDavid L. Jones }
152f561ababSDavid L. Jones
153f561ababSDavid L. Jones // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
154f561ababSDavid L. Jones CmdArgs.push_back("--allow-multiple-definition");
155f561ababSDavid L. Jones
156f561ababSDavid L. Jones CmdArgs.push_back("-o");
157f561ababSDavid L. Jones CmdArgs.push_back(Output.getFilename());
158f561ababSDavid L. Jones
159f561ababSDavid L. Jones if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
160f561ababSDavid L. Jones SmallString<261> ImpLib(Output.getFilename());
161f561ababSDavid L. Jones llvm::sys::path::replace_extension(ImpLib, ".lib");
162f561ababSDavid L. Jones
163f561ababSDavid L. Jones CmdArgs.push_back("--out-implib");
164f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString(ImpLib));
165f561ababSDavid L. Jones }
166f561ababSDavid L. Jones
167f561ababSDavid L. Jones Args.AddAllArgs(CmdArgs, options::OPT_L);
168f561ababSDavid L. Jones TC.AddFilePathLibArgs(Args, CmdArgs);
169f561ababSDavid L. Jones AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
170f561ababSDavid L. Jones
1710ee47d92SNico Weber if (TC.ShouldLinkCXXStdlib(Args)) {
172f561ababSDavid L. Jones bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
173f561ababSDavid L. Jones !Args.hasArg(options::OPT_static);
174f561ababSDavid L. Jones if (StaticCXX)
175f561ababSDavid L. Jones CmdArgs.push_back("-Bstatic");
176f561ababSDavid L. Jones TC.AddCXXStdlibLibArgs(Args, CmdArgs);
177f561ababSDavid L. Jones if (StaticCXX)
178f561ababSDavid L. Jones CmdArgs.push_back("-Bdynamic");
179f561ababSDavid L. Jones }
180f561ababSDavid L. Jones
181f561ababSDavid L. Jones if (!Args.hasArg(options::OPT_nostdlib)) {
182f561ababSDavid L. Jones if (!Args.hasArg(options::OPT_nodefaultlibs)) {
183f561ababSDavid L. Jones // TODO handle /MT[d] /MD[d]
184f561ababSDavid L. Jones CmdArgs.push_back("-lmsvcrt");
185f561ababSDavid L. Jones AddRunTimeLibs(TC, D, CmdArgs, Args);
186f561ababSDavid L. Jones }
187f561ababSDavid L. Jones }
188f561ababSDavid L. Jones
1890309e50fSYaxun (Sam) Liu if (TC.getSanitizerArgs(Args).needsAsanRt()) {
190f561ababSDavid L. Jones // TODO handle /MT[d] /MD[d]
191f561ababSDavid L. Jones if (Args.hasArg(options::OPT_shared)) {
192f561ababSDavid L. Jones CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
193f561ababSDavid L. Jones } else {
194f561ababSDavid L. Jones for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
195f561ababSDavid L. Jones CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
196f561ababSDavid L. Jones // Make sure the dynamic runtime thunk is not optimized out at link time
197f561ababSDavid L. Jones // to ensure proper SEH handling.
198f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString("--undefined"));
199f561ababSDavid L. Jones CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
200f561ababSDavid L. Jones ? "___asan_seh_interceptor"
201f561ababSDavid L. Jones : "__asan_seh_interceptor"));
202f561ababSDavid L. Jones }
203f561ababSDavid L. Jones }
204f561ababSDavid L. Jones
205f561ababSDavid L. Jones Exec = Args.MakeArgString(TC.GetLinkerPath());
206f561ababSDavid L. Jones
20770bf3507SSerge Pavlov C.addCommand(std::make_unique<Command>(JA, *this,
20870bf3507SSerge Pavlov ResponseFileSupport::AtFileUTF8(),
20970bf3507SSerge Pavlov Exec, CmdArgs, Inputs, Output));
210f561ababSDavid L. Jones }
211f561ababSDavid L. Jones
CrossWindowsToolChain(const Driver & D,const llvm::Triple & T,const llvm::opt::ArgList & Args)212f561ababSDavid L. Jones CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
213f561ababSDavid L. Jones const llvm::Triple &T,
214f561ababSDavid L. Jones const llvm::opt::ArgList &Args)
21583e2838dSSaleem Abdulrasool : Generic_GCC(D, T, Args) {}
216f561ababSDavid L. Jones
2174388b56dSTim Northover ToolChain::UnwindTableLevel
getDefaultUnwindTableLevel(const ArgList & Args) const2184388b56dSTim Northover CrossWindowsToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
219f561ababSDavid L. Jones // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
220f561ababSDavid L. Jones // not know how to emit them.
2214388b56dSTim Northover return getArch() == llvm::Triple::x86_64 ? UnwindTableLevel::Asynchronous : UnwindTableLevel::None;
222f561ababSDavid L. Jones }
223f561ababSDavid L. Jones
isPICDefault() const224f561ababSDavid L. Jones bool CrossWindowsToolChain::isPICDefault() const {
225f561ababSDavid L. Jones return getArch() == llvm::Triple::x86_64;
226f561ababSDavid L. Jones }
227f561ababSDavid L. Jones
isPIEDefault(const llvm::opt::ArgList & Args) const2280309e50fSYaxun (Sam) Liu bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
229f561ababSDavid L. Jones return getArch() == llvm::Triple::x86_64;
230f561ababSDavid L. Jones }
231f561ababSDavid L. Jones
isPICDefaultForced() const232f561ababSDavid L. Jones bool CrossWindowsToolChain::isPICDefaultForced() const {
233f561ababSDavid L. Jones return getArch() == llvm::Triple::x86_64;
234f561ababSDavid L. Jones }
235f561ababSDavid L. Jones
236f561ababSDavid L. Jones void CrossWindowsToolChain::
AddClangSystemIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const237f561ababSDavid L. Jones AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
238f561ababSDavid L. Jones llvm::opt::ArgStringList &CC1Args) const {
239f561ababSDavid L. Jones const Driver &D = getDriver();
240f561ababSDavid L. Jones const std::string &SysRoot = D.SysRoot;
241f561ababSDavid L. Jones
242a517a0a5SSaleem Abdulrasool auto AddSystemAfterIncludes = [&]() {
243a517a0a5SSaleem Abdulrasool for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
244a517a0a5SSaleem Abdulrasool addSystemInclude(DriverArgs, CC1Args, P);
245a517a0a5SSaleem Abdulrasool };
246a517a0a5SSaleem Abdulrasool
247a517a0a5SSaleem Abdulrasool if (DriverArgs.hasArg(options::OPT_nostdinc)) {
248a517a0a5SSaleem Abdulrasool AddSystemAfterIncludes();
249f561ababSDavid L. Jones return;
250a517a0a5SSaleem Abdulrasool }
251f561ababSDavid L. Jones
252f561ababSDavid L. Jones addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
253f561ababSDavid L. Jones if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
254f561ababSDavid L. Jones SmallString<128> ResourceDir(D.ResourceDir);
255f561ababSDavid L. Jones llvm::sys::path::append(ResourceDir, "include");
256f561ababSDavid L. Jones addSystemInclude(DriverArgs, CC1Args, ResourceDir);
257f561ababSDavid L. Jones }
258a517a0a5SSaleem Abdulrasool AddSystemAfterIncludes();
259f561ababSDavid L. Jones addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
260f561ababSDavid L. Jones }
261f561ababSDavid L. Jones
262f561ababSDavid L. Jones void CrossWindowsToolChain::
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList & DriverArgs,llvm::opt::ArgStringList & CC1Args) const263f561ababSDavid L. Jones AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
264f561ababSDavid L. Jones llvm::opt::ArgStringList &CC1Args) const {
265f561ababSDavid L. Jones const std::string &SysRoot = getDriver().SysRoot;
266f561ababSDavid L. Jones
267a517a0a5SSaleem Abdulrasool if (DriverArgs.hasArg(options::OPT_nostdinc) ||
268f561ababSDavid L. Jones DriverArgs.hasArg(options::OPT_nostdincxx))
269f561ababSDavid L. Jones return;
270f561ababSDavid L. Jones
27183e2838dSSaleem Abdulrasool if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
272f561ababSDavid L. Jones addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
273f561ababSDavid L. Jones }
274f561ababSDavid L. Jones
275f561ababSDavid L. Jones void CrossWindowsToolChain::
AddCXXStdlibLibArgs(const llvm::opt::ArgList & Args,llvm::opt::ArgStringList & CmdArgs) const2760627140cSSimon Pilgrim AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
2770627140cSSimon Pilgrim llvm::opt::ArgStringList &CmdArgs) const {
278ca495e36SLouis Dionne if (GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) {
2790627140cSSimon Pilgrim CmdArgs.push_back("-lc++");
280ca495e36SLouis Dionne if (Args.hasArg(options::OPT_fexperimental_library))
281ca495e36SLouis Dionne CmdArgs.push_back("-lc++experimental");
282ca495e36SLouis Dionne }
283f561ababSDavid L. Jones }
284f561ababSDavid L. Jones
getSupportedSanitizers() const285f561ababSDavid L. Jones clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
286f561ababSDavid L. Jones SanitizerMask Res = ToolChain::getSupportedSanitizers();
287f561ababSDavid L. Jones Res |= SanitizerKind::Address;
2881e39fc1fSPierre Gousseau Res |= SanitizerKind::PointerCompare;
2891e39fc1fSPierre Gousseau Res |= SanitizerKind::PointerSubtract;
290f561ababSDavid L. Jones return Res;
291f561ababSDavid L. Jones }
292f561ababSDavid L. Jones
buildLinker() const293f561ababSDavid L. Jones Tool *CrossWindowsToolChain::buildLinker() const {
294f561ababSDavid L. Jones return new tools::CrossWindows::Linker(*this);
295f561ababSDavid L. Jones }
296f561ababSDavid L. Jones
buildAssembler() const297f561ababSDavid L. Jones Tool *CrossWindowsToolChain::buildAssembler() const {
298f561ababSDavid L. Jones return new tools::CrossWindows::Assembler(*this);
299f561ababSDavid L. Jones }
300