Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Int128 and UInt128 with a base software implementation #69204

Merged
merged 20 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
897fdb9
Adding barebones Int128 and UInt128 structs
tannergooding Apr 11, 2022
2fe1618
Special case Int128 and UInt128 alignment on x64 Unix and Arm64
tannergooding May 2, 2022
6559609
Implementing Int128 and UInt128
tannergooding May 3, 2022
2c820b5
Adding tests for Int128 and UInt128
tannergooding May 7, 2022
e7970fb
Updating Int128/UInt128 to respect the System V ABI ordering
tannergooding May 11, 2022
828440f
Merge remote-tracking branch 'dotnet/main' into generic-math-int128
tannergooding May 11, 2022
6904e73
Fixing an issue with UInt128->BigInteger setting the wrong sign
tannergooding May 12, 2022
bcbc375
Merge remote-tracking branch 'dotnet/main' into generic-math-int128
tannergooding May 12, 2022
09e8bfc
Don't use Unsafe.As in the Int128/UInt128 hex parsing logic
tannergooding May 12, 2022
5f9d22f
Adding Int128 P/Invoke tests and ensure R2R correctly sets the packing
tannergooding May 13, 2022
b6b85e6
Fixing some issues with the Int128 interop test for non-Windows
tannergooding May 13, 2022
9de4e76
Ensure that floating-point conversions exist for Int128 and UInt128
tannergooding May 13, 2022
a1dc14f
Fixing the casing of a couple fields
tannergooding May 16, 2022
7666952
Revert "Don't use Unsafe.As in the Int128/UInt128 hex parsing logic"
tannergooding May 16, 2022
f0a30cb
Adjusting the Int128/UInt128 generic math tests to have consistent or…
tannergooding May 16, 2022
cb5a82e
Responding to PR feedback
tannergooding May 18, 2022
384e572
Ensure that pNativeLayoutInfo alignment is initialized for Int128/UIn…
tannergooding May 18, 2022
ab85c7b
Don't use Unsafe.As in the Int128/UInt128 hex parsing logic
tannergooding May 12, 2022
163cfda
Merge remote-tracking branch 'dotnet/main' into generic-math-int128
tannergooding May 19, 2022
cd3c9e9
Skip the Interop/PInvoke/Int128 tests on Mono
tannergooding May 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion THIRD-PARTY-NOTICES.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -1072,4 +1072,30 @@ Copyright (c) Microsoft Corporation.
Licensed under the MIT License.

Available at
https://github.com/microsoft/msquic/blob/main/LICENSE
https://github.com/microsoft/msquic/blob/main/LICENSE

License notice for m-ou-se/floatconv
tannergooding marked this conversation as resolved.
Show resolved Hide resolved
-------------------------------

Copyright (c) 2020 Mara Bos <m-ou.se@m-ou.se>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
79 changes: 79 additions & 0 deletions src/coreclr/tools/Common/Compiler/Int128FieldLayoutAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
/// <summary>
/// Represents an algorithm that computes field layout for intrinsic integer types (Int128/UInt128).
/// </summary>
public class Int128FieldLayoutAlgorithm : FieldLayoutAlgorithm
{
private readonly FieldLayoutAlgorithm _fallbackAlgorithm;

public Int128FieldLayoutAlgorithm(FieldLayoutAlgorithm fallbackAlgorithm)
{
_fallbackAlgorithm = fallbackAlgorithm;
}

public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
{
Debug.Assert(IsIntegerType(defType));

string name = defType.Name;
Debug.Assert((name == "Int128") || (name == "UInt128"));

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

if (defType.Context.Target.IsWindows || (defType.Context.Target.PointerSize == 4))
{
return layoutFromMetadata;
}

// 64-bit Unix systems follow the System V ABI and have a 16-byte packing requirement for Int128/UInt128

return new ComputedInstanceFieldLayout
{
ByteCountUnaligned = layoutFromMetadata.ByteCountUnaligned,
ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
FieldAlignment = new LayoutInt(16),
FieldSize = layoutFromMetadata.FieldSize,
Offsets = layoutFromMetadata.Offsets,
LayoutAbiStable = true
};
}

public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defType, StaticLayoutKind layoutKind)
{
return _fallbackAlgorithm.ComputeStaticFieldLayout(defType, layoutKind);
}

public override bool ComputeContainsGCPointers(DefType type)
{
Debug.Assert(!_fallbackAlgorithm.ComputeContainsGCPointers(type));
return false;
}

public override bool ComputeIsUnsafeValueType(DefType type)
{
Debug.Assert(!_fallbackAlgorithm.ComputeIsUnsafeValueType(type));
return false;
}

public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type)
{
Debug.Assert(_fallbackAlgorithm.ComputeValueTypeShapeCharacteristics(type) == ValueTypeShapeCharacteristics.None);
return ValueTypeShapeCharacteristics.None;
}

public static bool IsIntegerType(DefType type)
{
return type.IsIntrinsic
&& type.Namespace == "System."
&& ((type.Name == "Int128") || (type.Name == "UInt128"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal SystemVStructRegisterPassingHelper(int totalStructSize)
FieldClassifications = new SystemVClassificationType[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];
FieldSizes = new int[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];
FieldOffsets = new int[SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT];

for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
{
EightByteClassifications[i] = SystemVClassificationTypeNoClass;
Expand Down Expand Up @@ -94,7 +94,7 @@ public static void GetSystemVAmd64PassStructInRegisterDescriptor(TypeDesc typeDe
{
structPassInRegDescPtr = default;
structPassInRegDescPtr.passedInRegisters = false;

int typeSize = typeDesc.GetElementSize().AsInt;
if (typeDesc.IsValueType && (typeSize <= CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS))
{
Expand All @@ -114,7 +114,7 @@ public static void GetSystemVAmd64PassStructInRegisterDescriptor(TypeDesc typeDe
structPassInRegDescPtr.eightByteClassifications0 = helper.EightByteClassifications[0];
structPassInRegDescPtr.eightByteSizes0 = (byte)helper.EightByteSizes[0];
structPassInRegDescPtr.eightByteOffsets0 = (byte)helper.EightByteOffsets[0];

structPassInRegDescPtr.eightByteClassifications1 = helper.EightByteClassifications[1];
structPassInRegDescPtr.eightByteSizes1 = (byte)helper.EightByteSizes[1];
structPassInRegDescPtr.eightByteOffsets1 = (byte)helper.EightByteOffsets[1];
Expand Down Expand Up @@ -216,7 +216,7 @@ static SystemVClassificationType ReClassifyField(SystemVClassificationType origi
/// <summary>
/// Returns 'true' if the struct is passed in registers, 'false' otherwise.
/// </summary>
private static bool ClassifyEightBytes(TypeDesc typeDesc,
private static bool ClassifyEightBytes(TypeDesc typeDesc,
ref SystemVStructRegisterPassingHelper helper,
int startOffsetOfStruct)
{
Expand All @@ -239,14 +239,15 @@ private static bool ClassifyEightBytes(TypeDesc typeDesc,
return false;
}

// The SIMD Intrinsic types are meant to be handled specially and should not be passed as struct registers
// The SIMD and Int128 Intrinsic types are meant to be handled specially and should not be passed as struct registers
if (typeDesc.IsIntrinsic)
{
InstantiatedType instantiatedType = typeDesc as InstantiatedType;
if (instantiatedType != null)
{
if (VectorFieldLayoutAlgorithm.IsVectorType(instantiatedType) ||
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(instantiatedType))
VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(instantiatedType) ||
Int128FieldLayoutAlgorithm.IsIntegerType(instantiatedType))
{
return false;
}
Expand Down Expand Up @@ -316,7 +317,7 @@ private static bool ClassifyEightBytes(TypeDesc typeDesc,

bool structRet = false;
structRet = ClassifyEightBytes(field.FieldType, ref helper, normalizedFieldOffset);

helper.InEmbeddedStruct = inEmbeddedStructPrev;

if (!structRet)
Expand Down Expand Up @@ -482,7 +483,7 @@ private static void AssignClassifiedEightByteTypes(ref SystemVStructRegisterPass
else if ((helper.EightByteClassifications[currentFieldEightByte] == SystemVClassificationTypeInteger) ||
(fieldClassificationType == SystemVClassificationTypeInteger))
{
Debug.Assert((fieldClassificationType != SystemVClassificationTypeIntegerReference) &&
Debug.Assert((fieldClassificationType != SystemVClassificationTypeIntegerReference) &&
(fieldClassificationType != SystemVClassificationTypeIntegerByRef));

helper.EightByteClassifications[currentFieldEightByte] = SystemVClassificationTypeInteger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public SharedGenericsConfiguration GenericsConfig
private readonly RuntimeDeterminedFieldLayoutAlgorithm _runtimeDeterminedFieldLayoutAlgorithm = new RuntimeDeterminedFieldLayoutAlgorithm();
private readonly VectorOfTFieldLayoutAlgorithm _vectorOfTFieldLayoutAlgorithm;
private readonly VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm;
private readonly Int128FieldLayoutAlgorithm _int128FieldLayoutAlgorithm;

private TypeDesc[] _arrayOfTInterfaces;
private ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
Expand All @@ -45,6 +46,7 @@ public CompilerTypeSystemContext(TargetDetails details, SharedGenericsMode gener

_vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_metadataFieldLayoutAlgorithm);
_vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_metadataFieldLayoutAlgorithm);
_int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_metadataFieldLayoutAlgorithm);

_delegateInfoHashtable = new DelegateInfoHashtable(delegateFeatures);

Expand Down Expand Up @@ -72,6 +74,8 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
return _vectorOfTFieldLayoutAlgorithm;
else if (VectorFieldLayoutAlgorithm.IsVectorType(type))
return _vectorFieldLayoutAlgorithm;
else if (Int128FieldLayoutAlgorithm.IsIntegerType(type))
return _int128FieldLayoutAlgorithm;
else
return _metadataFieldLayoutAlgorithm;
}
Expand Down Expand Up @@ -220,8 +224,8 @@ public class SharedGenericsConfiguration
// method table.
public long UniversalCanonReflectionMethodRootHeuristic_InstantiationCount { get; }

// To avoid infinite generic recursion issues during debug type record generation, attempt to
// use canonical form for types with high generic complexity.
// To avoid infinite generic recursion issues during debug type record generation, attempt to
// use canonical form for types with high generic complexity.
public long MaxGenericDepthOfDebugRecord { get; }

public SharedGenericsConfiguration()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@
<Compile Include="..\..\Common\Compiler\HardwareIntrinsicHelpers.cs" Link="Compiler\HardwareIntrinsicHelpers.cs" />
<Compile Include="..\..\Common\Compiler\ICompilationRootProvider.cs" Link="Compiler\ICompilationRootProvider.cs" />
<Compile Include="..\..\Common\Compiler\InstructionSetSupport.cs" Link="Compiler\InstructionSetSupport.cs" />
<Compile Include="..\..\Common\Compiler\Int128FieldLayoutAlgorithm.cs" Link="Compiler\Int128FieldLayoutAlgorithm.cs" />
<Compile Include="..\..\Common\Compiler\InternalCompilerErrorException.cs" Link="Compiler\InternalCompilerErrorException.cs" />
<Compile Include="..\..\Common\Compiler\NameMangler.cs" Link="Compiler\NameMangler.cs" />
<Compile Include="..\..\Common\Compiler\SingleMethodRootProvider.cs" Link="Compiler\SingleMethodRootProvider.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public partial class ReadyToRunCompilerContext : CompilerTypeSystemContext
private SystemObjectFieldLayoutAlgorithm _systemObjectFieldLayoutAlgorithm;
private VectorOfTFieldLayoutAlgorithm _vectorOfTFieldLayoutAlgorithm;
private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm;
private Int128FieldLayoutAlgorithm _int128FieldLayoutAlgorithm;

public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode genericsMode, bool bubbleIncludesCorelib, CompilerTypeSystemContext oldTypeSystemContext = null)
: base(details, genericsMode)
Expand All @@ -55,6 +56,9 @@ public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode gener
// No architecture has completely stable handling of Vector<T> in the abi (Arm64 may change to SVE)
_vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm, _vectorFieldLayoutAlgorithm, matchingVectorType, bubbleIncludesCorelib);

// Int128 and UInt128 should be ABI stable on all currently supported platforms
_int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);

if (oldTypeSystemContext != null)
{
InheritOpenModules(oldTypeSystemContext);
Expand All @@ -77,6 +81,10 @@ public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
{
return _vectorFieldLayoutAlgorithm;
}
else if (Int128FieldLayoutAlgorithm.IsIntegerType(type))
{
return _int128FieldLayoutAlgorithm;
}
else
{
Debug.Assert(_r2rFieldLayoutAlgorithm != null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<Compile Include="..\..\Common\Compiler\HardwareIntrinsicHelpers.cs" Link="Compiler\HardwareIntrinsicHelpers.cs" />
<Compile Include="..\..\Common\Compiler\ICompilationRootProvider.cs" Link="Compiler\ICompilationRootProvider.cs" />
<Compile Include="..\..\Common\Compiler\InstructionSetSupport.cs" Link="Compiler\InstructionSetSupport.cs" />
<Compile Include="..\..\Common\Compiler\Int128FieldLayoutAlgorithm.cs" Link="Compiler\Int128FieldLayoutAlgorithm.cs" />
<Compile Include="..\..\Common\Compiler\InternalCompilerErrorException.cs" Link="Compiler\InternalCompilerErrorException.cs" />
<Compile Include="..\..\Common\Compiler\NameMangler.cs" Link="Compiler\NameMangler.cs" />
<Compile Include="..\..\Common\Compiler\SingleMethodRootProvider.cs" Link="Compiler\SingleMethodRootProvider.cs" />
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/classnames.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
#define g_DateTimeOffsetClassName "System.DateTimeOffset"
#define g_DecimalClassName "System.Decimal"

#define g_Int128ClassName "System.Int128"
#define g_Int128Name "Int128"

#define g_UInt128ClassName "System.UInt128"
#define g_UInt128Name "UInt128"

#define g_Vector64ClassName "System.Runtime.Intrinsics.Vector64`1"
#define g_Vector64Name "Vector64`1"

Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ DEFINE_FIELD(DELEGATE, METHOD_PTR_AUX, _methodPtrAux)
DEFINE_METHOD(DELEGATE, CONSTRUCT_DELEGATE, DelegateConstruct, IM_Obj_IntPtr_RetVoid)
DEFINE_METHOD(DELEGATE, GET_INVOKE_METHOD, GetInvokeMethod, IM_RetIntPtr)

DEFINE_CLASS(INT128, System, Int128)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what defines g_Int128

g_Int128Name is defined in classnames.h. This macro defines CLASS_INT128 that I do not see used anywhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, I was getting two two things mixed up.

Looks like this is missing handling in classlayoutinfo.cpp which copies the alignment requirement to the pNativeLayoutInfo: https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/classlayoutinfo.cpp#L947-L964

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed. The only other usage of CLASS__* for the Vector* types was blocking interop which isn't required for Int128/UInt128 given the interop tests are all passing.

DEFINE_CLASS(UINT128, System, UInt128)

DEFINE_CLASS(DYNAMICMETHOD, ReflectionEmit, DynamicMethod)

DEFINE_CLASS(DYNAMICRESOLVER, ReflectionEmit, DynamicResolver)
Expand Down
18 changes: 16 additions & 2 deletions src/coreclr/vm/methodtablebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9844,7 +9844,7 @@ void MethodTableBuilder::CheckForSystemTypes()

if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
{
EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();

// The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
// * Vector64<T>: __m64
Expand All @@ -9854,7 +9854,6 @@ void MethodTableBuilder::CheckForSystemTypes()
// These __m128 and __m256 types, among other requirements, are special in that they must always
// be aligned properly.


if (strcmp(name, g_Vector64Name) == 0)
{
// The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
Expand Down Expand Up @@ -9898,6 +9897,21 @@ void MethodTableBuilder::CheckForSystemTypes()

return;
}
#if defined(UNIX_AMD64_ABI) || defined(TARGET_ARM64)
else if (strcmp(nameSpace, g_SystemNS) == 0)
{
EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();

// These types correspond to fundamental data types in the underlying ABIs:
// * Int128: __int128
// * UInt128: unsigned __int128

if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0))
{
pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs equivalent fix in crossgen/NativeAOT and in Mono

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fanyang-mono could you point me to where Mono handles custom struct packing/alignment?

I tried checking for where that's handled for the vector types, but couldn't find it.

Int128 and UInt128 need to have 16-byte packing when targeting the System V ABI (used by Unix) and the same packing/alignment as Int64/UInt64 otherwise (such as on Windows or 32-bit platforms).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-- I fixed this up for crossgen/NativeAOT already and added corresponding P/Invoke tests to ensure the data is passed correctly to/from Native.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's handled in mono_class_layout_fields () in metadata/class-init.c.
Not sure the mono gc supports 16 byte aligned objects on 32 bit platforms.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't impact 32-bit platforms, only 64-bit platforms (and only 64-bit Unix at that).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vargaz, looks like its just blocked everywhere not just 32-bit platforms: https://github.com/dotnet/runtime/blob/main/src/mono/mono/metadata/class-init.c#L2058-L2065

It looks like Mono also isn't differentiating "alignment" from "packing" and so the layout of types that include the new Int128, UInt128, or the existing Vector64<T>, Vector128<T>, Vector256<T> types will be incorrect.

This would explain why I couldn't find any logic touching Vector128<T> and ensuring that it has the right packing (and therefore layout) even if the GC couldn't correctly align the overall allocation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it looks like this is not implemented right now in mono.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll log an issue to ensure this is tracked (I don't see an existing issue).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logged #69399

}
}
#endif // UNIX_AMD64_ABI || TARGET_ARM64
}

if (g_pNullableClass != NULL)
Expand Down
12 changes: 12 additions & 0 deletions src/libraries/System.Private.CoreLib/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,9 @@
<data name="Arg_MustBeInt64" xml:space="preserve">
<value>Object must be of type Int64.</value>
</data>
<data name="Arg_MustBeInt128" xml:space="preserve">
<value>Object must be of type Int128.</value>
</data>
<data name="Arg_MustBeIntPtr" xml:space="preserve">
<value>Object must be of type IntPtr.</value>
</data>
Expand Down Expand Up @@ -567,6 +570,9 @@
<data name="Arg_MustBeUInt64" xml:space="preserve">
<value>Object must be of type UInt64.</value>
</data>
<data name="Arg_MustBeUInt128" xml:space="preserve">
<value>Object must be of type UInt128.</value>
</data>
<data name="Arg_MustBeUIntPtr" xml:space="preserve">
<value>Object must be of type UIntPtr.</value>
</data>
Expand Down Expand Up @@ -3022,6 +3028,9 @@
<data name="Overflow_Int64" xml:space="preserve">
<value>Value was either too large or too small for an Int64.</value>
</data>
<data name="Overflow_Int128" xml:space="preserve">
<value>Value was either too large or too small for an Int128.</value>
</data>
<data name="Overflow_MutexReacquireCount" xml:space="preserve">
<value>The current thread attempted to reacquire a mutex that has reached its maximum acquire count.</value>
</data>
Expand Down Expand Up @@ -3049,6 +3058,9 @@
<data name="Overflow_UInt64" xml:space="preserve">
<value>Value was either too large or too small for a UInt64.</value>
</data>
<data name="Overflow_UInt128" xml:space="preserve">
<value>Value was either too large or too small for a UInt128.</value>
</data>
<data name="PlatformNotSupported_ArgIterator" xml:space="preserve">
<value>ArgIterator is not supported on this platform.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Int16.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Int32.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Int64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Int128.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IntPtr.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidCastException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidOperationException.cs" />
Expand Down Expand Up @@ -1166,6 +1167,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\UInt16.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UInt32.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UInt64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UInt128.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UIntPtr.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UnauthorizedAccessException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventArgs.cs" />
Expand Down
Loading