Skip to content

[cdac] x86 GCInfo decoder + PromoteCallerStack -> GCRefMap; enforce 0 known issues on windows-x86/x64 - #129858

Merged
max-charlamb merged 4 commits into
dotnet:mainfrom
max-charlamb:x86-gc-info-w-argiterator
Jun 30, 2026
Merged

[cdac] x86 GCInfo decoder + PromoteCallerStack -> GCRefMap; enforce 0 known issues on windows-x86/x64#129858
max-charlamb merged 4 commits into
dotnet:mainfrom
max-charlamb:x86-gc-info-w-argiterator

Conversation

@max-charlamb

@max-charlambmax-charlamb commented Jun 25, 2026

Copy link
Copy Markdown
Member

Note

This PR was authored with assistance from GitHub Copilot.

Summary

Fixes#126359.

Brings the cDAC IGCInfoDecoder x86 implementation (originally on the now-closed PR #129547) plus the GcScanner.PromoteCallerStack rewire (using ICallingConvention.TryComputeArgGCRefMapBlob from #129769) into a single change, and tightens the GCREFS stress assertion so any non-zero KnownIssues count on Windows x86 / x64 fails the test.

After this change, x86 cDAC stack walking is at full parity with the runtime for the cdacstress GCREFS suite (BasicAlloc local run: 4798 / 4798 pass, 0 known, 0 fail).

Three logical groupings

1. x86 IGCInfoDecoder implementation (28 commits, the bulk of the diff)

Implements EnumerateLiveSlots and GetInterruptibleRanges on x86 by walking the legacy InfoHdr byte-stream and the per-offset Transitions already decoded in GCInfo.cs / GCArgTable.cs. Includes a long tail of correctness fixes uncovered by the cdacstress harness: 0xFB huge-encoding code-delta is cumulative; partial-EBP this-pointer-tag bytes do not record a call entry; ESP-frame untracked / VarPtr slots need a pushedSize bias; ApplyPointerTransition honors IsPtr=false for non-pointer pushes; etc.

2. GcScanner.PromoteCallerStack rewire (1 commit + 1 supporting commit)

Replaces the RecordDeferredFrame stub with a real implementation that synthesizes a GCRefMap blob via ICallingConvention.TryComputeArgGCRefMapBlob and runs the same token-iteration loop as the R2R-backed PromoteCallerStackUsingGCRefMap. Falls back to RecordDeferredFrame on unsupported targets (non-Windows or non-x86/x64) and on any failure to synthesize a blob. The supporting commit adds the PInvokeCalliFrame data class used by the x86 HandleTransitionFrame override (PInvokeCalliFrame has no MethodDesc so it falls back to VASigCookie.SizeOfArgs).

Also adds:

  • GCRefMapDecoder(byte[]) second constructor so synthesized blobs can be decoded with the same bit-stream reader as TargetPointer-resident blobs.
  • X86FrameHandler.HandleTransitionFrame override -- decodes the leading ReadStackPop() of the synthesized blob to recover cbStackPop on x86.
  • EnumerateGCRefMapTokens helper, factored out so both the R2R-blob and synthesized-blob paths share the same token-iteration loop.

3. Stress framework hardening

  • CdacStressTests.GCRefStress_AllVerificationsPass: removed the if (arch == Architecture.X86) throw new SkipTestException block.
  • CdacStressTestBase.AssertAllPassed: on Windows x86 / x64, fail the test if results.KnownIssues > 0. Every transition Frame's caller-stack scan must succeed via ICallingConvention.TryComputeArgGCRefMapBlob.

Local validation (windows-x86 Checked)

BasicAlloc smoke test:

Total verifications: 4,798
Passed: 4,798
Failed: 0
Known issues: 0
Frames examined: 64,406 (all matched)

cDAC unit tests: 2611 / 2611 pass.

Full GCRefStress suite will be validated by CI.

Scope notes

CopilotAI 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 expands the cDAC stack-walking and stress infrastructure by wiring Windows x86 transition-frame caller scanning to the shared ICallingConvention/GCRefMap machinery, and by extending the in-proc cdacstress harness to support multiple sub-checks (GCREFS + ARGITER) with richer test/debuggee coverage.

Changes:

  • Reworked caller-stack promotion to optionally synthesize and decode GCRefMap blobs via a new ICallingConvention.TryComputeArgGCRefMapBlob path and shared token enumeration.
  • Extended cdacstress configuration/telemetry (flag layout, [GC_STATS] / [ARG_STATS]) and updated managed stress harness parsing/assertions; added multiple new stress debuggees.
  • Refactored/shared calling convention code (ArgIterator/TransitionBlock/ITypeHandle) for reuse by cDAC and ReadyToRun tooling.

Reviewed changes

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

Show a summary per file
FileDescription
src/native/managed/cdac/tests/StressTests/RunStressTests.ps1Updates stress flag documentation/defaults to new WHERE/WHAT/MODIFIER layout.
src/native/managed/cdac/tests/StressTests/README.mdDocuments new flag regions, sub-check markers, and updated defaults.
src/native/managed/cdac/tests/StressTests/known-issues.mdUpdates defaults and adds documentation for an intermittent x86 flake.
src/native/managed/cdac/tests/StressTests/Debuggees/VarArgs/VarArgs.csprojAdds VarArgs debuggee project file.
src/native/managed/cdac/tests/StressTests/Debuggees/VarArgs/Program.csAdds varargs-focused ARGITER debuggee.
src/native/managed/cdac/tests/StressTests/Debuggees/StructScenarios/Program.csAdds nested-struct scenario to stress ArgIterator/GCDesc paths.
src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Program.csAdds cross-module signature/type-resolution debuggee.
src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/Types.csAdds library types used by CrossModule debuggee to force cross-module resolution.
src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/CrossModuleLib.csprojAdds library project for CrossModule debuggee.
src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/CrossModule.csprojAdds main CrossModule debuggee project file + ProjectReference wiring.
src/native/managed/cdac/tests/StressTests/Debuggees/CallSignatures/Program.csAdds comprehensive ARGITER signature-shape coverage debuggee.
src/native/managed/cdac/tests/StressTests/Debuggees/CallSignatures/CallSignatures.csprojAdds CallSignatures debuggee project file and warning suppressions.
src/native/managed/cdac/tests/StressTests/CdacStressTests.csReplaces prior basic test entrypoint with expanded debuggee catalog and GCREFS/ARGITER theories.
src/native/managed/cdac/tests/StressTests/CdacStressTestBase.csAdds per-mode stress runner and stricter assertions/target detection.
src/native/managed/cdac/tests/StressTests/CdacStressResults.csAdds parsing of [GC_STATS] / [ARG_STATS] and captures ARGITER divergence lines.
src/native/managed/cdac/tests/StressTests/BasicCdacStressTests.csRemoves the older stress test harness class (superseded by CdacStressTests).
src/native/managed/cdac/tests/DumpTests/StackReferenceDumpTests.csRemoves x86 skip now that x86 GCInfo decoding is supported.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/StressTestApi/CdacStressApi.csAdds legacy DAC request handlers for cdacstress private opcodes, including ARGITER blob request.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.csRoutes stress private requests to the new CdacStressApi helper.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/MethodTableFlags_1.csExtends MethodTable flags helpers (shared instantiation + byreflike).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Microsoft.Diagnostics.DataContractReader.Contracts.csprojLinks in shared CallingConvention/ArgIterator sources into Contracts build.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.csAdds PInvokeCalliFrame to the cDAC type discriminator enum.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/TransitionBlock.csAdds OffsetOfArgs field address to support correct x86 GCRefMap pos->addr mapping.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/PInvokeCalliFrame.csAdds cDAC data type to expose VASigCookiePtr for PInvokeCalliFrame.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.csRegisters the new ICallingConvention contract implementation.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/StackWalk_1.csSwallows NotImplementedException per-frame to allow partial stack-walk results.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanner.csReworks caller-stack scanning to use synthesized GCRefMap blobs on Windows x86/x64; factors shared token iteration; fixes x86 DynamicHelperFrame arg-reg offsets; corrects x86 pos->addr mapping.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GCRefMapDecoder.csAdds a byte[]-backed decoder constructor for host-synthesized blobs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/X86FrameHandler.csComputes x86 transition-frame caller SP by decoding stack-pop prefix (or VASigCookie for PInvokeCalliFrame).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.csImplements new RTS helpers (byreflike, unboxing stub, approx field type handle).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/GCInfo/X86/GCTransition.csFixes ctor assignments for IsThis/Iptr fields.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/GCInfo/X86/GCArgTable.csFixes several x86 arg table decoding issues and removes debug prints; adjusts stack-depth transition deltas.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.csAdds cDAC-backed ITypeHandle implementation for shared ArgIterator.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.csAdds internal argument-location record for encoder bookkeeping.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.csAdds new contract APIs (byreflike, unboxing stub, approx field type handle).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ICallingConvention.csIntroduces new calling-convention contract + public surface.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.csExposes CallingConvention contract property on registry.
src/coreclr/vm/frames.hExposes PInvokeCalliFrame::m_pVASigCookie via cdac_data specialization.
src/coreclr/vm/datadescriptor/datadescriptor.incAdds PInvokeCalliFrame descriptor and registers CallingConvention global contract.
src/coreclr/vm/cdacstress.cppAdds WHAT/WHERE/MODIFIER flag regions, ARGITER sub-check (runtime-vs-cDAC blob comparison), and emits [GC_STATS]/[ARG_STATS].
src/coreclr/tools/Common/CallingConvention/TransitionBlock.csMoves TransitionBlock into Internal.CallingConvention and refactors to use ITypeHandle.
src/coreclr/tools/Common/CallingConvention/SystemVAmd64PassingDescriptor.csAdds extracted SystemV descriptor types for shared use.
src/coreclr/tools/Common/CallingConvention/ITypeHandle.csAdds shared type abstraction for calling convention computation.
src/coreclr/tools/Common/CallingConvention/FpStructInRegistersInfo.csAdds extracted RISC-V/LoongArch FP struct classification types for shared use.
src/coreclr/tools/Common/CallingConvention/ArgIterator.csRefactors ArgIterator into Internal.CallingConvention and reworks it to use ITypeHandle + shared TransitionBlock.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/WasmLowering.ReadyToRun.csUpdates Wasm lowering code to use new ITypeHandle shape.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csprojLinks in shared CallingConvention sources and adjusts ReadyToRun file list.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmR2RToInterpreterThunkNode.csUpdates using/aliasing for new ArgIterator namespace.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmInterpreterToR2RThunkNode.csUpdates using/aliasing for new ArgIterator namespace.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/WasmImportThunk.csUpdates using/aliasing for new ArgIterator namespace.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeHandle.csAdds crossgen2-backed ITypeHandle implementation.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.csUpdates builder to use shared TransitionBlock/ArgIterator/ITypeHandle.
src/coreclr/inc/dacprivate.hAdds new private request opcode and request struct for ARGITER blob retrieval (CDAC_STRESS).
src/coreclr/inc/clrconfigvalues.hSimplifies CdacStress config description now that layout is more complex.
eng/pipelines/runtime-diagnostics.ymlAdds windows_x86 to runtime-diagnostics pipeline parameter default list.
docs/design/datacontracts/RuntimeTypeSystem.mdDocuments new RTS APIs and flags.
docs/design/datacontracts/GCInfo.mdUpdates x86 behavior documentation and adds x86 specifics section.
docs/design/datacontracts/CallingConvention.mdAdds new CallingConvention contract design doc.

CopilotAI 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 3 out of 3 changed files in this pull request and generated 2 comments.

Comment threadsrc/native/managed/cdac/tests/StressTests/CdacStressTestBase.cs Outdated
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@max-charlamb
max-charlambforce-pushed the x86-gc-info-w-argiterator branch from 2869d31 to 2c648d9CompareJune 27, 2026 21:29
@max-charlambmax-charlamb changed the title [cdac] Wire PromoteCallerStack to ICallingConvention; enforce 0 known issues on windows-x64[cdac] x86 GCInfo decoder + PromoteCallerStack -> GCRefMap; enforce 0 known issues on windows-x86/x64Jun 27, 2026
- Add x86 IGCInfoDecoder (EnumerateLiveSlots, GetInterruptibleRanges)
- Rewire GcScanner.PromoteCallerStack to use ICallingConvention.TryComputeArgGCRefMapBlob
- Centralize x86 cbStackPop handling inside EnumerateGCRefMapTokens
- Encapsulate x86 ENUM_ARGUMENT_REGISTERS_BACKWARD layout in ArgSlotAddress helper
- GCRefMapDecoder: add byte[] ctor for synthesized blobs + MemberNotNullWhen attrs
- TransitionBlock.OffsetOfArgs uses [InstanceDataStart] (drop redundant datadescriptor field)
- Add PInvokeCalliFrame data class + datadescriptor wiring for X86FrameHandler fallback
- Stress tests: enforce KnownIssues == 0 on Windows x86/x64, remove x86 skip from GCRefStress
Verified: x86 + x64 GCRefStress 11/11 pass, 0 known issues.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 28, 2026 20:12
@max-charlamb
max-charlambforce-pushed the x86-gc-info-w-argiterator branch from 2c648d9 to e335d6aCompareJune 28, 2026 20:12

CopilotAI 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 15 out of 15 changed files in this pull request and generated 6 comments.

Comment threadsrc/native/managed/cdac/tests/StressTests/CdacStressTests.cs
Comment threadsrc/native/managed/cdac/tests/StressTests/CdacStressTests.cs
Comment threadsrc/native/managed/cdac/tests/StressTests/CdacStressTestBase.cs Outdated
…nused arch
- CdacStressTestBase: reword the Windows-x86/x64 KnownIssues failure
message to a generic explanation (the prior wording was PR-scope
specific and pinned a single root cause).
- CdacStressTests: discard the unused 'arch' out parameter in
GCRefStress_AllVerificationsPass; the x86 skip has been removed so
only 'os' is consulted now.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@max-charlamb
max-charlamb marked this pull request as ready for review June 29, 2026 20:09
CopilotAI review requested due to automatic review settings June 29, 2026 20:09
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 14 out of 14 changed files in this pull request and generated 2 comments.

Comment threadsrc/native/managed/cdac/tests/StressTests/CdacStressTests.cs
- GCArgTable (0xFB huge encoding): remove "pre-PR cDAC port" commentary;
keep only the description of current behavior.
- GcScanner.PromoteCallerStack: add TODO referencing dotnet#130008 for extending
ICallingConvention.TryComputeArgGCRefMapBlob coverage beyond Windows x86/x64.
- CdacStressTests.GCRefStress: add TODO referencing dotnet#130008 for extending
GCREFS stress coverage to non-Windows / ARM targets.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@max-charlamb
max-charlamb merged commit 3ae0f12 into dotnet:mainJun 30, 2026
139 checks passed
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 1, 2026
max-charlamb added a commit that referenced this pull request Jul 2, 2026
…ws ARM64 + Linux ARM/ARM64 (#130090)
Fills in the HFA / HVA classification paths in the cDAC's shared
ArgIterator port so `ICallingConvention.TryComputeArgGCRefMapBlob`
produces correct output on FEATURE_HFA targets, then lights up **Windows
ARM64**, **Linux ARM**, and **Linux ARM64** for both the ARGITER stress
sub-check and the zero-known-issues GCREFS assertion.
Follow-up to #129769 and #129858. Advances the platform matrix tracked
in #130008.
## What lights up in CI
| Platform | ARGITER stress | GCREFS 0-known-issues |
|---|---|---|
| Windows x64 | ✅ pre-existing | ✅ pre-existing |
| Windows x86 | ✅ pre-existing | ✅ pre-existing |
| **Windows ARM64** | ✅ **new** | ✅ **new** |
| **Linux ARM** | ✅ **new** | ✅ **new** |
| **Linux ARM64** | ✅ **new** | ✅ **new** |
| Linux / macOS x64 | ⏭ still deferred (SystemV-AMD64 eightbyte
classifier) | ⏭ tolerated |
| RISC-V, LoongArch, WASM | ⏭ still deferred | ⏭ tolerated |
The Helix stress matrix in `runtime-diagnostics.yml` already covers all
six platforms; this PR is purely lifting the xunit-level and
contract-level gates.
## Contract addition
Single new API on `IRuntimeTypeSystem`:
```csharp
bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize);
```
Returns `4` / `8` / `16` for HFA / HVA types, `false` otherwise.
Self-gates on target architecture (FEATURE_HFA = ARM/ARM64) so callers
don't need to. Mirrors `MethodTable::GetHFAType`
(src/coreclr/vm/class.cpp:1867):
- At each recursion level, first checks `GetVectorHFAElementSize` for an
intrinsic Vector shape (`Vector64<T>` / `Vector128<T>` /
`System.Numerics.Vector<T>`)
- Then walks the first non-static instance field. `R4` -> 4, `R8` -> 8,
`ValueType` -> recurse via the existing `GetFieldDescApproxTypeHandle`
- HVA detection uses `enum_flag_IsIntrinsicType`
(`WFLAGS2_ENUM.IsIntrinsicType = 0x0020`) plus TypeDef name+namespace
match, with T-must-be-numerical verification (`CorIsNumericalType`:
`I1..R8 || I || U`)
`MethodTable` flag `WFLAGS_LOW.IsHFA = 0x00000800` is added to
`MethodTableFlags_1.cs`. That bit is repurposed on `UNIX_AMD64_ABI` as
`enum_flag_IsRegStructPassed`, hence the arch self-gate baked into the
API.
## `CdacTypeHandle` (thin adapter)
```csharp
public bool IsHomogeneousAggregate()
=> !_typeHandle.IsNull && Rts.TryGetHFAElementSize(_typeHandle, out _);
public int GetHomogeneousAggregateElementSize()
{
if (Arch == RuntimeInfoArchitecture.Arm)
return RequiresAlign8() ? 8 : 4; // ARM has no HVA; shortcut avoids the field walk
return _typeHandle.IsNull ? 0
: (Rts.TryGetHFAElementSize(_typeHandle, out int size) ? size : 0);
}
```
The ARM shortcut avoids a field walk: on ARM there's no HVA, and
`RequiresAlign8` mirrors `CheckForHFA`'s element-type-driven alignment
choice.
## Test coverage additions
`CallSignatures` debuggee gains an `HfaCategory` (~100 LOC) exercising:
- **Scalar HFAs**: `Float2/3/4`, `Double2/3/4` (all legal HFA arities)
- **Nested HFAs**: `NestedFloat3`, `NestedDouble4` (first-field
recursion)
- **Mixed args**: `HfaThenRef` / `RefThenHfa` / `TwoFloatHfas` — FP-reg
+ int-reg interaction; validates GCRefMap tokens for trailing ref args
after FP-reg consumption
- **HFA returns**: `ReturnFloat3`, `ReturnDouble2` (FP-register return
path, no `HasRetBufArg`)
- **HVA args**: `Vector64<float>`, `Vector128<float>`,
`System.Numerics.Vector<float>` (ARM64-only classification; benign on
other targets)
- **Negative shapes**: `Float5` (>4 fields), `MixedR4R8` (mixed FP) —
runtime correctly declines to flag as HFA, cDAC matches
Same debuggee compiles/passes everywhere; only exercises the new HFA
walker on ARM/ARM64.
## Gate expansions
Three gates now all match: **Windows {x86, x64, ARM64} + Linux {ARM,
ARM64}**
1. **`CdacStressTests.ArgIterStress_AllVerificationsPass`**: admits the
new ARM/ARM64 platforms.
2. **`CdacStressTestBase.AssertAllPassed.requiresZeroKnownIssues`**:
extended from Windows x86/x64 to include the same set. Any deferred
Frame on these platforms is now a hard failure.
3. **`GcScanner.PromoteCallerStack.supportedByCallingConvention`**:
lifted to match, so on ARM/ARM64 caller-stack refs are enumerated via
`TryComputeArgGCRefMapBlob` instead of falling through to
`RecordDeferredFrame`.
## Local validation
- `dotnet build src/native/managed/cdac/cdac.slnx -c Release` -- clean
- `dotnet test
.../UnitTests/Microsoft.Diagnostics.DataContractReader.Tests.csproj` --
2611 pass / 0 fail / 16 skipped
- No local ARM hardware; the ARM/ARM64 paths are validated by CI. If any
HFA/HVA shape produces a divergence, the ARGITER assertion will surface
the exact `MethodDesc` + slot mismatch.
## Known gaps (follow-ups, tracked in #130008)
- Linux / macOS x64: SystemV-AMD64 eightbyte struct classifier not
ported (`CdacTypeHandle.GetSystemVAmd64PassStructInRegisterDescriptor`
throws)
- RISC-V64 / LoongArch64: FP struct classifier not ported
(`GetFpStructInRegistersInfo` throws)
- WASM32: `GetFieldAlignment` not ported
> [!NOTE]
> This change was authored with assistance from GitHub Copilot.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
…ws ARM64 + Linux ARM/ARM64 (#130090)
Fills in the HFA / HVA classification paths in the cDAC's shared
ArgIterator port so `ICallingConvention.TryComputeArgGCRefMapBlob`
produces correct output on FEATURE_HFA targets, then lights up **Windows
ARM64**, **Linux ARM**, and **Linux ARM64** for both the ARGITER stress
sub-check and the zero-known-issues GCREFS assertion.
Follow-up to #129769 and #129858. Advances the platform matrix tracked
in #130008.
## What lights up in CI
| Platform | ARGITER stress | GCREFS 0-known-issues |
|---|---|---|
| Windows x64 | ✅ pre-existing | ✅ pre-existing |
| Windows x86 | ✅ pre-existing | ✅ pre-existing |
| **Windows ARM64** | ✅ **new** | ✅ **new** |
| **Linux ARM** | ✅ **new** | ✅ **new** |
| **Linux ARM64** | ✅ **new** | ✅ **new** |
| Linux / macOS x64 | ⏭ still deferred (SystemV-AMD64 eightbyte
classifier) | ⏭ tolerated |
| RISC-V, LoongArch, WASM | ⏭ still deferred | ⏭ tolerated |
The Helix stress matrix in `runtime-diagnostics.yml` already covers all
six platforms; this PR is purely lifting the xunit-level and
contract-level gates.
## Contract addition
Single new API on `IRuntimeTypeSystem`:
```csharp
bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize);
```
Returns `4` / `8` / `16` for HFA / HVA types, `false` otherwise.
Self-gates on target architecture (FEATURE_HFA = ARM/ARM64) so callers
don't need to. Mirrors `MethodTable::GetHFAType`
(src/coreclr/vm/class.cpp:1867):
- At each recursion level, first checks `GetVectorHFAElementSize` for an
intrinsic Vector shape (`Vector64<T>` / `Vector128<T>` /
`System.Numerics.Vector<T>`)
- Then walks the first non-static instance field. `R4` -> 4, `R8` -> 8,
`ValueType` -> recurse via the existing `GetFieldDescApproxTypeHandle`
- HVA detection uses `enum_flag_IsIntrinsicType`
(`WFLAGS2_ENUM.IsIntrinsicType = 0x0020`) plus TypeDef name+namespace
match, with T-must-be-numerical verification (`CorIsNumericalType`:
`I1..R8 || I || U`)
`MethodTable` flag `WFLAGS_LOW.IsHFA = 0x00000800` is added to
`MethodTableFlags_1.cs`. That bit is repurposed on `UNIX_AMD64_ABI` as
`enum_flag_IsRegStructPassed`, hence the arch self-gate baked into the
API.
## `CdacTypeHandle` (thin adapter)
```csharp
public bool IsHomogeneousAggregate()
=> !_typeHandle.IsNull && Rts.TryGetHFAElementSize(_typeHandle, out _);
public int GetHomogeneousAggregateElementSize()
{
if (Arch == RuntimeInfoArchitecture.Arm)
return RequiresAlign8() ? 8 : 4; // ARM has no HVA; shortcut avoids the field walk
return _typeHandle.IsNull ? 0
: (Rts.TryGetHFAElementSize(_typeHandle, out int size) ? size : 0);
}
```
The ARM shortcut avoids a field walk: on ARM there's no HVA, and
`RequiresAlign8` mirrors `CheckForHFA`'s element-type-driven alignment
choice.
## Test coverage additions
`CallSignatures` debuggee gains an `HfaCategory` (~100 LOC) exercising:
- **Scalar HFAs**: `Float2/3/4`, `Double2/3/4` (all legal HFA arities)
- **Nested HFAs**: `NestedFloat3`, `NestedDouble4` (first-field
recursion)
- **Mixed args**: `HfaThenRef` / `RefThenHfa` / `TwoFloatHfas` — FP-reg
+ int-reg interaction; validates GCRefMap tokens for trailing ref args
after FP-reg consumption
- **HFA returns**: `ReturnFloat3`, `ReturnDouble2` (FP-register return
path, no `HasRetBufArg`)
- **HVA args**: `Vector64<float>`, `Vector128<float>`,
`System.Numerics.Vector<float>` (ARM64-only classification; benign on
other targets)
- **Negative shapes**: `Float5` (>4 fields), `MixedR4R8` (mixed FP) —
runtime correctly declines to flag as HFA, cDAC matches
Same debuggee compiles/passes everywhere; only exercises the new HFA
walker on ARM/ARM64.
## Gate expansions
Three gates now all match: **Windows {x86, x64, ARM64} + Linux {ARM,
ARM64}**
1. **`CdacStressTests.ArgIterStress_AllVerificationsPass`**: admits the
new ARM/ARM64 platforms.
2. **`CdacStressTestBase.AssertAllPassed.requiresZeroKnownIssues`**:
extended from Windows x86/x64 to include the same set. Any deferred
Frame on these platforms is now a hard failure.
3. **`GcScanner.PromoteCallerStack.supportedByCallingConvention`**:
lifted to match, so on ARM/ARM64 caller-stack refs are enumerated via
`TryComputeArgGCRefMapBlob` instead of falling through to
`RecordDeferredFrame`.
## Local validation
- `dotnet build src/native/managed/cdac/cdac.slnx -c Release` -- clean
- `dotnet test
.../UnitTests/Microsoft.Diagnostics.DataContractReader.Tests.csproj` --
2611 pass / 0 fail / 16 skipped
- No local ARM hardware; the ARM/ARM64 paths are validated by CI. If any
HFA/HVA shape produces a divergence, the ARGITER assertion will surface
the exact `MethodDesc` + slot mismatch.
## Known gaps (follow-ups, tracked in #130008)
- Linux / macOS x64: SystemV-AMD64 eightbyte struct classifier not
ported (`CdacTypeHandle.GetSystemVAmd64PassStructInRegisterDescriptor`
throws)
- RISC-V64 / LoongArch64: FP struct classifier not ported
(`GetFpStructInRegistersInfo` throws)
- WASM32: `GetFieldAlignment` not ported
> [!NOTE]
> This change was authored with assistance from GitHub Copilot.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 1, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cDAC: GCInfo decoder does not support x86

3 participants

@max-charlamb@davidwrighton