Skip to content

Commit c414752

Browse files
rolfbjarneCopilot
andcommitted
[ObjCRuntime] Enable nullability and clean up Stret.
This is file 3 of 7 files with nullability disabled in ObjCRuntime. * Enable nullability (#nullable enable). * Add null argument validation for stret helpers to improve static analysis and runtime diagnostics. * Add nullable-safe handling for reflection-based attributes and ByValArray element types. * Improve XML documentation comments by adding missing public API docs. Contributes towards #17285. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9c6a586 commit c414752

File tree

1 file changed

+46
-9
lines changed

1 file changed

+46
-9
lines changed

src/ObjCRuntime/Stret.cs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,21 @@
3030
#if !RGEN
3131
#endif
3232

33-
// Disable until we get around to enable + fix any issues.
34-
#nullable disable
33+
#nullable enable
3534

3635
namespace ObjCRuntime {
3736
class Stret {
38-
public static bool X86_64NeedStret (Type returnType, Generator generator)
37+
/// <summary>Determines whether a return type requires x86_64 stret calling conventions.</summary>
38+
/// <param name="returnType">The return type to inspect.</param>
39+
/// <param name="generator">The generator context.</param>
40+
/// <returns><see langword="true"/> if stret calling conventions are required; otherwise, <see langword="false"/>.</returns>
41+
public static bool X86_64NeedStret (Type returnType, Generator? generator)
3942
{
43+
ArgumentNullException.ThrowIfNull (returnType);
44+
#if BGENERATOR
45+
ArgumentNullException.ThrowIfNull (generator);
46+
#endif
47+
4048
Type t = returnType;
4149

4250
if (!t.IsValueType || t.IsEnum || IsBuiltInType (t))
@@ -48,8 +56,14 @@ public static bool X86_64NeedStret (Type returnType, Generator generator)
4856

4957
// 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<Type>, 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.
5058
[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).")]
51-
internal static int GetValueTypeSize (Type type, List<Type> fieldTypes, Generator generator)
59+
internal static int GetValueTypeSize (Type type, List<Type> fieldTypes, Generator? generator)
5260
{
61+
ArgumentNullException.ThrowIfNull (type);
62+
ArgumentNullException.ThrowIfNull (fieldTypes);
63+
#if BGENERATOR
64+
ArgumentNullException.ThrowIfNull (generator);
65+
#endif
66+
5367
int size = 0;
5468
int maxElementSize = 1;
5569

@@ -59,8 +73,10 @@ internal static int GetValueTypeSize (Type type, List<Type> fieldTypes, Generato
5973
#if BGENERATOR
6074
var fieldOffset = generator.AttributeManager.GetCustomAttribute<FieldOffsetAttribute> (field);
6175
#else
62-
var fieldOffset = (FieldOffsetAttribute) Attribute.GetCustomAttribute (field, typeof (FieldOffsetAttribute));
76+
var fieldOffset = (FieldOffsetAttribute?) Attribute.GetCustomAttribute (field, typeof (FieldOffsetAttribute));
6377
#endif
78+
if (fieldOffset is null)
79+
throw new Exception ($"Unable to find a FieldOffset attribute on field {GetTypeName (field.DeclaringType)}.{field.Name}");
6480
var elementSize = 0;
6581
GetValueTypeSize (type, field.FieldType, fieldTypes, ref elementSize, ref maxElementSize, generator);
6682
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
85101

86102
static bool IsBuiltInType (Type type)
87103
{
104+
ArgumentNullException.ThrowIfNull (type);
88105
return IsBuiltInType (type, out var _);
89106
}
90107

91108
internal static bool IsBuiltInType (Type type, out int type_size)
92109
{
110+
ArgumentNullException.ThrowIfNull (type);
93111
type_size = 0;
94112

95113
if (type.IsNested)
@@ -150,8 +168,15 @@ internal static bool IsBuiltInType (Type type, out int type_size)
150168

151169
// 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<Type>, 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.
152170
[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).")]
153-
static void GetValueTypeSize (Type original_type, Type type, List<Type> field_types, ref int size, ref int max_element_size, Generator generator)
171+
static void GetValueTypeSize (Type original_type, Type type, List<Type> field_types, ref int size, ref int max_element_size, Generator? generator)
154172
{
173+
ArgumentNullException.ThrowIfNull (original_type);
174+
ArgumentNullException.ThrowIfNull (type);
175+
ArgumentNullException.ThrowIfNull (field_types);
176+
#if BGENERATOR
177+
ArgumentNullException.ThrowIfNull (generator);
178+
#endif
179+
155180
// FIXME:
156181
// SIMD types are not handled correctly here (they need 16-bit alignment).
157182
// 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<Type> field_ty
168193
#if BGENERATOR
169194
var marshalAs = generator.AttributeManager.GetCustomAttribute<MarshalAsAttribute> (field);
170195
#else
171-
var marshalAs = (MarshalAsAttribute) Attribute.GetCustomAttribute (field, typeof (MarshalAsAttribute));
196+
var marshalAs = (MarshalAsAttribute?) Attribute.GetCustomAttribute (field, typeof (MarshalAsAttribute));
172197
#endif
173198
if (marshalAs is null) {
174199
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<Type> field_ty
179204
switch (marshalAs.Value) {
180205
case UnmanagedType.ByValArray:
181206
var types = new List<Type> ();
182-
GetValueTypeSize (original_type, field.FieldType.GetElementType (), types, ref type_size, ref max_element_size, generator);
207+
var elementType = field.FieldType.GetElementType ();
208+
if (elementType is null)
209+
throw new Exception ($"Unable to find the element type for field {GetTypeName (field.DeclaringType)}.{field.Name}");
210+
GetValueTypeSize (original_type, elementType, types, ref type_size, ref max_element_size, generator);
183211
multiplier = marshalAs.SizeConst;
184212
break;
185213
case UnmanagedType.U1:
@@ -201,15 +229,24 @@ static void GetValueTypeSize (Type original_type, Type type, List<Type> field_ty
201229
type_size = 8;
202230
break;
203231
default:
204-
throw new Exception ($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {field.DeclaringType.FullName}.{field.Name}");
232+
throw new Exception ($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {GetTypeName (field.DeclaringType)}.{field.Name}");
205233
}
206234
field_types.Add (field.FieldType);
207235
size = AlignAndAdd (original_type, size, type_size, ref max_element_size);
208236
size += (multiplier - 1) * size;
209237
}
210238
}
211239

240+
static string GetTypeName (Type? type)
241+
{
242+
return type?.FullName ?? type?.Name ?? "<unknown>";
243+
}
244+
212245
#if BGENERATOR
246+
/// <summary>Determines whether the specified return type requires stret calling conventions.</summary>
247+
/// <param name="returnType">The return type to inspect.</param>
248+
/// <param name="generator">The generator context.</param>
249+
/// <returns><see langword="true"/> if stret calling conventions are required; otherwise, <see langword="false"/>.</returns>
213250
public static bool NeedStret (Type returnType, Generator generator)
214251
{
215252
return X86_64NeedStret (returnType, generator);

0 commit comments

Comments
 (0)