From 08f265695e7c00b82b49190586216d4b758139f1 Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Wed, 24 Jun 2026 17:19:41 -0700 Subject: [PATCH] Use indirect field access for types spanning multiple inexact compilation units Fixes the Verify_FieldOffset failfast in crossgen2-composite Large Version Bubble R2R legs (dotnet/runtime#128968). When a reference type's layout chain spans 2+ inexact compilation units, crossgen2 conservatively aligns the derived type's fields after a cross-compilation-unit base. At runtime those framework modules can instead bind into a single composite image, where the runtime back-fills the derived fields into the base type's trailing alignment padding. Neither a baked relative (ENCODE_FIELD_BASE_OFFSET) nor absolute offset is valid for both layouts, so route these fields to an indirect, runtime-resolved field offset (ENCODE_FIELD_OFFSET), which is correct regardless of how the modules are grouped and emits no layout-verification fixup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 3f1bcab55b112f..ce81545834795c 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3095,6 +3095,25 @@ private void EncodeFieldBaseOffset(FieldDesc field, ref CORINFO_RESOLVED_TOKEN p } // ENCODE_NONE } + else if (_compilation.CompilationModuleGroup.TypeLayoutCompilationUnits(pMT).HasMultipleInexactCompilationUnits) + { + PreventRecursiveFieldInlinesOutsideVersionBubble(field, callerMethod); + + // The layout of this type spans multiple inexact compilation units (assemblies that version + // with the current compilation but whose grouping into composite images is not fixed at + // compile time). When that is the case the offset of this field relative to its base class is + // unknowable: depending on whether those modules are ultimately bound as a single composite + // image or as individual assemblies, the runtime may either insert alignment before this + // type's fields or back-fill them into the base type's trailing alignment padding. Neither the + // relative ENCODE_FIELD_BASE_OFFSET encoding nor a baked absolute offset (with a relative + // field-offset verification) is valid for both layouts, so fall back to an indirect, + // runtime-resolved field offset, which is correct regardless of how the modules are grouped. + + // ENCODE_FIELD_OFFSET + pResult->offset = 0; + pResult->fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_INSTANCE_WITH_BASE; + pResult->fieldLookup = CreateConstLookupToSymbol(_compilation.SymbolNodeFactory.FieldOffset(ComputeFieldWithToken(field, ref pResolvedToken))); + } else if (_compilation.IsInheritanceChainLayoutFixedInCurrentVersionBubble(pMT.BaseType)) { if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && !callerMethod.IsNonVersionable() && (pResult->offset <= FieldFixupSignature.MaxCheckableOffset))