From 1eef2a8b5e97e16166c0e51b4d345378ab2a725e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 12:10:23 +0900 Subject: [PATCH] [qfcc] Implement type aliasing again When a type is aliased, the alias has two type chains: the simple type chain with all other aliases stripped, and the full type chain. There are still plenty of bugs in it, but having the clean type chain takes care of the major issue that was in the previous attempt as only the head of the type-chain needs to be skipped for type comparison. Most of the bugs are in finding the locations where the head needs to be skipped. --- include/QF/pr_type.h | 7 +- ruamoko/include/types.h | 1 + tools/qfcc/include/expr.h | 7 +- tools/qfcc/include/type.h | 5 +- tools/qfcc/source/dump_globals.c | 6 +- tools/qfcc/source/expr.c | 31 ++++--- tools/qfcc/source/expr_compound.c | 7 +- tools/qfcc/source/function.c | 11 +-- tools/qfcc/source/obj_file.c | 10 ++- tools/qfcc/source/obj_type.c | 23 ++++++ tools/qfcc/source/qc-parse.y | 3 + tools/qfcc/source/type.c | 133 ++++++++++++++++++++++-------- 12 files changed, 180 insertions(+), 64 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index db3376684..c74ad3c26 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -52,8 +52,9 @@ typedef enum { typedef struct qfot_alias_s { pr_int_t type; ///< type at end of alias chain - pointer_t aux_type; ///< referenced type - string_t name; ///< alias name + pointer_t aux_type; ///< referenced type: stripped of aliases + pointer_t full_type; ///< includes full alias info + string_t name; ///< alias name, may be null } qfot_alias_t; typedef struct qfot_fldptr_s { @@ -101,7 +102,7 @@ typedef struct qfot_array_s { */ typedef struct qfot_type_s { ty_meta_e meta:32; ///< meta type - pr_int_t size; ///< total word size of this encoding + pr_uint_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { etype_t type:32; ///< ty_basic: etype_t diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index b435a6bab..c57603ada 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -33,6 +33,7 @@ typedef enum { typedef struct qfot_alias_s { etype_t type; struct qfot_type_s *aux_type; + struct qfot_type_s *full_type; string name; } qfot_alias_t; diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index be1640ffc..79fd77f99 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -380,10 +380,11 @@ expr_t *build_block_expr (expr_t *expr_list); element_t *new_element (expr_t *expr, struct symbol_s *symbol); expr_t *new_compound_init (void); expr_t *append_element (expr_t *compound, element_t *element); -expr_t *initialized_temp_expr (struct type_s *type, expr_t *compound); +expr_t *initialized_temp_expr (const struct type_s *type, expr_t *compound); void assign_elements (expr_t *local_expr, expr_t *ptr, element_chain_t *element_chain); -void build_element_chain (element_chain_t *element_chain, struct type_s *type, +void build_element_chain (element_chain_t *element_chain, + const struct type_s *type, expr_t *eles, int base_offset); void free_element_chain (element_chain_t *element_chain); @@ -433,7 +434,7 @@ expr_t *new_symbol_expr (struct symbol_s *symbol); \param type The type of the temporary variable. \return The new temporary variable expression node (ex_temp_t). */ -expr_t *new_temp_def_expr (struct type_s *type); +expr_t *new_temp_def_expr (const struct type_s *type); /** Create a new nil expression node. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index bb6133bb1..70c650c52 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -52,7 +52,8 @@ typedef struct ty_array_s { } ty_array_t; typedef struct ty_alias_s { - struct type_s *type; + struct type_s *aux_type; ///< other aliases stripped + struct type_s *full_type; ///< full alias chain } ty_alias_t; typedef struct type_s { @@ -148,6 +149,8 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); 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); +const type_t *unalias_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); const char *encode_params (const type_t *type); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e02d35753..1695769e0 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -580,8 +580,10 @@ dump_qfo_types (qfo_t *qfo, int base_address) printf (" %-5x\n", type->t.class); break; case ty_alias: - printf (" %s %d %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), - type->t.alias.type, type->t.alias.aux_type); + printf (" %s %d %5x %5x\n", + QFO_GETSTR (qfo, type->t.alias.name), + type->t.alias.type, type->t.alias.aux_type, + type->t.alias.full_type); break; } } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f4291bb33..73151b902 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -211,6 +211,7 @@ convert_vector (expr_t *e) type_t * get_type (expr_t *e) { + const type_t *type = 0; convert_name (e); switch (e->type) { case ex_labelref: @@ -238,19 +239,23 @@ get_type (expr_t *e) return &type_void; case ex_expr: case ex_uexpr: - return e->e.expr.type; + type = e->e.expr.type; + break; case ex_def: - return e->e.def->type; + type = e->e.def->type; + break; case ex_symbol: - return e->e.symbol->type; + type = e->e.symbol->type; + break; case ex_temp: return e->e.temp.type; case ex_value: - return e->e.value->type; + type = e->e.value->type; + break; case ex_vector: return e->e.vector.type; } - return 0; + return (type_t *) unalias_type (type);//FIXME cast } etype_t @@ -632,12 +637,12 @@ new_symbol_expr (symbol_t *symbol) } expr_t * -new_temp_def_expr (type_t *type) +new_temp_def_expr (const type_t *type) { expr_t *e = new_expr (); e->type = ex_temp; - e->e.temp.type = type; + e->e.temp.type = (type_t *) unalias_type (type); // FIXME cast return e; } @@ -2026,8 +2031,9 @@ goto_expr (expr_t *label) expr_t * return_expr (function_t *f, expr_t *e) { - type_t *t; - type_t *ret_type = f->sym->type->t.func.type; + const type_t *t; + const type_t *func_type = unalias_type (f->sym->type); + const type_t *ret_type = unalias_type (func_type->t.func.type); if (!e) { if (!is_void(ret_type)) { @@ -2064,7 +2070,7 @@ return_expr (function_t *f, expr_t *e) warning (e, "returning a value for a void function"); } if (e->type == ex_bool) { - e = convert_from_bool (e, ret_type); + e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } if (is_float(ret_type) && is_integer_val (e)) { convert_int (e); @@ -2073,7 +2079,7 @@ return_expr (function_t *f, expr_t *e) if (is_void(t)) { if (e->type == ex_nil) { t = ret_type; - convert_nil (e, t); + convert_nil (e, (type_t *) t);//FIXME cast } else { if (!options.traditional) return error (e, "void value not ignored as it ought to be"); @@ -2091,7 +2097,7 @@ return_expr (function_t *f, expr_t *e) f->sym->name); } else { if (ret_type != t) { - e = cast_expr (ret_type, e); + e = cast_expr ((type_t *) ret_type, e);//FIXME cast t = f->sym->type->t.func.type; } } @@ -2621,6 +2627,7 @@ cast_expr (type_t *dstType, expr_t *e) if (e->type == ex_error) return e; + dstType = (type_t *) unalias_type (dstType); //FIXME cast srcType = get_type (e); if (dstType == srcType) diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index 5ead7de7a..40b4e01c5 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -83,11 +83,13 @@ new_compound_init (void) } void -build_element_chain (element_chain_t *element_chain, type_t *type, +build_element_chain (element_chain_t *element_chain, const type_t *type, expr_t *eles, int base_offset) { element_t *ele = eles->e.compound.head; + type = unalias_type (type); + if (is_array (type)) { type_t *array_type = type->t.array.type; int array_size = type->t.array.size; @@ -193,8 +195,9 @@ assign_elements (expr_t *local_expr, expr_t *init, } expr_t * -initialized_temp_expr (type_t *type, expr_t *compound) +initialized_temp_expr (const type_t *type, expr_t *compound) { + type = unalias_type (type); element_chain_t element_chain; expr_t *temp = new_temp_def_expr (type); expr_t *block = new_block_expr (); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e9cb0c823..5758eabd5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -235,7 +235,7 @@ check_params (param_t *params) } static overloaded_function_t * -get_function (const char *name, type_t *type, int overload, int create) +get_function (const char *name, const type_t *type, int overload, int create) { const char *full_name; overloaded_function_t *func; @@ -251,7 +251,7 @@ get_function (const char *name, type_t *type, int overload, int create) func = Hash_Find (overloaded_functions, full_name); if (func) { - if (func->type != type) { + if (unalias_type (func->type) != type) { error (0, "can't overload on return types"); return func; } @@ -277,7 +277,7 @@ get_function (const char *name, type_t *type, int overload, int create) func = calloc (1, sizeof (overloaded_function_t)); func->name = name; func->full_name = full_name; - func->type = type; + func->type = (type_t *) type; //FIXME cast func->overloaded = overload; func->file = pr.source_file; func->line = pr.source_line; @@ -294,7 +294,7 @@ function_symbol (symbol_t *sym, int overload, int create) overloaded_function_t *func; symbol_t *s; - func = get_function (name, sym->type, overload, create); + func = get_function (name, unalias_type (sym->type), overload, create); if (func && func->overloaded) name = func->full_name; @@ -615,7 +615,8 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, static void build_function (symbol_t *fsym) { - if (fsym->type->t.func.num_params > MAX_PARMS) { + const type_t *func_type = unalias_type (fsym->type); + if (func_type->t.func.num_params > MAX_PARMS) { error (0, "too many params"); } // FIXME diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 0c08810f0..be76f06c4 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -774,7 +774,11 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) if (func->type >= qfo->spaces[qfo_type_space].data_size) return; type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); - if (type->meta != ty_basic && type->t.type != ev_func) + if (type->meta == ty_alias) { + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, + type->t.alias.aux_type); + } + if (type->meta != ty_basic || type->t.type != ev_func) return; df->numparms = num_params = type->t.func.num_params; if (num_params < 0) @@ -1228,6 +1232,10 @@ qfo_to_sym (qfo_t *qfo, int *size) aux->num_locals = num_locals; //FIXME check type type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); + if (type->meta == ty_alias) { + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, + type->t.alias.aux_type); + } aux->return_type = type->t.func.return_type; aux++; } diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index d56cd98b9..8850ebac6 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -254,6 +254,28 @@ qfo_encode_class (type_t *type) return def; } +static def_t * +qfo_encode_alias (type_t *type) +{ + qfot_type_t *enc; + def_t *def; + def_t *type_def; + def_t *full_def; + + type_def = qfo_encode_type (type->t.alias.aux_type); + full_def = qfo_encode_type (type->t.alias.full_type); + + def = qfo_new_encoding (type, sizeof (enc->t.alias)); + enc = D_POINTER (qfot_type_t, def); + enc->t.alias.type = type->type; + ENC_DEF (enc->t.alias.aux_type, type_def); + ENC_DEF (enc->t.alias.full_type, full_def); + if (type->name) { + ENC_STR (enc->t.alias.name, type->name); + } + return def; +} + def_t * qfo_encode_type (type_t *type) { @@ -266,6 +288,7 @@ qfo_encode_type (type_t *type) qfo_encode_struct, // ty_enum qfo_encode_array, // ty_array qfo_encode_class, // ty_class + qfo_encode_alias, // ty_alias }; if (type->type_def && type->type_def->external) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index bdac72d30..3529c1a1f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -456,6 +456,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, 0, current_symtab->space, spec.storage); @@ -471,6 +472,7 @@ external_decl if (spec.is_typedef) { error (0, "typedef %s is initialized", $1->name); $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, $2, current_symtab->space, spec.storage); @@ -484,6 +486,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { $1 = function_symbol ($1, spec.is_overload, 1); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0b54267b6..475a4e1aa 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -213,39 +213,53 @@ append_type (type_t *type, type_t *new) type_t **t = &type; while (*t) { - switch ((*t)->type) { - case ev_void: - case ev_string: - case ev_float: - case ev_vector: - case ev_entity: - case ev_type_count: - case ev_quat: - case ev_integer: - case ev_uinteger: - case ev_short: - case ev_double: - internal_error (0, "append to basic type"); - case ev_field: - case ev_pointer: - t = &(*t)->t.fldptr.type; - type->alignment = 1; - break; - case ev_func: - t = &(*t)->t.func.type; - type->alignment = 1; - break; - case ev_invalid: - if ((*t)->meta == ty_array) { - t = &(*t)->t.array.type; - type->alignment = new->alignment; - } else { - internal_error (0, "append to object type"); + switch ((*t)->meta) { + case ty_basic: + switch ((*t)->type) { + case ev_void: + case ev_string: + case ev_float: + case ev_vector: + case ev_entity: + case ev_type_count: + case ev_quat: + case ev_integer: + case ev_uinteger: + case ev_short: + case ev_double: + internal_error (0, "append to basic type"); + case ev_field: + case ev_pointer: + t = &(*t)->t.fldptr.type; + type->alignment = 1; + break; + case ev_func: + t = &(*t)->t.func.type; + type->alignment = 1; + break; + case ev_invalid: + internal_error (0, "invalid basic type"); + break; } break; + case ty_array: + t = &(*t)->t.array.type; + type->alignment = new->alignment; + break; + case ty_struct: + case ty_union: + case ty_enum: + case ty_class: + case ty_alias: //XXX is this correct? + internal_error (0, "append to object type"); } } - *t = new; + if (new->meta == ty_alias) { + *t = new->t.alias.aux_type; + type = alias_type (type, new, 0); + } else { + *t = new; + } return type; } @@ -298,7 +312,10 @@ types_same (type_t *a, type_t *b) return 0; return compare_protocols (a->protos, b->protos); case ty_alias: - return !strcmp (a->name, b->name); + // names have gone through save_string + return (a->name == b->name + && a->t.alias.aux_type == b->t.alias.aux_type + && a->t.alias.full_type == b->t.alias.full_type); } internal_error (0, "we be broke"); } @@ -349,7 +366,7 @@ find_type (type_t *type) case ty_class: break; case ty_alias: - type->t.alias.type = find_type (type->t.alias.type); + type->t.alias.aux_type = find_type (type->t.alias.aux_type); break; } } @@ -450,6 +467,30 @@ based_array_type (type_t *aux, int base, int top) return new; } +type_t * +alias_type (type_t *type, type_t *alias_chain, const char *name) +{ + type_t *alias = new_type (); + alias->meta = ty_alias; + alias->type = type->type; + alias->alignment = type->alignment; + alias->t.alias.aux_type = type; + alias->t.alias.full_type = alias_chain; + if (name) { + alias->name = save_string (name); + } + return alias; +} + +const type_t * +unalias_type (const type_t *type) +{ + if (type->meta == ty_alias) { + return type->t.alias.aux_type; + } + return type; +} + void print_type_str (dstring_t *str, const type_t *type) { @@ -460,7 +501,7 @@ print_type_str (dstring_t *str, const type_t *type) switch (type->meta) { case ty_alias: dasprintf (str, "({%s=", type->name); - print_type_str (str, type->t.alias.type); + print_type_str (str, type->t.alias.aux_type); dstring_appendstr (str, "})"); return; case ty_class: @@ -569,7 +610,7 @@ encode_params (const type_t *type) else count = type->t.func.num_params; for (i = 0; i < count; i++) - encode_type (encoding, type->t.func.param_types[i]); + encode_type (encoding, unalias_type (type->t.func.param_types[i])); if (type->t.func.num_params < 0) dasprintf (encoding, "."); @@ -622,7 +663,7 @@ encode_type (dstring_t *encoding, const type_t *type) switch (type->meta) { case ty_alias: // XXX do I want this, or just the unaliased type? dasprintf (encoding, "{%s>", type->name); - encode_type (encoding, type->t.alias.type); + encode_type (encoding, type->t.alias.aux_type); dasprintf (encoding, "}"); return; case ty_class: @@ -714,12 +755,14 @@ encode_type (dstring_t *encoding, const type_t *type) int is_void (const type_t *type) { + type = unalias_type (type); return type->type == ev_void; } int is_enum (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_enum) return 1; return 0; @@ -728,6 +771,7 @@ is_enum (const type_t *type) int is_integer (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_integer) @@ -738,6 +782,7 @@ is_integer (const type_t *type) int is_uinteger (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_uinteger) @@ -748,6 +793,7 @@ is_uinteger (const type_t *type) int is_short (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_short) @@ -758,6 +804,7 @@ is_short (const type_t *type) int is_integral (const type_t *type) { + type = unalias_type (type); if (is_integer (type) || is_uinteger (type) || is_short (type)) return 1; return is_enum (type); @@ -766,36 +813,42 @@ is_integral (const type_t *type) int is_double (const type_t *type) { + type = unalias_type (type); return type->type == ev_double; } int is_float (const type_t *type) { + type = unalias_type (type); return type->type == ev_float; } int is_scalar (const type_t *type) { + type = unalias_type (type); return is_float (type) || is_integral (type) || is_double (type); } int is_vector (const type_t *type) { + type = unalias_type (type); return type->type == ev_vector; } int is_quaternion (const type_t *type) { + type = unalias_type (type); return type->type == ev_quat; } int is_math (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; return t == ev_vector || t == ev_quat || is_scalar (type); @@ -804,6 +857,7 @@ is_math (const type_t *type) int is_struct (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && (type->meta == ty_struct || type->meta == ty_union)) return 1; @@ -813,6 +867,7 @@ is_struct (const type_t *type) int is_pointer (const type_t *type) { + type = unalias_type (type); if (type->type == ev_pointer) return 1; return 0; @@ -821,6 +876,7 @@ is_pointer (const type_t *type) int is_field (const type_t *type) { + type = unalias_type (type); if (type->type == ev_field) return 1; return 0; @@ -829,6 +885,7 @@ is_field (const type_t *type) int is_entity (const type_t *type) { + type = unalias_type (type); if (type->type == ev_entity) return 1; return 0; @@ -837,6 +894,7 @@ is_entity (const type_t *type) int is_array (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_array) return 1; return 0; @@ -845,6 +903,7 @@ is_array (const type_t *type) int is_func (const type_t *type) { + type = unalias_type (type); if (type->type == ev_func) return 1; return 0; @@ -853,12 +912,14 @@ is_func (const type_t *type) int is_structural (const type_t *type) { + type = unalias_type (type); return is_struct (type) || is_array (type); } int is_string (const type_t *type) { + type = unalias_type (type); if (type->type == ev_string) return 1; return 0; @@ -888,6 +949,8 @@ type_assignable (const type_t *dst, const type_t *src) { int ret; + dst = unalias_type (dst); + src = unalias_type (src); // same type if (dst == src) return 1; @@ -952,7 +1015,7 @@ type_size (const type_t *type) return size; } case ty_alias: - return type_size (type->t.alias.type); + return type_size (type->t.alias.aux_type); } return 0; }