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 llvm_unreachable("unsupported architecture");
98 case llvm::Triple::arm
:
99 case llvm::Triple::thumb
:
100 // FIXME: this is incorrect for WinCE
101 CmdArgs
.push_back("thumb2pe");
103 case llvm::Triple::aarch64
:
104 CmdArgs
.push_back("arm64pe");
106 case llvm::Triple::x86
:
107 CmdArgs
.push_back("i386pe");
108 EntryPoint
.append("_");
110 case llvm::Triple::x86_64
:
111 CmdArgs
.push_back("i386pep");
115 if (Args
.hasArg(options::OPT_shared
)) {
116 switch (T
.getArch()) {
118 llvm_unreachable("unsupported architecture");
119 case llvm::Triple::aarch64
:
120 case llvm::Triple::arm
:
121 case llvm::Triple::thumb
:
122 case llvm::Triple::x86_64
:
123 EntryPoint
.append("_DllMainCRTStartup");
125 case llvm::Triple::x86
:
126 EntryPoint
.append("_DllMainCRTStartup@12");
130 CmdArgs
.push_back("-shared");
131 CmdArgs
.push_back(Args
.hasArg(options::OPT_static
) ? "-Bstatic"
134 CmdArgs
.push_back("--enable-auto-image-base");
136 CmdArgs
.push_back("--entry");
137 CmdArgs
.push_back(Args
.MakeArgString(EntryPoint
));
139 EntryPoint
.append("mainCRTStartup");
141 CmdArgs
.push_back(Args
.hasArg(options::OPT_static
) ? "-Bstatic"
144 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
)) {
145 CmdArgs
.push_back("--entry");
146 CmdArgs
.push_back(Args
.MakeArgString(EntryPoint
));
149 // FIXME: handle subsystem
152 // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
153 CmdArgs
.push_back("--allow-multiple-definition");
155 CmdArgs
.push_back("-o");
156 CmdArgs
.push_back(Output
.getFilename());
158 if (Args
.hasArg(options::OPT_shared
) || Args
.hasArg(options::OPT_rdynamic
)) {
159 SmallString
<261> ImpLib(Output
.getFilename());
160 llvm::sys::path::replace_extension(ImpLib
, ".lib");
162 CmdArgs
.push_back("--out-implib");
163 CmdArgs
.push_back(Args
.MakeArgString(ImpLib
));
166 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
167 TC
.AddFilePathLibArgs(Args
, CmdArgs
);
168 AddLinkerInputs(TC
, Inputs
, Args
, CmdArgs
, JA
);
170 if (TC
.ShouldLinkCXXStdlib(Args
)) {
171 bool StaticCXX
= Args
.hasArg(options::OPT_static_libstdcxx
) &&
172 !Args
.hasArg(options::OPT_static
);
174 CmdArgs
.push_back("-Bstatic");
175 TC
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
177 CmdArgs
.push_back("-Bdynamic");
180 if (!Args
.hasArg(options::OPT_nostdlib
)) {
181 if (!Args
.hasArg(options::OPT_nodefaultlibs
)) {
182 // TODO handle /MT[d] /MD[d]
183 CmdArgs
.push_back("-lmsvcrt");
184 AddRunTimeLibs(TC
, D
, CmdArgs
, Args
);
188 if (TC
.getSanitizerArgs(Args
).needsAsanRt()) {
189 // TODO handle /MT[d] /MD[d]
190 if (Args
.hasArg(options::OPT_shared
)) {
191 CmdArgs
.push_back(TC
.getCompilerRTArgString(Args
, "asan_dll_thunk"));
193 for (const auto &Lib
: {"asan_dynamic", "asan_dynamic_runtime_thunk"})
194 CmdArgs
.push_back(TC
.getCompilerRTArgString(Args
, Lib
));
195 // Make sure the dynamic runtime thunk is not optimized out at link time
196 // to ensure proper SEH handling.
197 CmdArgs
.push_back(Args
.MakeArgString("--undefined"));
198 CmdArgs
.push_back(Args
.MakeArgString(TC
.getArch() == llvm::Triple::x86
199 ? "___asan_seh_interceptor"
200 : "__asan_seh_interceptor"));
204 Exec
= Args
.MakeArgString(TC
.GetLinkerPath());
206 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
207 ResponseFileSupport::AtFileUTF8(),
208 Exec
, CmdArgs
, Inputs
, Output
));
211 CrossWindowsToolChain::CrossWindowsToolChain(const Driver
&D
,
212 const llvm::Triple
&T
,
213 const llvm::opt::ArgList
&Args
)
214 : Generic_GCC(D
, T
, Args
) {}
216 bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList
&Args
) const {
217 // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
218 // not know how to emit them.
219 return getArch() == llvm::Triple::x86_64
;
222 bool CrossWindowsToolChain::isPICDefault() const {
223 return getArch() == llvm::Triple::x86_64
;
226 bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList
&Args
) const {
227 return getArch() == llvm::Triple::x86_64
;
230 bool CrossWindowsToolChain::isPICDefaultForced() const {
231 return getArch() == llvm::Triple::x86_64
;
234 void CrossWindowsToolChain::
235 AddClangSystemIncludeArgs(const llvm::opt::ArgList
&DriverArgs
,
236 llvm::opt::ArgStringList
&CC1Args
) const {
237 const Driver
&D
= getDriver();
238 const std::string
&SysRoot
= D
.SysRoot
;
240 auto AddSystemAfterIncludes
= [&]() {
241 for (const auto &P
: DriverArgs
.getAllArgValues(options::OPT_isystem_after
))
242 addSystemInclude(DriverArgs
, CC1Args
, P
);
245 if (DriverArgs
.hasArg(options::OPT_nostdinc
)) {
246 AddSystemAfterIncludes();
250 addSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/local/include");
251 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
252 SmallString
<128> ResourceDir(D
.ResourceDir
);
253 llvm::sys::path::append(ResourceDir
, "include");
254 addSystemInclude(DriverArgs
, CC1Args
, ResourceDir
);
256 AddSystemAfterIncludes();
257 addExternCSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/include");
260 void CrossWindowsToolChain::
261 AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList
&DriverArgs
,
262 llvm::opt::ArgStringList
&CC1Args
) const {
263 const std::string
&SysRoot
= getDriver().SysRoot
;
265 if (DriverArgs
.hasArg(options::OPT_nostdinc
) ||
266 DriverArgs
.hasArg(options::OPT_nostdincxx
))
269 if (GetCXXStdlibType(DriverArgs
) == ToolChain::CST_Libcxx
)
270 addSystemInclude(DriverArgs
, CC1Args
, SysRoot
+ "/usr/include/c++/v1");
273 void CrossWindowsToolChain::
274 AddCXXStdlibLibArgs(const llvm::opt::ArgList
&Args
,
275 llvm::opt::ArgStringList
&CmdArgs
) const {
276 if (GetCXXStdlibType(Args
) == ToolChain::CST_Libcxx
) {
277 CmdArgs
.push_back("-lc++");
278 if (Args
.hasArg(options::OPT_fexperimental_library
))
279 CmdArgs
.push_back("-lc++experimental");
283 clang::SanitizerMask
CrossWindowsToolChain::getSupportedSanitizers() const {
284 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
285 Res
|= SanitizerKind::Address
;
286 Res
|= SanitizerKind::PointerCompare
;
287 Res
|= SanitizerKind::PointerSubtract
;
291 Tool
*CrossWindowsToolChain::buildLinker() const {
292 return new tools::CrossWindows::Linker(*this);
295 Tool
*CrossWindowsToolChain::buildAssembler() const {
296 return new tools::CrossWindows::Assembler(*this);