[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.
This commit is contained in:
Bill Currie 2020-03-28 12:10:23 +09:00
parent 734f10d43e
commit 1eef2a8b5e
12 changed files with 180 additions and 64 deletions

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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 ();

View File

@ -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

View File

@ -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++;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}