mirror of https://github.com/WebAssembly/wasi-sdk
commit
1ace2ed4da
@ -1,2 +1,3 @@
|
||||
build
|
||||
dist
|
||||
experimental
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
# Ubuntu 24.04 is used here (rather than AlmaLinux 8) because it has
|
||||
# riscv64 cross-compilation packages in its repositories.
|
||||
FROM ubuntu:24.04
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
ca-certificates \
|
||||
crossbuild-essential-riscv64 \
|
||||
clang \
|
||||
lld \
|
||||
python3 \
|
||||
git \
|
||||
unzip \
|
||||
cmake \
|
||||
ninja-build \
|
||||
ccache \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Cargo needs an explicit linker when cross-compiling for riscv64.
|
||||
# The C/C++ cross-compiler is passed via CMAKE_C/CXX_COMPILER cmake flags
|
||||
# rather than CC/CXX env vars so that LLVM's native tblgen sub-build can
|
||||
# still find the host compiler (cmake cache vars are not inherited by
|
||||
# subprocess cmake invocations, but env vars are).
|
||||
ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc
|
||||
|
||||
# Tell programs to cache in a location that both isn't a `--volume` mounted root
|
||||
# and isn't `/root` in the container as that won't be writable during the build.
|
||||
ENV XDG_CACHE_HOME=/tmp/cache
|
||||
@ -0,0 +1,105 @@
|
||||
From d702761d9135ebbb83590d4dd1323be433701ebd Mon Sep 17 00:00:00 2001
|
||||
From: Alex Crichton <alex@alexcrichton.com>
|
||||
Date: Tue, 10 Mar 2026 15:49:55 -0700
|
||||
Subject: [PATCH] [WebAssembly] Move __cpp_exception to libunwind
|
||||
|
||||
The `__cpp_exception` symbol is now defined in libunwind instead of
|
||||
compiler-rt. This is moved for a few reasons, but the primary reason is
|
||||
that compiler-rt is linked duplicate-ly into all shared objects meaning
|
||||
that it's not suitable for define-once symbols such as
|
||||
`__cpp_exception`. By moving the definition to the user of the symbol,
|
||||
libunwind itself, that guarantees that the symbol should be defined
|
||||
exactly once and only when appropriate. A secondary reason for this
|
||||
movement is that it avoids the need to compile compiler-rt twice: once
|
||||
with exception and once without, and instead the same build can be used
|
||||
for both exceptions-and-not.
|
||||
---
|
||||
compiler-rt/lib/builtins/CMakeLists.txt | 1 -
|
||||
.../lib/builtins/wasm/__cpp_exception.S | 26 -------------------
|
||||
libunwind/src/Unwind-wasm.c | 15 +++++++++++
|
||||
.../compiler-rt/lib/builtins/sources.gni | 1 -
|
||||
4 files changed, 15 insertions(+), 28 deletions(-)
|
||||
delete mode 100644 compiler-rt/lib/builtins/wasm/__cpp_exception.S
|
||||
|
||||
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
|
||||
index 6c27f6d4d529e..f0570a9092f40 100644
|
||||
--- a/compiler-rt/lib/builtins/CMakeLists.txt
|
||||
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
|
||||
@@ -891,7 +891,6 @@ set(s390x_SOURCES
|
||||
|
||||
set(wasm_SOURCES
|
||||
wasm/__c_longjmp.S
|
||||
- wasm/__cpp_exception.S
|
||||
${GENERIC_TF_SOURCES}
|
||||
${GENERIC_SOURCES}
|
||||
)
|
||||
diff --git a/compiler-rt/lib/builtins/wasm/__cpp_exception.S b/compiler-rt/lib/builtins/wasm/__cpp_exception.S
|
||||
deleted file mode 100644
|
||||
index 0496e1dbf6158..0000000000000
|
||||
--- a/compiler-rt/lib/builtins/wasm/__cpp_exception.S
|
||||
+++ /dev/null
|
||||
@@ -1,26 +0,0 @@
|
||||
-//===-- __cpp_exception.S - Implement __cpp_exception ---------------------===//
|
||||
-//
|
||||
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
-// See https://llvm.org/LICENSE.txt for license information.
|
||||
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
-//
|
||||
-//===----------------------------------------------------------------------===//
|
||||
-//
|
||||
-// This file implements __cpp_exception which LLVM uses to implement exception
|
||||
-// handling when Wasm EH is enabled.
|
||||
-//
|
||||
-//===----------------------------------------------------------------------===//
|
||||
-
|
||||
-#ifdef __wasm_exception_handling__
|
||||
-
|
||||
-#ifdef __wasm64__
|
||||
-#define PTR i64
|
||||
-#else
|
||||
-#define PTR i32
|
||||
-#endif
|
||||
-
|
||||
-.globl __cpp_exception
|
||||
-.tagtype __cpp_exception PTR
|
||||
-__cpp_exception:
|
||||
-
|
||||
-#endif // !__wasm_exception_handling__
|
||||
diff --git a/libunwind/src/Unwind-wasm.c b/libunwind/src/Unwind-wasm.c
|
||||
index 2f4498c3f3989..c0ca9b775d244 100644
|
||||
--- a/libunwind/src/Unwind-wasm.c
|
||||
+++ b/libunwind/src/Unwind-wasm.c
|
||||
@@ -69,6 +69,21 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
|
||||
__builtin_wasm_throw(0, exception_object);
|
||||
}
|
||||
|
||||
+// Define the `__cpp_exception` symbol which `__builtin_wasm_throw` above will
|
||||
+// reference. This is defined here in `libunwind` as the single canonical
|
||||
+// definition for this API and it's required for users to ensure that there's
|
||||
+// only one copy of `libunwind` within a wasm module to ensure this is only
|
||||
+// defined once and exactly once.
|
||||
+__asm__(".globl __cpp_exception\n"
|
||||
+#if defined(__wasm32__)
|
||||
+ ".tagtype __cpp_exception i32\n"
|
||||
+#elif defined(__wasm64__)
|
||||
+ ".tagtype __cpp_exception i64\n"
|
||||
+#else
|
||||
+#error "Unsupported Wasm architecture"
|
||||
+#endif
|
||||
+ "__cpp_exception:\n");
|
||||
+
|
||||
/// Called by __cxa_end_catch.
|
||||
_LIBUNWIND_EXPORT void
|
||||
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
|
||||
diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/builtins/sources.gni b/llvm/utils/gn/secondary/compiler-rt/lib/builtins/sources.gni
|
||||
index 2ac71aa8e8367..c9eeede16e3eb 100644
|
||||
--- a/llvm/utils/gn/secondary/compiler-rt/lib/builtins/sources.gni
|
||||
+++ b/llvm/utils/gn/secondary/compiler-rt/lib/builtins/sources.gni
|
||||
@@ -539,7 +539,6 @@ if (current_cpu == "ve") {
|
||||
if (current_cpu == "wasm") {
|
||||
builtins_sources += [
|
||||
"wasm/__c_longjmp.S",
|
||||
- "wasm/__cpp_exception.S",
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
From 0e36e8f304cd5f3997916f5d85201bb17e340337 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Crichton <alex@alexcrichton.com>
|
||||
Date: Tue, 10 Mar 2026 16:14:36 -0700
|
||||
Subject: [PATCH] [WebAssembly] Clang support for exception-based lookup paths
|
||||
|
||||
This commit is an attempt to make progress on WebAssembly/wasi-sdk#565
|
||||
where with wasi-sdk I'd like to ship a single toolchain which is
|
||||
capable of building binaries both with C++ exceptions and without. This
|
||||
means that there can't be a single set of precompiled libraries that are
|
||||
used because one set of libraries is wrong for the other mode. The
|
||||
support added here is to use `-fwasm-exceptions` to automatically select
|
||||
a lookup path in the sysroot. The intention is then that wasi-sdk will
|
||||
ship both a "eh" set of C++ libraries as well as a "noeh" set of C++
|
||||
libraries too. Clang will automatically select the correct one based on
|
||||
compilation flags which means that the final distribution will be able
|
||||
to build both binaries with exceptions and without.
|
||||
---
|
||||
clang/lib/Driver/ToolChains/WebAssembly.cpp | 51 ++++++++++++++-------
|
||||
clang/test/Driver/wasm-toolchain.cpp | 35 ++++++++++++++
|
||||
2 files changed, 70 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
|
||||
index b5fa5760a46a0..e532ef0743cc2 100644
|
||||
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
|
||||
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
|
||||
@@ -34,6 +34,15 @@ std::string WebAssembly::getMultiarchTriple(const Driver &D,
|
||||
TargetTriple.getOSAndEnvironmentName()).str();
|
||||
}
|
||||
|
||||
+/// Returns a directory name in which separate objects compile with/without
|
||||
+/// exceptions may lie. This is used both for `#include` paths as well as lib
|
||||
+/// paths.
|
||||
+static std::string GetCXXExceptionsDir(const ArgList &DriverArgs) {
|
||||
+ if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions))
|
||||
+ return "eh";
|
||||
+ return "noeh";
|
||||
+}
|
||||
+
|
||||
std::string wasm::Linker::getLinkerPath(const ArgList &Args) const {
|
||||
const ToolChain &ToolChain = getToolChain();
|
||||
if (const Arg* A = Args.getLastArg(options::OPT_fuse_ld_EQ)) {
|
||||
@@ -230,12 +239,16 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
}
|
||||
}
|
||||
|
||||
-/// Given a base library directory, append path components to form the
|
||||
-/// LTO directory.
|
||||
-static std::string AppendLTOLibDir(const std::string &Dir) {
|
||||
+/// Append `Dir` to `Paths`, but also include the LTO directories before that if
|
||||
+/// LTO is eanbled.
|
||||
+static void AppendLibDirAndLTODir(ToolChain::path_list &Paths, const Driver &D,
|
||||
+ const std::string &Dir) {
|
||||
+ if (D.isUsingLTO()) {
|
||||
// The version allows the path to be keyed to the specific version of
|
||||
// LLVM in used, as the bitcode format is not stable.
|
||||
- return Dir + "/llvm-lto/" LLVM_VERSION_STRING;
|
||||
+ Paths.push_back(Dir + "/llvm-lto/" LLVM_VERSION_STRING);
|
||||
+ }
|
||||
+ Paths.push_back(Dir);
|
||||
}
|
||||
|
||||
WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
|
||||
@@ -256,14 +269,15 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
|
||||
} else {
|
||||
const std::string MultiarchTriple =
|
||||
getMultiarchTriple(getDriver(), Triple, SysRoot);
|
||||
- if (D.isUsingLTO()) {
|
||||
- // For LTO, enable use of lto-enabled sysroot libraries too, if available.
|
||||
- // Note that the directory is keyed to the LLVM revision, as LLVM's
|
||||
- // bitcode format is not stable.
|
||||
- auto Dir = AppendLTOLibDir(SysRoot + "/lib/" + MultiarchTriple);
|
||||
- getFilePaths().push_back(Dir);
|
||||
- }
|
||||
- getFilePaths().push_back(SysRoot + "/lib/" + MultiarchTriple);
|
||||
+ std::string TripleLibDir = SysRoot + "/lib/" + MultiarchTriple;
|
||||
+ // Allow sysroots to segregate objects based on whether exceptions are
|
||||
+ // enabled or not. This is intended to assist with distribution of pre-built
|
||||
+ // sysroots that contain libraries that are capable of producing binaries
|
||||
+ // entirely without exception-handling instructions but also with if
|
||||
+ // exceptions are enabled, for example.
|
||||
+ AppendLibDirAndLTODir(getFilePaths(), D,
|
||||
+ TripleLibDir + "/" + GetCXXExceptionsDir(Args));
|
||||
+ AppendLibDirAndLTODir(getFilePaths(), D, TripleLibDir);
|
||||
}
|
||||
|
||||
if (getTriple().getOS() == llvm::Triple::WASI) {
|
||||
@@ -580,13 +594,18 @@ void WebAssembly::addLibCxxIncludePaths(
|
||||
if (Version.empty())
|
||||
return;
|
||||
|
||||
- // First add the per-target include path if the OS is known.
|
||||
+ // First add the per-target-per-exception-handling include path if the
|
||||
+ // OS is known, then second add the per-target include path.
|
||||
if (IsKnownOs) {
|
||||
- std::string TargetDir = LibPath + "/" + MultiarchTriple + "/c++/" + Version;
|
||||
- addSystemInclude(DriverArgs, CC1Args, TargetDir);
|
||||
+ std::string TargetDir = LibPath + "/" + MultiarchTriple;
|
||||
+ std::string Suffix = "/c++/" + Version;
|
||||
+ addSystemInclude(DriverArgs, CC1Args,
|
||||
+ TargetDir + "/" + GetCXXExceptionsDir(DriverArgs) +
|
||||
+ Suffix);
|
||||
+ addSystemInclude(DriverArgs, CC1Args, TargetDir + Suffix);
|
||||
}
|
||||
|
||||
- // Second add the generic one.
|
||||
+ // Third add the generic one.
|
||||
addSystemInclude(DriverArgs, CC1Args, LibPath + "/c++/" + Version);
|
||||
}
|
||||
|
||||
diff --git a/clang/test/Driver/wasm-toolchain.cpp b/clang/test/Driver/wasm-toolchain.cpp
|
||||
index d7ff76cedfd10..30a2f9397e3f4 100644
|
||||
--- a/clang/test/Driver/wasm-toolchain.cpp
|
||||
+++ b/clang/test/Driver/wasm-toolchain.cpp
|
||||
@@ -111,3 +111,38 @@
|
||||
// COMPILE_WALI_STDCXX: "-internal-isystem" "[[RESOURCE_DIR]]{{(/|\\\\)}}include"
|
||||
// COMPILE_WALI_STDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-linux-muslwali"
|
||||
// COMPILE_WALI_STDCXX: "-internal-isystem" "[[SYSROOT:[^"]+]]/include"
|
||||
+
|
||||
+// With a known OS "eh" and "noeh" directories are added to enable segregating
|
||||
+// object built with/without exception-handling
|
||||
+
|
||||
+// RUN: %clangxx -### --target=wasm32-wasi --stdlib=libc++ %s 2>&1 \
|
||||
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/usr \
|
||||
+// RUN: | FileCheck -check-prefix=EH_OFF %s
|
||||
+// EH_OFF: "-cc1"
|
||||
+// EH_OFF: "-isysroot" "[[SYSROOT:[^"]+]]"
|
||||
+// EH_OFF: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/noeh/c++/v1"
|
||||
+// EH_OFF-NOT: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/eh/c++/v1"
|
||||
+// EH_OFF: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/c++/v1"
|
||||
+// EH_OFF: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/v1"
|
||||
+// EH_OFF: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi"
|
||||
+// EH_OFF: "-internal-isystem" "[[SYSROOT:[^"]+]]/include"
|
||||
+
|
||||
+// RUN: %clangxx -### --target=wasm32-wasi -fwasm-exceptions --stdlib=libc++ %s 2>&1 \
|
||||
+// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/usr \
|
||||
+// RUN: | FileCheck -check-prefix=EH_ON %s
|
||||
+// EH_ON: "-cc1"
|
||||
+// EH_ON: "-isysroot" "[[SYSROOT:[^"]+]]"
|
||||
+// EH_ON: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/eh/c++/v1"
|
||||
+// EH_ON-NOT: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/noeh/c++/v1"
|
||||
+// EH_ON: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi/c++/v1"
|
||||
+// EH_ON: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/c++/v1"
|
||||
+// EH_ON: "-internal-isystem" "[[SYSROOT:[^"]+]]/include/wasm32-wasi"
|
||||
+// EH_ON: "-internal-isystem" "[[SYSROOT:[^"]+]]/include"
|
||||
+//
|
||||
+// RUN: %clangxx -### --target=wasm32-wasi --sysroot=/foo --stdlib=libc++ %s 2>&1 \
|
||||
+// RUN: | FileCheck -check-prefix=EH_OFF_LINK %s
|
||||
+// EH_OFF_LINK: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi/noeh" "-L/foo/lib/wasm32-wasi"
|
||||
+//
|
||||
+// RUN: %clangxx -### --target=wasm32-wasi -fwasm-exceptions --sysroot=/foo --stdlib=libc++ %s 2>&1 \
|
||||
+// RUN: | FileCheck -check-prefix=EH_ON_LINK %s
|
||||
+// EH_ON_LINK: wasm-ld{{.*}}" "-L/foo/lib/wasm32-wasi/eh" "-L/foo/lib/wasm32-wasi"
|
||||
@ -0,0 +1,48 @@
|
||||
From f71fdfcbd6fcc7b521c74b5856ebeacdd6cf55d9 Mon Sep 17 00:00:00 2001
|
||||
From: Catherine <whitequark@whitequark.org>
|
||||
Date: Thu, 12 Mar 2026 08:19:49 +0000
|
||||
Subject: [PATCH] [libc++abi] Revert gating of `__cxa_thread_atexit` on
|
||||
Linux||Fuchsia
|
||||
|
||||
This was done in the commit 3c100d5d548d with the description
|
||||
"Enable -Wmissing-prototypes" which seems incongruent to me.
|
||||
|
||||
Since then it's made its way into a release and broke the use of
|
||||
`thread_local` variables with destructors on Wasm/WASI:
|
||||
|
||||
```cc
|
||||
// repro.cc
|
||||
struct c { ~c() {} };
|
||||
thread_local c v;
|
||||
int main() { (void)v; }
|
||||
```
|
||||
|
||||
```console
|
||||
$ ./wasi-sdk-31.0-x86_64-linux/bin/clang++ repro.cc
|
||||
wasm-ld: error: /tmp/repro-dd1ad7.o: undefined symbol: __cxa_thread_atexit
|
||||
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
|
||||
```
|
||||
---
|
||||
libcxxabi/src/cxa_thread_atexit.cpp | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libcxxabi/src/cxa_thread_atexit.cpp b/libcxxabi/src/cxa_thread_atexit.cpp
|
||||
index 402a52c741012..1bdcb4ef192b4 100644
|
||||
--- a/libcxxabi/src/cxa_thread_atexit.cpp
|
||||
+++ b/libcxxabi/src/cxa_thread_atexit.cpp
|
||||
@@ -106,7 +106,6 @@ namespace {
|
||||
|
||||
#endif // HAVE___CXA_THREAD_ATEXIT_IMPL
|
||||
|
||||
-#if defined(__linux__) || defined(__Fuchsia__)
|
||||
extern "C" {
|
||||
|
||||
_LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(Dtor dtor, void* obj, void* dso_symbol) throw() {
|
||||
@@ -141,6 +140,5 @@ extern "C" {
|
||||
}
|
||||
#endif // HAVE___CXA_THREAD_ATEXIT_IMPL
|
||||
}
|
||||
-} // extern "C"
|
||||
-#endif // defined(__linux__) || defined(__Fuchsia__)
|
||||
+ } // extern "C"
|
||||
} // namespace __cxxabiv1
|
||||
@ -1 +1 @@
|
||||
Subproject commit fd5840e1ba9d23cbf610abe99f5ff59a4f1bec0e
|
||||
Subproject commit 161b3195fc2558d2b1ba3eb9ffae3b2b47407623
|
||||
@ -1,9 +1,3 @@
|
||||
file(GLOB c_compile_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c")
|
||||
file(GLOB cxx_compile_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc")
|
||||
|
||||
set(compile_tests ${c_compile_tests} ${cxx_compile_tests})
|
||||
|
||||
foreach(test IN LISTS compile_tests)
|
||||
add_testcase("" ${test})
|
||||
endforeach()
|
||||
|
||||
add_testcase(addresses.c COMPILE_ONLY)
|
||||
add_testcase(printf-long-double.c COMPILE_ONLY)
|
||||
add_testcase(test.cc COMPILE_ONLY)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
0
|
||||
@ -1,8 +1,69 @@
|
||||
file(GLOB c_general_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c")
|
||||
file(GLOB cxx_general_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc")
|
||||
add_testcase(abort.c PASS_REGULAR_EXPRESSION "wasm trap.*unreachable")
|
||||
add_testcase(argc_argv_main.c PASS_REGULAR_EXPRESSION "hello from argc argv main")
|
||||
add_testcase(argc_argv_main.cc PASS_REGULAR_EXPRESSION "hello from C\\+\\+ argc argv main")
|
||||
add_testcase(assert-fail.c PASS_REGULAR_EXPRESSION "Assertion failed: false.*wasm trap:.*unreachable")
|
||||
add_testcase(assert-pass.c)
|
||||
add_testcase(clocks.c EMULATED_CLOCKS)
|
||||
add_testcase(cpp_thread_local.cc)
|
||||
add_testcase(ctors_dtors.c PASS_REGULAR_EXPRESSION "\
|
||||
hello from_constructor101
|
||||
hello from_constructor
|
||||
hello from_constructor65535
|
||||
hello main
|
||||
goodbye main
|
||||
hello another_from_atexit
|
||||
hello from_atexit
|
||||
hello from_destructor65535
|
||||
hello from_destructor
|
||||
hello from_destructor101
|
||||
"
|
||||
)
|
||||
add_testcase(ctors_dtors.cc PASS_REGULAR_EXPRESSION "\
|
||||
hello from_constructor101
|
||||
hello from_constructor
|
||||
hello from_constructor65535
|
||||
hello StaticObject::StaticObject
|
||||
hello main
|
||||
goodbye main
|
||||
hello another_from_atexit
|
||||
hello from_atexit
|
||||
hello from_destructor65535
|
||||
hello from_destructor
|
||||
hello StaticObject::~StaticObject
|
||||
hello from_destructor101
|
||||
")
|
||||
add_testcase(empty.c)
|
||||
add_testcase(env-absent.c PASS_REGULAR_EXPRESSION "HELLO = \\(null\\)")
|
||||
add_testcase(env.c ENV HELLO=hello PASS_REGULAR_EXPRESSION "HELLO = hello")
|
||||
add_testcase(environ.c ENV HELLO=hello PASS_REGULAR_EXPRESSION "HELLO = hello")
|
||||
add_testcase(exceptions.cc)
|
||||
add_testcase(getentropy.c)
|
||||
add_testcase(iostream_main.cc PASS_REGULAR_EXPRESSION "hello from C\\+\\+ main with cout")
|
||||
add_testcase(main_errno.c PASS_REGULAR_EXPRESSION "initial errno is 0: Success")
|
||||
add_testcase(mmap.c EMULATED_MMAN FSDIR PASS_REGULAR_EXPRESSION "\
|
||||
“Would you tell me, please, which way I ought to go from here\\?”
|
||||
|
||||
set(general_tests ${c_general_tests} ${cxx_general_tests})
|
||||
|
||||
foreach(test IN LISTS general_tests)
|
||||
add_testcase(${WASI_SDK_RUNWASI} ${test})
|
||||
endforeach()
|
||||
“That depends a good deal on where you want to get to,” said the Cat.
|
||||
"
|
||||
)
|
||||
add_testcase(no_arg_main.c PASS_REGULAR_EXPRESSION "hello from no-arg main")
|
||||
add_testcase(no_arg_main.cc PASS_REGULAR_EXPRESSION "hello from C\\+\\+ no-arg main")
|
||||
add_testcase(opendir.c FSDIR)
|
||||
add_testcase(printf-long-double-enabled.c PRINTSCAN_LONG_DOUBLE PASS_REGULAR_EXPRESSION "the answer is 42.000000")
|
||||
add_testcase(printf-no-float.c PASS_REGULAR_EXPRESSION "the answer is 42")
|
||||
add_testcase(printf-no-long-double.c PASS_REGULAR_EXPRESSION "the answer is 42.000000")
|
||||
add_testcase(sigabrt.c EMULATED_SIGNAL PASS_REGULAR_EXPRESSION "\
|
||||
raising SIGABRT...
|
||||
Program received fatal signal: Aborted
|
||||
.*failed to run main module.*
|
||||
")
|
||||
add_testcase(signals.c EMULATED_SIGNAL PASS_REGULAR_EXPRESSION "\
|
||||
psignal message for SIGINT: Interrupt
|
||||
strsignal for SIGHUP: 'Hangup'
|
||||
beginning handler test:
|
||||
handler for signal Window changed
|
||||
finished handler test
|
||||
")
|
||||
add_testcase(stat.c FSDIR)
|
||||
add_testcase(void_main.c PASS_REGULAR_EXPRESSION "hello from void main")
|
||||
add_testcase(void_main.cc PASS_REGULAR_EXPRESSION "hello from C\\+\\+ void main")
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
void __wasm_set_tls_base(void *base);
|
||||
int main(void) {
|
||||
__wasm_set_tls_base(NULL);
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
134
|
||||
@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cat \
|
||||
| sed -e 's/main module `.*abort\.c\.wasm`/main module `abort.c.---.wasm`/' \
|
||||
| sed -e 's/failed to invoke.*/failed to invoke ---/' \
|
||||
| sed -E '/0x[[:xdigit:]]+/d'
|
||||
@ -1 +0,0 @@
|
||||
hello from argc argv main!
|
||||
@ -1 +0,0 @@
|
||||
hello from C++ argc argv main!
|
||||
@ -1 +0,0 @@
|
||||
134
|
||||
@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cat \
|
||||
| sed -e 's/main module `.*assert-fail\.c\.wasm`/main module `assert-fail.c.---.wasm`/' \
|
||||
| sed -e 's/failed to invoke.*/failed to invoke ---/' \
|
||||
| sed -e 's/Assertion failed: false (.*assert-fail.c/Assertion failed: false (assert-fail.c/' \
|
||||
| sed -E '/0x[[:xdigit:]]+/d'
|
||||
@ -0,0 +1,3 @@
|
||||
struct c { ~c() {} };
|
||||
thread_local c v;
|
||||
int main() { (void)v; }
|
||||
@ -1,10 +0,0 @@
|
||||
hello from_constructor101
|
||||
hello from_constructor
|
||||
hello from_constructor65535
|
||||
hello main
|
||||
goodbye main
|
||||
hello another_from_atexit
|
||||
hello from_atexit
|
||||
hello from_destructor65535
|
||||
hello from_destructor
|
||||
hello from_destructor101
|
||||
@ -1,12 +0,0 @@
|
||||
hello from_constructor101
|
||||
hello from_constructor
|
||||
hello from_constructor65535
|
||||
hello StaticObject::StaticObject
|
||||
hello main
|
||||
goodbye main
|
||||
hello another_from_atexit
|
||||
hello from_atexit
|
||||
hello from_destructor65535
|
||||
hello from_destructor
|
||||
hello StaticObject::~StaticObject
|
||||
hello from_destructor101
|
||||
@ -1 +0,0 @@
|
||||
HELLO = (null)
|
||||
@ -1 +0,0 @@
|
||||
HELLO=hello
|
||||
@ -1 +0,0 @@
|
||||
HELLO = hello
|
||||
@ -1 +0,0 @@
|
||||
HELLO=hello
|
||||
@ -1 +0,0 @@
|
||||
HELLO = hello
|
||||
@ -1 +0,0 @@
|
||||
hello from C++ main with cout!
|
||||
@ -1 +0,0 @@
|
||||
initial errno is 0: Success
|
||||
@ -1,3 +0,0 @@
|
||||
“Would you tell me, please, which way I ought to go from here?”
|
||||
|
||||
“That depends a good deal on where you want to get to,” said the Cat.
|
||||
@ -1 +0,0 @@
|
||||
hello from no-arg main!
|
||||
@ -1 +0,0 @@
|
||||
hello from C++ no-arg main!
|
||||
@ -1 +0,0 @@
|
||||
the answer is 42.000000
|
||||
@ -1 +0,0 @@
|
||||
the answer is 42
|
||||
@ -1 +0,0 @@
|
||||
the answer is 42.000000
|
||||
@ -1 +0,0 @@
|
||||
134
|
||||
@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
cat \
|
||||
| sed -e 's/main module `.*sigabrt\.c\.wasm`/main module `sigabrt.c.---.wasm`/' \
|
||||
| sed -e 's/source location: @[[:xdigit:]]*$/source location: @----/' \
|
||||
| sed -e 's/failed to invoke.*/failed to invoke ---/' \
|
||||
| head -n 6
|
||||
@ -1,6 +0,0 @@
|
||||
raising SIGABRT...
|
||||
Program received fatal signal: Aborted
|
||||
Error: failed to run main module `sigabrt.c.---.wasm`
|
||||
|
||||
Caused by:
|
||||
0: failed to invoke `run` function
|
||||
@ -1,6 +0,0 @@
|
||||
raising SIGABRT...
|
||||
Program received fatal signal: Aborted
|
||||
Error: failed to run main module `sigabrt.c.---.wasm`
|
||||
|
||||
Caused by:
|
||||
0: failed to invoke `run` function
|
||||
@ -1 +0,0 @@
|
||||
psignal message for SIGINT: Interrupt
|
||||
@ -1,4 +0,0 @@
|
||||
strsignal for SIGHUP: 'Hangup'
|
||||
beginning handler test:
|
||||
handler for signal Window changed
|
||||
finished handler test
|
||||
@ -1 +0,0 @@
|
||||
hello from void main!
|
||||
@ -1 +0,0 @@
|
||||
hello from C++ void main!
|
||||
@ -1,102 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -ueo pipefail
|
||||
|
||||
# A simple testcase runner that runs a command, captures all its command-line
|
||||
# outputs, and compares them against expected outputs.
|
||||
|
||||
# Command-line parsing; this script is meant to be run from a higher-level
|
||||
# script, so don't do anything fancy.
|
||||
runwasi="$1"
|
||||
input="$2"
|
||||
wasm="$3"
|
||||
|
||||
# Compile names for generated files.
|
||||
stdout_observed="$wasm.stdout.observed"
|
||||
stderr_observed="$wasm.stderr.observed"
|
||||
exit_status_observed="$wasm.exit_status.observed"
|
||||
|
||||
# Double-check that a runwasi command was specified since otherwise this script
|
||||
# was invoked with no arguments which isn't as intended.
|
||||
if [ "$runwasi" == "" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine the input file to write to stdin.
|
||||
if [ -e "$input.stdin" ]; then
|
||||
stdin="$input.stdin"
|
||||
else
|
||||
stdin="/dev/null"
|
||||
fi
|
||||
|
||||
# Determine any environment variables to set.
|
||||
if [ -e "$input.env" ]; then
|
||||
env=$(sed -e 's/^/--env /' < "$input.env")
|
||||
else
|
||||
env=""
|
||||
fi
|
||||
|
||||
# Determine a preopened directory to provide.
|
||||
if [ -e "$input.dir" ]; then
|
||||
dir="--dir $input.dir"
|
||||
dirarg="$input.dir"
|
||||
else
|
||||
dir=""
|
||||
dirarg=""
|
||||
fi
|
||||
|
||||
# Run the test, capturing stdout, stderr, and the exit status.
|
||||
exit_status=0
|
||||
$runwasi $env $dir "$wasm" $dirarg \
|
||||
< "$stdin" \
|
||||
> "$stdout_observed" \
|
||||
2> "$stderr_observed" \
|
||||
|| exit_status=$?
|
||||
echo $exit_status > "$exit_status_observed"
|
||||
|
||||
# On Windows Wasmtime will exit with error code 3 for aborts. On Unix Wasmtime
|
||||
# will exit with status 134. Paper over this difference by pretending to be Unix
|
||||
# on Windows and converting exit code 3 into 134 for the purposes of asserting
|
||||
# test output.
|
||||
if [ "$OSTYPE" = "msys" ] && [ "$exit_status" = "3" ]; then
|
||||
echo 134 > "$exit_status_observed"
|
||||
fi
|
||||
|
||||
# Determine the reference files to compare with.
|
||||
if [ -e "$input.stdout.expected" ]; then
|
||||
stdout_expected="$input.stdout.expected"
|
||||
|
||||
# Apply output filters.
|
||||
if [ -e "$input.stdout.expected.filter" ]; then
|
||||
cat "$stdout_observed" \
|
||||
| "$input.stdout.expected.filter" \
|
||||
> "${stdout_observed}.filtered"
|
||||
stdout_observed="${stdout_observed}.filtered"
|
||||
fi
|
||||
else
|
||||
stdout_expected="/dev/null"
|
||||
fi
|
||||
|
||||
if [ -e "$input.stderr.expected" ]; then
|
||||
stderr_expected="$input.stderr.expected"
|
||||
|
||||
# Apply output filters.
|
||||
if [ -e "$input.stderr.expected.filter" ]; then
|
||||
cat "$stderr_observed" \
|
||||
| "./$input.stderr.expected.filter" \
|
||||
> "${stderr_observed}.filtered"
|
||||
stderr_observed="${stderr_observed}.filtered"
|
||||
fi
|
||||
else
|
||||
stderr_expected="/dev/null"
|
||||
fi
|
||||
if [ -e "$input.exit_status.expected" ]; then
|
||||
exit_status_expected="$input.exit_status.expected"
|
||||
else
|
||||
exit_status_expected=../exit_status_zero
|
||||
fi
|
||||
|
||||
# If there are any differences, diff will return a non-zero exit status, and
|
||||
# since this script uses "set -e", it will return a non-zero exit status too.
|
||||
diff --ignore-space-change -u "$stderr_expected" "$stderr_observed"
|
||||
diff --ignore-space-change -u "$stdout_expected" "$stdout_observed"
|
||||
diff --ignore-space-change -u "$exit_status_expected" "$exit_status_observed"
|
||||
Loading…
Reference in new issue