Skip to content

[WIP] Virtual ip handling and other things#128423

Open
davidwrighton wants to merge 9 commits into
dotnet:mainfrom
davidwrighton:virtual_ip_handling_and_other_things
Open

[WIP] Virtual ip handling and other things#128423
davidwrighton wants to merge 9 commits into
dotnet:mainfrom
davidwrighton:virtual_ip_handling_and_other_things

Conversation

@davidwrighton
Copy link
Copy Markdown
Member

@davidwrighton davidwrighton commented May 21, 2026

Work in progress to convert Wasm R2R to use virtual ips

Notable not-done work

  • Stack walk not hooked up right
  • R2RDump is unaware of how to find the code
  • Various bugs around GCDecoder correctness
  • JIT generation of reasonable Virtual IP ranges (Andy has work in progress that looks pretty good)
  • Documentation about RUNTIME_FUNCTION design and Unwind info

…function table indices

- Add parallel table for lookup which uses a secondary list for virtual ip lookup to RangeSection
- Adjust handling to provide a different base address for looking up details from the RUNTIME_FUNCTION
- Adjust ExceptionInfoLookupTable to point at virtual ips
- Remove hot/cold split map from WebAssembly R2R
- Adjust Unwind format to include virtual ips. Put some stub code into the JIT to tell the runtime about how many virtual ips are associated with each chunk of code
…ening (looks like infinite loop building stack trace)
Copilot AI review requested due to automatic review settings May 21, 2026 00:10
@github-actions github-actions Bot added the area-crossgen2-coreclr only use for closed issues label May 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 introduces initial support for using virtual IPs (instead of linear-memory code addresses) for WASM ReadyToRun (R2R) method identification and lookup. It wires up new VM/ExecutionManager plumbing to register and resolve virtual-IP ranges and updates the R2R toolchain to emit/consume WASM-specific metadata (notably RUNTIME_FUNCTION entries and unwind blob decoding), with follow-on updates in r2rdump and Webcil readers to recognize WASM machine targets.

Changes:

  • Add WASM virtual-IP range + function-table-index range registration in ExecutionManager / ReadyToRunInfo, and route some lookups through these ranges.
  • Change the WASM RUNTIME_FUNCTION table encoding to store virtual-IP indices (and a post-sentinel min function-table index), and update readers/writers accordingly.
  • Extend tooling (ILCompiler.Reflection.ReadyToRun + r2rdump + object writer) to recognize Wasm32 in parsing/printing paths.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/vm/wasm/helpers.cpp Adds WASM helpers for virtual IP / frame-pointer extraction and WASM RtlpGetFunctionEndAddress implementation.
src/coreclr/vm/readytoruninfo.h Adds WASM state for min function-table index / min virtual IP; gates hot/cold code pieces.
src/coreclr/vm/readytoruninfo.cpp Registers virtual IP ranges for WASM and adjusts entrypoint bookkeeping.
src/coreclr/vm/frames.h Adds WASM transition-frame SP/return-address logic using virtual IPs.
src/coreclr/vm/eetwain.cpp WASM-specific workaround for code-length decoding.
src/coreclr/vm/datadescriptor/datadescriptor.inc Updates CDAC field emission conditionals for gated ReadyToRunInfo fields.
src/coreclr/vm/codeman.inl Splits module base concepts (functions base vs RVA base) for WASM virtual IP ranges.
src/coreclr/vm/codeman.h Introduces virtual-IP range structures/APIs on WASM and new IJitManager base helpers.
src/coreclr/vm/codeman.cpp Implements WASM virtual-IP range registration/lookup and function-table-index mapping.
src/coreclr/vm/ceeload.h Adds Module base-address accessor used by WASM RVA base logic.
src/coreclr/vm/ceeload.cpp Hooks eager fixups to register virtual-IP ranges on WASM instead of code ranges.
src/coreclr/tools/r2rdump/Program.cs Recognizes WASM machine type for selecting target architecture.
src/coreclr/tools/r2rdump/CoreDisTools.cs Adds WASM to indentation configuration.
src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs Tightens relocation invariants/assertions for Webcil section relocation handling.
src/coreclr/tools/Common/Compiler/ObjectWriter/ObjectWriter.cs Adjusts IMAGE_REL_SYMBOL_SIZE relocation resolution behavior.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/WebcilImageReader.cs Reports Webcil “machine” as Wasm32 placeholder.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/Wasm32/UnwindInfo.cs Adds WASM unwind blob parser for tooling.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/TransitionBlock.cs Adds WASM transition block shape for tooling-side decoding.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs Introduces WasmMachine placeholder and updates pointer-size/import-section sizing logic.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs Uses WASM unwind info decoder when parsing runtime functions.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/GCInfoTypes.cs Adds WASM constants for tooling-side GC info decoding.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/DebugInfo.cs Adds WASM register-name placeholder for debug info printing.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/Amd64/GcTransition.cs Throws for WASM machine in a path that isn’t implemented for WASM tooling.
src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/Amd64/GcSlotTable.cs Throws for WASM machine in a path that isn’t implemented for WASM tooling.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs Avoids emitting DelayLoadMethodCallThunks section for WASM.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs Emits WASM RUNTIME_FUNCTION BeginAddress as virtual-IP index + funclet bit; emits min table index after sentinel.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHeaderNode.cs Adjusts RuntimeFunctions section size accounting for WASM (sentinel + trailing min index).
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs Uses virtual-IP values in EH lookup table for WASM instead of method pointers.
src/coreclr/jit/unwindwasm.cpp Extends WASM unwind blob format to include virtual IP count.
src/coreclr/jit/flowgraph.cpp Initializes per-funclet WASM virtual IP count (placeholder).
src/coreclr/jit/compiler.h Adds funWasmVirtualIPCount to funclet info.
src/coreclr/inc/clrnt.h Changes WASM RUNTIME_FUNCTION BeginAddress encoding to carry a funclet flag bit and declares decode helpers.

VirtualIPRangeSection* pOldRangeSection = nullptr;
do
{
VirtualIPRangeSection* pOldRangeSection = VolatileLoadWithoutBarrier(&s_pVirtualIPRangeList);
Comment on lines +5274 to +5281
#ifdef TARGET_WASM
if (IsVirtualIP(currentPC))
{
VirtualIPRangeSection* pVIPRange = FindVirtualIPRangeSection(currentPC);
if (pVIPRange != nullptr)
return &pVIPRange->rangeSection;
return NULL;
}
Comment on lines +5853 to +5862
do
{
PTR_RUNTIME_FUNCTION pRuntimeFunction = pR2RInfo->GetRuntimeFunctions() + localIndex;
if (RUNTIME_FUNCTION__IsFunclet(pRuntimeFunction))
{
localIndex--;
continue;
}
return pR2RInfo->GetMinVirtualIP() + RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction);
} while (true);
Comment on lines 378 to 400
@@ -394,7 +394,7 @@ bool ReadyToRunInfo::SetMethodDescForEntryPointInNativeImage(PCODE entryPoint, M
CONTRACTL_END;

CrstHolder ch(&m_Crst);
if ((TADDR)m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPoint), (LPVOID)PCODEToPINSTR(entryPoint)) == (TADDR)INVALIDENTRY)
if ((TADDR)m_entryPointToMethodDescMap.LookupValue(PCODEToPINSTR(entryPoint), 0) == (TADDR)INVALIDENTRY)
{
m_entryPointToMethodDescMap.InsertValue(PCODEToPINSTR(entryPoint), methodDesc);
return true;
Comment on lines +2873 to +2886
// The last RUNTIME_FUNCTION entry's BeginAddress is the virtual IP index of that entry.
// Total virtual IPs = lastEntry.BeginAddress + virtualIPCount(lastEntry)
T_RUNTIME_FUNCTION* pLastEntry = &m_pRuntimeFunctions[m_nRuntimeFunctions - 1];
UINT32 lastEntryVirtualIPIndex = RUNTIME_FUNCTION__BeginAddress(pLastEntry);

// Decode the virtual IP count from the last entry's unwind data.
// Unwind format: ULEB128(frameSize) ULEB128(virtualIPCount)
PTR_BYTE pUnwindData = dac_cast<PTR_BYTE>(imageBase + pLastEntry->UnwindData);
DecodeULEB128AsU32(&pUnwindData); // skip frame size
UINT32 lastEntryVIPCount = DecodeULEB128AsU32(&pUnwindData);

UINT32 totalVirtualIPs = lastEntryVirtualIPIndex + lastEntryVIPCount;

m_minVirtualIP = ExecutionManager::AddVirtualIPRange(
Comment on lines +131 to +136
/// </summary>
private static uint GetVirtualIPCountFromUnwindBlob(byte[] blobData)
{
int offset = 0;
DecodeULEB128(blobData, ref offset); // skip frame size
return DecodeULEB128(blobData, ref offset) * 2; // Multiply by 2 to force all virtual IPs to be an even number.
Comment on lines +119 to +120
// This might be right?
return SizeOfTransitionBlock + pos * PointerSize;
namespace ILCompiler.Reflection.ReadyToRun.Wasm32
{
/// <summary>
/// based on <a href="https://github.com/dotnet/runtime/src/coreclr/jit/unwindriscv64.cpp">src/jit/unwindriscv64.cpp</a> DumpUnwindInfo
Comment on lines 1406 to +1412
PCODE actualEntryPoint;
actualEntryPoint = m_pRuntimeFunctions[id].BeginAddress;
actualEntryPoint = GetMinFunctionTableIndex() + id;
PCODE virtualEntrypointIP;
virtualEntrypointIP = GetMinVirtualIP() + RUNTIME_FUNCTION__BeginAddress(&m_pRuntimeFunctions[id]);
pEntryPoint = pMD->GetTemporaryEntryPoint();
PortableEntryPoint::SetActualCode(pEntryPoint, actualEntryPoint);
m_pCompositeInfo->SetMethodDescForEntryPointInNativeImage(virtualEntrypointIP, pMD);
#ifdef TARGET_WASM
VirtualIPRangeSection* ExecutionManager::s_pVirtualIPRangeList = nullptr;
FunctionTableIndexRangeSection* ExecutionManager::s_pFunctionTableIndexRangeList = nullptr;
static TADDR s_nextVirtualIP = 0x80000001;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-crossgen2-coreclr only use for closed issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants