From 09cdf87f67fe4638f8d8c8968b0e9173bfd227fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Aug 2023 13:59:12 +0900 Subject: [PATCH] [qfcc] Used aligned type sizes for sizeof And geometric algebra vectors. This does break things a little in GA, but it does bring qfcc's C closer to standard C in that sizeof respects the alignment of the type (very important for arrays). --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/algebra.c | 20 +++++++++++++++++++- tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/type.c | 7 +++++++ tools/qfcc/test/pga2d.r | 8 +++++--- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 7391d872d..337d0f4fa 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -230,6 +230,7 @@ int type_promotes (const type_t *dst, const type_t *src) __attribute__((pure)); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); int type_width (const type_t *type) __attribute__((pure)); +int type_aligned_size (const type_t *type) __attribute__((pure)); void init_types (void); void chain_initial_types (void); diff --git a/tools/qfcc/source/algebra.c b/tools/qfcc/source/algebra.c index fdaa7e99b..e0447a0bf 100644 --- a/tools/qfcc/source/algebra.c +++ b/tools/qfcc/source/algebra.c @@ -445,6 +445,11 @@ algebra_subtype (type_t *type, attribute_t *attr) static int algebra_alignment (const type_t *type, int width) { + if (width > 4) { + // don't need more than 4 units + width = 4; + } + // alignment reflects the size for doubles vs floats return type->alignment * BITOP_RUP (width); } @@ -657,7 +662,20 @@ algebra_type_size (const type_t *type) return a->num_components * type_size (a->type); } else if (type->type == ev_float || type->type == ev_double) { auto m = type->t.multivec; - return m->num_components * type_size (m->algebra->type); + auto a = m->algebra; + auto layout = &a->layout; + int size = 0; + if (m->group_mask & (m->group_mask - 1)) { + for (int i = 0; i < layout->count; i++) { + if (m->group_mask & (1u << i)) { + auto t = algebra_mvec_type (a, m->group_mask & (1u << i)); + size += type_aligned_size (t); + } + } + } else { + size = m->num_components * type_size (m->algebra->type); + } + return size; } else { internal_error (0, "invalid algebra type"); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 095c16d9e..e895e7efc 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -3009,7 +3009,7 @@ sizeof_expr (expr_t *expr, struct type_s *type) if (!type) type = get_type (expr); if (type) { - expr = new_int_expr (type_size (type)); + expr = new_int_expr (type_aligned_size (type)); } return expr; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 463a986b9..5b40aa6a6 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1444,6 +1444,13 @@ type_width (const type_t *type) internal_error (0, "invalid type meta: %d", type->meta); } +int +type_aligned_size (const type_t *type) +{ + int size = type_size (type); + return RUP (size, type->alignment); +} + static void chain_basic_types (void) { diff --git a/tools/qfcc/test/pga2d.r b/tools/qfcc/test/pga2d.r index 6074fd46d..c2c427d2b 100644 --- a/tools/qfcc/test/pga2d.r +++ b/tools/qfcc/test/pga2d.r @@ -27,11 +27,13 @@ main (void) printf ("scalar has wrong size: %d\n", sizeof (scalar_t)); return 1; } - if (sizeof (vector_t) != 3 * sizeof (scalar_t)) { - printf ("bivector has wrong size: %d\n", sizeof (vector_t)); + // vector_t is a vec3 but has alignment of 4 thus sizeof of 4 * scalar + if (sizeof (vector_t) != 4 * sizeof (scalar_t)) { + printf ("vector has wrong size: %d\n", sizeof (vector_t)); return 1; } - if (sizeof (bivector_t) != 3 * sizeof (scalar_t)) { + // bivector_t is a vec3 but has alignment of 4 thus sizeof of 4 * scalar + if (sizeof (bivector_t) != 4 * sizeof (scalar_t)) { printf ("bivector has wrong size: %d\n", sizeof (bivector_t)); return 1; }