From 6cb9d7ae53fd5a6a0f79d56de82b425cb003947c Mon Sep 17 00:00:00 2001 From: Benjamin Oldenburg Date: Mon, 16 Mar 2026 01:09:10 +0700 Subject: [PATCH] arm64: use union type tags in HFA classification --- arm64-gen.c | 20 +------------------- tests/tests2/73_arm64.c | 15 +++++++++++++++ tests/tests2/73_arm64.expect | 4 ++++ 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/arm64-gen.c b/arm64-gen.c index 9cd76943..ea5b64eb 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -778,28 +778,10 @@ static int arm64_hfa_aux(CType *type, int *fsize, int num) return num + 1; } else if ((type->t & VT_BTYPE) == VT_STRUCT) { - int is_struct = 1; /* assume struct, check if union */ Sym *field; if (!type->ref) return -1; - /* A union has all fields at offset 0, a struct has increasing offsets */ - for (field = type->ref->next; field; field = field->next) - if (field->c != 0) { - is_struct = 1; - break; - } - /* If all fields are at offset 0 and there's more than one field, it's a union */ - if (type->ref->next && type->ref->next->next && !type->ref->next->c) { - /* Check if all fields are at offset 0 (union) */ - int all_zero = 1; - for (field = type->ref->next; field; field = field->next) - if (field->c != 0) { - all_zero = 0; - break; - } - is_struct = !all_zero; - } - if (is_struct) { + if (!IS_UNION(type->t)) { int num0 = num; for (field = type->ref->next; field; field = field->next) { if (field->c != (num - num0) * *fsize) diff --git a/tests/tests2/73_arm64.c b/tests/tests2/73_arm64.c index 855c4767..16be1047 100644 --- a/tests/tests2/73_arm64.c +++ b/tests/tests2/73_arm64.c @@ -38,6 +38,11 @@ struct hfa32 { long double a, b; } hfa32 = { 32.1, 32.2 }; struct hfa33 { long double a, b, c; } hfa33 = { 33.1, 33.2, 33.3 }; struct hfa34 { long double a, b, c, d; } hfa34 = { 34.1, 34.2, 34.3, 34.4 }; +struct empty { }; +/* Keep the top-level offsets at zero without changing the type into a union. */ +struct hfae12 { struct empty e; struct hfa12 h; } hfae12 = { { }, { 112.1, 112.2 } }; +struct hfae22 { struct empty e; struct hfa22 h; } hfae22 = { { }, { 122.1, 122.2 } }; + void fa_s1(struct s1 a) { printf("%.1s\n", a.x); } void fa_s2(struct s2 a) { printf("%.2s\n", a.x); } void fa_s3(struct s3 a) { printf("%.3s\n", a.x); } @@ -82,6 +87,10 @@ void fa_hfa33(struct hfa33 a) { printf("%.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c); } void fa_hfa34(struct hfa34 a) { printf("%.1Lf %.1Lf %.1Lf %.1Lf\n", a.a, a.b, a.c, a.d); } +void fa_hfae12(struct hfae12 a) +{ printf("%.1f %.1f\n", a.h.a, a.h.b); } +void fa_hfae22(struct hfae22 a) +{ printf("%.1f %.1f\n", a.h.a, a.h.b); } void fa1(struct s8 a, struct s9 b, struct s10 c, struct s11 d, struct s12 e, struct s13 f) @@ -140,6 +149,8 @@ void arg(void) fa_hfa32(hfa32); fa_hfa33(hfa33); fa_hfa34(hfa34); + fa_hfae12(hfae12); + fa_hfae22(hfae22); fa1(s8, s9, s10, s11, s12, s13); fa2(s9, s10, s11, s12, s13, s14); fa3(hfa14, hfa23, hfa32); @@ -178,6 +189,8 @@ struct hfa31 fr_hfa31(void) { return hfa31; } struct hfa32 fr_hfa32(void) { return hfa32; } struct hfa33 fr_hfa33(void) { return hfa33; } struct hfa34 fr_hfa34(void) { return hfa34; } +struct hfae12 fr_hfae12(void) { return hfae12; } +struct hfae22 fr_hfae22(void) { return hfae22; } void ret(void) { @@ -228,6 +241,8 @@ void ret(void) printf("%.1Lf %.1Lf\n", fr_hfa32().a, fr_hfa32().b); printf("%.1Lf %.1Lf\n", fr_hfa33().a, fr_hfa33().c); printf("%.1Lf %.1Lf\n", fr_hfa34().a, fr_hfa34().d); + printf("%.1f %.1f\n", fr_hfae12().h.a, fr_hfae12().h.b); + printf("%.1f %.1f\n", fr_hfae22().h.a, fr_hfae22().h.b); } void* diff --git a/tests/tests2/73_arm64.expect b/tests/tests2/73_arm64.expect index 7bdebd30..7bc07500 100644 --- a/tests/tests2/73_arm64.expect +++ b/tests/tests2/73_arm64.expect @@ -28,6 +28,8 @@ cdefghijklmnopqrs 32.1 32.1 33.1 33.2 33.3 34.1 34.2 34.3 34.4 +112.1 112.2 +122.1 122.2 stu ABC JKL TUV 456 ghi ABC JKL TUV 456 ghi tuv 14.1 14.4 23.1 23.3 32.1 32.2 @@ -62,6 +64,8 @@ cdefghijklmnopqrs 32.1 32.2 33.1 33.3 34.1 34.4 +112.1 112.2 +122.1 122.2 stdarg: ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI lmnopqr ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI ABCDEFGHI