From 6915a36895f6f32a267448db597e3033dd790157 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 15 Sep 2025 06:20:45 +0000 Subject: [PATCH 1/3] [NFC][wasm] Fix incorrect comment about reserved low addresses --- lib/Driver/WebAssemblyToolChains.cpp | 4 ++-- stdlib/public/SwiftShims/swift/shims/System.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Driver/WebAssemblyToolChains.cpp b/lib/Driver/WebAssemblyToolChains.cpp index eb257f1ddbffe..5872ede6cda0b 100644 --- a/lib/Driver/WebAssemblyToolChains.cpp +++ b/lib/Driver/WebAssemblyToolChains.cpp @@ -188,8 +188,8 @@ toolchains::WebAssembly::constructInvocation(const DynamicLinkJobAction &job, // WebAssembly doesn't reserve low addresses But without "extra inhabitants" // of the pointer representation, runtime performance and memory footprint are - // worse. So assume that compiler driver uses wasm-ld and --global-base=1024 - // to reserve low 1KB. + // worse. So assume that compiler driver uses wasm-ld and --global-base=4096 + // to reserve low 4KB. Arguments.push_back("-Xlinker"); Arguments.push_back(context.Args.MakeArgString( Twine("--global-base=") + diff --git a/stdlib/public/SwiftShims/swift/shims/System.h b/stdlib/public/SwiftShims/swift/shims/System.h index 53afedf3eff97..328f81ebece67 100644 --- a/stdlib/public/SwiftShims/swift/shims/System.h +++ b/stdlib/public/SwiftShims/swift/shims/System.h @@ -220,8 +220,8 @@ // WebAssembly doesn't reserve low addresses. But without "extra inhabitants" of // the pointer representation, runtime performance and memory footprint are -// worse. So assume that compiler driver uses wasm-ld and --global-base=1024 to -// reserve low 1KB. +// worse. So assume that compiler driver uses wasm-ld and --global-base=4096 to +// reserve low 4KB. #define SWIFT_ABI_WASM32_LEAST_VALID_POINTER 4096 #endif // SWIFT_STDLIB_SHIMS_ABI_SYSTEM_H From e12642f91735d9cee334e7aade3c784b5b7493bc Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 15 Sep 2025 06:22:20 +0000 Subject: [PATCH 2/3] [Legacy Driver][wasm] Pass `--table-base` to reserve low function addresses WebAssembly does not have a reserved address space by default, so we need to explicitly reserve low addresses for extra inhabitants for enum types with pointer payloads. https://github.com/swiftlang/swift/pull/39300 added `--global-base` to reserve low data addresses, but we also need to reserve low function addresses with `--table-base` for function pointers because WebAssembly uses a separate address space for function pointers. --- lib/Driver/WebAssemblyToolChains.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Driver/WebAssemblyToolChains.cpp b/lib/Driver/WebAssemblyToolChains.cpp index 5872ede6cda0b..3d09649edd4c5 100644 --- a/lib/Driver/WebAssemblyToolChains.cpp +++ b/lib/Driver/WebAssemblyToolChains.cpp @@ -194,6 +194,10 @@ toolchains::WebAssembly::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back(context.Args.MakeArgString( Twine("--global-base=") + std::to_string(SWIFT_ABI_WASM32_LEAST_VALID_POINTER))); + Arguments.push_back("-Xlinker"); + Arguments.push_back(context.Args.MakeArgString( + Twine("--table-base=") + + std::to_string(SWIFT_ABI_WASM32_LEAST_VALID_POINTER))); // These custom arguments should be right before the object file at the end. context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); From 5431bb115b184ed5faa170aca2d26d4995a6203b Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 15 Sep 2025 14:26:08 +0000 Subject: [PATCH 3/3] [test][wasm] Add test to kill the missing func addr reservation --- test/Interpreter/enum.swift | 42 +++++++++++++++++++ .../products/wasmstdlib.py | 6 ++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/test/Interpreter/enum.swift b/test/Interpreter/enum.swift index 7746ea218ca61..1995cc8078cec 100644 --- a/test/Interpreter/enum.swift +++ b/test/Interpreter/enum.swift @@ -745,3 +745,45 @@ func reproduction(_ x: Int, _ y: Int, _ t: T) { // CHECK: there is no byte reproduction(2, 3, TrailingByte()) + +do { + // regression test for https://github.com/swiftlang/swift-driver/pull/1987 + @inline(never) func blackhole(_ t: T) { } + + final class Context { + func doSomething() {} + deinit { + print("Context deinit") + } + } + + enum MyOptional { + case some(Value) + case none + } + + final class _GenericStorage { + let value: MyOptional + + init(value: Value) { + self.value = .some(value) + } + + func unwrapAndCopy() { + if case .some(let value) = value { + blackhole(value) + } + } + } + + let test = _GenericStorage( + value: Context().doSomething, + ) + // CHECK: test.unwrapAndCopy + print("test.unwrapAndCopy") + test.unwrapAndCopy() + // CHECK: test.unwrapAndCopy + print("test.unwrapAndCopy") + test.unwrapAndCopy() + // CHECK: Context deinit +} diff --git a/utils/swift_build_support/swift_build_support/products/wasmstdlib.py b/utils/swift_build_support/swift_build_support/products/wasmstdlib.py index 404c0366b76d3..18b8021af57e3 100644 --- a/utils/swift_build_support/swift_build_support/products/wasmstdlib.py +++ b/utils/swift_build_support/swift_build_support/products/wasmstdlib.py @@ -191,7 +191,11 @@ def _build_stdlib(self, host_target, target_triple, llvm_cmake_dir): # Test configuration self.cmake_options.define('SWIFT_INCLUDE_TESTS:BOOL', 'TRUE') self.cmake_options.define('SWIFT_ENABLE_SOURCEKIT_TESTS:BOOL', 'FALSE') - lit_test_paths = ['IRGen', 'stdlib', 'Concurrency/Runtime', 'embedded'] + lit_test_paths = [ + 'IRGen', 'stdlib', 'Concurrency/Runtime', 'embedded', + # TODO(katei): Enable all interpreter tests + 'Interpreter/enum.swift', + ] lit_test_paths = [os.path.join( self.build_dir, 'test-wasi-wasm32', path) for path in lit_test_paths] self.cmake_options.define('SWIFT_LIT_TEST_PATHS:STRING',