Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -187,7 +187,8 @@ AMDPAL, // AMD PAL Runtime HermitCore, // HermitCore Unikernel/Multikernel Hurd, // GNU/Hurd - LastOSType = Hurd + COWS, // Capability-Oriented WebAssembly Syscalls + LastOSType = COWS }; enum EnvironmentType { UnknownEnvironment, @@ -588,6 +589,11 @@ return getOS() == Triple::Hurd; } + /// Tests whether the OS is COWS. + bool isOSCOWS() const { + return getOS() == Triple::COWS; + } + /// Tests whether the OS uses glibc. bool isOSGlibc() const { return (getOS() == Triple::Linux || getOS() == Triple::KFreeBSD || Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -211,6 +211,7 @@ case AMDPAL: return "amdpal"; case HermitCore: return "hermit"; case Hurd: return "hurd"; + case COWS: return "cows"; } llvm_unreachable("Invalid OSType"); @@ -510,6 +511,7 @@ .StartsWith("amdpal", Triple::AMDPAL) .StartsWith("hermit", Triple::HermitCore) .StartsWith("hurd", Triple::Hurd) + .StartsWith("cows", Triple::COWS) .Default(Triple::UnknownOS); } Index: tools/clang/lib/Basic/Targets.cpp =================================================================== --- tools/clang/lib/Basic/Targets.cpp +++ tools/clang/lib/Basic/Targets.cpp @@ -572,18 +572,20 @@ case llvm::Triple::wasm32: if (Triple.getSubArch() != llvm::Triple::NoSubArch || Triple.getVendor() != llvm::Triple::UnknownVendor || - Triple.getOS() != llvm::Triple::UnknownOS || - Triple.getEnvironment() != llvm::Triple::UnknownEnvironment || - !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm())) + !Triple.isOSBinFormatWasm()) return nullptr; + if (Triple.getOS() != llvm::Triple::UnknownOS && + Triple.getOS() != llvm::Triple::COWS) + return nullptr; return new WebAssemblyOSTargetInfo(Triple, Opts); case llvm::Triple::wasm64: if (Triple.getSubArch() != llvm::Triple::NoSubArch || Triple.getVendor() != llvm::Triple::UnknownVendor || - Triple.getOS() != llvm::Triple::UnknownOS || - Triple.getEnvironment() != llvm::Triple::UnknownEnvironment || - !(Triple.isOSBinFormatELF() || Triple.isOSBinFormatWasm())) + !Triple.isOSBinFormatWasm()) return nullptr; + if (Triple.getOS() != llvm::Triple::UnknownOS && + Triple.getOS() != llvm::Triple::COWS) + return nullptr; return new WebAssemblyOSTargetInfo(Triple, Opts); case llvm::Triple::renderscript32: Index: tools/clang/lib/Driver/ToolChains/WebAssembly.cpp =================================================================== --- tools/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ tools/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -24,6 +24,15 @@ wasm::Linker::Linker(const ToolChain &TC) : GnuTool("wasm::Linker", "lld", TC) {} +/// Following the conventions in https://wiki.debian.org/Multiarch/Tuples, +/// we remove the vendor field to form the multiarch triple. +static std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) { + return TargetTriple.getArchName() + "-" + + TargetTriple.getOSAndEnvironmentName(); +} + bool wasm::Linker::isLinkJob() const { return true; } bool wasm::Linker::hasIntegratedCPP() const { return false; } @@ -75,7 +84,16 @@ getProgramPaths().push_back(getDriver().getInstalledDir()); - getFilePaths().push_back(getDriver().SysRoot + "/lib"); + if (Triple.getOS() == Triple::UnknownOS) { + // Theoretically an "unknown" OS should mean no standard libraries, however + // it could also mean that a custom set of libraries is in use, so just add + // /lib to the search path. Disable multiarch in this case, to discourage + // paths containing "unknown" from acquiring meanings. + getFilePaths().push_back(getDriver().SysRoot + "/lib"); + } else { + const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); + getFilePaths().push_back(getDriver().SysRoot + "/lib/" + MultiarchTriple); + } } bool WebAssembly::IsMathErrnoDefault() const { return false; } @@ -124,16 +142,27 @@ void WebAssembly::AddClangSystemIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { - if (!DriverArgs.hasArg(options::OPT_nostdinc)) + if (!DriverArgs.hasArg(options::OPT_nostdinc)) { + if (Triple.getOS() != Triple::UnknownOS) { + const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/" + MultiarchTriple); + } addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include"); + } } void WebAssembly::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { if (!DriverArgs.hasArg(options::OPT_nostdlibinc) && - !DriverArgs.hasArg(options::OPT_nostdincxx)) + !DriverArgs.hasArg(options::OPT_nostdincxx)) { + if (Triple.getOS() != Triple::UnknownOS) { + const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/include/" + MultiarchTriple + "/c++/v1"); + } addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/include/c++/v1"); + } } void WebAssembly::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, Index: tools/clang/test/Driver/wasm-toolchain.c =================================================================== --- tools/clang/test/Driver/wasm-toolchain.c +++ tools/clang/test/Driver/wasm-toolchain.c @@ -10,14 +10,31 @@ // RUN: %clang %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s // FVISIBILITY_DEFAULT-NOT: hidden -// A basic C link command-line. +// A basic C link command-line with unknown OS. // RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK %s // LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" -// A basic C link command-line with optimization. +// A basic C link command-line with optimization with unknown OS. // RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s // LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C link command-line with known OS. + +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK %s +// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK: wasm-ld{{.*}}" "-L/foo/lib/wasm32-cows-musl" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C link command-line with optimization with known OS. + +// RUN: %clang -### -O2 -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK_OPT %s +// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib/wasm32-cows-musl" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C compile command-line with known OS. + +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo %s 2>&1 | FileCheck -check-prefix=COMPILE %s +// COMPILE: clang{{.*}}" "-cc1" {{.*}} -I /foo/wasm32-cows-musl/include -I /include Index: tools/clang/test/Driver/wasm-toolchain.cpp =================================================================== --- tools/clang/test/Driver/wasm-toolchain.cpp +++ tools/clang/test/Driver/wasm-toolchain.cpp @@ -10,14 +10,31 @@ // RUN: %clangxx %s -### -target wasm32-unknown-unknown -fvisibility=default 2>&1 | FileCheck -check-prefix=FVISIBILITY_DEFAULT %s // FVISIBILITY_DEFAULT-NOT: hidden -// A basic C++ link command-line. +// A basic C++ link command-line with unknown OS. -// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo --stdlib=c++ -fuse-ld=wasm-ld %s 2>&1 | FileCheck -check-prefix=LINK %s +// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo -fuse-ld=wasm-ld --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK %s // LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" -// A basic C++ link command-line with optimization. +// A basic C++ link command-line with optimization with unknown OS. // RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s --stdlib=c++ -fuse-ld=wasm-ld 2>&1 | FileCheck -check-prefix=LINK_OPT %s // LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" // LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C++ link command-line with known OS. + +// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo -fuse-ld=wasm-ld --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=LINK %s +// LINK: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK: wasm-ld{{.*}}" "-L/foo/lib/wasm32-cows-musl" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C++ link command-line with optimization with known OS. + +// RUN: %clangxx -### -O2 -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo %s --stdlib=c++ -fuse-ld=wasm-ld 2>&1 | FileCheck -check-prefix=LINK_OPT %s +// LINK_OPT: clang{{.*}}" "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_OPT: wasm-ld{{.*}}" "-L/foo/lib/wasm32-cows-musl" "crt1.o" "[[temp]]" "-lc++" "-lc++abi" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// A basic C++ compile command-line with known OS. + +// RUN: %clangxx -### -no-canonical-prefixes -target wasm32-unknown-cows-musl --sysroot=/foo --stdlib=c++ %s 2>&1 | FileCheck -check-prefix=COMPILE %s +// COMPILE: clang{{.*}}" "-cc1" {{.*}} -I /foo/wasm32-cows-musl/include -I /include -I /foo/wasm32-cows-musl/include/c++/v1 -I /foo/wasm32/include/c++/v1 Index: unittests/ADT/TripleTest.cpp =================================================================== --- unittests/ADT/TripleTest.cpp +++ unittests/ADT/TripleTest.cpp @@ -253,6 +253,12 @@ EXPECT_EQ(Triple::UnknownOS, T.getOS()); EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("wasm32-unknown-cows-musl"); + EXPECT_EQ(Triple::wasm32, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::COWS, T.getOS()); + EXPECT_EQ(Triple::Musl, T.getEnvironment()); + T = Triple("wasm64-unknown-unknown"); EXPECT_EQ(Triple::wasm64, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); @@ -259,6 +265,12 @@ EXPECT_EQ(Triple::UnknownOS, T.getOS()); EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("wasm64-unknown-cows-musl"); + EXPECT_EQ(Triple::wasm64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::COWS, T.getOS()); + EXPECT_EQ(Triple::Musl, T.getEnvironment()); + T = Triple("avr-unknown-unknown"); EXPECT_EQ(Triple::avr, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); @@ -1235,11 +1247,17 @@ EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-unknown").getObjectFormat()); EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-unknown").getObjectFormat()); + EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-cows-musl").getObjectFormat()); + EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-cows-musl").getObjectFormat()); EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-unknown-wasm").getObjectFormat()); EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-unknown-wasm").getObjectFormat()); + EXPECT_EQ(Triple::Wasm, + Triple("wasm32-unknown-cows-musl-wasm").getObjectFormat()); + EXPECT_EQ(Triple::Wasm, + Triple("wasm64-unknown-cows-musl-wasm").getObjectFormat()); Triple MSVCNormalized(Triple::normalize("i686-pc-windows-msvc-elf")); EXPECT_EQ(Triple::ELF, MSVCNormalized.getObjectFormat());