Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/CrossWindows.cpp
35294 views
1
//===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
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"
17
18
using namespace clang::driver;
19
using namespace clang::driver::toolchains;
20
21
using llvm::opt::ArgList;
22
using llvm::opt::ArgStringList;
23
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);
29
const auto &TC =
30
static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
31
ArgStringList CmdArgs;
32
const char *Exec;
33
34
switch (TC.getArch()) {
35
default:
36
llvm_unreachable("unsupported architecture");
37
case llvm::Triple::arm:
38
case llvm::Triple::thumb:
39
case llvm::Triple::aarch64:
40
break;
41
case llvm::Triple::x86:
42
CmdArgs.push_back("--32");
43
break;
44
case llvm::Triple::x86_64:
45
CmdArgs.push_back("--64");
46
break;
47
}
48
49
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
50
51
CmdArgs.push_back("-o");
52
CmdArgs.push_back(Output.getFilename());
53
54
for (const auto &Input : Inputs)
55
CmdArgs.push_back(Input.getFilename());
56
57
const std::string Assembler = TC.GetProgramPath("as");
58
Exec = Args.MakeArgString(Assembler);
59
60
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
61
Exec, CmdArgs, Inputs, Output));
62
}
63
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 {
68
const auto &TC =
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;
74
const char *Exec;
75
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.
83
84
if (!D.SysRoot.empty())
85
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
86
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");
93
94
CmdArgs.push_back("-m");
95
switch (TC.getArch()) {
96
default:
97
D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str();
98
break;
99
case llvm::Triple::arm:
100
case llvm::Triple::thumb:
101
// FIXME: this is incorrect for WinCE
102
CmdArgs.push_back("thumb2pe");
103
break;
104
case llvm::Triple::aarch64:
105
CmdArgs.push_back("arm64pe");
106
break;
107
case llvm::Triple::x86:
108
CmdArgs.push_back("i386pe");
109
EntryPoint.append("_");
110
break;
111
case llvm::Triple::x86_64:
112
CmdArgs.push_back("i386pep");
113
break;
114
}
115
116
if (Args.hasArg(options::OPT_shared)) {
117
switch (T.getArch()) {
118
default:
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");
125
break;
126
case llvm::Triple::x86:
127
EntryPoint.append("_DllMainCRTStartup@12");
128
break;
129
}
130
131
CmdArgs.push_back("-shared");
132
CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
133
: "-Bdynamic");
134
135
CmdArgs.push_back("--enable-auto-image-base");
136
137
CmdArgs.push_back("--entry");
138
CmdArgs.push_back(Args.MakeArgString(EntryPoint));
139
} else {
140
EntryPoint.append("mainCRTStartup");
141
142
CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
143
: "-Bdynamic");
144
145
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
146
CmdArgs.push_back("--entry");
147
CmdArgs.push_back(Args.MakeArgString(EntryPoint));
148
}
149
150
// FIXME: handle subsystem
151
}
152
153
// NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
154
CmdArgs.push_back("--allow-multiple-definition");
155
156
CmdArgs.push_back("-o");
157
CmdArgs.push_back(Output.getFilename());
158
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");
162
163
CmdArgs.push_back("--out-implib");
164
CmdArgs.push_back(Args.MakeArgString(ImpLib));
165
}
166
167
Args.AddAllArgs(CmdArgs, options::OPT_L);
168
TC.AddFilePathLibArgs(Args, CmdArgs);
169
AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
170
171
if (TC.ShouldLinkCXXStdlib(Args)) {
172
bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
173
!Args.hasArg(options::OPT_static);
174
if (StaticCXX)
175
CmdArgs.push_back("-Bstatic");
176
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
177
if (StaticCXX)
178
CmdArgs.push_back("-Bdynamic");
179
}
180
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);
186
}
187
}
188
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"));
193
} else {
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"));
202
}
203
}
204
205
Exec = Args.MakeArgString(TC.GetLinkerPath());
206
207
C.addCommand(std::make_unique<Command>(JA, *this,
208
ResponseFileSupport::AtFileUTF8(),
209
Exec, CmdArgs, Inputs, Output));
210
}
211
212
CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
213
const llvm::Triple &T,
214
const llvm::opt::ArgList &Args)
215
: Generic_GCC(D, T, Args) {}
216
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;
222
}
223
224
bool CrossWindowsToolChain::isPICDefault() const {
225
return getArch() == llvm::Triple::x86_64;
226
}
227
228
bool CrossWindowsToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
229
return getArch() == llvm::Triple::x86_64;
230
}
231
232
bool CrossWindowsToolChain::isPICDefaultForced() const {
233
return getArch() == llvm::Triple::x86_64;
234
}
235
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;
241
242
auto AddSystemAfterIncludes = [&]() {
243
for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
244
addSystemInclude(DriverArgs, CC1Args, P);
245
};
246
247
if (DriverArgs.hasArg(options::OPT_nostdinc)) {
248
AddSystemAfterIncludes();
249
return;
250
}
251
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);
257
}
258
AddSystemAfterIncludes();
259
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
260
}
261
262
void CrossWindowsToolChain::
263
AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
264
llvm::opt::ArgStringList &CC1Args) const {
265
const std::string &SysRoot = getDriver().SysRoot;
266
267
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
268
DriverArgs.hasArg(options::OPT_nostdincxx))
269
return;
270
271
if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
272
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
273
}
274
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");
282
}
283
}
284
285
clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
286
SanitizerMask Res = ToolChain::getSupportedSanitizers();
287
Res |= SanitizerKind::Address;
288
Res |= SanitizerKind::PointerCompare;
289
Res |= SanitizerKind::PointerSubtract;
290
return Res;
291
}
292
293
Tool *CrossWindowsToolChain::buildLinker() const {
294
return new tools::CrossWindows::Linker(*this);
295
}
296
297
Tool *CrossWindowsToolChain::buildAssembler() const {
298
return new tools::CrossWindows::Assembler(*this);
299
}
300
301