diff --git a/src/ObjCRuntime/Stret.cs b/src/ObjCRuntime/Stret.cs
index 88be24d88627..978f155d2bc2 100644
--- a/src/ObjCRuntime/Stret.cs
+++ b/src/ObjCRuntime/Stret.cs
@@ -30,13 +30,21 @@
#if !RGEN
#endif
-// Disable until we get around to enable + fix any issues.
-#nullable disable
+#nullable enable
namespace ObjCRuntime {
class Stret {
- public static bool X86_64NeedStret (Type returnType, Generator generator)
+ /// Determines whether a return type requires x86_64 stret calling conventions.
+ /// The return type to inspect.
+ /// The generator context.
+ /// if stret calling conventions are required; otherwise, .
+ public static bool X86_64NeedStret (Type returnType, Generator? generator)
{
+ ArgumentNullException.ThrowIfNull (returnType);
+#if BGENERATOR
+ ArgumentNullException.ThrowIfNull (generator);
+#endif
+
Type t = returnType;
if (!t.IsValueType || t.IsEnum || IsBuiltInType (t))
@@ -48,8 +56,14 @@ public static bool X86_64NeedStret (Type returnType, Generator generator)
// IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields' in call to 'System.Type.GetFields(BindingFlags)'. The parameter 'type' of method 'ObjCRuntime.Stret.GetValueTypeSize(Type, List, Boolean, Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
[UnconditionalSuppressMessage ("", "IL2070", Justification = "Computing the size of a struct is safe, because the trimmer can't remove fields that would affect the size of a marshallable struct (it could affect marshalling behavior).")]
- internal static int GetValueTypeSize (Type type, List fieldTypes, Generator generator)
+ internal static int GetValueTypeSize (Type type, List fieldTypes, Generator? generator)
{
+ ArgumentNullException.ThrowIfNull (type);
+ ArgumentNullException.ThrowIfNull (fieldTypes);
+#if BGENERATOR
+ ArgumentNullException.ThrowIfNull (generator);
+#endif
+
int size = 0;
int maxElementSize = 1;
@@ -59,8 +73,10 @@ internal static int GetValueTypeSize (Type type, List fieldTypes, Generato
#if BGENERATOR
var fieldOffset = generator.AttributeManager.GetCustomAttribute (field);
#else
- var fieldOffset = (FieldOffsetAttribute) Attribute.GetCustomAttribute (field, typeof (FieldOffsetAttribute));
+ var fieldOffset = (FieldOffsetAttribute?) Attribute.GetCustomAttribute (field, typeof (FieldOffsetAttribute));
#endif
+ if (fieldOffset is null)
+ throw new Exception ($"Unable to find a FieldOffset attribute on field {GetTypeName (field.DeclaringType)}.{field.Name}");
var elementSize = 0;
GetValueTypeSize (type, field.FieldType, fieldTypes, ref elementSize, ref maxElementSize, generator);
size = Math.Max (size, elementSize + fieldOffset.Value);
@@ -85,11 +101,13 @@ static int AlignAndAdd (Type original_type, int size, int add, ref int max_eleme
static bool IsBuiltInType (Type type)
{
+ ArgumentNullException.ThrowIfNull (type);
return IsBuiltInType (type, out var _);
}
internal static bool IsBuiltInType (Type type, out int type_size)
{
+ ArgumentNullException.ThrowIfNull (type);
type_size = 0;
if (type.IsNested)
@@ -150,8 +168,15 @@ internal static bool IsBuiltInType (Type type, out int type_size)
// IL2070: 'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields', 'DynamicallyAccessedMemberTypes.NonPublicFields' in call to 'System.Type.GetFields(BindingFlags)'. The parameter 'type' of method 'ObjCRuntime.Stret.GetValueTypeSize(Type, Type, List, Boolean, Int32&, Int32&, Object)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
[UnconditionalSuppressMessage ("", "IL2070", Justification = "Computing the size of a struct is safe, because the trimmer can't remove fields that would affect the size of a marshallable struct (it could affect marshalling behavior).")]
- static void GetValueTypeSize (Type original_type, Type type, List field_types, ref int size, ref int max_element_size, Generator generator)
+ static void GetValueTypeSize (Type original_type, Type type, List field_types, ref int size, ref int max_element_size, Generator? generator)
{
+ ArgumentNullException.ThrowIfNull (original_type);
+ ArgumentNullException.ThrowIfNull (type);
+ ArgumentNullException.ThrowIfNull (field_types);
+#if BGENERATOR
+ ArgumentNullException.ThrowIfNull (generator);
+#endif
+
// FIXME:
// SIMD types are not handled correctly here (they need 16-bit alignment).
// However we don't annotate those types in any way currently, so first we'd need to
@@ -168,7 +193,7 @@ static void GetValueTypeSize (Type original_type, Type type, List field_ty
#if BGENERATOR
var marshalAs = generator.AttributeManager.GetCustomAttribute (field);
#else
- var marshalAs = (MarshalAsAttribute) Attribute.GetCustomAttribute (field, typeof (MarshalAsAttribute));
+ var marshalAs = (MarshalAsAttribute?) Attribute.GetCustomAttribute (field, typeof (MarshalAsAttribute));
#endif
if (marshalAs is null) {
GetValueTypeSize (original_type, field.FieldType, field_types, ref size, ref max_element_size, generator);
@@ -179,7 +204,10 @@ static void GetValueTypeSize (Type original_type, Type type, List field_ty
switch (marshalAs.Value) {
case UnmanagedType.ByValArray:
var types = new List ();
- GetValueTypeSize (original_type, field.FieldType.GetElementType (), types, ref type_size, ref max_element_size, generator);
+ var elementType = field.FieldType.GetElementType ();
+ if (elementType is null)
+ throw new Exception ($"Unable to find the element type for field {GetTypeName (field.DeclaringType)}.{field.Name}");
+ GetValueTypeSize (original_type, elementType, types, ref type_size, ref max_element_size, generator);
multiplier = marshalAs.SizeConst;
break;
case UnmanagedType.U1:
@@ -201,7 +229,7 @@ static void GetValueTypeSize (Type original_type, Type type, List field_ty
type_size = 8;
break;
default:
- throw new Exception ($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {field.DeclaringType.FullName}.{field.Name}");
+ throw new Exception ($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {GetTypeName (field.DeclaringType)}.{field.Name}");
}
field_types.Add (field.FieldType);
size = AlignAndAdd (original_type, size, type_size, ref max_element_size);
@@ -209,7 +237,19 @@ static void GetValueTypeSize (Type original_type, Type type, List field_ty
}
}
+ static string GetTypeName (Type? type)
+ {
+ if (type is null)
+ return "";
+
+ return type.FullName ?? type.Name ?? "";
+ }
+
#if BGENERATOR
+ /// Determines whether the specified return type requires stret calling conventions.
+ /// The return type to inspect.
+ /// The generator context.
+ /// if stret calling conventions are required; otherwise, .
public static bool NeedStret (Type returnType, Generator generator)
{
return X86_64NeedStret (returnType, generator);
diff --git a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt
index ce6a3817b719..acf0667de870 100644
--- a/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt
+++ b/tests/dotnet/UnitTests/expected/iOS-MonoVM-interpreter-preservedapis.txt
@@ -794,6 +794,7 @@ Microsoft.iOS.dll:ObjCRuntime.Selector.sel_isMapped(System.IntPtr)
Microsoft.iOS.dll:ObjCRuntime.Selector.sel_registerName(System.IntPtr)
Microsoft.iOS.dll:ObjCRuntime.Stret
Microsoft.iOS.dll:ObjCRuntime.Stret.AlignAndAdd(System.Type, System.Int32, System.Int32, System.Int32&)
+Microsoft.iOS.dll:ObjCRuntime.Stret.GetTypeName(System.Type)
Microsoft.iOS.dll:ObjCRuntime.Stret.GetValueTypeSize(System.Type, System.Collections.Generic.List`1, System.Object)
Microsoft.iOS.dll:ObjCRuntime.Stret.GetValueTypeSize(System.Type, System.Type, System.Collections.Generic.List`1, System.Int32&, System.Int32&, System.Object)
Microsoft.iOS.dll:ObjCRuntime.Stret.IsBuiltInType(System.Type, out System.Int32&)