mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-11 20:03:11 +00:00
[qfcc] Support (partially) attributes on types
For now, it's just recording that type type has attributes (encoding begins with %) and resurrecting types_same which is used only when matching with types with attributes, so there's still a fair bit of work to do.
This commit is contained in:
parent
5e605aee36
commit
03c47f8af7
2 changed files with 94 additions and 12 deletions
|
@ -91,6 +91,7 @@ typedef struct type_s {
|
|||
struct multivector_s *multivec;
|
||||
ty_alias_t alias;
|
||||
};
|
||||
attribute_t *attributes;
|
||||
struct type_s *next;
|
||||
int freeable;
|
||||
int allocated;
|
||||
|
|
|
@ -572,6 +572,73 @@ default_type (specifier_t spec, const symbol_t *sym)
|
|||
return spec;
|
||||
}
|
||||
|
||||
static __attribute__((pure)) bool
|
||||
types_same (const type_t *a, const type_t *b)
|
||||
{
|
||||
int i, count;
|
||||
|
||||
if (a->type != b->type || a->meta != b->meta)
|
||||
return false;
|
||||
switch (a->meta) {
|
||||
case ty_basic:
|
||||
switch (a->type) {
|
||||
case ev_field:
|
||||
case ev_ptr:
|
||||
if (a->fldptr.type != b->fldptr.type)
|
||||
return false;
|
||||
case ev_func:
|
||||
if (a->func.ret_type != b->func.ret_type
|
||||
|| a->func.num_params != b->func.num_params
|
||||
|| a->func.attribute_bits != b->func.attribute_bits)
|
||||
return false;
|
||||
count = a->func.num_params;
|
||||
if (count < 0)
|
||||
count = ~count; // param count is one's complement
|
||||
for (i = 0; i < count; i++)
|
||||
if (a->func.param_types[i]
|
||||
!= b->func.param_types[i])
|
||||
return false;
|
||||
return 1;
|
||||
default: // other types don't have aux data
|
||||
return a->width == b->width && a->columns == b->columns;
|
||||
}
|
||||
break;
|
||||
case ty_struct:
|
||||
case ty_union:
|
||||
case ty_enum:
|
||||
if (strcmp (a->name, b->name))
|
||||
return false;
|
||||
if (a->meta == ty_struct)
|
||||
return compare_protocols (a->protos, b->protos);
|
||||
return 1;
|
||||
case ty_array:
|
||||
if (a->array.type != b->array.type
|
||||
|| a->array.base != b->array.base
|
||||
|| a->array.count != b->array.count)
|
||||
return false;
|
||||
return 1;
|
||||
case ty_class:
|
||||
if (a->class != b->class)
|
||||
return false;
|
||||
return compare_protocols (a->protos, b->protos);
|
||||
case ty_alias:
|
||||
// names have gone through save_string
|
||||
return (a->name == b->name
|
||||
&& a->alias.aux_type == b->alias.aux_type
|
||||
&& a->alias.full_type == b->alias.full_type);
|
||||
case ty_handle:
|
||||
// names have gone through save_string
|
||||
return a->name == b->name;
|
||||
case ty_algebra:
|
||||
return a->algebra == b->algebra;
|
||||
case ty_bool:
|
||||
return a->type == b->type;
|
||||
case ty_meta_count:
|
||||
break;
|
||||
}
|
||||
internal_error (nullptr, "we be broke");
|
||||
}
|
||||
|
||||
/*
|
||||
find_type
|
||||
|
||||
|
@ -581,7 +648,6 @@ default_type (specifier_t spec, const symbol_t *sym)
|
|||
const type_t *
|
||||
find_type (const type_t *type)
|
||||
{
|
||||
type_t *check;
|
||||
int i, count;
|
||||
|
||||
if (!type || type == &type_auto)
|
||||
|
@ -636,35 +702,47 @@ find_type (const type_t *type)
|
|||
}
|
||||
}
|
||||
|
||||
check = Hash_Find (type_tab, type->encoding);
|
||||
const type_t *check;
|
||||
if (strchr (type->encoding, '%')) {
|
||||
// type chain has attributes so the encoding may be aliased
|
||||
auto list = (const type_t **) Hash_FindList (type_tab, type->encoding);
|
||||
for (auto c = list; (check = *c); c++) {
|
||||
if (types_same (check, type)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free (list);
|
||||
} else {
|
||||
check = Hash_Find (type_tab, type->encoding);
|
||||
}
|
||||
if (check) {
|
||||
return check;
|
||||
}
|
||||
|
||||
// allocate a new one
|
||||
check = new_type ();
|
||||
*check = *type;
|
||||
auto new = new_type ();
|
||||
*new = *type;
|
||||
if (is_func (type)) {
|
||||
check->func.param_types = 0;
|
||||
new->func.param_types = 0;
|
||||
const type_t *t = unalias_type (type);
|
||||
int num_params = t->func.num_params;
|
||||
if (num_params < 0) {
|
||||
num_params = ~num_params;
|
||||
}
|
||||
if (num_params) {
|
||||
check->func.param_types = malloc (sizeof (type_t *) * num_params);
|
||||
check->func.param_quals = malloc (sizeof (param_qual_t)*num_params);
|
||||
new->func.param_types = malloc (sizeof (type_t *) * num_params);
|
||||
new->func.param_quals = malloc (sizeof (param_qual_t)*num_params);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
check->func.param_types[i] = t->func.param_types[i];
|
||||
check->func.param_quals[i] = t->func.param_quals[i];
|
||||
new->func.param_types[i] = t->func.param_types[i];
|
||||
new->func.param_quals[i] = t->func.param_quals[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
check->freeable = false;
|
||||
new->freeable = false;
|
||||
|
||||
chain_type (check);
|
||||
chain_type (new);
|
||||
|
||||
return check;
|
||||
return new;
|
||||
}
|
||||
|
||||
const type_t *
|
||||
|
@ -1202,6 +1280,9 @@ encode_type (dstring_t *encoding, const type_t *type)
|
|||
{
|
||||
if (!type)
|
||||
return;
|
||||
if (type->attributes && is_func (type) && type->func.attribute_bits) {
|
||||
dstring_appendstr (encoding, "%");
|
||||
}
|
||||
switch (type->meta) {
|
||||
case ty_meta_count:
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue