clang 20.0.0git
WebAssembly.cpp
Go to the documentation of this file.
1//===--- WebAssembly.cpp - WebAssembly ToolChain Implementation -*- C++ -*-===//
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 "WebAssembly.h"
10#include "CommonArgs.h"
11#include "Gnu.h"
12#include "clang/Basic/Version.h"
13#include "clang/Config/config.h"
15#include "clang/Driver/Driver.h"
18#include "llvm/Option/ArgList.h"
19#include "llvm/Support/FileSystem.h"
20#include "llvm/Support/Path.h"
21#include "llvm/Support/VirtualFileSystem.h"
22
23using namespace clang::driver;
24using namespace clang::driver::tools;
25using namespace clang::driver::toolchains;
26using namespace clang;
27using namespace llvm::opt;
28
29/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples,
30/// we remove the vendor field to form the multiarch triple.
31std::string WebAssembly::getMultiarchTriple(const Driver &D,
32 const llvm::Triple &TargetTriple,
33 StringRef SysRoot) const {
34 return (TargetTriple.getArchName() + "-" +
35 TargetTriple.getOSAndEnvironmentName()).str();
36}
37
38std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
39 const ToolChain &ToolChain = getToolChain();
40 if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
41 StringRef UseLinker = A->getValue();
42 if (!UseLinker.empty()) {
43 if (llvm::sys::path::is_absolute(UseLinker) &&
44 llvm::sys::fs::can_execute(UseLinker))
45 return std::string(UseLinker);
46
47 // Interpret 'lld' as explicitly requesting `wasm-ld`, so look for that
48 // linker. Note that for `wasm32-wasip2` this overrides the default linker
49 // of `wasm-component-ld`.
50 if (UseLinker == "lld") {
51 return ToolChain.GetProgramPath("wasm-ld");
52 }
53
54 // Allow 'ld' as an alias for the default linker
55 if (UseLinker != "ld")
56 ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name)
57 << A->getAsString(Args);
58 }
59 }
60
62}
63
64static bool TargetBuildsComponents(const llvm::Triple &TargetTriple) {
65 // WASIp2 and above are all based on components, so test for WASI but exclude
66 // the original `wasi` target in addition to the `wasip1` name.
67 return TargetTriple.isOSWASI() && TargetTriple.getOSName() != "wasip1" &&
68 TargetTriple.getOSName() != "wasi";
69}
70
72 const InputInfo &Output,
73 const InputInfoList &Inputs,
74 const ArgList &Args,
75 const char *LinkingOutput) const {
76
77 const ToolChain &ToolChain = getToolChain();
78 const char *Linker = Args.MakeArgString(getLinkerPath(Args));
79 ArgStringList CmdArgs;
80
81 CmdArgs.push_back("-m");
82 if (ToolChain.getTriple().isArch64Bit())
83 CmdArgs.push_back("wasm64");
84 else
85 CmdArgs.push_back("wasm32");
86
87 if (Args.hasArg(options::OPT_s))
88 CmdArgs.push_back("--strip-all");
89
90 // On `wasip2` the default linker is `wasm-component-ld` which wraps the
91 // execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where
92 // to find it to avoid it needing to hunt and rediscover or search `PATH` for
93 // where it is.
94 if (llvm::sys::path::stem(Linker).ends_with_insensitive(
95 "wasm-component-ld")) {
96 CmdArgs.push_back("--wasm-ld-path");
97 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetProgramPath("wasm-ld")));
98 }
99
100 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
101
102 ToolChain.AddFilePathLibArgs(Args, CmdArgs);
103
104 bool IsCommand = true;
105 const char *Crt1;
106 const char *Entry = nullptr;
107
108 // When -shared is specified, use the reactor exec model unless
109 // specified otherwise.
110 if (Args.hasArg(options::OPT_shared))
111 IsCommand = false;
112
113 if (const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
114 StringRef CM = A->getValue();
115 if (CM == "command") {
116 IsCommand = true;
117 } else if (CM == "reactor") {
118 IsCommand = false;
119 } else {
120 ToolChain.getDriver().Diag(diag::err_drv_invalid_argument_to_option)
121 << CM << A->getOption().getName();
122 }
123 }
124
125 if (IsCommand) {
126 // If crt1-command.o exists, it supports new-style commands, so use it.
127 // Otherwise, use the old crt1.o. This is a temporary transition measure.
128 // Once WASI libc no longer needs to support LLVM versions which lack
129 // support for new-style command, it can make crt1.o the same as
130 // crt1-command.o. And once LLVM no longer needs to support WASI libc
131 // versions before that, it can switch to using crt1-command.o.
132 Crt1 = "crt1.o";
133 if (ToolChain.GetFilePath("crt1-command.o") != "crt1-command.o")
134 Crt1 = "crt1-command.o";
135 } else {
136 Crt1 = "crt1-reactor.o";
137 Entry = "_initialize";
138 }
139
140 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
141 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(Crt1)));
142 if (Entry) {
143 CmdArgs.push_back(Args.MakeArgString("--entry"));
144 CmdArgs.push_back(Args.MakeArgString(Entry));
145 }
146
147 if (Args.hasArg(options::OPT_shared))
148 CmdArgs.push_back(Args.MakeArgString("-shared"));
149
150 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
151
152 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
154 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
155
156 if (Args.hasArg(options::OPT_pthread)) {
157 CmdArgs.push_back("-lpthread");
158 CmdArgs.push_back("--shared-memory");
159 }
160
161 CmdArgs.push_back("-lc");
162 AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
163 }
164
165 CmdArgs.push_back("-o");
166 CmdArgs.push_back(Output.getFilename());
167
168 // Don't use wasm-opt by default on `wasip2` as it doesn't have support for
169 // components at this time. Retain the historical default otherwise, though,
170 // of running `wasm-opt` by default.
171 bool WasmOptDefault = !TargetBuildsComponents(ToolChain.getTriple());
172 bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt,
173 options::OPT_no_wasm_opt, WasmOptDefault);
174
175 // If wasm-opt is enabled and optimizations are happening look for the
176 // `wasm-opt` program. If it's not found auto-disable it.
177 std::string WasmOptPath;
178 if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) {
179 WasmOptPath = ToolChain.GetProgramPath("wasm-opt");
180 if (WasmOptPath == "wasm-opt") {
181 WasmOptPath = {};
182 }
183 }
184
185 if (!WasmOptPath.empty()) {
186 CmdArgs.push_back("--keep-section=target_features");
187 }
188
189 C.addCommand(std::make_unique<Command>(JA, *this,
191 Linker, CmdArgs, Inputs, Output));
192
193 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
194 if (!WasmOptPath.empty()) {
195 StringRef OOpt = "s";
196 if (A->getOption().matches(options::OPT_O4) ||
197 A->getOption().matches(options::OPT_Ofast))
198 OOpt = "4";
199 else if (A->getOption().matches(options::OPT_O0))
200 OOpt = "0";
201 else if (A->getOption().matches(options::OPT_O))
202 OOpt = A->getValue();
203
204 if (OOpt != "0") {
205 const char *WasmOpt = Args.MakeArgString(WasmOptPath);
206 ArgStringList OptArgs;
207 OptArgs.push_back(Output.getFilename());
208 OptArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt));
209 OptArgs.push_back("-o");
210 OptArgs.push_back(Output.getFilename());
211 C.addCommand(std::make_unique<Command>(
212 JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, OptArgs,
213 Inputs, Output));
214 }
215 }
216 }
217}
218
219/// Given a base library directory, append path components to form the
220/// LTO directory.
221static std::string AppendLTOLibDir(const std::string &Dir) {
222 // The version allows the path to be keyed to the specific version of
223 // LLVM in used, as the bitcode format is not stable.
224 return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
225}
226
227WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
228 const llvm::opt::ArgList &Args)
229 : ToolChain(D, Triple, Args) {
230
231 assert(Triple.isArch32Bit() != Triple.isArch64Bit());
232
233 getProgramPaths().push_back(getDriver().Dir);
234
235 auto SysRoot = getDriver().SysRoot;
236 if (getTriple().getOS() == llvm::Triple::UnknownOS) {
237 // Theoretically an "unknown" OS should mean no standard libraries, however
238 // it could also mean that a custom set of libraries is in use, so just add
239 // /lib to the search path. Disable multiarch in this case, to discourage
240 // paths containing "unknown" from acquiring meanings.
241 getFilePaths().push_back(SysRoot + "/lib");
242 } else {
243 const std::string MultiarchTriple =
244 getMultiarchTriple(getDriver(), Triple, SysRoot);
245 if (D.isUsingLTO()) {
246 // For LTO, enable use of lto-enabled sysroot libraries too, if available.
247 // Note that the directory is keyed to the LLVM revision, as LLVM's
248 // bitcode format is not stable.
249 auto Dir = AppendLTOLibDir(SysRoot + "/lib/" + MultiarchTriple);
250 getFilePaths().push_back(Dir);
251 }
252 getFilePaths().push_back(SysRoot + "/lib/" + MultiarchTriple);
253 }
254}
255
256const char *WebAssembly::getDefaultLinker() const {
258 return "wasm-component-ld";
259 return "wasm-ld";
260}
261
262bool WebAssembly::IsMathErrnoDefault() const { return false; }
263
264bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; }
265
266bool WebAssembly::UseObjCMixedDispatch() const { return true; }
267
268bool WebAssembly::isPICDefault() const { return false; }
269
270bool WebAssembly::isPIEDefault(const llvm::opt::ArgList &Args) const {
271 return false;
272}
273
274bool WebAssembly::isPICDefaultForced() const { return false; }
275
276bool WebAssembly::hasBlocksRuntime() const { return false; }
277
278// TODO: Support profiling.
279bool WebAssembly::SupportsProfiling() const { return false; }
280
281bool WebAssembly::HasNativeLLVMSupport() const { return true; }
282
283void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
284 ArgStringList &CC1Args,
285 Action::OffloadKind) const {
286 if (!DriverArgs.hasFlag(clang::driver::options::OPT_fuse_init_array,
287 options::OPT_fno_use_init_array, true))
288 CC1Args.push_back("-fno-use-init-array");
289
290 // '-pthread' implies atomics, bulk-memory, mutable-globals, and sign-ext
291 if (DriverArgs.hasFlag(options::OPT_pthread, options::OPT_no_pthread,
292 false)) {
293 if (DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics,
294 false))
295 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
296 << "-pthread"
297 << "-mno-atomics";
298 if (DriverArgs.hasFlag(options::OPT_mno_bulk_memory,
299 options::OPT_mbulk_memory, false))
300 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
301 << "-pthread"
302 << "-mno-bulk-memory";
303 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
304 options::OPT_mmutable_globals, false))
305 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
306 << "-pthread"
307 << "-mno-mutable-globals";
308 if (DriverArgs.hasFlag(options::OPT_mno_sign_ext, options::OPT_msign_ext,
309 false))
310 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
311 << "-pthread"
312 << "-mno-sign-ext";
313 CC1Args.push_back("-target-feature");
314 CC1Args.push_back("+atomics");
315 CC1Args.push_back("-target-feature");
316 CC1Args.push_back("+bulk-memory");
317 CC1Args.push_back("-target-feature");
318 CC1Args.push_back("+mutable-globals");
319 CC1Args.push_back("-target-feature");
320 CC1Args.push_back("+sign-ext");
321 }
322
323 if (!DriverArgs.hasFlag(options::OPT_mmutable_globals,
324 options::OPT_mno_mutable_globals, false)) {
325 // -fPIC implies +mutable-globals because the PIC ABI used by the linker
326 // depends on importing and exporting mutable globals.
327 llvm::Reloc::Model RelocationModel;
328 unsigned PICLevel;
329 bool IsPIE;
330 std::tie(RelocationModel, PICLevel, IsPIE) =
331 ParsePICArgs(*this, DriverArgs);
332 if (RelocationModel == llvm::Reloc::PIC_) {
333 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
334 options::OPT_mmutable_globals, false)) {
335 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
336 << "-fPIC"
337 << "-mno-mutable-globals";
338 }
339 CC1Args.push_back("-target-feature");
340 CC1Args.push_back("+mutable-globals");
341 }
342 }
343
344 if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) {
345 // '-fwasm-exceptions' is not compatible with '-mno-exception-handling'
346 if (DriverArgs.hasFlag(options::OPT_mno_exception_handing,
347 options::OPT_mexception_handing, false))
348 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
349 << "-fwasm-exceptions"
350 << "-mno-exception-handling";
351 // '-fwasm-exceptions' is not compatible with
352 // '-mllvm -enable-emscripten-cxx-exceptions'
353 for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
354 if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions")
355 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
356 << "-fwasm-exceptions"
357 << "-mllvm -enable-emscripten-cxx-exceptions";
358 }
359 // '-fwasm-exceptions' implies exception-handling feature
360 CC1Args.push_back("-target-feature");
361 CC1Args.push_back("+exception-handling");
362 // Backend needs -wasm-enable-eh to enable Wasm EH
363 CC1Args.push_back("-mllvm");
364 CC1Args.push_back("-wasm-enable-eh");
365
366 // New Wasm EH spec (adopted in Oct 2023) requires multivalue and
367 // reference-types.
368 if (DriverArgs.hasFlag(options::OPT_mno_multivalue,
369 options::OPT_mmultivalue, false)) {
370 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
371 << "-fwasm-exceptions" << "-mno-multivalue";
372 }
373 if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
374 options::OPT_mreference_types, false)) {
375 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
376 << "-fwasm-exceptions" << "-mno-reference-types";
377 }
378 CC1Args.push_back("-target-feature");
379 CC1Args.push_back("+multivalue");
380 CC1Args.push_back("-target-feature");
381 CC1Args.push_back("+reference-types");
382 }
383
384 for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
385 StringRef Opt = A->getValue(0);
386 if (Opt.starts_with("-emscripten-cxx-exceptions-allowed")) {
387 // '-mllvm -emscripten-cxx-exceptions-allowed' should be used with
388 // '-mllvm -enable-emscripten-cxx-exceptions'
389 bool EmEHArgExists = false;
390 for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
391 if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") {
392 EmEHArgExists = true;
393 break;
394 }
395 }
396 if (!EmEHArgExists)
397 getDriver().Diag(diag::err_drv_argument_only_allowed_with)
398 << "-mllvm -emscripten-cxx-exceptions-allowed"
399 << "-mllvm -enable-emscripten-cxx-exceptions";
400
401 // Prevent functions specified in -emscripten-cxx-exceptions-allowed list
402 // from being inlined before reaching the wasm backend.
403 StringRef FuncNamesStr = Opt.split('=').second;
405 FuncNamesStr.split(FuncNames, ',');
406 for (auto Name : FuncNames) {
407 CC1Args.push_back("-mllvm");
408 CC1Args.push_back(DriverArgs.MakeArgString("--force-attribute=" + Name +
409 ":noinline"));
410 }
411 }
412
413 if (Opt.starts_with("-wasm-enable-sjlj")) {
414 // '-mllvm -wasm-enable-sjlj' is not compatible with
415 // '-mno-exception-handling'
416 if (DriverArgs.hasFlag(options::OPT_mno_exception_handing,
417 options::OPT_mexception_handing, false))
418 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
419 << "-mllvm -wasm-enable-sjlj"
420 << "-mno-exception-handling";
421 // '-mllvm -wasm-enable-sjlj' is not compatible with
422 // '-mllvm -enable-emscripten-cxx-exceptions'
423 // because we don't allow Emscripten EH + Wasm SjLj
424 for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
425 if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions")
426 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
427 << "-mllvm -wasm-enable-sjlj"
428 << "-mllvm -enable-emscripten-cxx-exceptions";
429 }
430 // '-mllvm -wasm-enable-sjlj' is not compatible with
431 // '-mllvm -enable-emscripten-sjlj'
432 for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
433 if (StringRef(A->getValue(0)) == "-enable-emscripten-sjlj")
434 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
435 << "-mllvm -wasm-enable-sjlj"
436 << "-mllvm -enable-emscripten-sjlj";
437 }
438 // '-mllvm -wasm-enable-sjlj' implies exception-handling feature
439 CC1Args.push_back("-target-feature");
440 CC1Args.push_back("+exception-handling");
441 // Backend needs '-exception-model=wasm' to use Wasm EH instructions
442 CC1Args.push_back("-exception-model=wasm");
443
444 // New Wasm EH spec (adopted in Oct 2023) requires multivalue and
445 // reference-types.
446 if (DriverArgs.hasFlag(options::OPT_mno_multivalue,
447 options::OPT_mmultivalue, false)) {
448 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
449 << "-mllvm -wasm-enable-sjlj" << "-mno-multivalue";
450 }
451 if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
452 options::OPT_mreference_types, false)) {
453 getDriver().Diag(diag::err_drv_argument_not_allowed_with)
454 << "-mllvm -wasm-enable-sjlj" << "-mno-reference-types";
455 }
456 CC1Args.push_back("-target-feature");
457 CC1Args.push_back("+multivalue");
458 CC1Args.push_back("-target-feature");
459 CC1Args.push_back("+reference-types");
460 }
461 }
462}
463
464ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {
466}
467
469WebAssembly::GetCXXStdlibType(const ArgList &Args) const {
470 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
471 StringRef Value = A->getValue();
472 if (Value == "libc++")
474 else if (Value == "libstdc++")
476 else
477 getDriver().Diag(diag::err_drv_invalid_stdlib_name)
478 << A->getAsString(Args);
479 }
481}
482
483void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
484 ArgStringList &CC1Args) const {
485 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
486 return;
487
488 const Driver &D = getDriver();
489
490 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
491 SmallString<128> P(D.ResourceDir);
492 llvm::sys::path::append(P, "include");
493 addSystemInclude(DriverArgs, CC1Args, P);
494 }
495
496 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
497 return;
498
499 // Check for configure-time C include directories.
500 StringRef CIncludeDirs(C_INCLUDE_DIRS);
501 if (CIncludeDirs != "") {
503 CIncludeDirs.split(dirs, ":");
504 for (StringRef dir : dirs) {
505 StringRef Prefix =
506 llvm::sys::path::is_absolute(dir) ? "" : StringRef(D.SysRoot);
507 addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir);
508 }
509 return;
510 }
511
512 if (getTriple().getOS() != llvm::Triple::UnknownOS) {
513 const std::string MultiarchTriple =
514 getMultiarchTriple(D, getTriple(), D.SysRoot);
515 addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include/" + MultiarchTriple);
516 }
517 addSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include");
518}
519
520void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
521 ArgStringList &CC1Args) const {
522
523 if (DriverArgs.hasArg(options::OPT_nostdlibinc, options::OPT_nostdinc,
524 options::OPT_nostdincxx))
525 return;
526
527 switch (GetCXXStdlibType(DriverArgs)) {
529 addLibCxxIncludePaths(DriverArgs, CC1Args);
530 break;
532 addLibStdCXXIncludePaths(DriverArgs, CC1Args);
533 break;
534 }
535}
536
537void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
538 llvm::opt::ArgStringList &CmdArgs) const {
539
540 switch (GetCXXStdlibType(Args)) {
542 CmdArgs.push_back("-lc++");
543 if (Args.hasArg(options::OPT_fexperimental_library))
544 CmdArgs.push_back("-lc++experimental");
545 CmdArgs.push_back("-lc++abi");
546 break;
548 CmdArgs.push_back("-lstdc++");
549 break;
550 }
551}
552
553SanitizerMask WebAssembly::getSupportedSanitizers() const {
555 if (getTriple().isOSEmscripten()) {
556 Res |= SanitizerKind::Vptr | SanitizerKind::Leak | SanitizerKind::Address;
557 }
558 // -fsanitize=function places two words before the function label, which are
559 // -unsupported.
561 return Res;
562}
563
564Tool *WebAssembly::buildLinker() const {
565 return new tools::wasm::Linker(*this);
566}
567
568void WebAssembly::addLibCxxIncludePaths(
569 const llvm::opt::ArgList &DriverArgs,
570 llvm::opt::ArgStringList &CC1Args) const {
571 const Driver &D = getDriver();
572 std::string SysRoot = computeSysRoot();
573 std::string LibPath = SysRoot + "/include";
574 const std::string MultiarchTriple =
575 getMultiarchTriple(D, getTriple(), SysRoot);
576 bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
577
578 std::string Version = detectLibcxxVersion(LibPath);
579 if (Version.empty())
580 return;
581
582 // First add the per-target include path if the OS is known.
583 if (IsKnownOs) {
584 std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version;
585 addSystemInclude(DriverArgs, CC1Args, TargetDir);
586 }
587
588 // Second add the generic one.
589 addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
590}
591
592void WebAssembly::addLibStdCXXIncludePaths(
593 const llvm::opt::ArgList &DriverArgs,
594 llvm::opt::ArgStringList &CC1Args) const {
595 // We cannot use GCCInstallationDetector here as the sysroot usually does
596 // not contain a full GCC installation.
597 // Instead, we search the given sysroot for /usr/include/xx, similar
598 // to how we do it for libc++.
599 const Driver &D = getDriver();
600 std::string SysRoot = computeSysRoot();
601 std::string LibPath = SysRoot + "/include";
602 const std::string MultiarchTriple =
603 getMultiarchTriple(D, getTriple(), SysRoot);
604 bool IsKnownOs = (getTriple().getOS() != llvm::Triple::UnknownOS);
605
606 // This is similar to detectLibcxxVersion()
607 std::string Version;
608 {
609 std::error_code EC;
610 Generic_GCC::GCCVersion MaxVersion =
612 SmallString<128> Path(LibPath);
613 llvm::sys::path::append(Path, "c++");
614 for (llvm::vfs::directory_iterator LI = getVFS().dir_begin(Path, EC), LE;
615 !EC && LI != LE; LI = LI.increment(EC)) {
616 StringRef VersionText = llvm::sys::path::filename(LI->path());
617 if (VersionText[0] != 'v') {
618 auto Version = Generic_GCC::GCCVersion::Parse(VersionText);
619 if (Version > MaxVersion)
620 MaxVersion = Version;
621 }
622 }
623 if (MaxVersion.Major > 0)
624 Version = MaxVersion.Text;
625 }
626
627 if (Version.empty())
628 return;
629
630 // First add the per-target include path if the OS is known.
631 if (IsKnownOs) {
632 std::string TargetDir = LibPath + "/c++/" + Version + "/" + MultiarchTriple;
633 addSystemInclude(DriverArgs, CC1Args, TargetDir);
634 }
635
636 // Second add the generic one.
637 addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
638 // Third the backward one.
639 addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version + "/backward");
640}
StringRef P
const Decl * D
IndirectLocalPath & Path
static bool TargetBuildsComponents(const llvm::Triple &TargetTriple)
Definition: WebAssembly.cpp:64
static std::string AppendLTOLibDir(const std::string &Dir)
Given a base library directory, append path components to form the LTO directory.
Defines version macros and version-related utility functions for Clang.
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:77
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:144
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
const char * getFilename() const
Definition: InputInfo.h:83
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:92
static void addSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory to CC1 arguments.
Definition: ToolChain.cpp:1180
virtual std::string computeSysRoot() const
Return the sysroot, possibly searching for a default sysroot using target-specific logic.
Definition: ToolChain.cpp:1066
bool ShouldLinkCXXStdlib(const llvm::opt::ArgList &Args) const
Returns if the C++ standard library should be linked in.
Definition: ToolChain.cpp:1282
static void addExternCSystemInclude(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, const Twine &Path)
Utility function to add a system include directory with extern "C" semantics to CC1 arguments.
Definition: ToolChain.cpp:1195
std::string GetFilePath(const char *Name) const
Definition: ToolChain.cpp:870
StringRef getOS() const
Definition: ToolChain.h:272
const Driver & getDriver() const
Definition: ToolChain.h:253
virtual std::string detectLibcxxVersion(StringRef IncludePath) const
Definition: ToolChain.cpp:1227
llvm::vfs::FileSystem & getVFS() const
Definition: ToolChain.cpp:141
virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const
AddCXXStdlibLibArgs - Add the system specific linker arguments to use for the given C++ standard libr...
Definition: ToolChain.cpp:1288
virtual const char * getDefaultLinker() const
GetDefaultLinker - Get the default linker to use.
Definition: ToolChain.h:494
const llvm::Triple & getTriple() const
Definition: ToolChain.h:255
std::string GetProgramPath(const char *Name) const
Definition: ToolChain.cpp:874
void AddFilePathLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const
AddFilePathLibArgs - Add each thing in getFilePaths() as a "-L" option.
Definition: ToolChain.cpp:1307
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:1371
Tool - Information on a specific compilation tool.
Definition: Tool.h:32
WebAssembly(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args)
std::string getLinkerPath(const llvm::opt::ArgList &Args) const
Definition: WebAssembly.cpp:38
void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs, const char *LinkingOutput) const override
ConstructJob - Construct jobs to perform the action JA, writing to Output and with Inputs,...
Definition: WebAssembly.cpp:71
void AddRunTimeLibs(const ToolChain &TC, const Driver &D, llvm::opt::ArgStringList &CmdArgs, const llvm::opt::ArgList &Args)
std::tuple< llvm::Reloc::Model, unsigned, bool > ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args)
void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, const JobAction &JA)
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1109
The JSON file list parser is used to communicate input to InstallAPI.
static constexpr ResponseFileSupport AtFileCurCP()
Definition: Job.h:92
Struct to store and manipulate GCC versions.
Definition: Gnu.h:162
int Major
The parsed major, minor, and patch numbers.
Definition: Gnu.h:167
std::string Text
The unparsed text of the version.
Definition: Gnu.h:164
static GCCVersion Parse(StringRef VersionText)
Parse a GCCVersion object out of a string of text.
Definition: Gnu.cpp:2121