Repository navigation
[cDAC] Expose EEClass layout alignment so the WASM ArgIterator can reconstruct value-type argument layout #131343
Description
Summary
The cDAC's WASM ArgIterator cannot reconstruct the stack layout of value-type arguments, because CdacTypeHandle.GetFieldAlignment() is unimplemented:
public int GetFieldAlignment()
{
throw new NotImplementedException("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):
align = std::clamp(CEEInfo::getClassAlignmentRequirementStatic(thValueType.GetMethodTable()),
INTERP_STACK_SLOT_SIZE, INTERP_STACK_ALIGNMENT);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:
else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0))
{
...
#elif defined(TARGET_WASM)
pLayout->SetAlignmentRequirement(16); // sizeof(v128)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_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. - cDAC data type + contract: a
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.- 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.
Context
- The WASM cDAC stack walk itself ([cDAC] WebAssembly support: stack walking and managed metadata resolution #130988) does not depend on this — it resolves frames independently of
ArgIterator. This is required for the argument-enumeration / GC-ref-reporting milestone. - A v128-only partial implementation was proposed and deliberately dropped in favor of doing this properly, for the reasons above.
Note
This issue was authored with the assistance of GitHub Copilot.
Activity
dotnet-policy-service commentedon Jul 24, 2026
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.
[wasm][R2R] Fix Vector128 argument alignment in crossgen ArgIterator (#…
[wasm][R2R] Fix Vector128 argument alignment in crossgen ArgIterator (d…
[cDAC] Implement GetFieldAlignment via EEClass layout alignment (dotn…