Skip to content

Commit 591ef5f

Browse files
authored
[runtime] Fix numerous marshalling bugs in the dynamic registrar. (#22209)
For arm64: * We didn't take into account that a register can contain more than one field of a struct (for fields where the total size is less than or equal to 8 bytes). Example: a struct with 8 separate bytes fields will be passed in a single register, instead of using 8 registers. * We didn't take alignment / padding of elements in structs into account. * We didn't correctly detect which structs can be fully passed in floating point registers. For x64: * We didn't take alignment / padding of elements in structs into account. * We didn't correctly detect which structs can be fully passed in floating point registers. * We didn't correctly detect when we can't pass any more values in registers. * We didn't correctly marshal structs with non-standard small sizes (anything between 1 and 16, inclusive). Fixes #22196.
1 parent 00e24b9 commit 591ef5f

11 files changed

+859
-229
lines changed

runtime/runtime-internal.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,32 @@ void xamarin_dyn_objc_msgSend_stret ();
4444
void xamarin_dyn_objc_msgSendSuper_stret ();
4545
void xamarin_add_internal_call (const char *name, const void *method);
4646

47+
static inline size_t align_size (size_t target, uint64_t alignment)
48+
{
49+
target = (target + (alignment - 1)) & ~(alignment - 1);
50+
return target;
51+
}
52+
53+
static inline unsigned long align_ulong (unsigned long target, unsigned long alignment)
54+
{
55+
target = (target + (alignment - 1)) & ~(alignment - 1);
56+
return target;
57+
}
58+
59+
static inline int32_t align_int32 (int32_t target, int32_t alignment)
60+
{
61+
target = (target + (alignment - 1)) & ~(alignment - 1);
62+
return target;
63+
}
64+
65+
static inline void* align_ptr (void* target, uint64_t alignment)
66+
{
67+
uint64_t ptr = (uint64_t) target;
68+
ptr = (ptr + (alignment - 1)) & ~(alignment - 1);
69+
return (void *) ptr;
70+
}
71+
72+
4773
#ifdef __cplusplus
4874
}
4975
#endif

runtime/runtime.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,10 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
16771677
xamarin_assertion_message ("Unsupported struct type: %s", original_type);
16781678
unsigned long item_size = xamarin_objc_type_size (type);
16791679

1680-
size += (item_size + (sizeof (void *) - 1)) & ~((sizeof (void *) - 1));
1680+
// first align the accumulated size to the current item's size (this would be any padding between struct elements)
1681+
size = align_ulong (size, item_size);
1682+
// accumulate this item's size
1683+
size += item_size;
16811684

16821685
type = objc_skip_type (type);
16831686
}

runtime/trampolines-arm64.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,18 @@ struct BigDouble {
99
struct _f {
1010
float f1;
1111
float f2;
12+
float f3;
13+
float f4;
14+
};
15+
struct _d {
16+
double d1;
17+
double d2;
1218
};
1319
union {
1420
__int128 bits;
15-
long double d;
21+
long double q;
1622
_f f;
23+
_d d;
1724
};
1825
};
1926

@@ -52,6 +59,7 @@ struct ParamIterator {
5259
struct XamarinCallState *state;
5360
int ngrn; // Next General-purpose Register Number
5461
int nsrn; // Next SIMD and Floating-point Register Number
62+
size_t ngrn_offset; // Offset into the current general purpose register number
5563
uint8_t *nsaa; // Next stacked argument address.
5664

5765
// computed values

0 commit comments

Comments
 (0)