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();
41 if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions))
48 if (
const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
49 StringRef UseLinker = A->getValue();
50 if (!UseLinker.empty()) {
51 if (llvm::sys::path::is_absolute(UseLinker) &&
52 llvm::sys::fs::can_execute(UseLinker))
53 return std::string(UseLinker);
58 if (UseLinker ==
"lld") {
63 if (UseLinker !=
"ld")
65 << A->getAsString(Args);
75 return TargetTriple.isOSWASI() && TargetTriple.getOSName() !=
"wasip1" &&
76 TargetTriple.getOSName() !=
"wasi";
79static bool WantsPthread(
const llvm::Triple &Triple,
const ArgList &Args) {
84 if (Triple.isOSWASI() && Triple.getEnvironmentName() ==
"threads")
88 if (Triple.getOS() == llvm::Triple::WASIp3)
95 const ArgList &Args) {
96 return Triple.getOS() == llvm::Triple::WASIp3;
108 const char *LinkingOutput)
const {
112 ArgStringList CmdArgs;
114 CmdArgs.push_back(
"-m");
116 CmdArgs.push_back(
"wasm64");
118 CmdArgs.push_back(
"wasm32");
120 if (Args.hasArg(options::OPT_s))
121 CmdArgs.push_back(
"--strip-all");
123 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
124 CmdArgs.push_back(
"--no-demangle");
130 if (llvm::sys::path::stem(
Linker).ends_with_insensitive(
131 "wasm-component-ld")) {
132 CmdArgs.push_back(
"--wasm-ld-path");
136 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});
140 bool IsCommand =
true;
142 const char *Entry =
nullptr;
146 if (Args.hasArg(options::OPT_shared))
149 if (
const Arg *A = Args.getLastArg(options::OPT_mexec_model_EQ)) {
150 StringRef CM = A->getValue();
151 if (CM ==
"command") {
153 }
else if (CM ==
"reactor") {
157 << CM << A->getOption().getName();
170 Crt1 =
"crt1-command.o";
172 Crt1 =
"crt1-reactor.o";
173 Entry =
"_initialize";
176 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles))
179 CmdArgs.push_back(Args.MakeArgString(
"--entry"));
180 CmdArgs.push_back(Args.MakeArgString(Entry));
183 if (Args.hasArg(options::OPT_shared))
184 CmdArgs.push_back(Args.MakeArgString(
"-shared"));
189 CmdArgs.push_back(
"--cooperative-threading");
192 CmdArgs.push_back(
"--shared-memory");
194 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
199 CmdArgs.push_back(
"-lpthread");
201 CmdArgs.push_back(
"-lc");
207 CmdArgs.push_back(
"-o");
214 bool RunWasmOpt = Args.hasFlag(options::OPT_wasm_opt,
215 options::OPT_no_wasm_opt, WasmOptDefault);
219 std::string WasmOptPath;
220 if (RunWasmOpt && Args.getLastArg(options::OPT_O_Group)) {
222 if (WasmOptPath ==
"wasm-opt") {
227 if (!WasmOptPath.empty()) {
228 CmdArgs.push_back(
"--keep-section=target_features");
231 C.addCommand(std::make_unique<Command>(JA, *
this,
233 Linker, CmdArgs, Inputs, Output));
235 if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
236 if (!WasmOptPath.empty()) {
237 StringRef OOpt =
"s";
238 if (A->getOption().matches(options::OPT_O4) ||
239 A->getOption().matches(options::OPT_Ofast))
241 else if (A->getOption().matches(options::OPT_O0))
243 else if (A->getOption().matches(options::OPT_O))
244 OOpt = A->getValue();
247 const char *WasmOpt = Args.MakeArgString(WasmOptPath);
248 ArgStringList OptArgs;
250 OptArgs.push_back(Args.MakeArgString(llvm::Twine(
"-O") + OOpt));
251 OptArgs.push_back(
"-o");
253 C.addCommand(std::make_unique<Command>(
265 const llvm::opt::ArgList &Args,
266 const std::string &Dir) {
270 Paths.push_back(Dir +
"/llvm-lto/" LLVM_VERSION_STRING);
272 Paths.push_back(Dir);
276 const llvm::opt::ArgList &Args)
277 : ToolChain(D, Triple, Args) {
279 assert(Triple.isArch32Bit() != Triple.isArch64Bit());
281 getProgramPaths().push_back(getDriver().Dir);
283 auto SysRoot = getDriver().SysRoot;
284 if (
getTriple().getOS() == llvm::Triple::UnknownOS) {
289 getFilePaths().push_back(SysRoot +
"/lib");
291 const std::string MultiarchTriple =
292 getMultiarchTriple(getDriver(), Triple, SysRoot);
293 std::string TripleLibDir = SysRoot +
"/lib/" + MultiarchTriple;
304 if (
getTriple().getOS() == llvm::Triple::WASI) {
305 D.
Diag(diag::warn_drv_deprecated_custom)
306 <<
"--target=wasm32-wasi"
307 <<
"use --target=wasm32-wasip1 instead";
311const char *WebAssembly::getDefaultLinker()
const {
313 return "wasm-component-ld";
325bool WebAssembly::isPIEDefault(
const llvm::opt::ArgList &Args)
const {
338void WebAssembly::addClangTargetOptions(
const ArgList &DriverArgs,
339 ArgStringList &CC1Args, BoundArch BA,
341 if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
342 options::OPT_fno_use_init_array,
true))
343 CC1Args.push_back(
"-fno-use-init-array");
350 DriverArgs.hasFlag(options::OPT_mno_atomics, options::OPT_matomics,
355 if (DriverArgs.hasFlag(options::OPT_mno_bulk_memory,
356 options::OPT_mbulk_memory,
false))
359 <<
"-mno-bulk-memory";
360 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
361 options::OPT_mmutable_globals,
false))
364 <<
"-mno-mutable-globals";
365 if (DriverArgs.hasFlag(options::OPT_mno_sign_ext, options::OPT_msign_ext,
371 CC1Args.push_back(
"-target-feature");
372 CC1Args.push_back(
"+atomics");
374 CC1Args.push_back(
"-target-feature");
375 CC1Args.push_back(
"+bulk-memory");
376 CC1Args.push_back(
"-target-feature");
377 CC1Args.push_back(
"+mutable-globals");
378 CC1Args.push_back(
"-target-feature");
379 CC1Args.push_back(
"+sign-ext");
382 if (!DriverArgs.hasFlag(options::OPT_mmutable_globals,
383 options::OPT_mno_mutable_globals,
false)) {
386 llvm::Reloc::Model RelocationModel;
389 std::tie(RelocationModel, PICLevel, IsPIE) =
391 if (RelocationModel == llvm::Reloc::PIC_) {
392 if (DriverArgs.hasFlag(options::OPT_mno_mutable_globals,
393 options::OPT_mmutable_globals,
false)) {
396 <<
"-mno-mutable-globals";
398 CC1Args.push_back(
"-target-feature");
399 CC1Args.push_back(
"+mutable-globals");
403 bool HasBannedIncompatibleOptionsForWasmEHSjLj =
false;
404 bool HasEnabledFeaturesForWasmEHSjLj =
false;
408 auto BanIncompatibleOptionsForWasmEHSjLj = [&](StringRef CurOption) {
409 if (HasBannedIncompatibleOptionsForWasmEHSjLj)
411 HasBannedIncompatibleOptionsForWasmEHSjLj =
true;
412 if (DriverArgs.hasFlag(options::OPT_mno_exception_handing,
413 options::OPT_mexception_handing,
false))
415 << CurOption <<
"-mno-exception-handling";
417 if (DriverArgs.hasFlag(options::OPT_mno_multivalue,
418 options::OPT_mmultivalue,
false))
420 << CurOption <<
"-mno-multivalue";
421 if (DriverArgs.hasFlag(options::OPT_mno_reference_types,
422 options::OPT_mreference_types,
false))
424 << CurOption <<
"-mno-reference-types";
426 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
427 for (
const auto *Option :
428 {
"-enable-emscripten-cxx-exceptions",
"-enable-emscripten-sjlj",
429 "-emscripten-cxx-exceptions-allowed"}) {
430 if (StringRef(A->getValue(0)) == Option)
432 << CurOption << Option;
438 auto EnableFeaturesForWasmEHSjLj = [&]() {
439 if (HasEnabledFeaturesForWasmEHSjLj)
441 HasEnabledFeaturesForWasmEHSjLj =
true;
442 CC1Args.push_back(
"-target-feature");
443 CC1Args.push_back(
"+exception-handling");
445 CC1Args.push_back(
"-target-feature");
446 CC1Args.push_back(
"+multivalue");
447 CC1Args.push_back(
"-target-feature");
448 CC1Args.push_back(
"+reference-types");
450 CC1Args.push_back(
"-exception-model=wasm");
453 if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) {
454 BanIncompatibleOptionsForWasmEHSjLj(
"-fwasm-exceptions");
455 EnableFeaturesForWasmEHSjLj();
457 CC1Args.push_back(
"-mllvm");
458 CC1Args.push_back(
"-wasm-enable-eh");
461 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
462 StringRef Opt = A->getValue(0);
463 if (Opt.starts_with(
"-emscripten-cxx-exceptions-allowed")) {
466 bool EmEHArgExists =
false;
467 for (
const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
468 if (StringRef(A->getValue(0)) ==
"-enable-emscripten-cxx-exceptions") {
469 EmEHArgExists =
true;
475 <<
"-mllvm -emscripten-cxx-exceptions-allowed"
476 <<
"-mllvm -enable-emscripten-cxx-exceptions";
480 StringRef FuncNamesStr = Opt.split(
'=').second;
481 SmallVector<StringRef, 4> FuncNames;
482 FuncNamesStr.split(FuncNames,
',');
483 for (
auto Name : FuncNames) {
484 CC1Args.push_back(
"-mllvm");
485 CC1Args.push_back(DriverArgs.MakeArgString(
"--force-attribute=" + Name +
490 for (
const auto *Option :
491 {
"-wasm-enable-eh",
"-wasm-enable-sjlj",
"-wasm-use-legacy-eh"}) {
492 if (Opt.starts_with(Option)) {
493 BanIncompatibleOptionsForWasmEHSjLj(Option);
494 EnableFeaturesForWasmEHSjLj();
505WebAssembly::GetCXXStdlibType(
const ArgList &Args)
const {
506 if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
507 StringRef
Value = A->getValue();
508 if (
Value ==
"libc++")
510 else if (
Value ==
"libstdc++")
514 << A->getAsString(Args);
519void WebAssembly::AddClangSystemIncludeArgs(
const ArgList &DriverArgs,
520 ArgStringList &CC1Args)
const {
521 if (DriverArgs.hasArg(options::OPT_nostdinc))
526 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
527 SmallString<128> P(D.ResourceDir);
528 llvm::sys::path::append(P,
"include");
532 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
536 StringRef CIncludeDirs(C_INCLUDE_DIRS);
537 if (CIncludeDirs !=
"") {
538 SmallVector<StringRef, 5> dirs;
539 CIncludeDirs.split(dirs,
":");
540 for (StringRef dir : dirs) {
542 llvm::sys::path::is_absolute(dir) ?
"" : StringRef(D.SysRoot);
549 const std::string MultiarchTriple =
550 getMultiarchTriple(D,
getTriple(), D.SysRoot);
551 addSystemInclude(DriverArgs, CC1Args, D.SysRoot +
"/include/" + MultiarchTriple);
556void WebAssembly::AddClangCXXStdlibIncludeArgs(
const ArgList &DriverArgs,
557 ArgStringList &CC1Args)
const {
559 if (DriverArgs.hasArg(options::OPT_nostdlibinc, options::OPT_nostdinc,
560 options::OPT_nostdincxx))
563 switch (GetCXXStdlibType(DriverArgs)) {
565 addLibCxxIncludePaths(DriverArgs, CC1Args);
568 addLibStdCXXIncludePaths(DriverArgs, CC1Args);
573void WebAssembly::AddCXXStdlibLibArgs(
const llvm::opt::ArgList &Args,
574 llvm::opt::ArgStringList &CmdArgs)
const {
576 switch (GetCXXStdlibType(Args)) {
578 CmdArgs.push_back(
"-lc++");
579 if (Args.hasArg(options::OPT_fexperimental_library))
580 CmdArgs.push_back(
"-lc++experimental");
581 CmdArgs.push_back(
"-lc++abi");
584 CmdArgs.push_back(
"-lstdc++");
589SanitizerMask WebAssembly::getSupportedSanitizers(
593 Res |= SanitizerKind::Vptr | SanitizerKind::Leak;
597 Res |= SanitizerKind::Address;
607 return new tools::wasm::Linker(*
this);
610void WebAssembly::addLibCxxIncludePaths(
611 const llvm::opt::ArgList &DriverArgs,
612 llvm::opt::ArgStringList &CC1Args)
const {
615 std::string LibPath = SysRoot +
"/include";
616 const std::string MultiarchTriple =
617 getMultiarchTriple(D,
getTriple(), SysRoot);
618 bool IsKnownOs = (
getTriple().getOS() != llvm::Triple::UnknownOS);
627 std::string TargetDir = LibPath +
"/" + MultiarchTriple;
628 std::string Suffix =
"/c++/" + Version;
639void WebAssembly::addLibStdCXXIncludePaths(
640 const llvm::opt::ArgList &DriverArgs,
641 llvm::opt::ArgStringList &CC1Args)
const {
648 std::string LibPath = SysRoot +
"/include";
649 const std::string MultiarchTriple =
650 getMultiarchTriple(D,
getTriple(), SysRoot);
651 bool IsKnownOs = (
getTriple().getOS() != llvm::Triple::UnknownOS);
657 Generic_GCC::GCCVersion MaxVersion =
659 SmallString<128> Path(LibPath);
660 llvm::sys::path::append(Path,
"c++");
661 for (llvm::vfs::directory_iterator LI =
getVFS().dir_begin(Path, EC), LE;
662 !EC && LI !=
LE; LI = LI.increment(EC)) {
663 StringRef VersionText = llvm::sys::path::filename(LI->path());
664 if (VersionText[0] !=
'v') {
666 if (Version > MaxVersion)
667 MaxVersion = Version;
670 if (MaxVersion.
Major > 0)
671 Version = MaxVersion.
Text;
679 std::string TargetDir = LibPath +
"/c++/" + Version +
"/" + MultiarchTriple;
686 addSystemInclude(DriverArgs, CC1Args, LibPath +
"/c++/" + Version +
"/backward");
static StringRef getTriple(const Command &Job)
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
SmallVector< InputInfo, 4 > InputInfoList
bool LE(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
bool(*)(llvm::ArrayRef< const char * >, llvm::raw_ostream &, llvm::raw_ostream &, bool, bool) Driver
static constexpr ResponseFileSupport AtFileCurCP()