Skip to content

Upgrade emsdk to 5.0.6#129299

Draft
akoeplinger wants to merge 19 commits into
mainfrom
emsdk-upgrade
Draft

Upgrade emsdk to 5.0.6#129299
akoeplinger wants to merge 19 commits into
mainfrom
emsdk-upgrade

Conversation

@akoeplinger

Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings June 11, 2026 16:44
@github-actions github-actions Bot added the area-codeflow for labeling automated codeflow label Jun 11, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Mono WASM/Browser toolchain to Emscripten (emsdk) 5.0.6, and refreshes several repo toolset dependency versions (Arcade/Helix/SDK pins) plus related engineering scripts/templates.

Changes:

  • Bump Emscripten version from 3.1.56 → 5.0.6 and update the Windows Python package path used for Browser/WASI builds.
  • Refresh dependency/version pins in global.json, eng/Versions.props, and eng/Version.Details.*.
  • Update engineering infrastructure (NuGet feed setup scripts, ADO templates, OpenBSD rootfs behavior, Helix monitor timeout), and add an opt-in native compiler detection target.

Reviewed changes

Copilot reviewed 8 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/mono/mono.proj Updates Browser/WASI Windows Python path property to match the new Emscripten package ID/version.
src/mono/browser/emscripten-version.txt Updates tracked Emscripten version to 5.0.6.
global.json Updates Arcade/Helix/SharedFramework SDK pins and IL SDK version.
eng/Versions.props Updates EmsdkVersion to 5.0.6.
eng/Version.Details.xml Updates dependency versions/SHAs to the newer dotnet/dotnet toolset flow.
eng/Version.Details.props Updates derived toolset version properties to match Version.Details.xml.
eng/native/tryrun.browser.cmake Updates the version marker for the browser-wasm try_run cache to 5.0.6.
eng/common/templates/vmr-build-pr.yml Switches VMR GitHub endpoint to public.
eng/common/templates/job/job.yml Removes public-only CG skip step (logic moved elsewhere).
eng/common/SetupNugetSources.sh Avoids triggering repo toolset setup as a side effect of feed configuration.
eng/common/SetupNugetSources.ps1 Same as above for PowerShell.
eng/common/native/LocateNativeCompiler.targets Adds an opt-in target to infer linker flags via init-compiler.sh output.
eng/common/cross/build-rootfs.sh Adjusts OpenBSD rootfs package extraction, symlink logic, and cleanup.
eng/common/core-templates/steps/enable-internal-sources.yml Adds non-Windows feed setup path (Bash) alongside Windows (PowerShell).
eng/common/core-templates/job/job.yml Sets public-project variables to skip CG detection / CodeQL auto-injection.
eng/common/core-templates/job/helix-job-monitor.yml Gives Helix monitor tool more buffer time vs. ADO job timeout.

Comment thread eng/common/native/LocateNativeCompiler.targets
Comment thread eng/common/native/LocateNativeCompiler.targets
Comment thread eng/native/tryrun.browser.cmake
Comment thread eng/common/cross/build-rootfs.sh
@github-actions

This comment has been minimized.

@akoeplinger

Copy link
Copy Markdown
Member Author

/azp run runtime-wasm

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Copilot AI review requested due to automatic review settings June 11, 2026 17:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 21 changed files in this pull request and generated no new comments.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings June 11, 2026 19:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 22 changed files in this pull request and generated 2 comments.

Comment thread eng/common/cross/build-rootfs.sh
Comment thread global.json
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@pavelsavara pavelsavara added arch-wasm WebAssembly architecture os-browser Browser variant of arch-wasm labels Jun 12, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@pavelsavara

Copy link
Copy Markdown
Member

/azp run runtime-wasm

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara

pavelsavara commented Jun 12, 2026

Copy link
Copy Markdown
Member

When passing a negative C int to LLVMConstInt, the value is implicitly
converted to unsigned long long via sign-extension. In LLVM 23,
LLVMConstInt now retains those upper bits when SignExtend is FALSE,
which broke constant folding of subsequent ZExt instructions (e.g.
'zext i32 -1 to i64' produced i64 -1 instead of i64 4294967295).

This manifested as wrong results for decimal arithmetic in mono+LLVM
AOT, e.g. the inlined Decimal..ctor(uint) with a constant argument
sign-extending to _lo64. Many CoreLib tests (System.Tests.DecimalTests,
System.Text.Tests.RuneTests, Vector128.NarrowWithSaturation*) were
failing as a result.

Mask the value to the destination width before passing to LLVMConstInt.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings June 12, 2026 18:09
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 25 changed files in this pull request and generated 3 comments.

Comment thread eng/common/cross/build-rootfs.sh
Comment thread eng/common/SetupNugetSources.sh
@pavelsavara

pavelsavara commented Jun 12, 2026

Copy link
Copy Markdown
Member

Log
[20:16:41] info: [FAIL] System.IO.Tests.FileInfo_GetSetTimes.CopyToNanosecondsPresent

Log

[20:03:19] info: [FAIL] System.Runtime.Intrinsics.Tests.Vectors.Vector128Tests.NarrowWithSaturationUInt32Test
[20:03:19] info: Assert.Equal() Failure: Values differ
[20:03:19] info: Expected: 65535
[20:03:19] info: Actual:   0

Copilot AI review requested due to automatic review settings June 12, 2026 20:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 32 changed files in this pull request and generated 3 comments.

Comment on lines +108 to +111
# Node.js doesn't have good support for WASM_BIGINT
# so it only is added when running in the browser.
target_link_options(corerun PRIVATE
-sWASM_BIGINT=0)
Comment on lines 20 to 23
protected static bool isHFS => driveFormat != null && driveFormat.Equals(HFS, StringComparison.InvariantCultureIgnoreCase);

protected static bool LowTemporalResolution => PlatformDetection.IsBrowser || isHFS;
protected static bool LowTemporalResolution => isHFS;
protected static bool HighTemporalResolution => !LowTemporalResolution;
Comment on lines +43 to 48
# This script only consumes helper functions from tools.sh to configure NuGet feeds.
# Skip importing configure-toolset.sh so that repo-specific toolset setup (e.g. acquiring
# a bootstrap SDK) is not triggered as a side effect of feed configuration.
disable_configure_toolset_import=1

. "$scriptroot/tools.sh"
Updated comments to clarify that OSX HFS driver format does not support millisecond granularity.
Copilot AI review requested due to automatic review settings June 12, 2026 21:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 32 changed files in this pull request and generated 4 comments.

Comment on lines 620 to 624
if [[ "$__hasWget" == 1 ]]; then
wget -O- "$PKG_MIRROR/$PKG_FILE" | tar -C "$__RootfsDir" -xzpf -
wget -O- "$PKG_MIRROR/$PKG_FILE" | tar -C "$__RootfsDir/usr/local" -xzpf -
else
curl -SL "$PKG_MIRROR/$PKG_FILE" | tar -C "$__RootfsDir" -xzpf -
curl -SL "$PKG_MIRROR/$PKG_FILE" | tar -C "$__RootfsDir/usr/local" -xzpf -
fi
Comment on lines +108 to +111
# Node.js doesn't have good support for WASM_BIGINT
# so it only is added when running in the browser.
target_link_options(corerun PRIVATE
-sWASM_BIGINT=0)
Comment on lines +33 to +37
// Mono's LLVM backend uses the global-context LLVM-C type accessors (LLVMInt32Type, etc.)
// pervasively. These are deprecated in newer LLVM versions in favor of the *InContext variants.
// Suppress the deprecation warnings rather than threading an LLVMContextRef through every call site.
#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Comment on lines 291 to 296
await mono_wasm_after_user_runtime_initialized();
endMeasure(mark, MeasuredBlock.onRuntimeInitialized);
} catch (err) {
Module.runtimeKeepalivePop();
mono_log_error("onRuntimeInitializedAsync() failed", err);
loaderHelpers.mono_exit(1, err);
throw err;
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #129299

Note

This review was generated by GitHub Copilot.

Holistic Assessment

Motivation: Upgrading emsdk from 3.1.56 to 5.0.6 (with LLVM 19.x → 23.x) is a justified infrastructure update to keep the WASM toolchain current for .NET 11. The accompanying fixes for LLVM API changes, Wasm exception handling, keepalive management, and the _WasmDefaultFlags bug are all required to make the new emsdk work correctly.

Approach: The approach is sound — version bumps are consistent across all config files, the Mono LLVM C++ code correctly adapts to the deprecated global-context API, the new Wasm EH (exnref) is properly configured with -sWASM_LEGACY_EXCEPTIONS=0, and the const_int8/const_int32 masking fixes address a real LLVM 23 behavior change. The bundled Arcade SDK update (26302.118 → 26311.101) is a standard co-dependency flow.

Summary: ⚠️ Needs Human Review. The code changes are technically correct for the emsdk 5.x upgrade, but the PR is large in scope (32 files, emsdk + LLVM + Arcade + runtime fixes + test changes) and a few residual comment inconsistencies exist. CI validation is the primary verification mechanism here; a human reviewer familiar with the WASM infrastructure should confirm the keepalive management changes and the WASM_BIGINT default behavior change.


Detailed Findings

✅ LLVM 23 API Adaptation — Correct context threading

The changes in mini-llvm-cpp.cpp properly thread LLVMContextRef through functions that previously used the deprecated LLVMGetGlobalContext():

  • mono_llvm_create_constant_data_array now accepts a context parameter
  • mono_llvm_get_ptr_type now accepts a context parameter
  • mono_llvm_add_param_attr_with_type and related functions use func->getContext() instead of global context
  • mono_llvm_di_create_location correctly derives context from the scope metadata node
  • Intrinsic::getOrInsertDeclaration is properly version-gated with #if LLVM_API_VERSION >= 2100

All call sites in mini-llvm.c have been updated consistently to pass ctx->module->context or module->context.

const_int8/const_int32 Masking — Correct fix for LLVM 23

The cast to (guint8) and (guint32) in const_int8() and const_int32() is the right approach. LLVM 23 changed LLVMConstInt to retain upper bits when SignExtend=FALSE, causing zext i8 -1 to i64 to yield -1 instead of 255. The comment explains the rationale well.

_WasmDefaultFlags SIMD Bug Fix — Fixes latent bug

The old code had:

<_WasmDefaultFlags Condition="'$(WasmEnableSIMD)' == 'true'">-msimd128</_WasmDefaultFlags>

This would overwrite the exception-handling flags. The fix correctly appends:

<_WasmDefaultFlags Condition="'$(WasmEnableSIMD)' == 'true'">$(_WasmDefaultFlags) -msimd128</_WasmDefaultFlags>

This is a real bug fix that was masked because SIMD and exception-handling flags happened to work independently.

✅ Wasm Exception Handling — Correct migration to exnref

The standardized Wasm EH (-sWASM_LEGACY_EXCEPTIONS=0) is consistently applied across:

  • BrowserWasmApp.targets (compile+link)
  • eng/native/configureplatform.cmake
  • src/mono/mono/mini/CMakeLists.txt (mono-wasm-eh-wasm target)

The flag is applied to both compile and link stages as required by Emscripten.

✅ HEAP* Exports — Necessary for emsdk 5.x

The explicit export of HEAP8, HEAP16, HEAPU8, etc. in eng/native.wasm.targets is necessary because emsdk 5.x no longer auto-exports these heap view accessors.

⚠️ Keepalive Management Changes — Correct but complex; needs careful CI validation

The runtimeKeepalivePop() additions in scheduling.ts and dotnet-gcdump.ts balance the implicit runtimeKeepalivePush() done by Emscripten's safeSetTimeout. When clearTimeout cancels a pending timer, the push needs to be manually popped. The removal of runtimeKeepalivePop() from startup.ts error path is also correct (it was unbalanced there).

The reordering in mono_wasm_schedule_timer_tick (moving lastScheduledTimeoutId = undefined before maybeExit()) ensures maybeExit() sees the correct timer state. This is logically correct but subtle — CI validation on browser/Node.js scenarios is the key verification.

⚠️ WASM_BIGINT Comment Inaccuracy — Minor but misleading

In src/coreclr/hosts/corerun/CMakeLists.txt (line 108-109), the comment still reads:

# Node.js doesn't have good support for WASM_BIGINT
# so it only is added when running in the browser.

But the code now explicitly disables WASM_BIGINT for Node.js (-sWASM_BIGINT=0), implying emsdk 5.x enables it by default. The comment should say something like "Node.js doesn't have good support for WASM_BIGINT, so we explicitly disable it here (it's enabled by default in the browser)." This was already flagged in prior review comments but remains unresolved.

⚠️ File-Wide Deprecation Suppression — Acceptable trade-off, worth tracking

The #pragma GCC diagnostic ignored "-Wdeprecated-declarations" in mini-llvm.c suppresses all deprecation warnings file-wide. The comment explains this is because global-context type accessors (LLVMInt32Type(), etc.) are used pervasively and threading context through every call site is impractical. This is a reasonable pragmatic choice for now, but could mask future deprecation warnings for other LLVM APIs. Consider tracking this as tech debt to incrementally migrate call sites in the future.

💡 flush_node_streams Guard — Defensive but harmless

Adding if (!ENVIRONMENT_IS_NODE) return; at the top of flush_node_streams() is a defensive guard. The dynamic import("process") would likely fail in non-Node environments anyway, but the early return avoids unnecessary async work and potential error noise.

💡 Scope — Large but cohesive

The PR bundles emsdk upgrade + LLVM adaptation + Arcade dependency flow + runtime/test fixes. While large (32 files), the changes are cohesive — the emsdk upgrade necessitates all the other changes. The Arcade eng/common changes come from the dotnet/dotnet dependency flow and are expected to be overwritten by future syncs.

Generated by Code Review for issue #129299 · ● 8.5M ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-codeflow for labeling automated codeflow os-browser Browser variant of arch-wasm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants