Skip to content

Commit e6b5e67

Browse files
Disable Int128 use in by value ABI scenarios, and fix field layout behavior (#74123)
Unfortunately, attempting to actually fix all the ABI issues is probably too complex for this time in the release cycle. - Mark `Int128` as being ABI unstable in Crossgen2. This will prevent it from appearing in function signatures - Adjust layout so that crossgen2 and the runtime agree about layout - Arm32 - Alignment of 8 bytes - Everywhere else - Alignment of 16 bytes - Disable use of `Int128` in pinvokes as a by value parameter or return value. (Match behavior of `Vector128<T>`) (Unlike Vector128<T> handle scenarios such as having fields of `Int128` types.) - Disable tests that will fail now that pinvokes are disabled - Build a test that will succeed now that pinvokes are disabled - Add test that alignment matches OS behavior - Add unit tests for alignment behavior - Update R2R version Fixes #72206
1 parent 33164ff commit e6b5e67

36 files changed

+758
-51
lines changed

src/coreclr/dlls/mscorrc/mscorrc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ BEGIN
271271
IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE "Returned CriticalHandles cannot be abstract."
272272
IDS_EE_BADMARSHAL_CUSTOMMARSHALER "Custom marshalers are only allowed on classes, strings, arrays, and boxed value types."
273273
IDS_EE_BADMARSHAL_GENERICS_RESTRICTION "Non-blittable generic types cannot be marshaled."
274+
IDS_EE_BADMARSHAL_INT128_RESTRICTION "System.Int128 and System.UInt128 cannot be passed by value to unmanaged."
274275
IDS_EE_BADMARSHAL_AUTOLAYOUT "Structures marked with [StructLayout(LayoutKind.Auto)] cannot be marshaled."
275276
IDS_EE_BADMARSHAL_STRING_OUT "Cannot marshal a string by-value with the [Out] attribute."
276277
IDS_EE_BADMARSHAL_MARSHAL_DISABLED "Cannot marshal managed types when the runtime marshalling system is disabled."

src/coreclr/dlls/mscorrc/resource.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@
283283
#define IDS_EE_BADMARSHAL_ABSTRACTOUTCRITICALHANDLE 0x1a63
284284
#define IDS_EE_BADMARSHAL_RETURNCHCOMTONATIVE 0x1a64
285285
#define IDS_EE_BADMARSHAL_CRITICALHANDLE 0x1a65
286+
#define IDS_EE_BADMARSHAL_INT128_RESTRICTION 0x1a66
286287

287288
#define IDS_EE_BADMARSHAL_ABSTRACTRETCRITICALHANDLE 0x1a6a
288289
#define IDS_EE_CH_IN_VARIANT_NOT_SUPPORTED 0x1a6b

src/coreclr/inc/readytorun.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@
1515
#define READYTORUN_SIGNATURE 0x00525452 // 'RTR'
1616

1717
// Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs
18-
#define READYTORUN_MAJOR_VERSION 0x0007
19-
#define READYTORUN_MINOR_VERSION 0x0001
18+
#define READYTORUN_MAJOR_VERSION 0x0008
19+
#define READYTORUN_MINOR_VERSION 0x0000
2020

21-
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x006
21+
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x008
2222

2323
// R2R Version 2.1 adds the InliningInfo section
2424
// R2R Version 2.2 adds the ProfileDataInfo section
2525
// R2R Version 3.0 changes calling conventions to correctly handle explicit structures to spec.
2626
// R2R 3.0 is not backward compatible with 2.x.
2727
// R2R Version 6.0 changes managed layout for sequential types with any unmanaged non-blittable fields.
2828
// R2R 6.0 is not backward compatible with 5.x or earlier.
29+
// R2R Version 8.0 Changes the alignment of the Int128 type
2930

3031
struct READYTORUN_CORE_HEADER
3132
{

src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ struct ReadyToRunHeaderConstants
1010
{
1111
static const uint32_t Signature = 0x00525452; // 'RTR'
1212

13-
static const uint32_t CurrentMajorVersion = 7;
14-
static const uint32_t CurrentMinorVersion = 1;
13+
static const uint32_t CurrentMajorVersion = 8;
14+
static const uint32_t CurrentMinorVersion = 0;
1515
};
1616

1717
struct ReadyToRunHeader

src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp
2828

2929
ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);
3030

31-
if (defType.Context.Target.IsWindows || (defType.Context.Target.PointerSize == 4))
31+
// 32bit platforms use standard metadata layout engine
32+
if (defType.Context.Target.Architecture == TargetArchitecture.ARM)
3233
{
34+
layoutFromMetadata.LayoutAbiStable = false; // Int128 parameter passing ABI is unstable at this time
35+
layoutFromMetadata.IsInt128OrHasInt128Fields = true;
3336
return layoutFromMetadata;
3437
}
3538

@@ -42,7 +45,8 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp
4245
FieldAlignment = new LayoutInt(16),
4346
FieldSize = layoutFromMetadata.FieldSize,
4447
Offsets = layoutFromMetadata.Offsets,
45-
LayoutAbiStable = true
48+
LayoutAbiStable = false, // Int128 parameter passing ABI is unstable at this time
49+
IsInt128OrHasInt128Fields = true
4650
};
4751
}
4852

@@ -72,7 +76,7 @@ public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristi
7276
public static bool IsIntegerType(DefType type)
7377
{
7478
return type.IsIntrinsic
75-
&& type.Namespace == "System."
79+
&& type.Namespace == "System"
7680
&& ((type.Name == "Int128") || (type.Name == "UInt128"));
7781
}
7882
}

src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ internal struct ReadyToRunHeaderConstants
1414
{
1515
public const uint Signature = 0x00525452; // 'RTR'
1616

17-
public const ushort CurrentMajorVersion = 7;
18-
public const ushort CurrentMinorVersion = 1;
17+
public const ushort CurrentMajorVersion = 8;
18+
public const ushort CurrentMinorVersion = 0;
1919
}
2020

2121
#pragma warning disable 0169

src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ private static class FieldLayoutFlags
6868
/// True if the type transitively has any types with LayoutKind.Auto in its layout.
6969
/// </summary>
7070
public const int IsAutoLayoutOrHasAutoLayoutFields = 0x400;
71+
72+
/// <summary>
73+
/// True if the type transitively has an Int128 in it or is an Int128
74+
/// </summary>
75+
public const int IsInt128OrHasInt128Fields = 0x800;
7176
}
7277

7378
private class StaticBlockInfo
@@ -135,6 +140,20 @@ public virtual bool IsAutoLayoutOrHasAutoLayoutFields
135140
}
136141
}
137142

143+
/// <summary>
144+
/// Is a type Int128 or transitively have any fields of a type Int128.
145+
/// </summary>
146+
public virtual bool IsInt128OrHasInt128Fields
147+
{
148+
get
149+
{
150+
if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout))
151+
{
152+
ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields);
153+
}
154+
return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields);
155+
}
156+
}
138157

139158
/// <summary>
140159
/// The number of bytes required to hold a field of this type
@@ -430,6 +449,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind)
430449
{
431450
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsAutoLayoutOrHasAutoLayoutFields);
432451
}
452+
if (computedLayout.IsInt128OrHasInt128Fields)
453+
{
454+
_fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields);
455+
}
433456

434457
if (computedLayout.Offsets != null)
435458
{

src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public struct ComputedInstanceFieldLayout
8383
public LayoutInt ByteCountAlignment;
8484
public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions
8585
public bool IsAutoLayoutOrHasAutoLayoutFields;
86+
public bool IsInt128OrHasInt128Fields;
8687

8788
/// <summary>
8889
/// If Offsets is non-null, then all field based layout is complete.

src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ out instanceByteSizeAndAlignment
110110
FieldSize = sizeAndAlignment.Size,
111111
LayoutAbiStable = true,
112112
IsAutoLayoutOrHasAutoLayoutFields = false,
113+
IsInt128OrHasInt128Fields = false,
113114
};
114115

115116
if (numInstanceFields > 0)
@@ -211,7 +212,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy
211212
}
212213

213214
ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field);
214-
SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _);
215+
SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _, out bool _);
215216

216217
block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target);
217218
result.Offsets[index] = new FieldAndOffset(field, block.Size);
@@ -303,15 +304,18 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
303304
int fieldOrdinal = 0;
304305
bool layoutAbiStable = true;
305306
bool hasAutoLayoutField = false;
307+
bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields;
306308

307309
foreach (var fieldAndOffset in layoutMetadata.Offsets)
308310
{
309311
TypeDesc fieldType = fieldAndOffset.Field.FieldType;
310-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
312+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field);
311313
if (!fieldLayoutAbiStable)
312314
layoutAbiStable = false;
313315
if (fieldHasAutoLayout)
314316
hasAutoLayoutField = true;
317+
if (fieldHasInt128Field)
318+
hasInt128Field = true;
315319

316320
largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired);
317321

@@ -357,6 +361,7 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty
357361
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
358362
{
359363
IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
364+
IsInt128OrHasInt128Fields = hasInt128Field,
360365
};
361366
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
362367
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
@@ -392,17 +397,20 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
392397
int packingSize = ComputePackingSize(type, layoutMetadata);
393398
bool layoutAbiStable = true;
394399
bool hasAutoLayoutField = false;
400+
bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields;
395401

396402
foreach (var field in type.GetFields())
397403
{
398404
if (field.IsStatic)
399405
continue;
400406

401-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout);
407+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field);
402408
if (!fieldLayoutAbiStable)
403409
layoutAbiStable = false;
404410
if (fieldHasAutoLayout)
405411
hasAutoLayoutField = true;
412+
if (fieldHasInt128Field)
413+
hasInt128Field = true;
406414

407415
largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement);
408416

@@ -424,6 +432,7 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType
424432
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
425433
{
426434
IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField,
435+
IsInt128OrHasInt128Fields = hasInt128Field,
427436
};
428437
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
429438
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
@@ -459,6 +468,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
459468
int instanceValueClassFieldCount = 0;
460469
int instanceGCPointerFieldsCount = 0;
461470
int[] instanceNonGCPointerFieldsCount = new int[maxLog2Size + 1];
471+
bool hasInt128Field = false;
462472

463473
foreach (var field in type.GetFields())
464474
{
@@ -471,6 +481,8 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
471481
{
472482
// Valuetypes which are not primitives or enums
473483
instanceValueClassFieldCount++;
484+
if (((DefType)fieldType).IsInt128OrHasInt128Fields)
485+
hasInt128Field = true;
474486
}
475487
else if (fieldType.IsGCPointer)
476488
{
@@ -480,7 +492,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
480492
{
481493
Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef);
482494

483-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _);
495+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _, out bool _);
484496
instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++;
485497
}
486498
}
@@ -517,7 +529,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
517529

518530
TypeDesc fieldType = field.FieldType;
519531

520-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
532+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _);
521533
if (!fieldLayoutAbiStable)
522534
layoutAbiStable = false;
523535

@@ -678,7 +690,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
678690
for (int i = 0; i < instanceValueClassFieldsArr.Length; i++)
679691
{
680692
// Align the cumulative field offset to the indeterminate value
681-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _);
693+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _);
682694
if (!fieldLayoutAbiStable)
683695
layoutAbiStable = false;
684696

@@ -729,6 +741,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
729741
ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout
730742
{
731743
IsAutoLayoutOrHasAutoLayoutFields = true,
744+
IsInt128OrHasInt128Fields = hasInt128Field,
732745
};
733746
computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment;
734747
computedLayout.FieldSize = instanceSizeAndAlignment.Size;
@@ -742,7 +755,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type,
742755

743756
private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias)
744757
{
745-
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _);
758+
var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _, out bool _);
746759

747760
instanceFieldPos = AlignUpInstanceFieldOffset(field.OwningType, instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target);
748761
offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias);
@@ -802,11 +815,12 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8
802815
return cumulativeInstanceFieldPos;
803816
}
804817

805-
private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout)
818+
private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout, out bool fieldTypeHasInt128Field)
806819
{
807820
SizeAndAlignment result;
808821
layoutAbiStable = true;
809822
fieldTypeHasAutoLayout = true;
823+
fieldTypeHasInt128Field = false;
810824

811825
if (fieldType.IsDefType)
812826
{
@@ -817,6 +831,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType,
817831
result.Alignment = defType.InstanceFieldAlignment;
818832
layoutAbiStable = defType.LayoutAbiStable;
819833
fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields;
834+
fieldTypeHasInt128Field = defType.IsInt128OrHasInt128Fields;
820835
}
821836
else
822837
{

src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ internal static MarshallerKind GetMarshallerKind(
434434
return MarshallerKind.Invalid;
435435
}
436436

437+
if (!isField && InteropTypes.IsInt128Type(context, type))
438+
{
439+
// Int128 types cannot be passed by value
440+
return MarshallerKind.Invalid;
441+
}
442+
437443
if (isBlittable)
438444
{
439445
if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct)
@@ -887,7 +893,7 @@ internal static MarshallerKind GetDisabledMarshallerKind(
887893
else if (underlyingType.IsValueType)
888894
{
889895
var defType = (DefType)underlyingType;
890-
if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields)
896+
if (!defType.ContainsGCPointers && !defType.IsAutoLayoutOrHasAutoLayoutFields && !defType.IsInt128OrHasInt128Fields)
891897
{
892898
return MarshallerKind.BlittableValue;
893899
}

0 commit comments

Comments
 (0)