From d387b56f6075375581a71fa2f065bf991505d171 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 11 Sep 2023 00:24:50 +0900 Subject: [PATCH] [qfcc] Support block initializers for multi-vectors They're not supported (yet) for single-group multi-vectors, and designators are required for all initializer elements. --- tools/qfcc/include/algebra.h | 1 + tools/qfcc/source/algebra.c | 13 +++++++++++++ tools/qfcc/source/expr_algebra.c | 13 ++++++++++--- tools/qfcc/source/expr_compound.c | 23 ++++++++++++++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/algebra.h b/tools/qfcc/include/algebra.h index c62d6abfb..169c1395c 100644 --- a/tools/qfcc/include/algebra.h +++ b/tools/qfcc/include/algebra.h @@ -104,6 +104,7 @@ algebra_t *algebra_get (const struct type_s *type) __attribute__((pure)); int algebra_type_assignable (const struct type_s *dst, const struct type_s *src) __attribute__((pure)); struct type_s *algebra_base_type (const struct type_s *type) __attribute__((pure)); +struct type_s *algebra_struct_type (const struct type_s *type) __attribute__((pure)); bool is_mono_grade (const struct type_s *type) __attribute__((pure)); int algebra_get_grade (const struct type_s *type) __attribute__((pure)); int algebra_blade_grade (basis_blade_t blade) __attribute__((const)); diff --git a/tools/qfcc/source/algebra.c b/tools/qfcc/source/algebra.c index d54451b24..f25a686ec 100644 --- a/tools/qfcc/source/algebra.c +++ b/tools/qfcc/source/algebra.c @@ -782,6 +782,19 @@ algebra_base_type (const type_t *type) return ev_types[type->type]; } +type_t * +algebra_struct_type (const type_t *type) +{ + symbol_t *sym = 0; + + if (type->type == ev_invalid) { + sym = type->t.algebra->mvec_sym; + } else { + sym = type->t.multivec->mvec_sym; + } + return sym ? sym->type : 0; +} + int algebra_blade_grade (basis_blade_t blade) { diff --git a/tools/qfcc/source/expr_algebra.c b/tools/qfcc/source/expr_algebra.c index f464f22d4..3df26920b 100644 --- a/tools/qfcc/source/expr_algebra.c +++ b/tools/qfcc/source/expr_algebra.c @@ -176,8 +176,8 @@ offset_cast (type_t *type, expr_t *expr, int offset) return alias_expr (type, expr, offset); } -static symbol_t * -get_mvec_sym (type_t *type) +static symtab_t * +get_mvec_struct (type_t *type) { symbol_t *sym = 0; if (type->type == ev_invalid) { @@ -185,7 +185,14 @@ get_mvec_sym (type_t *type) } else { sym = type->t.multivec->mvec_sym; } - return sym->type->t.symtab->symbols; + return sym ? sym->type->t.symtab : 0; +} + +static symbol_t * +get_mvec_sym (type_t *type) +{ + auto symtab = get_mvec_struct (type); + return symtab ? symtab->symbols : 0; } static bool diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index 95f29230b..c235f22f9 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -206,8 +206,19 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, initstate_t state = {}; if (is_algebra (type)) { - error (eles, "block initializer of multi-vector type"); - return; + for (auto e = ele; e; e = e->next) { + if (!e->designator) { + error (eles, "block initializer of multi-vector type requires " + "designators for all initializer elements"); + return; + } + } + auto t = algebra_struct_type (type); + if (!t) { + error (eles, "block initializer on simple multi-vector type"); + return; + } + type = t; } else if (is_struct (type) || is_union (type) || (is_nonscalar (type) && type->t.symtab)) { state.field = type->t.symtab->symbols; @@ -308,7 +319,7 @@ assign_elements (expr_t *local_expr, expr_t *init, expr_t *c; if (type_size (type) == 0) - internal_error (init, "wtf"); + internal_error (init, "wtw"); if (element->expr) { c = constant_expr (element->expr); } else { @@ -336,6 +347,12 @@ assign_elements (expr_t *local_expr, expr_t *init, start = in->element; } } + if (start < (unsigned) type_size (init_type)) { + expr_t *dst = new_offset_alias_expr (&type_int, init, start); + expr_t *zero = new_int_expr (0); + expr_t *count = new_int_expr (type_size (init_type) - start); + append_expr (local_expr, new_memset_expr (dst, zero, count)); + } set_delete (initialized); }