#include #include "ansi.h" #include "config.h" #include "host.h" #include "files.h" #include "hash.h" #include "il.h" #include "type_util.h" #undef NULL #define NULL 0 int is_typedef(sym) symbol_t *sym; { return sym->sym_kind == type_symbol; } int is_enum_literal(sym) symbol_t *sym; { return sym->sym_kind == enum_literal; } int is_array(typ) typeinfo_t *typ; { assert(typ != NULL); return typ->type_kind == array_of; } int is_access(typ) typeinfo_t *typ; { assert(typ != NULL); return typ->type_kind == pointer_to; } int is_aggregate(typ) typeinfo_t *typ; { assert(typ != NULL); switch (typ->type_kind) { case array_of: case struct_of: case union_of: return 1; } return 0; } int is_access_to_record(typ) typeinfo_t *typ; { assert(typ != NULL); if (is_access(typ)) { typ = typ->type_next; assert(typ != NULL); switch (typ->type_kind) { case struct_of: case union_of: return 1; } } return 0; } int is_static_function(typ) typeinfo_t *typ; { top: assert(typ != NULL); if (typ->_static) { return 1; } switch (typ->type_kind) { case function_type: case pointer_to: typ = typ->type_next; goto top; } return 0; } int is_function_pointer(typ) typeinfo_t *typ; { assert(typ != NULL); if (typ->type_kind == pointer_to) { assert(typ->type_next != NULL); return typ->type_next->type_kind == function_type; } return 0; } int alignto(val, align) int val, align; { if (align <= 2) { return val; } align--; return (val + align) & ~align; } /* * Type allocator. */ typeinfo_t* new_type(kind) typekind_t kind; { typeinfo_t *typ; typ = (typeinfo_t*) allocate(sizeof(typeinfo_t)); typ->type_kind = kind; set_hash_for_type(typ); return typ; } typeinfo_t* copy_type(typ) typeinfo_t *typ; { typeinfo_t *t; if (typ == NULL) { return NULL; } t = (typeinfo_t*) allocate(sizeof(typeinfo_t)); *t = *typ; t->type_next = copy_type(typ->type_next); return t; } typeinfo_t* concat_types(t1,t2) typeinfo_t *t1, *t2; { typeinfo_t* t; if (t1 == NULL) return t2; if (t2 == NULL) return t1; for (t = t1; t->type_next; t = t->type_next); t->type_next = t2; return t1; } int type_alignof(typ) typeinfo_t *typ; { assert(typ != NULL); return typ->_alignof; } int type_sizeof(typ) typeinfo_t *typ; { assert(typ != NULL); return typ->_sizeof; } typeinfo_t* set_signed_type(typ) typeinfo_t *typ; { typ->_unsigned = 0; typ->_signed = 1; set_hash_for_type(typ); return typ; } typeinfo_t* set_unsigned_type(typ) typeinfo_t *typ; { typ->_unsigned = 1; typ->_signed = 0; set_hash_for_type(typ); return typ; } typeinfo_t* add_pointer_type(typ) typeinfo_t *typ; { typeinfo_t *ptr_type; assert(typ != NULL); ptr_type = new_type(pointer_to); ptr_type->type_next = typ; ptr_type->_typedef = typ->_typedef; ptr_type->_sizeof = SIZEOF_ADDRESS; ptr_type->_alignof = ALIGNOF_ADDRESS; set_hash_for_type(ptr_type); return ptr_type; } typeinfo_t* add_function_type(typ) typeinfo_t *typ; { typeinfo_t *ftype; assert(typ != NULL); ftype = new_type(function_type); ftype->type_next = typ; ftype->_typedef = typ->_typedef; set_hash_for_type(ftype); return ftype; } typeinfo_t* add_array_type(typ, nelem) typeinfo_t *typ; host_int_t nelem; { typeinfo_t *array_type; unsigned long bsize; array_type = new_type(array_of); array_type->type_info.array_elements = nelem; array_type->type_next = typ; array_type->_typedef = typ->_typedef; switch (nelem) { case -1: array_type->_sizeof = SIZEOF_ADDRESS; array_type->_alignof = ALIGNOF_ADDRESS; break; case 0: array_type->_sizeof = 0; array_type->_alignof = 0; break; default: array_type->_alignof = type_alignof(typ); bsize = alignto(type_sizeof(typ), array_type->_alignof); array_type->_sizeof = bsize * nelem; break; } set_hash_for_type(array_type); return array_type; } /* * All types get hashed to make type comparisons faster and * to maintain the anonymous type tables. Anonymous types * must be generated for things like: extern int foo[]; * The integer array type must be defined for Ada. */ unsigned int set_hash_for_type(typ) typeinfo_t *typ; { unsigned int hash = 0; assert(typ != NULL); hash += 7 * typ->type_kind; if (typ->type_kind != array_of) { hash += typ->_sizeof; } hash += typ->_alignof; if (typ->_unsigned) hash += 3; if (typ->_signed) hash += 5; if (typ->type_next != NULL) { hash += set_hash_for_type(typ->type_next); } typ->type_hash = hash; return hash; } /* * Tags can be function parameters, fields of * unions and structs, or enumeration literals. */ static int equal_tags(t1, t2) typeinfo_t *t1, *t2; { symbol_t *bt1, *bt2; symbol_t *tags1, *tags2; if (t1 == t2) return 1; bt1 = t1->type_base; bt2 = t2->type_base; if (bt1 == bt2) return 1; if (bt1 == NULL || bt2 == NULL) return 0; return bt1->sym_tags == bt2->sym_tags; } /* * Type comparison routine. */ int equal_types(t1, t2) typeinfo_t *t1, *t2; { if (t1 == t2) return 1; for (; t1 && t2; t1 = t1->type_next, t2 = t2->type_next) { if (t1->type_hash != t2->type_hash) return 0; if (t1->type_kind != t2->type_kind) return 0; if (t1->_unsigned != t2->_unsigned) return 0; if (t1->_signed != t2->_signed) return 0; if (t1->type_base != NULL && t2->type_base != NULL) { if (t1->type_base != t2->type_base) return 0; } if (t1->type_kind != array_of) { if (t1->_sizeof != t2->_sizeof) return 0; } if (t1->_alignof != t2->_alignof) return 0; switch (t1->type_kind) { case array_of: #if 0 if (t1->type_info.array_elements != t2->type_info.array_elements) { return 0; } #endif break; case struct_of: case union_of: if (! equal_tags(t1, t2)) { return 0; } default: break; } } return (t1 == NULL && t2 == NULL); }