[WASM] Use relocs for tableBase / imageBase / stackPointer globals#129717
Open
jtschuster wants to merge 7 commits into
Open
[WASM] Use relocs for tableBase / imageBase / stackPointer globals#129717jtschuster wants to merge 7 commits into
jtschuster wants to merge 7 commits into
Conversation
The wasm JIT previously referenced the three ABI "base globals" (shadow stack pointer, image base, table base) with bare `global.get <fixedIdx>` immediates and no relocation. That prevents a relocatable NativeAOT object from letting wasm-ld renumber the global index space. Make the shared wasm JIT emit these three sites as relocatable, maximally padded `global.get` instructions carrying WASM_GLOBAL_INDEX_LEB relocations against the well-known symbols __stack_pointer/__memory_base/__table_base. This is uniform for both R2R (crossgen2) and NativeAOT: - JIT: new IF_GLOBALIDX instruction format and emitIns_BaseGlobal emitter; the three emit sites (codegenwasm prologue stack pointer, emitAddressConstant image base, emitFuncletAddressConstant table base) now emit the relocatable form. - recordRelocation maps the encoded fixed base-global index to a new shared WasmBaseGlobalSymbolNode so the relocation has a symbol target. - The R2R WasmObjectWriter self-resolves WASM_GLOBAL_INDEX_LEB back to the fixed global index (0/1/2) before the defined-symbol lookup, so existing R2R output stays functionally identical (validated: WebAssembly.validate is true, relocations section empty, base-global gets resolve to the same indices, only widened to the padded encoding). The NativeAOT object writer does not exist yet; the AOT path only needs to compile here and will emit these as undefined imported global symbols once that writer lands. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a static-data-reading method (SumStaticData) to the WasmWebcilModule test case. Reading static data makes the wasm JIT materialize the image base and table base via 'global.get' of the base globals, which are now emitted as WASM_GLOBAL_INDEX_LEB relocations that the R2R object writer must self-resolve. This exercises the base-global relocation path end-to-end: with the self-resolution in WasmObjectWriter.ResolveRelocations, crossgen2 emits the method and the test passes; without it, crossgen2 throws KeyNotFoundException for the undefined '__table_base'/'__memory_base' symbols and the test fails. Verified the test fails when the self-resolution is disabled and passes when it is restored. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… test Previously the WasmWebcilModule R2R test only checked that methods were present in the R2R metadata; it never inspected the emitted wasm bytecode, so a regression in base-global relocation self-resolution would not be caught by the assertions. - Add SumWithFinally, whose try/finally drives genCallFinally to emit the table-base 'global.get'. (A function pointer would not exercise this: it emits i32.const_funcptr / WASM_TABLE_INDEX_SLEB, not the table-base global.) - Add R2RAssert.WasmImageContainsBaseGlobalGet, which scans wasm function bodies for a maximally padded 'global.get' (opcode 0x23 + 5-byte padded ULEB128) of a given base global. - Assert the image-base (1) and table-base (2) global.get patterns are present, confirming the R2R object writer self-resolved the WASM_GLOBAL_INDEX_LEB relocations to the fixed indices. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The JIT only ever reads the three wasm ABI base globals: the shadow stack pointer is read once at the root frame and then threaded through locals and the SP argument, while the image base and table base are immutable relocation bases supplied by the loader. No code path emits global.set on any of them (INS_global_set is never constructed anywhere in the JIT). Narrow emitIns_BaseGlobal to emitIns_BaseGlobalGet: drop the instruction parameter, always emit INS_global_get, and assert the index is one of the known base globals (<= table base). The emitted code is unchanged since every caller already passed INS_global_get. This keeps the relocation behavior (WASM_GLOBAL_INDEX_LEB) intact; if a future design needs to write a base global back, both a global.set emit path and this helper would be widened. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Introduce a new JIT-EE interface method getWasmBaseGlobals that returns symbol handles for the three wasm ABI base globals (shadow stack pointer, image base, and table base) in a single out-struct, modeled on getAsyncInfo and cached in the JIT after the first call. The wasm emitter now targets these real WasmBaseGlobalSymbolNode handles in WASM_GLOBAL_INDEX_LEB relocations instead of having crossgen2 special-case a bare global index in CorInfoImpl.recordRelocation. The base-global reloc now flows through the normal out-of-block symbol resolution path, producing byte-identical R2R output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Have WasmObjectWriter look up the global index from the WasmBaseGlobalSymbolNode mapping instead of switching over the symbol name, and revert unrelated churn in recordRelocation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the WASM JIT/codegen and related toolchain plumbing so that references to the well-known WASM “base globals” (stack pointer, image base, table base) flow through relocations/symbol handles instead of relying on hard-coded global indices. It wires a new JIT-EE query (getWasmBaseGlobals) end-to-end (JIT ↔ EE ↔ SuperPMI ↔ thunks) and updates the WASM object writer plus ReadyToRun tests to validate expected encoding.
Changes:
- Add a new JIT-EE interface method
getWasmBaseGlobalsand thread it through the managed JIT interface, wrappers, and SuperPMI record/replay. - Teach the WASM emitter to generate
global.getfor base globals viaWASM_GLOBAL_INDEX_LEBrelocations, and update the WASM object writer to self-resolve these in ReadyToRun. - Add a small R2R WASM test case and a byte-pattern smoke check to ensure the resolved
global.getencodings are present.
Reviewed changes
Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/inc/corinfo.h | Adds CORINFO_WASM_BASE_GLOBALS and the getWasmBaseGlobals interface method. |
| src/coreclr/inc/icorjitinfoimpl_generated.h | Declares the VM-side override for the new interface method. |
| src/coreclr/inc/jiteeversionguid.h | Bumps the JIT-EE version GUID to reflect the interface change. |
| src/coreclr/vm/jitinterface.cpp | Adds the VM implementation stub for CEEInfo::getWasmBaseGlobals. |
| src/coreclr/jit/compiler.h | Adds JIT-side caching fields and accessor declaration for base globals. |
| src/coreclr/jit/ee_il_dll.hpp | Adds inline Compiler::eeGetWasmBaseGlobals helper. |
| src/coreclr/jit/emitfmtswasm.h | Introduces a new WASM emitter format for global-index relocations. |
| src/coreclr/jit/emitwasm.h | Declares emitIns_BaseGlobalGet to emit relocatable base-global reads. |
| src/coreclr/jit/emitwasm.cpp | Implements emitIns_BaseGlobalGet and routes image/table base users through it. |
| src/coreclr/jit/codegenwasm.cpp | Switches stack-pointer global.get emission to the new base-global path. |
| src/coreclr/jit/ICorJitInfo_names_generated.h | Adds the new API name to the generated API name list. |
| src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp | Adds wrapper forwarding for getWasmBaseGlobals. |
| src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt | Updates thunk generator inputs for the new struct and API. |
| src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs | Adds managed projections for the new handle and base-globals struct. |
| src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | Implements managed-side callback filling CORINFO_WASM_BASE_GLOBALS. |
| src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs | Wires the callback trampoline for getWasmBaseGlobals. |
| src/coreclr/tools/Common/Compiler/DependencyAnalysis/WasmBaseGlobalSymbolNode.cs | New node type representing well-known base-global symbols. |
| src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs | Self-resolves WASM_GLOBAL_INDEX_LEB relocations for base globals in R2R output. |
| src/coreclr/tools/aot/jitinterface/jitinterface_generated.h | Adds wrapper support for the new callback in the AOT jitinterface layer. |
| src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj | Links in the new WasmBaseGlobalSymbolNode source file. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj | Links in the new WasmBaseGlobalSymbolNode source file. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs | Adds a WASM byte-pattern scan helper for padded base-global global.get. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/Webcil/WasmWebcilModule.cs | Adds methods designed to force image-base/table-base materialization in codegen. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs | Extends the WASM WebCIL test to assert expected base-global global.get encodings exist. |
| src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp | Adds SuperPMI replay hook for getWasmBaseGlobals. |
| src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp | Adds passthrough for the new API in the “simple” shim. |
| src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp | Adds call-counting support for the new API in the “counter” shim. |
| src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp | Records the new API call and its outputs during collection. |
| src/coreclr/tools/superpmi/superpmi-shared/agnostic.h | Adds agnostic serialization struct for CORINFO_WASM_BASE_GLOBALS. |
| src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h | Registers a new lightweight map for recording/replaying the call. |
| src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h | Adds record/dump/replay declarations and a new packet id. |
| src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp | Implements record/dump/replay for getWasmBaseGlobals. |
…T fields - Move getWasmBaseGlobals to the end of ICorStaticInfo (after getWasmLowering) to preserve vtable slot ordering and minimize generated-wrapper churn; regenerated the thunk wrapper files via the ThunkGenerator. - Guard the wasm-only base-globals cache fields and inline accessor in Compiler with #if defined(TARGET_WASM), matching existing wasm-only fields, so non-wasm JIT builds don't carry the extra per-compilation state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For NativeAOT, we need to use relocatable tableBase / imageBase / stackPointer globals rather than hard-coded indices.
Add a new JIT-EE API to get handles for the globals needed. The JIT emits the maximum LEB size for the relocation, and the crossgen2 ObjectWriter fixes up the relocations to insert the index of the global. This does increase code size, but should have no other behavioral changes.
The NativeAOT ObjectWriter will leave emit WASM relocations into the emitted object for wasm-ld to fix up when linking to the NativeAOT WASM runtime.
This was implemented with a new JIT interface method, but I think it also could be implemented as ReadyToRun helpers instead if that's preferred.
Fixes #129712.