You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The cDAC's WASM ArgIterator cannot reconstruct the stack layout of value-type arguments, because CdacTypeHandle.GetFieldAlignment() is unimplemented:
publicintGetFieldAlignment(){thrownewNotImplementedException("Field alignment is not yet implemented.");}
The shared ArgIterator Wasm32 case computes align = Math.Clamp(_argTypeHandle.GetFieldAlignment(), 8, 16), so any managed stack walk over a wasm frame whose signature contains a value-type argument (Guid, DateTime, an ordinary struct, Int128, a SIMD vector, ...) throws instead of producing an argument layout.
This blocks cDAC-side argument enumeration / GC-ref reporting on wasm, which builds on the WASM stack walk added in #130988.
What the runtime does
The runtime's wasm ArgIterator reads the class's real alignment requirement (src/coreclr/vm/callingconvention.h):
which resolves to EEClassLayoutInfo::GetAlignmentRequirement() (src/coreclr/vm/class.h), returning m_ManagedLargestAlignmentRequirementOfAllMembers. The faithful cDAC implementation is to read that same value, with the same clamp.
Why "special-case the SIMD types" is not sufficient
An earlier attempt derived the alignment by matching type metadata (namespace/name) to identify 16-byte SIMD vectors. That approach cannot converge on the runtime's behavior, because the runtime's set of 16-byte-aligned wasm types is strictly broader than the SIMD vector types. Int128/UInt128 are the existing counterexample — src/coreclr/vm/methodtablebuilder.cpp does:
Any name-matching predicate that enumerates a hand-picked subset of the runtime's alignment policy will drift from it. Reading the computed alignment is the only approach that stays correct as that policy evolves, and it fixes every value type at once rather than one family.
Work required
Runtime data descriptor: expose the layout-info alignment. Note that EEClassLayoutInfo m_LayoutInfo lives on LayoutEEClass : public EEClass (src/coreclr/vm/class.h), not on EEClass itself, so this needs a cdac_data<LayoutEEClass> specialization (in the style of the existing cdac_data<EEClassOptionalFields>) plus the EEClassLayoutInfo field offset, and matching datadescriptor.h entries.
cDAC data type + contract: a Data type for the layout info and a contract surface to read the alignment requirement for a MethodTable/EEClass.
CdacTypeHandle.GetFieldAlignment: return the alignment requirement, mirroring getClassAlignmentRequirementStatic.
HasLayout gating: EEClass::GetLayoutInfo() asserts HasLayout(). The reader must check the corresponding flag before reading the layout info, or it will read unrelated memory for classes without layout. The behavior for value types without layout info needs to be established to match the runtime.
Docs: update the affected contract doc(s).
Tests: cDAC unit tests covering a non-SIMD struct, a 16-byte-aligned type (e.g. Int128), and the no-layout case.
Summary
The cDAC's WASM
ArgIteratorcannot reconstruct the stack layout of value-type arguments, becauseCdacTypeHandle.GetFieldAlignment()is unimplemented:The shared
ArgIteratorWasm32 case computesalign = Math.Clamp(_argTypeHandle.GetFieldAlignment(), 8, 16), so any managed stack walk over a wasm frame whose signature contains a value-type argument (Guid,DateTime, an ordinary struct,Int128, a SIMD vector, ...) throws instead of producing an argument layout.This blocks cDAC-side argument enumeration / GC-ref reporting on wasm, which builds on the WASM stack walk added in #130988.
What the runtime does
The runtime's wasm
ArgIteratorreads the class's real alignment requirement (src/coreclr/vm/callingconvention.h):align = std::clamp(CEEInfo::getClassAlignmentRequirementStatic(thValueType.GetMethodTable()), INTERP_STACK_SLOT_SIZE, INTERP_STACK_ALIGNMENT);which resolves to
EEClassLayoutInfo::GetAlignmentRequirement()(src/coreclr/vm/class.h), returningm_ManagedLargestAlignmentRequirementOfAllMembers. The faithful cDAC implementation is to read that same value, with the same clamp.Why "special-case the SIMD types" is not sufficient
An earlier attempt derived the alignment by matching type metadata (namespace/name) to identify 16-byte SIMD vectors. That approach cannot converge on the runtime's behavior, because the runtime's set of 16-byte-aligned wasm types is strictly broader than the SIMD vector types.
Int128/UInt128are the existing counterexample —src/coreclr/vm/methodtablebuilder.cppdoes:Any name-matching predicate that enumerates a hand-picked subset of the runtime's alignment policy will drift from it. Reading the computed alignment is the only approach that stays correct as that policy evolves, and it fixes every value type at once rather than one family.
Work required
EEClassLayoutInfo m_LayoutInfolives onLayoutEEClass : public EEClass(src/coreclr/vm/class.h), not onEEClassitself, so this needs acdac_data<LayoutEEClass>specialization (in the style of the existingcdac_data<EEClassOptionalFields>) plus theEEClassLayoutInfofield offset, and matchingdatadescriptor.hentries.Datatype for the layout info and a contract surface to read the alignment requirement for aMethodTable/EEClass.CdacTypeHandle.GetFieldAlignment: return the alignment requirement, mirroringgetClassAlignmentRequirementStatic.HasLayoutgating:EEClass::GetLayoutInfo()assertsHasLayout(). The reader must check the corresponding flag before reading the layout info, or it will read unrelated memory for classes without layout. The behavior for value types without layout info needs to be established to match the runtime.Int128), and the no-layout case.Context
ArgIterator. This is required for the argument-enumeration / GC-ref-reporting milestone.Note
This issue was authored with the assistance of GitHub Copilot.