diff --git a/docs/workflow/building/coreclr/nativeaot.md b/docs/workflow/building/coreclr/nativeaot.md index f356ed1b9252..845b397650ef 100644 --- a/docs/workflow/building/coreclr/nativeaot.md +++ b/docs/workflow/building/coreclr/nativeaot.md @@ -24,7 +24,7 @@ The Native AOT toolchain can be currently built for Linux (x64/arm64), macOS (x6 There are two kinds of binary artifacts produced by the build and needed for development: the runtime libraries and the cross-targeting compilers, ILC and RyuJit. They are built differently and separately. For the runtime libraries: -- Clone the [emsdk](https://github.com/emscripten-core/emsdk) repository and use the `emsdk.bat` script it comes with to [install](https://emscripten.org/docs/getting_started/downloads.html) (and optionally "activate", i. e. set the relevant environment variables permanently) the Emscripten SDK, which will be used by the native build as a sort of "virtualized" build environment. It is recommended to use the same Emscripten version that [the CI](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.ps1#L16-L20) uses. +- To build for web browsers, clone the [emsdk](https://github.com/emscripten-core/emsdk) repository and use the `emsdk.bat` script it comes with to [install](https://emscripten.org/docs/getting_started/downloads.html) (and optionally "activate", i. e. set the relevant environment variables permanently) the Emscripten SDK, which will be used by the native build as a sort of "virtualized" build environment. It is recommended to use the same Emscripten version that [the CI](https://github.com/dotnet/runtimelab/blob/feature/NativeAOT-LLVM/eng/pipelines/runtimelab/install-emscripten.ps1#L16-L20) uses. ``` git clone https://github.com/emscripten-core/emsdk cd emsdk @@ -34,7 +34,7 @@ For the runtime libraries: ./emsdk install 3.1.47 ./emsdk activate 3.1.47 ``` -- To build for WASI, download and install the Wasi SDK from https://github.com/WebAssembly/wasi-sdk/releases (only Windows is supported currently) and set the `WASI_SDK_PATH` environment variable to the location where it is installed, e.g. `set WASI_SDK_PATH=c:\github\wasi-sdk`. +- To build for WASI, download and install WASI-SDK 22 from https://github.com/WebAssembly/wasi-sdk/releases (only Windows and Linux are supported currently) and set the `WASI_SDK_PATH` environment variable to the location where it is installed, e.g. `set WASI_SDK_PATH=c:\github\wasi-sdk`. Note that WASI-SDK 22 only includes a copy of `pthread.h` for the `wasm32-wasi-threads` target, which we must copy to the include directory for the `wasm32-wasi` target, e.g. `cp $WASI_SDK\share\wasi-sysroot\include\wasm32-wasi-threads\pthread.h $WASI_SDK\share\wasi-sysroot\include\wasm32-wasi\`. This is a temporary workaround until https://github.com/WebAssembly/wasi-libc/issues/501 has been addressed and released. - Run `build clr.aot+libs -c [Debug|Release] -a wasm -os [browser|wasi]`. This will create the architecture-dependent libraries needed for linking and runtime execution, as well as the managed binaries to be used as input to ILC. For the compilers: diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh index 4c1ed0943c45..054f7de94564 100755 --- a/eng/native/gen-buildsys.sh +++ b/eng/native/gen-buildsys.sh @@ -93,11 +93,17 @@ if [[ "$scan_build" == "ON" && -n "$SCAN_BUILD_COMMAND" ]]; then cmake_command="$SCAN_BUILD_COMMAND $cmake_command" fi +cmake_extra_defines_wasm=() if [[ "$host_arch" == "wasm" ]]; then if [[ "$target_os" == "browser" ]]; then cmake_command="emcmake $cmake_command" elif [[ "$target_os" == "wasi" ]]; then - true + if [[ -z $WASI_SDK_PATH ]]; then + echo "Error: Should set WASI_SDK_PATH environment variable pointing to WASI SDK root." + exit 1 + fi + + cmake_extra_defines_wasm=("-DCLR_CMAKE_TARGET_OS=wasi" "-DCLR_CMAKE_TARGET_ARCH=wasm" "-DWASI_SDK_PREFIX=$WASI_SDK_PATH" "-DCMAKE_TOOLCHAIN_FILE=$WASI_SDK_PATH/share/cmake/wasi-sdk.cmake" "-DCMAKE_CROSSCOMPILING_EMULATOR=node --experimental-wasm-bigint --experimental-wasi-unstable-preview1") else echo "target_os was not specified" exit 1 @@ -110,6 +116,7 @@ $cmake_command \ "-DCMAKE_BUILD_TYPE=$buildtype" \ "-DCMAKE_INSTALL_PREFIX=$__CMakeBinDir" \ $cmake_extra_defines \ + "${cmake_extra_defines_wasm[@]}" \ $__UnprocessedCMakeArgs \ -S "$1" \ -B "$2" diff --git a/eng/pipelines/runtimelab/install-wasi-sdk.ps1 b/eng/pipelines/runtimelab/install-wasi-sdk.ps1 index 11e80dd32e67..f6fa9e9e5c51 100644 --- a/eng/pipelines/runtimelab/install-wasi-sdk.ps1 +++ b/eng/pipelines/runtimelab/install-wasi-sdk.ps1 @@ -1,6 +1,13 @@ -Invoke-WebRequest -Uri https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0.m-mingw.tar.gz -OutFile wasi-sdk-20.0.m-mingw.tar.gz +Invoke-WebRequest -Uri https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-22/wasi-sdk-22.0.m-mingw64.tar.gz -OutFile wasi-sdk-22.0.m-mingw64.tar.gz -tar -xzf wasi-sdk-20.0.m-mingw.tar.gz +tar -xzf wasi-sdk-22.0.m-mingw64.tar.gz -mv wasi-sdk-20.0+m wasi-sdk +mv wasi-sdk-22.0+m wasi-sdk +# Temporary WASI-SDK 22 workaround: Until +# https://github.com/WebAssembly/wasi-libc/issues/501 is addressed, we copy +# pthread.h from the wasm32-wasi-threads include directory to the wasm32-wasi +# include directory. See https://github.com/dotnet/runtimelab/issues/2598 for +# the issue to remove this workaround once WASI-SDK 23 is released. + +cp wasi-sdk/share/wasi-sysroot/include/wasm32-wasi-threads/pthread.h wasi-sdk/share/wasi-sysroot/include/wasm32-wasi/ diff --git a/src/coreclr/build-runtime.sh b/src/coreclr/build-runtime.sh index 2d0685cd4399..722ddcb44763 100755 --- a/src/coreclr/build-runtime.sh +++ b/src/coreclr/build-runtime.sh @@ -177,11 +177,11 @@ if [[ "$__CMakeTarget" == *"wasmjit"* ]]; then if [[ "$__BuildType" == "Release" ]]; then if [[ -n $LLVM_CMAKE_CONFIG_RELEASE ]]; then - LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_RELEASE" + export LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_RELEASE" fi else if [[ -n $LLVM_CMAKE_CONFIG_DEBUG ]]; then - LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_DEBUG" + export LLVM_CMAKE_CONFIG="$LLVM_CMAKE_CONFIG_DEBUG" fi fi diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index 67848a9cc01d..7cbcaaf57011 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -706,16 +706,11 @@ else() create_standalone_jit(TARGET clrjit_win_x86_${ARCH_HOST_NAME} OS win ARCH x86 DESTINATIONS .) endif (CLR_CMAKE_TARGET_ARCH_RISCV64) -# Note that we currently do not support building the LLVM Jit on Unix. -# Note as well that we need this "CLR_CMAKE_BUILD_LLVM_JIT", defined by the build scripts, +# Note that we need this "CLR_CMAKE_BUILD_LLVM_JIT", defined by the build scripts, # because there is no way in CMake to ask "what --target's' am I being asked to configure?". if (CLR_CMAKE_BUILD_LLVM_JIT) # The LLVM clrjit needs to be the last clrjit to use create_standalone_jit as it modifies some cmake variables. # LLVM clrjit has an extra export - registerLlvmCallbacks. - set(CLRJIT_EXPORTS ${CMAKE_CURRENT_LIST_DIR}/ClrJit.Llvm.exports) - set(JIT_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/ClrJit.Llvm.exports.def) - preprocess_file (${CLRJIT_EXPORTS} ${JIT_EXPORTS_FILE}) - set(JIT_DEF_FILE ${JIT_EXPORTS_FILE}) # Exclude cpp files that are not required when not processing beyond rationalized LIR. # Use REGEX as this list contains the absolute paths. diff --git a/src/coreclr/jit/ClrJit.Llvm.exports b/src/coreclr/jit/ClrJit.Llvm.exports deleted file mode 100644 index 3adee7c3d36a..000000000000 --- a/src/coreclr/jit/ClrJit.Llvm.exports +++ /dev/null @@ -1,9 +0,0 @@ -; Licensed to the .NET Foundation under one or more agreements. -; The .NET Foundation licenses this file to you under the MIT license. - -EXPORTS - getJit - jitStartup - jitShutdown - registerLlvmCallbacks - diff --git a/src/coreclr/jit/ClrJit.PAL.exports b/src/coreclr/jit/ClrJit.PAL.exports index e4e6064db84e..066d2613e93a 100644 --- a/src/coreclr/jit/ClrJit.PAL.exports +++ b/src/coreclr/jit/ClrJit.PAL.exports @@ -3,3 +3,4 @@ jitStartup getLikelyClasses getLikelyMethods jitBuildString +registerLlvmCallbacks diff --git a/src/coreclr/jit/ClrJit.exports b/src/coreclr/jit/ClrJit.exports index 5430f7b16592..4496a1f926fd 100644 --- a/src/coreclr/jit/ClrJit.exports +++ b/src/coreclr/jit/ClrJit.exports @@ -7,3 +7,4 @@ EXPORTS getLikelyClasses getLikelyMethods jitBuildString + registerLlvmCallbacks diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index 5736b46daac0..ae4831f903d8 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1421,3 +1421,10 @@ unsigned Compiler::eeTryGetClassSize(CORINFO_CLASS_HANDLE clsHnd) } #endif // !DEBUG + +#ifndef TARGET_WASM +extern "C" DLLEXPORT void registerLlvmCallbacks(void** jitImports, void** jitExports) +{ + // No-op stub; see llvm.cpp for the real implementation for `TARGET_WASM` +} +#endif diff --git a/src/coreclr/jit/llvm.cpp b/src/coreclr/jit/llvm.cpp index 1ab4094d235d..ad43ad330810 100644 --- a/src/coreclr/jit/llvm.cpp +++ b/src/coreclr/jit/llvm.cpp @@ -770,7 +770,7 @@ CORINFO_GENERIC_HANDLE Llvm::getSymbolHandleForClassToken(mdToken token) template TReturn CallEEApi(TArgs... args) { - return static_cast(g_callbacks[static_cast(Func)])(args...); + return reinterpret_cast(g_callbacks[static_cast(Func)])(args...); } const char* Llvm::GetMangledMethodName(CORINFO_METHOD_HANDLE methodHandle) @@ -866,8 +866,8 @@ extern "C" DLLEXPORT void registerLlvmCallbacks(void** jitImports, void** jitExp assert(jitExports != nullptr); memcpy(g_callbacks, jitImports, static_cast(EEApiId::Count) * sizeof(void*)); - jitExports[static_cast(JitApiId::StartSingleThreadedCompilation)] = &Llvm::StartSingleThreadedCompilation; - jitExports[static_cast(JitApiId::FinishSingleThreadedCompilation)] = &Llvm::FinishSingleThreadedCompilation; + jitExports[static_cast(JitApiId::StartSingleThreadedCompilation)] = (void*)&Llvm::StartSingleThreadedCompilation; + jitExports[static_cast(JitApiId::FinishSingleThreadedCompilation)] = (void*)&Llvm::FinishSingleThreadedCompilation; jitExports[static_cast(JitApiId::Count)] = (void*)0x1234; } diff --git a/src/coreclr/jit/llvmcodegen.cpp b/src/coreclr/jit/llvmcodegen.cpp index d60ac8d5e5ab..8fb6beb1046d 100644 --- a/src/coreclr/jit/llvmcodegen.cpp +++ b/src/coreclr/jit/llvmcodegen.cpp @@ -1118,6 +1118,7 @@ void Llvm::visitNode(GenTree* node) break; case GT_JMP: NYI("LLVM/GT_JMP"); // Requires support for explicit tailcalls. + break; default: unreached(); } diff --git a/src/coreclr/jit/llvmlower.cpp b/src/coreclr/jit/llvmlower.cpp index e3605c26d2c6..55061b55b1b2 100644 --- a/src/coreclr/jit/llvmlower.cpp +++ b/src/coreclr/jit/llvmlower.cpp @@ -409,6 +409,9 @@ void Llvm::lowerFieldOfDependentlyPromotedStruct(GenTree* node) lclVar->gtFlags |= GTF_VAR_USEASG; } break; + + default: + break; } lclVar->SetLclNum(varDsc->lvParentLcl); diff --git a/src/coreclr/jit/llvmlssa.cpp b/src/coreclr/jit/llvmlssa.cpp index e5d6f4a1aa10..280bf0d2692c 100644 --- a/src/coreclr/jit/llvmlssa.cpp +++ b/src/coreclr/jit/llvmlssa.cpp @@ -1482,7 +1482,7 @@ class ShadowStackAllocator { if (block != m_currentBlock) { - m_actions.Push({AllocationActionKind::Block, m_currentBlockIndex++}); + m_actions.Push({AllocationActionKind::Block, {m_currentBlockIndex++}}); m_currentBlock = block; } } @@ -1636,6 +1636,10 @@ class ShadowStackAllocator template void PrintFormatted(char** pBuffer, const char* format, TArgs... args) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-security" +#endif // __clang__ if (pBuffer == nullptr) { printf(format, args...); @@ -1644,6 +1648,9 @@ class ShadowStackAllocator { *pBuffer += sprintf(*pBuffer, format, args...); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // __clang__ } void PrintAction(const AllocationAction& action, char** pBuffer = nullptr) diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 99d05624eb11..4e27bd6fefb1 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -388,9 +388,11 @@ The .NET Foundation licenses this file to you under the MIT license. + Condition="'$(EMSDK)' == '' and '$(_targetOS)' == 'browser'" /> + $(CompileWasmArgs) -fvisibility=default -mllvm -combiner-global-alias-analysis=false -mllvm -disable-lsr --sysroot="$(WASI_SDK_PATH)/share/wasi-sysroot" -target $(IlcLlvmTarget) .exe - - "$(EMSDK)/upstream/bin/clang++$(ExeExt)" + "$(WASI_SDK_PATH)/bin/clang++$(ExeExt)" "$(WASI_SDK_PATH)/bin/clang" diff --git a/src/native/libs/CMakeLists.txt b/src/native/libs/CMakeLists.txt index 51856e0e1dd0..4009719b7737 100644 --- a/src/native/libs/CMakeLists.txt +++ b/src/native/libs/CMakeLists.txt @@ -32,6 +32,9 @@ if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_BROWSER OR CLR_CMAKE_TARGET_WASI) set(CMAKE_INSTALL_PREFIX $ENV{__CMakeBinDir}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wno-declaration-after-statement") + # TODO-LLVM: remove once upstream moves to WASI SDK 22 as well (or otherwise fixes these warnings). + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-switch-default") + add_compile_options(-I${CMAKE_CURRENT_SOURCE_DIR}/Common) add_compile_options(-I${CMAKE_CURRENT_BINARY_DIR}/Common)