Create a separate sysroot for coop threads

This commit creates a separate sysroot for coop threads for the
`wasm32-wasip3` target. This is explicitly labeled with `experimental`
in the name and isn't passed anywhere by default. The intention is to
assist with testing of this sysroot by making it reasonably easy to use
it and test that everything works. Using it requires passing `--sysroot`
to the folder generated here, and a simple "hello world" with threads
completes locally. This necessitated a minor update to an LLVM patch
which reflects the updated state of a PR upstream.
pull/647/head
Alex Crichton 1 month ago
parent 2a48497113
commit f0cd74bda4

@ -45,6 +45,7 @@ endif()
set(wasi_tmp_install ${CMAKE_CURRENT_BINARY_DIR}/install) set(wasi_tmp_install ${CMAKE_CURRENT_BINARY_DIR}/install)
set(wasi_sysroot ${wasi_tmp_install}/share/wasi-sysroot) set(wasi_sysroot ${wasi_tmp_install}/share/wasi-sysroot)
set(coop_threads_sysroot ${wasi_sysroot}/experimental-coop-threads)
set(wasi_resource_dir ${wasi_tmp_install}/wasi-resource-dir) set(wasi_resource_dir ${wasi_tmp_install}/wasi-resource-dir)
if(WASI_SDK_DEBUG_PREFIX_MAP) if(WASI_SDK_DEBUG_PREFIX_MAP)
@ -64,7 +65,6 @@ set(default_cmake_args
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER_WORKS=ON -DCMAKE_C_COMPILER_WORKS=ON
-DCMAKE_CXX_COMPILER_WORKS=ON -DCMAKE_CXX_COMPILER_WORKS=ON
-DCMAKE_SYSROOT=${wasi_sysroot}
-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake -DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}/cmake
# CMake detects this based on `CMAKE_C_COMPILER` alone and when that compiler # CMake detects this based on `CMAKE_C_COMPILER` alone and when that compiler
# is just a bare "clang" installation then it can mistakenly deduce that this # is just a bare "clang" installation then it can mistakenly deduce that this
@ -109,6 +109,7 @@ function(define_compiler_rt target)
-DCMAKE_CXX_FLAGS=${WASI_SDK_CPU_CFLAGS} -DCMAKE_CXX_FLAGS=${WASI_SDK_CPU_CFLAGS}
-DCMAKE_ASM_FLAGS=${WASI_SDK_CPU_CFLAGS} -DCMAKE_ASM_FLAGS=${WASI_SDK_CPU_CFLAGS}
-DCMAKE_INSTALL_PREFIX=${wasi_resource_dir} -DCMAKE_INSTALL_PREFIX=${wasi_resource_dir}
-DCMAKE_SYSROOT=${wasi_sysroot}
EXCLUDE_FROM_ALL ON EXCLUDE_FROM_ALL ON
USES_TERMINAL_CONFIGURE ON USES_TERMINAL_CONFIGURE ON
USES_TERMINAL_BUILD ON USES_TERMINAL_BUILD ON
@ -165,7 +166,7 @@ add_custom_target(compiler-rt DEPENDS compiler-rt-build compiler-rt-post-build)
# wasi-libc build logic # wasi-libc build logic
# ============================================================================= # =============================================================================
function(define_wasi_libc_sub target target_suffix lto) function(define_wasi_libc_sub sysroot target target_suffix lto)
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER) string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
get_property(directory_cflags DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS) get_property(directory_cflags DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS)
set(extra_cflags_list "${WASI_SDK_CPU_CFLAGS} ${CMAKE_C_FLAGS} ${directory_cflags}") set(extra_cflags_list "${WASI_SDK_CPU_CFLAGS} ${CMAKE_C_FLAGS} ${directory_cflags}")
@ -205,34 +206,45 @@ function(define_wasi_libc_sub target target_suffix lto)
list(APPEND extra_cmake_args -DBUILD_SHARED=OFF) list(APPEND extra_cmake_args -DBUILD_SHARED=OFF)
endif() endif()
if (${sysroot} STREQUAL ${coop_threads_sysroot})
list(APPEND extra_cmake_args -DENABLE_COOP_THREADS=ON)
endif()
ExternalProject_Add(wasi-libc-${target}${target_suffix}-build ExternalProject_Add(wasi-libc-${target}${target_suffix}-build
SOURCE_DIR ${wasi_libc} SOURCE_DIR ${wasi_libc}
CMAKE_ARGS CMAKE_ARGS
${default_cmake_args} ${default_cmake_args}
${extra_cmake_args} ${extra_cmake_args}
-DTARGET_TRIPLE=${target} -DTARGET_TRIPLE=${target}
-DCMAKE_INSTALL_PREFIX=${wasi_sysroot} -DCMAKE_INSTALL_PREFIX=${sysroot}
-DCMAKE_C_FLAGS=${extra_cflags} -DCMAKE_C_FLAGS=${extra_cflags}
-DCMAKE_ASM_FLAGS=${extra_cflags} -DCMAKE_ASM_FLAGS=${extra_cflags}
-DBUILTINS_LIB=${libcompiler_rt_a} -DBUILTINS_LIB=${libcompiler_rt_a}
-DUSE_WASM_COMPONENT_LD=OFF -DUSE_WASM_COMPONENT_LD=OFF
-DWASI_SDK_VERSION=${wasi_sdk_version} -DWASI_SDK_VERSION=${wasi_sdk_version}
-DCMAKE_SYSROOT=${sysroot}
DEPENDS compiler-rt DEPENDS compiler-rt
EXCLUDE_FROM_ALL ON EXCLUDE_FROM_ALL ON
USES_TERMINAL_CONFIGURE ON USES_TERMINAL_CONFIGURE ON
USES_TERMINAL_BUILD ON USES_TERMINAL_BUILD ON
USES_TERMINAL_INSTALL ON USES_TERMINAL_INSTALL ON
) )
add_dependencies(wasi-libc-${target} wasi-libc-${target}${target_suffix}-build)
endfunction() endfunction()
function(define_wasi_libc target) function(define_wasi_libc target)
define_wasi_libc_sub (${target} "" OFF) add_custom_target(wasi-libc-${target})
define_wasi_libc_sub(${wasi_sysroot} ${target} "" OFF)
if(WASI_SDK_LTO) if(WASI_SDK_LTO)
define_wasi_libc_sub (${target} "-lto" ON) define_wasi_libc_sub(${wasi_sysroot} ${target} "-lto" ON)
endif() endif()
add_custom_target(wasi-libc-${target} # Temporary wasip3 experimental coop threads sysroot before it's enabled by
DEPENDS wasi-libc-${target}-build $<$<BOOL:${WASI_SDK_LTO}>:wasi-libc-${target}-lto-build>) # default.
if (${target} STREQUAL wasm32-wasip3)
define_wasi_libc_sub(${coop_threads_sysroot} ${target} "-coop" OFF)
endif()
endfunction() endfunction()
foreach(target IN LISTS WASI_SDK_TARGETS) foreach(target IN LISTS WASI_SDK_TARGETS)
@ -248,7 +260,7 @@ execute_process(
OUTPUT_VARIABLE llvm_version OUTPUT_VARIABLE llvm_version
OUTPUT_STRIP_TRAILING_WHITESPACE) OUTPUT_STRIP_TRAILING_WHITESPACE)
function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_suffix exceptions) function(define_libcxx_sub sysroot target target_suffix extra_target_flags extra_libdir_suffix exceptions)
if(${target} MATCHES threads) if(${target} MATCHES threads)
set(pic OFF) set(pic OFF)
set(target_flags -pthread) set(target_flags -pthread)
@ -271,7 +283,7 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_
--target=${target} --target=${target}
${dir_compile_opts} ${dir_compile_opts}
${dir_link_opts} ${dir_link_opts}
--sysroot ${wasi_sysroot} --sysroot ${sysroot}
-resource-dir ${wasi_resource_dir}) -resource-dir ${wasi_resource_dir})
set(exnsuffix "") set(exnsuffix "")
@ -309,6 +321,12 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_
set(shared OFF) set(shared OFF)
endif() endif()
# FIXME(WebAssembly/wasi-libc#813) - shared libraries don't work with coop
# threads right now.
if (${sysroot} STREQUAL ${coop_threads_sysroot})
set(shared OFF)
endif()
set(extra_cflags_list ${CMAKE_C_FLAGS} ${extra_flags}) set(extra_cflags_list ${CMAKE_C_FLAGS} ${extra_flags})
list(JOIN extra_cflags_list " " extra_cflags) list(JOIN extra_cflags_list " " extra_cflags)
set(extra_cxxflags_list ${CMAKE_CXX_FLAGS} ${extra_flags}) set(extra_cxxflags_list ${CMAKE_CXX_FLAGS} ${extra_flags})
@ -318,10 +336,11 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_
SOURCE_DIR ${llvm_proj_dir}/runtimes SOURCE_DIR ${llvm_proj_dir}/runtimes
CMAKE_ARGS CMAKE_ARGS
${default_cmake_args} ${default_cmake_args}
-DCMAKE_SYSROOT=${sysroot}
# Ensure headers are installed in a target-specific path instead of a # Ensure headers are installed in a target-specific path instead of a
# target-generic path. # target-generic path.
-DCMAKE_INSTALL_INCLUDEDIR=${wasi_sysroot}/include/${target}${exnsuffix} -DCMAKE_INSTALL_INCLUDEDIR=${sysroot}/include/${target}${exnsuffix}
-DCMAKE_STAGING_PREFIX=${wasi_sysroot} -DCMAKE_STAGING_PREFIX=${sysroot}
-DCMAKE_POSITION_INDEPENDENT_CODE=${pic} -DCMAKE_POSITION_INDEPENDENT_CODE=${pic}
-DLIBCXX_ENABLE_THREADS:BOOL=ON -DLIBCXX_ENABLE_THREADS:BOOL=ON
-DLIBCXX_HAS_PTHREAD_API:BOOL=ON -DLIBCXX_HAS_PTHREAD_API:BOOL=ON
@ -382,12 +401,12 @@ function(define_libcxx_sub target target_suffix extra_target_flags extra_libdir_
add_dependencies(libcxx-${target} libcxx-${target}${target_suffix}-build) add_dependencies(libcxx-${target} libcxx-${target}${target_suffix}-build)
endfunction() endfunction()
function(define_libcxx_and_lto target target_suffix exceptions) function(define_libcxx_and_lto sysroot target target_suffix exceptions)
define_libcxx_sub(${target} "${target_suffix}" "" "" ${exceptions}) define_libcxx_sub(${sysroot} ${target} "${target_suffix}" "" "" ${exceptions})
if (WASI_SDK_LTO) if (WASI_SDK_LTO)
# Note: clang knows this /llvm-lto/${llvm_version} convention. # Note: clang knows this /llvm-lto/${llvm_version} convention.
# https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/clang/lib/Driver/ToolChains/WebAssembly.cpp#L204-L210 # https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/clang/lib/Driver/ToolChains/WebAssembly.cpp#L204-L210
define_libcxx_sub(${target} ${target_suffix}-lto "-flto=full" "/llvm-lto/${llvm_version}" ${exceptions}) define_libcxx_sub(${sysroot} ${target} ${target_suffix}-lto "-flto=full" "/llvm-lto/${llvm_version}" ${exceptions})
endif() endif()
endfunction() endfunction()
@ -401,20 +420,32 @@ function(define_libcxx target)
# Otherwise there's only one build of libcxx and it's either got exceptions or # Otherwise there's only one build of libcxx and it's either got exceptions or
# it doesn't depending on configuration. # it doesn't depending on configuration.
if (WASI_SDK_EXCEPTIONS STREQUAL "DUAL") if (WASI_SDK_EXCEPTIONS STREQUAL "DUAL")
define_libcxx_and_lto(${target} "" OFF) define_libcxx_and_lto(${wasi_sysroot} ${target} "" OFF)
define_libcxx_and_lto(${target} "-exn" ON) define_libcxx_and_lto(${wasi_sysroot} ${target} "-exn" ON)
elseif(WASI_SDK_EXCEPTIONS STREQUAL "ON") elseif(WASI_SDK_EXCEPTIONS STREQUAL "ON")
define_libcxx_and_lto(${target} "" ON) define_libcxx_and_lto(${wasi_sysroot} ${target} "" ON)
else() else()
define_libcxx_and_lto(${target} "" OFF) define_libcxx_and_lto(${wasi_sysroot} ${target} "" OFF)
endif() endif()
# As of this writing, `clang++` will ignore the target-specific include dirs # As of this writing, `clang++` will ignore the target-specific include dirs
# unless this one also exists: # unless this one also exists:
add_custom_target(libcxx-${target}-extra-dir add_custom_target(libcxx-${target}-extra-dir
COMMAND ${CMAKE_COMMAND} -E make_directory ${wasi_sysroot}/include/c++/v1 COMMAND ${CMAKE_COMMAND} -E make_directory ${wasi_sysroot}/include/c++/v1
COMMENT "creating libcxx-specific header file folder") COMMENT "creating libcxx-specific header file folder")
add_dependencies(libcxx-${target} libcxx-${target}-extra-dir) add_dependencies(libcxx-${target} libcxx-${target}-extra-dir)
# Temporary wasip3 experimental coop threads sysroot before it's enabled by
# default.
if (${target} STREQUAL wasm32-wasip3)
define_libcxx_and_lto(${coop_threads_sysroot} ${target} "-coop" OFF)
add_custom_target(libcxx-${target}-extra-dir-coop-threads-sysroot
COMMAND ${CMAKE_COMMAND} -E make_directory ${coop_threads_sysroot}/include/c++/v1
COMMENT "creating libcxx-specific header file folder")
add_dependencies(libcxx-${target} libcxx-${target}-extra-dir-coop-threads-sysroot)
endif()
endfunction() endfunction()
foreach(target IN LISTS WASI_SDK_TARGETS) foreach(target IN LISTS WASI_SDK_TARGETS)

@ -73,7 +73,7 @@ index f3ff646cc3b1..2dd18d604df4 100644
# COMPRESS: 42 03 i64.const 3 # COMPRESS: 42 03 i64.const 3
diff --git a/lld/test/wasm/cooperative-threading.s b/lld/test/wasm/cooperative-threading.s diff --git a/lld/test/wasm/cooperative-threading.s b/lld/test/wasm/cooperative-threading.s
index 8b0f7eb1c256..0db72053692b 100644 index 8b0f7eb1c256..7b891febbb03 100644
--- a/lld/test/wasm/cooperative-threading.s --- a/lld/test/wasm/cooperative-threading.s
+++ b/lld/test/wasm/cooperative-threading.s +++ b/lld/test/wasm/cooperative-threading.s
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
@ -156,7 +156,7 @@ index 8b0f7eb1c256..0db72053692b 100644
+# CHECK-NEXT: Value: 65536 +# CHECK-NEXT: Value: 65536
+# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: - Index: 1
+# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Type: I32
+# CHECK-NEXT: Mutable: false +# CHECK-NEXT: Mutable: true
+# CHECK-NEXT: InitExpr: +# CHECK-NEXT: InitExpr:
+# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Opcode: I32_CONST
+# CHECK-NEXT: Value: 65544 +# CHECK-NEXT: Value: 65544
@ -534,7 +534,7 @@ index 9679074d6a0d..b5d130417774 100644
# ASM-NEXT: i32.store 0 # ASM-NEXT: i32.store 0
# ASM-NEXT: i32.const 12 # ASM-NEXT: i32.const 12
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 9a2e3a82a927..35892c283897 100644 index 9a2e3a82a927..2389c8f88a01 100644
--- a/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp
@@ -759,6 +759,14 @@ static void setConfigs() { @@ -759,6 +759,14 @@ static void setConfigs() {
@ -552,7 +552,7 @@ index 9a2e3a82a927..35892c283897 100644
} }
} }
@@ -970,12 +978,20 @@ static void createSyntheticSymbols() { @@ -970,12 +978,22 @@ static void createSyntheticSymbols() {
} }
if (ctx.arg.isMultithreaded()) { if (ctx.arg.isMultithreaded()) {
@ -560,20 +560,22 @@ index 9a2e3a82a927..35892c283897 100644
+ // TLS symbols are all hidden/dso-local, and note that the `tlsBase` global + // TLS symbols are all hidden/dso-local, and note that the `tlsBase` global
+ // serves a different purpose depending on `libcallThreadContext`. If + // serves a different purpose depending on `libcallThreadContext`. If
+ // `libcallThreadContext` is `false` it's the base address of TLS and it's + // `libcallThreadContext` is `false` it's the base address of TLS and it's
+ // initialized fresh by each thread. This requires a mutable global. + // initialized fresh by each thread. If `libcallThreadContext` is `true`,
+ // + // however, then it records the initial thread's TLS address at
+ // If `libcallThreadContext` is `true`, however, then it records the + // `start`-time. In non-PIC mode this is a constant determined during
+ // initial thread's TLS address at `start`-time. In non-PIC mode this is a + // linking, but in PIC mode it's calculated during instantiation. For
+ // constant determined during linking, but in PIC mode it's calculated + // simplicity this global is always mutable despite technically not being
+ // during instantiation. + // necessary in `libcallThreadContext` non-PIC mode. Given that the global
+ // type must match across linkage units it's easier to have it always be one
+ // type instead of depending on flags, for example it means that `libc.a`
+ // (not PIC) is compatible with `libc.so` (PIC) for linking.
auto tls_base_name = auto tls_base_name =
ctx.arg.libcallThreadContext ? "__init_tls_base" : "__tls_base"; ctx.arg.libcallThreadContext ? "__init_tls_base" : "__tls_base";
- ctx.sym.tlsBase = - ctx.sym.tlsBase =
- createGlobalVariable(tls_base_name, !ctx.arg.libcallThreadContext, - createGlobalVariable(tls_base_name, !ctx.arg.libcallThreadContext,
- WASM_SYMBOL_VISIBILITY_HIDDEN); - WASM_SYMBOL_VISIBILITY_HIDDEN);
+ ctx.sym.tlsBase = createGlobalVariable( + ctx.sym.tlsBase = createGlobalVariable(tls_base_name, true,
+ tls_base_name, !ctx.arg.libcallThreadContext || ctx.isPic, + WASM_SYMBOL_VISIBILITY_HIDDEN);
+ WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsSize = createGlobalVariable("__tls_size", false, ctx.sym.tlsSize = createGlobalVariable("__tls_size", false,
WASM_SYMBOL_VISIBILITY_HIDDEN); WASM_SYMBOL_VISIBILITY_HIDDEN);
ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false, ctx.sym.tlsAlign = createGlobalVariable("__tls_align", false,

Loading…
Cancel
Save