Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tweaks to enable NativeAOT-LLVM on Linux with WASI-SDK 22 #2592

Merged
merged 2 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/workflow/building/coreclr/nativeaot.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
9 changes: 8 additions & 1 deletion eng/native/gen-buildsys.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
13 changes: 10 additions & 3 deletions eng/pipelines/runtimelab/install-wasi-sdk.ps1
Original file line number Diff line number Diff line change
@@ -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/
4 changes: 2 additions & 2 deletions src/coreclr/build-runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 1 addition & 6 deletions src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/jit/ClrJit.Llvm.exports

This file was deleted.

1 change: 1 addition & 0 deletions src/coreclr/jit/ClrJit.PAL.exports
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ jitStartup
getLikelyClasses
getLikelyMethods
jitBuildString
registerLlvmCallbacks
1 change: 1 addition & 0 deletions src/coreclr/jit/ClrJit.exports
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ EXPORTS
getLikelyClasses
getLikelyMethods
jitBuildString
registerLlvmCallbacks
7 changes: 7 additions & 0 deletions src/coreclr/jit/ee_il_dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 3 additions & 3 deletions src/coreclr/jit/llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ CORINFO_GENERIC_HANDLE Llvm::getSymbolHandleForClassToken(mdToken token)
template <EEApiId Func, typename TReturn, typename... TArgs>
TReturn CallEEApi(TArgs... args)
{
return static_cast<TReturn (*)(TArgs...)>(g_callbacks[static_cast<int>(Func)])(args...);
return reinterpret_cast<TReturn (*)(TArgs...)>(g_callbacks[static_cast<int>(Func)])(args...);
}

const char* Llvm::GetMangledMethodName(CORINFO_METHOD_HANDLE methodHandle)
Expand Down Expand Up @@ -866,8 +866,8 @@ extern "C" DLLEXPORT void registerLlvmCallbacks(void** jitImports, void** jitExp
assert(jitExports != nullptr);

memcpy(g_callbacks, jitImports, static_cast<int>(EEApiId::Count) * sizeof(void*));
jitExports[static_cast<int>(JitApiId::StartSingleThreadedCompilation)] = &Llvm::StartSingleThreadedCompilation;
jitExports[static_cast<int>(JitApiId::FinishSingleThreadedCompilation)] = &Llvm::FinishSingleThreadedCompilation;
jitExports[static_cast<int>(JitApiId::StartSingleThreadedCompilation)] = (void*)&Llvm::StartSingleThreadedCompilation;
jitExports[static_cast<int>(JitApiId::FinishSingleThreadedCompilation)] = (void*)&Llvm::FinishSingleThreadedCompilation;
jitExports[static_cast<int>(JitApiId::Count)] = (void*)0x1234;
}

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/llvmcodegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/llvmlower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,9 @@ void Llvm::lowerFieldOfDependentlyPromotedStruct(GenTree* node)
lclVar->gtFlags |= GTF_VAR_USEASG;
}
break;

default:
break;
}

lclVar->SetLclNum(varDsc->lvParentLcl);
Expand Down
9 changes: 8 additions & 1 deletion src/coreclr/jit/llvmlssa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -1636,6 +1636,10 @@ class ShadowStackAllocator
template <typename... TArgs>
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...);
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,11 @@ The .NET Foundation licenses this file to you under the MIT license.

<Target Name="CheckWasmSdks">
<Error Text="Emscripten not found, not compiling to WebAssembly. To enable WebAssembly compilation, install Emscripten and ensure the EMSDK environment variable points to the directory containing upstream/emscripten/emcc.bat"
Condition="'$(EMSDK)' == ''" />
Condition="'$(EMSDK)' == '' and '$(_targetOS)' == 'browser'" />
<Error Text="Wasi SDK not found, not compiling to WebAssembly. To enable WebAssembly compilation, install Wasi SDK and ensure the WASI_SDK_PATH environment variable points to the directory containing share/wasi-sysroot"
Condition="'$(WASI_SDK_PATH)' == '' and '$(_targetOS)' == 'wasi'" />
<Warning Text="The WASI SDK version is too low. Please use WASI SDK 22 or newer with a 64 bit Clang."
Condition="!Exists('$(WASI_SDK_PATH)/VERSION')" />
dicej marked this conversation as resolved.
Show resolved Hide resolved
dicej marked this conversation as resolved.
Show resolved Hide resolved
</Target>

<Target Name="CompileWasmObjects"
Expand Down Expand Up @@ -420,8 +422,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<CompileWasmArgs>$(CompileWasmArgs) -fvisibility=default -mllvm -combiner-global-alias-analysis=false -mllvm -disable-lsr --sysroot=&quot;$(WASI_SDK_PATH)/share/wasi-sysroot&quot; -target $(IlcLlvmTarget)</CompileWasmArgs>

<ExeExt Condition="'$(OS)' == 'Windows_NT'">.exe</ExeExt>
<!-- using Emscripten's clang++ because of a crash in wasi-sdk's clang++ (https://github.com/WebAssembly/wasi-sdk/issues/326) -->
<WasmCompilerPath>&quot;$(EMSDK)/upstream/bin/clang++$(ExeExt)&quot;</WasmCompilerPath>
<WasmCompilerPath>&quot;$(WASI_SDK_PATH)/bin/clang++$(ExeExt)&quot;</WasmCompilerPath>
dicej marked this conversation as resolved.
Show resolved Hide resolved
<WasmLinkerPath>&quot;$(WASI_SDK_PATH)/bin/clang&quot;</WasmLinkerPath>
</PropertyGroup>

Expand Down
3 changes: 3 additions & 0 deletions src/native/libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Loading