From ae0b3a58706ccdc9e7453cfc0bdf6a5bb1b20b2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 21:32:41 +0900 Subject: [PATCH] [qfcc] Add some utility functions for working with vector types Finding vector types from base type and width, and getting the base type for a vector type, as well as basic promotion rules for math types. --- tools/qfcc/include/type.h | 5 +++ tools/qfcc/source/statements.c | 17 ++------ tools/qfcc/source/type.c | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 156189d33..69ca4bc4b 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -160,6 +160,8 @@ type_t *find_type (type_t *new); void new_typedef (const char *name, type_t *type); type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); +type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure)); +type_t *base_type (const type_t *vec_type) __attribute__((pure)); type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); @@ -187,6 +189,7 @@ int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); +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)); @@ -197,5 +200,7 @@ void chain_initial_types (void); void clear_typedefs (void); extern type_t *ev_types[]; +extern int type_cast_map[]; +#define TYPE_CAST_CODE(from, to, width) (((width) << 6) | ((from) << 3) | (to)) #endif//__type_h diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fda9e9a2e..7c7ad4d4b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1760,17 +1760,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } -static int type_map[ev_type_count] = { - [ev_int] = 0, - [ev_float] = 1, - [ev_long] = 2, - [ev_double] = 3, - [ev_uint] = 4, - //[ev_bool32] = 5, - [ev_ulong] = 6, - //[ev_bool64] = 7, -}; - static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1786,10 +1775,10 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) s = new_statement (st_expr, "conv", e); s->opa = src; if (options.code.progsversion == PROG_VERSION) { - int from = type_map[src_type->type]; - int to = type_map[type->type]; + int from = type_cast_map[src_type->type]; + int to = type_cast_map[type->type]; int width = type_width (src_type) - 1; - int conv = (width << 6) | (from << 3) | to; + int conv = TYPE_CAST_CODE (from, to, width); s->opb = short_operand (conv, e); } s->opc = *op; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0387f862b..f25cb6eba 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -89,6 +89,11 @@ type_t type_invalid = { }; #include "tools/qfcc/include/vec_types.h" +#define VEC_TYPE(type_name, base_type) &type_##type_name, +static type_t *vec_types[] = { +#include "tools/qfcc/include/vec_types.h" + 0 +}; type_t *type_nil; type_t *type_default; type_t *type_long_int; @@ -145,6 +150,17 @@ type_t *ev_types[ev_type_count] = { &type_invalid, }; +int type_cast_map[ev_type_count] = { + [ev_int] = 0, + [ev_float] = 1, + [ev_long] = 2, + [ev_double] = 3, + [ev_uint] = 4, + //[ev_bool32] = 5, + [ev_ulong] = 6, + //[ev_bool64] = 7, +}; + static type_t *types_freelist; etype_t @@ -524,6 +540,38 @@ pointer_type (type_t *aux) return new; } +type_t * +vector_type (const type_t *ele_type, int width) +{ + if (width == 1) { + for (type_t **t = ev_types; t - ev_types < ev_type_count; t++) { + if ((*t)->type == ele_type->type && (*t)->width == 1) { + return *t; + } + } + } + for (type_t **vtype = vec_types; *vtype; vtype++) { + if ((*vtype)->type == ele_type->type + && (*vtype)->width == width) { + return *vtype; + } + } + return 0; +} + +type_t * +base_type (const type_t *vec_type) +{ + if (!is_math (vec_type)) { + return 0; + } + // vec_type->type for quaternion and vector points back to itself + if (is_quaternion (vec_type) || is_vector (vec_type)) { + return &type_float; + } + return ev_types[vec_type->type]; +} + type_t * array_type (type_t *aux, int size) { @@ -1097,6 +1145,35 @@ type_assignable (const type_t *dst, const type_t *src) return 0; } +int +type_promotes (const type_t *dst, const type_t *src) +{ + dst = unalias_type (dst); + src = unalias_type (src); + // nothing promotes to int + if (is_int (dst)) { + return 0; + } + if (is_uint (dst) && is_int (src)) { + return 1; + } + if (is_long (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + if (is_ulong (dst) && (is_int (src) || is_uint (src) || is_long (src))) { + return 1; + } + if (is_float (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + //XXX what to do with (u)long<->float? + // everything promotes to double + if (is_double (dst)) { + return 1; + } + return 0; +} + int type_same (const type_t *dst, const type_t *src) {