11#include "clang/Config/config.h"
16#include "llvm/Config/llvm-config.h"
17#include "llvm/Option/ArgList.h"
18#include "llvm/Support/FileSystem.h"
19#include "llvm/Support/Path.h"
20#include "llvm/Support/VirtualFileSystem.h"
30std::string WebAssembly::getMultiarchTriple(
const Driver &D,
31 const llvm::Triple &TargetTriple,
32 StringRef SysRoot)
const {
33 return (TargetTriple.getArchName() +
"-" +
34 TargetTriple.getOSAndEnvironmentName()).str();
39 if (
const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
40 StringRef UseLinker = A->getValue();
41 if (!UseLinker.empty()) {
42 if (llvm::sys::path::is_absolute(UseLinker) &&
43 llvm::sys::fs::can_execute(UseLinker))
44 return std::string(UseLinker);
49 if (UseLinker ==
"lld") {
54 if (UseLinker !=
"ld")
56 << A->getAsString(Args);
66 return TargetTriple.isOSWASI() && TargetTriple.getOSName() !=
"wasip1" &&
67 TargetTriple.getOSName() !=
"wasi";
70static bool WantsPthread(
const llvm::Triple &Triple,
const ArgList &Args) {
72 Args.hasFlag(options::OPT_pthread, options::OPT_no_pthread,
false);
76 if (Triple.isOSWASI() && Triple.getEnvironmentName() ==
"threads")
86 const char *LinkingOutput)
const {
90 ArgStringList CmdArgs;
92 CmdArgs.push_back(
"-m");
94 CmdArgs.push_back(
"wasm64");
96 CmdArgs.push_back(
"wasm32");
98 if (Args.hasArg(options::OPT_s))
99 CmdArgs.push_back(
"--strip-all");
105 if (llvm::sys::path::stem(
Linker).ends_with_insensitive(
106 "wasm-component-ld")) {
107 CmdArgs.push_back(
"--wasm-ld-path");
111 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
115 bool IsCommand =
true;
117 const char *Entry =
nullptr;
121 if (Args.hasArg(options::OPT_shared))
124 if (
const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
125 StringRef CM = A->getValue();
126 if (CM ==
"command") {
128 }
else if (CM ==
"reactor") {
132 << CM << A->getOption().getName();
145 Crt1 =
"crt1-command.o";
147 Crt1 =
"crt1-reactor.o";
148 Entry =
"_initialize";
151 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
154 CmdArgs.push_back(Args.MakeArgString(
"--entry"));
155 CmdArgs.push_back(Args.MakeArgString(Entry));
158 if (Args.hasArg(options::OPT_shared))
159 CmdArgs.push_back(Args.MakeArgString(
"-shared"));
164 CmdArgs.push_back(
"--shared-memory");
166 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
171 CmdArgs.push_back(
"-lpthread");
173 CmdArgs.push_back(
"-lc");
179 CmdArgs.push_back(
"-o");
186 bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt,
187 options::OPT_no_wasm_opt, WasmOptDefault);
191 std::string WasmOptPath;
192 if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) {
194 if (WasmOptPath ==
"wasm-opt") {
199 if (!WasmOptPath.empty()) {
200 CmdArgs.push_back(
"--keep-section=target_features");
203 C.addCommand(std::make_unique<Command>(JA, *
this,
205 Linker, CmdArgs, Inputs, Output));
207 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
208 if (!WasmOptPath.empty()) {
209 StringRef OOpt =
"s";
210 if (A->getOption().matches(options::OPT_O4) ||
211 A->getOption().matches(options::OPT_Ofast))
213 else if (A->getOption().matches(options::OPT_O0))
215 else if (A->getOption().matches(options::OPT_O))
216 OOpt = A->getValue();
219 const char *WasmOpt = Args.MakeArgString(WasmOptPath);
220 ArgStringList OptArgs;
222 OptArgs.push_back(Args.MakeArgString(llvm::Twine(
"-O") + OOpt));
223 OptArgs.push_back(
"-o");
225 C.addCommand(std::make_unique<Command>(
238 return Dir +
"/llvm-lto/" LLVM_VERSION_STRING;
242 const llvm::opt::ArgList &Args)
243 : ToolChain(D, Triple, Args) {
245 assert(Triple.isArch32Bit() != Triple.isArch64Bit());
247 getProgramPaths().push_back(getDriver().Dir);
249 auto SysRoot = getDriver().SysRoot;
250 if (getTriple().getOS() == llvm::Triple::UnknownOS) {
255 getFilePaths().push_back(SysRoot +
"/lib");
257 const std::string MultiarchTriple =
258 getMultiarchTriple(getDriver(), Triple, SysRoot);
264 getFilePaths().push_back(Dir);
266 getFilePaths().push_back(SysRoot +
"/lib/" + MultiarchTriple);
270const char *WebAssembly::getDefaultLinker()
const {
272 return "wasm-component-ld";
284bool WebAssembly::isPIEDefault(
const llvm::opt::ArgList &Args)
const {
297void WebAssembly::addClangTargetOptions(
const ArgList &DriverArgs,
298 ArgStringList &CC1Args,
300 if (!DriverArgs.hasFlag(clang::driver::options::OPT_fuse_init_array,
301 options::OPT_fno_use_init_array,
true))
302 CC1Args.push_back(
"-fno-use-init-array");
306 if (DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics,
311 if (DriverArgs.hasFlag(options::OPT_mno_bulk_memory,
312 options::OPT_mbulk_memory,
false))
315 <<
"-mno-bulk-memory";
316 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
317 options::OPT_mmutable_globals,
false))
320 <<
"-mno-mutable-globals";
321 if (DriverArgs.hasFlag(options::OPT_mno_sign_ext, options::OPT_msign_ext,
326 CC1Args.push_back(
"-target-feature");
327 CC1Args.push_back(
"+atomics");
328 CC1Args.push_back(
"-target-feature");
329 CC1Args.push_back(
"+bulk-memory");
330 CC1Args.push_back(
"-target-feature");
331 CC1Args.push_back(
"+mutable-globals");
332 CC1Args.push_back(
"-target-feature");
333 CC1Args.push_back(
"+sign-ext");
336 if (!DriverArgs.hasFlag(options::OPT_mmutable_globals,
337 options::OPT_mno_mutable_globals,
false)) {
340 llvm::Reloc::Model RelocationModel;
343 std::tie(RelocationModel, PICLevel, IsPIE) =
345 if (RelocationModel == llvm::Reloc::PIC_) {
346 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
347 options::OPT_mmutable_globals,
false)) {
350 <<
"-mno-mutable-globals";
352 CC1Args.push_back(
"-target-feature");
353 CC1Args.push_back(
"+mutable-globals");
357 bool HasBannedIncompatibleOptionsForWasmEHSjLj =
false;
358 bool HasEnabledFeaturesForWasmEHSjLj =
false;
362 auto BanIncompatibleOptionsForWasmEHSjLj = [&](StringRef CurOption) {
363 if (HasBannedIncompatibleOptionsForWasmEHSjLj)
365 HasBannedIncompatibleOptionsForWasmEHSjLj =
true;
366 if (DriverArgs.hasFlag(options::OPT_mno_exception_handing,
367 options::OPT_mexception_handing,
false))
369 << CurOption <<
"-mno-exception-handling";
371 if (DriverArgs.hasFlag(options::OPT_mno_multivalue,
372 options::OPT_mmultivalue,
false))
374 << CurOption <<
"-mno-multivalue";
375 if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
376 options::OPT_mreference_types,
false))
378 << CurOption <<
"-mno-reference-types";
380 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
381 for (
const auto *Option :
382 {
"-enable-emscripten-cxx-exceptions",
"-enable-emscripten-sjlj",
383 "-emscripten-cxx-exceptions-allowed"}) {
384 if (StringRef(A->getValue(0)) == Option)
386 << CurOption << Option;
392 auto EnableFeaturesForWasmEHSjLj = [&]() {
393 if (HasEnabledFeaturesForWasmEHSjLj)
395 HasEnabledFeaturesForWasmEHSjLj =
true;
396 CC1Args.push_back(
"-target-feature");
397 CC1Args.push_back(
"+exception-handling");
399 CC1Args.push_back(
"-target-feature");
400 CC1Args.push_back(
"+multivalue");
401 CC1Args.push_back(
"-target-feature");
402 CC1Args.push_back(
"+reference-types");
404 CC1Args.push_back(
"-exception-model=wasm");
407 if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) {
408 BanIncompatibleOptionsForWasmEHSjLj(
"-fwasm-exceptions");
409 EnableFeaturesForWasmEHSjLj();
411 CC1Args.push_back(
"-mllvm");
412 CC1Args.push_back(
"-wasm-enable-eh");
415 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
416 StringRef Opt = A->getValue(0);
417 if (Opt.starts_with(
"-emscripten-cxx-exceptions-allowed")) {
420 bool EmEHArgExists =
false;
421 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
422 if (StringRef(A->getValue(0)) ==
"-enable-emscripten-cxx-exceptions") {
423 EmEHArgExists =
true;
429 <<
"-mllvm -emscripten-cxx-exceptions-allowed"
430 <<
"-mllvm -enable-emscripten-cxx-exceptions";
434 StringRef FuncNamesStr = Opt.split(
'=').second;
435 SmallVector<StringRef, 4> FuncNames;
436 FuncNamesStr.split(FuncNames,
',');
437 for (
auto Name : FuncNames) {
438 CC1Args.push_back(
"-mllvm");
439 CC1Args.push_back(DriverArgs.MakeArgString(
"--force-attribute=" + Name +
444 for (
const auto *Option :
445 {
"-wasm-enable-eh",
"-wasm-enable-sjlj",
"-wasm-use-legacy-eh"}) {
446 if (Opt.starts_with(Option)) {
447 BanIncompatibleOptionsForWasmEHSjLj(Option);
448 EnableFeaturesForWasmEHSjLj();
459WebAssembly::GetCXXStdlibType(
const ArgList &Args)
const {
460 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
461 StringRef
Value = A->getValue();
462 if (
Value ==
"libc++")
464 else if (
Value ==
"libstdc++")
468 << A->getAsString(Args);
473void WebAssembly::AddClangSystemIncludeArgs(
const ArgList &DriverArgs,
474 ArgStringList &CC1Args)
const {
475 if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
480 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
481 SmallString<128> P(D.ResourceDir);
482 llvm::sys::path::append(P,
"include");
486 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
490 StringRef CIncludeDirs(C_INCLUDE_DIRS);
491 if (CIncludeDirs !=
"") {
492 SmallVector<StringRef, 5> dirs;
493 CIncludeDirs.split(dirs,
":");
494 for (StringRef dir : dirs) {
496 llvm::sys::path::is_absolute(dir) ?
"" : StringRef(D.SysRoot);
503 const std::string MultiarchTriple =
504 getMultiarchTriple(D,
getTriple(), D.SysRoot);
505 addSystemInclude(DriverArgs, CC1Args, D.SysRoot +
"/include/" + MultiarchTriple);
510void WebAssembly::AddClangCXXStdlibIncludeArgs(
const ArgList &DriverArgs,
511 ArgStringList &CC1Args)
const {
513 if (DriverArgs.hasArg(options::OPT_nostdlibinc, options::OPT_nostdinc,
514 options::OPT_nostdincxx))
517 switch (GetCXXStdlibType(DriverArgs)) {
519 addLibCxxIncludePaths(DriverArgs, CC1Args);
522 addLibStdCXXIncludePaths(DriverArgs, CC1Args);
527void WebAssembly::AddCXXStdlibLibArgs(
const llvm::opt::ArgList &Args,
528 llvm::opt::ArgStringList &CmdArgs)
const {
530 switch (GetCXXStdlibType(Args)) {
532 CmdArgs.push_back(
"-lc++");
533 if (Args.hasArg(options::OPT_fexperimental_library))
534 CmdArgs.push_back(
"-lc++experimental");
535 CmdArgs.push_back(
"-lc++abi");
538 CmdArgs.push_back(
"-lstdc++");
546 Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
550 Res |= SanitizerKind::Address;
560 return new tools::wasm::Linker(*
this);
563void WebAssembly::addLibCxxIncludePaths(
564 const llvm::opt::ArgList &DriverArgs,
565 llvm::opt::ArgStringList &CC1Args)
const {
568 std::string LibPath = SysRoot +
"/include";
569 const std::string MultiarchTriple =
570 getMultiarchTriple(D,
getTriple(), SysRoot);
571 bool IsKnownOs = (
getTriple().getOS() != llvm::Triple::UnknownOS);
579 std::string TargetDir = LibPath +
"/" + MultiarchTriple +
"/c++/" + Version;
587void WebAssembly::addLibStdCXXIncludePaths(
588 const llvm::opt::ArgList &DriverArgs,
589 llvm::opt::ArgStringList &CC1Args)
const {
596 std::string LibPath = SysRoot +
"/include";
597 const std::string MultiarchTriple =
598 getMultiarchTriple(D,
getTriple(), SysRoot);
599 bool IsKnownOs = (
getTriple().getOS() != llvm::Triple::UnknownOS);
605 Generic_GCC::GCCVersion MaxVersion =
607 SmallString<128> Path(LibPath);
608 llvm::sys::path::append(Path,
"c++");
609 for (llvm::vfs::directory_iterator LI =
getVFS().dir_begin(Path, EC), LE;
610 !EC && LI !=
LE; LI = LI.increment(EC)) {
611 StringRef VersionText = llvm::sys::path::filename(LI->path());
612 if (VersionText[0] !=
'v') {
614 if (Version > MaxVersion)
615 MaxVersion = Version;
618 if (MaxVersion.
Major > 0)
619 Version = MaxVersion.
Text;
627 std::string TargetDir = LibPath +
"/c++/" + Version +
"/" + MultiarchTriple;
634 addSystemInclude(DriverArgs, CC1Args, LibPath +
"/c++/" + Version +
"/backward");
Compilation - A set of tasks to perform for a single driver invocation.
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
DiagnosticBuilder Diag(unsigned DiagID) const
bool isUsingLTO() const
Returns true if we are performing any kind of LTO.
SmallVector< InputInfo, 4 > InputInfoList
bool LE(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
bool(*)(llvm::ArrayRef< const char * >, llvm::raw_ostream &, llvm::raw_ostream &, bool, bool) Driver
static constexpr ResponseFileSupport AtFileCurCP()