1 //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CrossWindows.h"
10 #include "CommonArgs.h"
11 #include "clang/Driver/Compilation.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/Options.h"
14 #include "clang/Driver/SanitizerArgs.h"
15 #include "llvm/Option/ArgList.h"
16 #include "llvm/Support/Path.h"
18 using namespace clang::driver
;
19 using namespace clang::driver::toolchains
;
21 using llvm::opt::ArgList
;
22 using llvm::opt::ArgStringList
;
24 void tools::CrossWindows::Assembler::ConstructJob(
25 Compilation
&C
, const JobAction
&JA
, const InputInfo
&Output
,
26 const InputInfoList
&Inputs
, const ArgList
&Args
,
27 const char *LinkingOutput
) const {
28 claimNoWarnArgs(Args
);
30 static_cast<const toolchains::CrossWindowsToolChain
&>(getToolChain());
31 ArgStringList CmdArgs
;
34 switch (TC
.getArch()) {
36 llvm_unreachable("unsupported architecture");
37 case llvm::Triple::arm
:
38 case llvm::Triple::thumb
:
39 case llvm::Triple::aarch64
:
41 case llvm::Triple::x86
:
42 CmdArgs
.push_back("--32");
44 case llvm::Triple::x86_64
:
45 CmdArgs
.push_back("--64");
49 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
51 CmdArgs
.push_back("-o");
52 CmdArgs
.push_back(Output
.getFilename());
54 for (const auto &Input
: Inputs
)
55 CmdArgs
.push_back(Input
.getFilename());
57 const std::string Assembler
= TC
.GetProgramPath("as");
58 Exec
= Args
.MakeArgString(Assembler
);
60 C
.addCommand(std::make_unique
<Command
>(JA
, *this, ResponseFileSupport::None(),
61 Exec
, CmdArgs
, Inputs
, Output
));
64 void tools::CrossWindows::Linker::ConstructJob(
65 Compilation
&C
, const JobAction
&JA
, const InputInfo
&Output
,
66 const InputInfoList
&Inputs
, const ArgList
&Args
,
67 const char *LinkingOutput
) const {
69 static_cast<const toolchains::CrossWindowsToolChain
&>(getToolChain());
70 const llvm::Triple
&T
= TC
.getTriple();
71 const Driver
&D
= TC
.getDriver();
72 SmallString
<128> EntryPoint
;
73 ArgStringList CmdArgs
;
76 // Silence warning for "clang -g foo.o -o foo"
77 Args
.ClaimAllArgs(options::OPT_g_Group
);
78 // and "clang -emit-llvm foo.o -o foo"
79 Args
.ClaimAllArgs(options::OPT_emit_llvm
);
80 // and for "clang -w foo.o -o foo"
81 Args
.ClaimAllArgs(options::OPT_w
);
82 // Other warning options are already handled somewhere else.
84 if (!D
.SysRoot
.empty())
85 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
87 if (Args
.hasArg(options::OPT_pie
))
88 CmdArgs
.push_back("-pie");
89 if (Args
.hasArg(options::OPT_rdynamic
))
90 CmdArgs
.push_back("-export-dynamic");
91 if (Args
.hasArg(options::OPT_s
))
92 CmdArgs
.push_back("--strip-all");
94 CmdArgs
.push_back("-m");
95 switch (TC
.getArch()) {
97 D
.Diag(diag::err_target_unknown_triple
) << TC
.getEffectiveTriple().str();
99 case llvm::Triple::arm
:
100 case llvm::Triple::thumb
:
101 // FIXME: this is incorrect for WinCE
102 CmdArgs
.push_back("thumb2pe");
104 case llvm::Triple::aarch64
:
105 CmdArgs
.push_back("arm64pe");
107 case llvm::Triple::x86
:
108 CmdArgs
.push_back("i386pe");
109 EntryPoint
.append("_");
111 case llvm::Triple::x86_64
:
112 CmdArgs
.push_back("i386pep");
116 if (Args
.hasArg(options::OPT_shared
)) {
117 switch (T
.getArch()) {
119 llvm_unreachable("unsupported architecture");
120 case llvm::Triple::aarch64
:
121 case llvm::Triple::arm
:
122 case llvm::Triple::thumb
:
123 case llvm::Triple::x86_64
:
124 EntryPoint
.append("_DllMainCRTStartup");
126 case llvm::Triple::x86
:
127 EntryPoint
.append("_DllMainCRTStartup@12");
131 CmdArgs
.push_back("-shared");
132 CmdArgs
.push_back(Args
.hasArg(options::OPT_static
) ? "-Bstatic"
135 CmdArgs
.push_back("--enable-auto-image-base");
137 CmdArgs
.push_back("--entry");
138 CmdArgs
.push_back(Args
.MakeArgString(EntryPoint
));
140 EntryPoint
.append("mainCRTStartup");
142 CmdArgs
.push_back(Args
.hasArg(options::OPT_static
) ? "-Bstatic"
145 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
)) {
146 CmdArgs
.push_back("--entry");
147 CmdArgs
.push_back(Args
.MakeArgString(EntryPoint
));
150 // FIXME: handle subsystem
153 // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
154 CmdArgs
.push_back("--allow-multiple-definition");
156 CmdArgs
.push_back("-o");
157 CmdArgs
.push_back(Output
.getFilename());
159 if (Args
.hasArg(options::OPT_shared
) || Args
.hasArg(options::OPT_rdynamic
)) {
160 SmallString
<261> ImpLib(Output
.getFilename());
161 llvm::sys::path::replace_extension(ImpLib
, ".lib");
163 CmdArgs
.push_back("--out-implib");
164 CmdArgs
.push_back(Args
.MakeArgString(ImpLib
));
167 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
168 TC
.AddFilePathLibArgs(Args
, CmdArgs
);
169 AddLinkerInputs(TC
, Inputs
, Args
, CmdArgs
, JA
);
171 if (TC
.ShouldLinkCXXStdlib(Args
)) {
172 bool StaticCXX
= Args
.hasArg(options::OPT_static_libstdcxx
) &&
173 !Args
.hasArg(options::OPT_static
);
175 CmdArgs
.push_back("-Bstatic");
176 TC
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
178 CmdArgs
.push_back("-Bdynamic");
181 if (!Args
.hasArg(options::OPT_nostdlib
)) {
182 if (!Args
.hasArg(options::OPT_nodefaultlibs
)) {
183 // TODO handle /MT[d] /MD[d]
184 CmdArgs
.push_back("-lmsvcrt");
185 AddRunTimeLibs(TC
, D
, CmdArgs
, Args
);
189 if (TC
.getSanitizerArgs(Args
).needsAsanRt()) {
190 // TODO handle /MT[d] /MD[d]
191 if (Args
.hasArg(options::OPT_shared
)) {
192 CmdArgs
.push_back(TC
.getCompilerRTArgString(Args
, "asan_dll_thunk"));
194 for (const auto &Lib
: {"asan_dynamic", "asan_dynamic_runtime_thunk"})
195 CmdArgs
.push_back(TC
.getCompilerRTArgString(Args
, Lib
));
196 // Make sure the dynamic runtime thunk is not optimized out at link time
197 // to ensure proper SEH handling.
198 CmdArgs
.push_back(Args
.MakeArgString("--undefined"));
199 CmdArgs
.push_back(Args
.MakeArgString(TC
.getArch() == llvm::Triple::x86
200 ? "___asan_seh_interceptor"
201 : "__asan_seh_interceptor"));
205 Exec
= Args
.MakeArgString(TC
.GetLinkerPath());
207 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
208 ResponseFileSupport::AtFileUTF8(),
209 Exec
, CmdArgs
, Inputs
, Output
));
212 CrossWindowsToolChain::CrossWindowsToolChain(const Driver
&D
,
213 const llvm::Triple
&T
,
214 const llvm::opt::ArgList
&Args
)
215 : Generic_GCC(D
, T
, Args
) {}
217 ToolChain::UnwindTableLevel
218 CrossWindowsToolChain::getDefaultUnwindTableLevel(const ArgList
&Args
) const {
219 // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
220 // not know how to emit them.
221 return getArch() == llvm::Triple::x86_64
? UnwindTableLevel::Asynchronous
: UnwindTableLevel::None
;
224 bool CrossWindowsToolChain::isPICDefault() const {
225 return getArch() == llvm::Triple::x86_64
;
228 bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList
&Args
) const {
229 return getArch() == llvm::Triple::x86_64
;
232 bool CrossWindowsToolChain::isPICDefaultForced() const {
233 return getArch() == llvm::Triple::x86_64
;
236 void CrossWindowsToolChain::
237 AddClangSystemIncludeArgs(const llvm::opt::ArgList
&DriverArgs
,
238 llvm::opt::ArgStringList
&CC1Args
) const {
239 const Driver
&D
= getDriver();
240 const std::string
&SysRoot
= D
.SysRoot
;
242 auto AddSystemAfterIncludes
= [&]() {
243 for (const auto &P
: DriverArgs
.getAllArgValues(options::OPT_isystem_after
))
244 addSystemInclude(DriverArgs
, CC1Args
, P
);
247 if (DriverArgs
.hasArg(options::OPT_nostdinc
)) {
248 AddSystemAfterIncludes();
252 addSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/local/include");
253 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
254 SmallString
<128> ResourceDir(D
.ResourceDir
);
255 llvm::sys::path::append(ResourceDir
, "include");
256 addSystemInclude(DriverArgs
, CC1Args
, ResourceDir
);
258 AddSystemAfterIncludes();
259 addExternCSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/include");
262 void CrossWindowsToolChain::
263 AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList
&DriverArgs
,
264 llvm::opt::ArgStringList
&CC1Args
) const {
265 const std::string
&SysRoot
= getDriver().SysRoot
;
267 if (DriverArgs
.hasArg(options::OPT_nostdinc
) ||
268 DriverArgs
.hasArg(options::OPT_nostdincxx
))
271 if (GetCXXStdlibType(DriverArgs
) == ToolChain::CST_Libcxx
)
272 addSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/include/c++/v1");
275 void CrossWindowsToolChain::
276 AddCXXStdlibLibArgs(const llvm::opt::ArgList
&Args
,
277 llvm::opt::ArgStringList
&CmdArgs
) const {
278 if (GetCXXStdlibType(Args
) == ToolChain::CST_Libcxx
) {
279 CmdArgs
.push_back("-lc++");
280 if (Args
.hasArg(options::OPT_fexperimental_library
))
281 CmdArgs
.push_back("-lc++experimental");
285 clang::SanitizerMask
CrossWindowsToolChain::getSupportedSanitizers() const {
286 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
287 Res
|= SanitizerKind::Address
;
288 Res
|= SanitizerKind::PointerCompare
;
289 Res
|= SanitizerKind::PointerSubtract
;
293 Tool
*CrossWindowsToolChain::buildLinker() const {
294 return new tools::CrossWindows::Linker(*this);
297 Tool
*CrossWindowsToolChain::buildAssembler() const {
298 return new tools::CrossWindows::Assembler(*this);