#include <sys/types.h>
#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);
}
syntax highlighted by Code2HTML, v. 0.9.1