/* ** Most of the semantic routines are found here. */ #include #include #include "ansi.h" #include "host.h" #include "files.h" #include "hash.h" #include "il.h" #include "type_util.h" #include "nodeop.h" #include "stab.h" #include "allocate.h" #include "gen.h" #include "ada_name.h" #ifndef CCPROTO #include "anonymous.h" #endif #include "config.h" /* Import from scanner */ extern file_pos_t yypos; extern int auto_package; #undef NULL #define NULL 0L #undef N_BUILTINS #define N_BUILTINS 5 static symbol_t builtins[N_BUILTINS]; static typeinfo_t builtin_types[N_BUILTINS]; static void dump_type _ANSI_PROTO_((typeinfo_t*)); static void dump_pos _ANSI_PROTO_((void)); void not_implemented(file, line) char *file; int line; { fatal(file_name(yypos), line_number(yypos), "This has not yet been implemented [%s:%d]", file, line); } /* * These are the builtin/intrinsic types */ void type_init() { int i; symbol_t *sym; typeinfo_t *typ; /* int must be 0 */ sym = &builtins[0]; sym->gened = 1; sym->intrinsic = 1; sym->sym_type = &builtin_types[0]; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, "int"); #ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_SIGNED_INT; #endif sym->sym_type->type_kind = int_type; sym->sym_type->_sizeof = SIZEOF_INT; sym->sym_type->_alignof = ALIGNOF_INT; sym->sym_type->type_base = sym; /*store_sym(sym);*/ /* void must be 1 */ sym = &builtins[1]; sym->gened = 1; sym->intrinsic = 1; sym->sym_type = &builtin_types[1]; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, "void"); #ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_VOID; #endif sym->sym_type->type_kind = void_type; sym->sym_type->_sizeof = SIZEOF_INT; sym->sym_type->_alignof = ALIGNOF_INT; sym->sym_type->type_base = sym; /*store_sym(sym);*/ /* char must be 2 */ sym = &builtins[2]; sym->gened = 1; sym->intrinsic = 1; sym->sym_type = &builtin_types[2]; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, "char"); sym->sym_type->type_kind = int_type; sym->sym_type->_sizeof = SIZEOF_CHAR; sym->sym_type->_alignof = ALIGNOF_CHAR; sym->sym_type->type_base = sym; #ifdef CHARS_ARE_UNSIGNED # ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_UNSIGNED_CHAR; # endif sym->sym_type->_unsigned = 1; #else sym->sym_type->_signed = 1; # ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_SIGNED_CHAR; # endif #endif /*store_sym(sym);*/ /* float must be 3 */ sym = &builtins[3]; sym->intrinsic = 1; sym->gened = 1; sym->sym_type = &builtin_types[3]; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, "float"); #ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_FLOAT; #endif sym->sym_type->type_kind = float_type; sym->sym_type->_sizeof = SIZEOF_FLOAT; sym->sym_type->_alignof = ALIGNOF_FLOAT; sym->sym_type->type_base = sym; /*store_sym(sym);*/ /* double must be 4 */ sym = &builtins[4]; sym->intrinsic = 1; sym->gened = 1; sym->sym_type = &builtin_types[4]; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, "double"); #ifndef CCPROTO sym->sym_ada_name = TYPE_NAMEOF_DOUBLE; #endif sym->sym_type->type_kind = float_type; sym->sym_type->_sizeof = SIZEOF_DOUBLE; sym->sym_type->_alignof = ALIGNOF_DOUBLE; sym->sym_type->type_base = sym; /*store_sym(sym);*/ for (i = 0; i < N_BUILTINS; i++) { typ = &builtin_types[i]; typ->_builtin = 1; set_hash_for_type(&builtin_types[i]); } #ifndef CCPROTO init_anonymous_types(); #endif } symbol_t* copy_sym(sym) symbol_t *sym; { symbol_t *d; d = new_sym(); d->sym_type = copy_type(sym->sym_type); return d; } typeinfo_t* typeof_int(is_unsigned) { typeinfo_t *typ; typ = copy_type(&builtin_types[0]); if (is_unsigned) typ->_unsigned = 1; return typ; } static symbol_t* int_basetype() { return &builtins[0]; } typeinfo_t* typeof_void() { return copy_type(&builtin_types[1]); } typeinfo_t* typeof_char() { return copy_type(&builtin_types[2]); } typeinfo_t* typeof_float() { return copy_type(&builtin_types[3]); } typeinfo_t* typeof_double() { return copy_type(&builtin_types[4]); } static typeinfo_t* typeof_enum() { typeinfo_t *typ; typ = new_type(enum_type); typ->_sizeof = SIZEOF_ENUM; /* See host.h */ typ->_alignof = ALIGNOF_ENUM; set_hash_for_type(typ); return typ; } static typeinfo_t* typeof_rec(is_union) int is_union; { return new_type(is_union ? union_of : struct_of); } decl_class_t decl_class(typ) typeinfo_t *typ; { if (typ == NULL) { return int_decl; } switch (typ->type_kind) { case field_type: return field_decl; case pointer_to: return pointer_decl; case array_of: return array_decl; case struct_of: case union_of: return struct_decl; case int_type: return int_decl; case float_type: return fp_decl; case void_type: return int_decl; case function_type: return func_decl; case enum_type: return enum_decl; default: fatal(__FILE__,__LINE__,"Unexpected type kind %d", typ->type_kind); return int_decl; } } static symbol_t* sym_decl(typ, n, uniq) typeinfo_t *typ; node_t *n; int uniq; /* symbol name must be uniq */ { symbol_t *sym; assert(typ != NULL); assert(n != NULL); assert(n->node_kind == _Ident); assert(n->node.id.name != NULL); sym = new_sym(); sym->sym_def = n->node_def; sym->sym_ident = n; #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, uniq ? FILE_ORD(sym->sym_def) : -1); #endif sym->sym_type = copy_type(typ); return sym; } symbol_t* concat_symbols(s1,s2) symbol_t *s1, *s2; { symbol_t *s; if (s1 == NULL) return s2; if (s2 == NULL) return s1; for (s = s1; s->sym_parse_list; s = s->sym_parse_list); s->sym_parse_list = s2; return s1; } #ifndef CCPROTO /* * OK. The following looks really crappy. Since C lets you * generate array types and pointer types without any formal * declaration, we'll need to traverse all types seen in the * C source and generate similar Ada types. For example, if * foo(int*) is seen we'll need to generate type a_int_t is * access c.signed_int automatically. OK wise guy, do you * have a better idea? */ static void gen_tag_types _ANSI_PROTO_((symbol_t*)); static void all_types_gened(typ) typeinfo_t *typ; { symbol_t *basetype; if (typ) { all_types_gened(typ->type_next); if (! typ->_builtin) { switch (typ->type_kind) { case pointer_to: case array_of: case struct_of: case union_of: case enum_type: break; case field_type: case void_type: case int_type: case float_type: case function_type: return; case typemodifier: default: assert(0); } basetype = typ->type_base; if (basetype == NULL) { basetype = get_anonymous_type(typ); assert(basetype != NULL); } if (! basetype->gened) { basetype->gened = 1; gen_tag_types(basetype->sym_tags); gen_ada_type(basetype); } } } } static void gen_tag_types(tags) symbol_t *tags; { for (; tags; tags = tags->sym_parse_list) { all_types_gened(tags->sym_type); } } #endif static typeinfo_t* grok_array_type(typ, elem) typeinfo_t *typ; node_t *elem; { host_int_t nelem = -1; typeinfo_t *array_type; unsigned long bsize; assert(typ != NULL); if (elem != NULL) { reduce_node(elem); if (elem->node_kind == _Int_Number) { nelem = elem->node.ival; if (nelem < 0) { warning(NODE_FNAME(elem), NODE_FLINE(elem), "Array length %d is not supported (see %s:%d)", nelem, __FILE__, __LINE__); nelem = -1; } free_node(elem); } else { nelem = -1; /* * Hell! Probably reduce_node() in nodeop.c isn't * doing the right thing. Or it could be in cpp_eval */ warning(NODE_FNAME(elem), NODE_FLINE(elem), "Failed reducing array index to a constant integer value (see %s:%d)", __FILE__, __LINE__); } } array_type = add_array_type(typ, nelem); all_types_gened(array_type); return array_type; #if 0 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; #endif } typeinfo_t* typeof_typemod(adj) int adj; { typeinfo_t *typ; typ = new_type(typemodifier); switch (adj) { case TYPEMOD_SHORT: typ->_short = 1; break; case TYPEMOD_LONG: typ->_long = 1; break; case TYPEMOD_SIGNED: typ->_signed = 1; typ->_unsigned = 0; break; case TYPEMOD_UNSIGNED: typ->_unsigned = 1; typ->_signed = 0; break; case TYPEMOD_CONST: typ->_constant = 1; break; case TYPEMOD_VOLATILE: typ->_volatile = 1; break; case TYPEMOD_TYPEDEF: typ->_typedef = 1; break; case TYPEMOD_EXTERN: typ->_extern = 1; break; case TYPEMOD_STATIC: typ->_static = 1; break; case TYPEMOD_AUTO: typ->_auto = 1; break; case TYPEMOD_REGISTER: typ->_register = 1; break; default: assert(0); break; } return typ; } static void combine_typespec(tmod) typeinfo_t *tmod; { typeinfo_t *typ; assert(tmod != NULL); assert(tmod->type_kind == typemodifier); assert(tmod->type_next != NULL); typ = tmod->type_next; if (typ->_volatile) tmod->_volatile = 1; if (typ->_constant) tmod->_constant = 1; if (typ->_extern) tmod->_extern = 1; if (typ->_static) tmod->_static = 1; if (typ->_auto) tmod->_auto = 1; if (typ->_register) tmod->_register = 1; if (typ->_typedef) tmod->_typedef = 1; if (tmod->_signed) { tmod->_unsigned = 0; } else if (tmod->_unsigned) { tmod->_signed = 0; } else if (typ->_unsigned) { tmod->_unsigned = 1; tmod->_signed = 0; } else if (typ->_signed) { tmod->_unsigned = 0; tmod->_signed = 1; } if (tmod->_short == 0) { if (typ->_short) tmod->_short = 1; if (typ->_long_long)tmod->_long_long = 1; if (typ->_long) { if (tmod->_long) { tmod->_long_long = 1; } else { tmod->_long = 1; } } } tmod->type_kind = typ->type_kind; tmod->type_info = typ->type_info; tmod->_sizeof = typ->_sizeof; tmod->_alignof = typ->_alignof; tmod->type_base = typ->type_base; tmod->type_next = typ->type_next; set_hash_for_type(tmod); deallocate(typ); } typeinfo_t* typeof_typespec(tlist) typeinfo_t *tlist; { typeinfo_t *prev = NULL; typeinfo_t *result = tlist; top: assert(tlist != NULL); switch (tlist->type_kind) { case typemodifier: if (tlist->type_next == NULL) { /* * If type is not specified it's assumed to be an int. * ie. short foo; == short int foo; */ result = tlist; result->type_kind = int_type; result->type_base = int_basetype(); if (result->_short) { result->_sizeof = SIZEOF_SHORT; result->_alignof = ALIGNOF_SHORT; } #ifdef SIZEOF_LONG_LONG else if (result->_long_long) { result->_sizeof = SIZEOF_LONG_LONG; result->_alignof = ALIGNOF_LONG_LONG; result->_short = 0; result->_long = 0; set_hash_for_type(result); } #endif else if (result->_long) { result->_sizeof = SIZEOF_LONG; result->_alignof = ALIGNOF_LONG; } else { result->_sizeof = SIZEOF_INT; result->_alignof = ALIGNOF_INT; } set_hash_for_type(result); } else { combine_typespec(tlist); goto top; } break; case void_type: case int_type: case float_type: case struct_of: case union_of: case enum_type: assert(tlist->type_next == NULL); break; case array_of: case pointer_to: case function_type: break; default: assert(0); break; } return result; } typeinfo_t* typeof_specifier(sym) symbol_t *sym; { typeinfo_t *typ; assert(sym != NULL); assert(sym->sym_type != NULL); typ = copy_type(sym->sym_type); typ->type_base = sym; return typ; } static symbol_t* KnR_formals(params) node_t *params; { symbol_t *p1, *p2; if (params == NULL) return NULL; switch (params->node_kind) { case _List: p1 = KnR_formals(params->node.binary.l); p2 = KnR_formals(params->node.binary.r); free_node(params); p1 = concat_symbols(p1, p2); break; case _Ident: p1 = sym_decl(typeof_int(0), params, 0); break; default: assert(0); break; } return p1; } static symbol_t* grok_formals(params) node_t *params; { symbol_t *p; if (params == NULL) return NULL; if (params->node_kind == _Sym) { /* Ansi function decl */ p = params->node.sym; free_node(params); return p; } return KnR_formals(params); } static void grok_subp(subp) symbol_t *subp; { symbol_t *param, *prev; prev = NULL; param = subp->sym_tags; for (; param && param->sym_parse_list; param = param->sym_parse_list) { prev = param; } if (param != NULL && param->var_params) { subp->var_params = 1; if (prev) { prev->sym_parse_list = NULL; } else { subp->sym_tags = NULL; } } } static typeinfo_t* add_field(typ, width) typeinfo_t *typ; node_t *width; { typeinfo_t *ftype; assert(typ != NULL); assert(width != NULL); reduce_node(width); if (width->node_kind != _Int_Number || width->node.ival < 1 || width->node.ival > 31) { warning(NODE_FNAME(width), NODE_FLINE(width), "Bit filed width not handled properly (see %s:%d)", __FILE__, __LINE__); return typ; } ftype = new_type(field_type); ftype->type_next = typ; ftype->_sizeof = width->node.ival; free_node(width); set_hash_for_type(ftype); return ftype; } static symbol_t* grok_decl_list(tspec, vlist, uniq) typeinfo_t *tspec; node_t *vlist; int uniq; /* Generate uniq Ada idenifer name */ { symbol_t *d1, *d2; assert(tspec != NULL); assert(vlist != NULL); switch (vlist->node_kind) { case _List: d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq); d2 = grok_decl_list(tspec, vlist->node.binary.r, uniq); free_node(vlist); return concat_symbols(d1, d2); case _Ident: assert(vlist->node.id.name != NULL); d1 = sym_decl(tspec, vlist, uniq); return d1; case _Assign: d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq); d1->sym_value.initializer = vlist->node.binary.r; d1->has_initializer = 1; free_node(vlist); return d1; case _Bit_Field: tspec = add_field(tspec, vlist->node.binary.r); if (vlist->node.binary.l == NULL) { d1 = new_sym(); d1->sym_type = copy_type(tspec); } else { d1 = grok_decl_list(tspec, vlist->node.binary.l, 0); } free_node(vlist); return d1; case _Array_Index: if (vlist->node.binary.l == NULL) { d1 = new_sym(); d1->sym_type = tspec; } else { d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq); } d1->sym_type = grok_array_type(d1->sym_type, vlist->node.binary.r); return d1; case _Indirect: tspec = add_pointer_type(tspec); if (vlist->node.unary == NULL) { d1 = new_sym(); d1->sym_type = tspec; return d1; } return grok_decl_list(tspec, vlist->node.unary, uniq); case _Func_Call: tspec = add_function_type(tspec); d1 = grok_decl_list(tspec, vlist->node.binary.l, uniq); if (d1->sym_tags == NULL) { d1->sym_tags = grok_formals(vlist->node.binary.r); grok_subp(d1); } tspec->type_info.subp_params = d1->sym_tags; return d1; default: fatal(file_name(yypos), line_number(yypos), "Unhandled node kind %d [%s:%d]", vlist->node_kind, __FILE__, __LINE__); break; } return NULL; } static void check_type_base(sym) symbol_t *sym; { typeinfo_t *typ; assert(sym != NULL); typ = sym->sym_type; assert(typ != NULL); switch (decl_class(typ)) { case pointer_decl: case array_decl: typ->type_base = sym; break; default: assert(typ->type_base != NULL); break; } } static symbol_t* set_symbol_kind(vlist) symbol_t *vlist; { symbol_t *s; typeinfo_t *typ; assert(vlist != NULL); for (s = vlist; s; s = s->sym_parse_list) { typ = s->sym_type; if (typ->_typedef) { s->sym_kind = type_symbol; if (is_array(typ)) { typ->type_base = s; } } else if (typ->type_kind == function_type) { s->sym_kind = func_symbol; } else { s->sym_kind = var_symbol; } } return vlist; } static void dump_pos() { fprintf(stderr, "%s:%d\n", file_name(yypos), line_number(yypos)); fflush(stderr); } /* * Useful routine for debugging if your debugger lets * you invoke it directly. If using verdix debugger * you can say: p debug_type(typ) * buy vads :-) */ static void dump_type(typ) typeinfo_t *typ; { symbol_t *basetype; for (; typ; typ = typ->type_next) { if (typ->_static) fputs("static/", stderr); if (typ->_typedef) fputs("typedef/", stderr); if (typ->_short) fputs("short/", stderr); if (typ->_long) fputs("long/", stderr); if (typ->_long_long) fputs("long_long/", stderr); if (typ->_signed) fputs("signed/", stderr); if (typ->_unsigned) fputs("unsigned/", stderr); switch (typ->type_kind) { case pointer_to: fputs("pointer_to", stderr); break; case array_of: fputs("array_of", stderr); break; case struct_of: fputs("struct_of", stderr); break; case union_of: fputs("union_of", stderr); break; case field_type: fputs("field_type", stderr); break; case int_type: fputs("int_type", stderr); break; case float_type: fputs("float_type", stderr); break; case void_type: fputs("void_type", stderr); break; case function_type: fputs("function_type", stderr); break; case enum_type: fputs("enum_type", stderr); break; case typemodifier: fputs("typemodifier", stderr); break; default: fputs("default", stderr); break; } fputc('[',stderr); basetype = typ->type_base; if (basetype != NULL) { assert(basetype->sym_ident != NULL); assert(basetype->sym_ident->node_kind == _Ident); assert(basetype->sym_ident->node.id.name != NULL); fputs(basetype->sym_ident->node.id.name, stderr); } fputs("] ",stderr); } fputc('\n',stderr); } static int decl_defined(sym) symbol_t *sym; { symbol_t *dup; assert(sym->sym_ident != NULL); assert(sym->sym_ident->node_kind == _Ident); assert(sym->sym_ident->node.id.name != NULL); dup = find_sym(sym->sym_ident->node.id.name); if (dup == NULL) { store_sym(sym); return 0; } if (sym->sym_kind != dup->sym_kind) { return 0; } return equal_types(sym->sym_type, dup->sym_type); } static void find_units(); static void get_basetype_unit_list(ord, sym) symbol_t *sym; { symbol_t *tags; for (tags = sym->sym_tags; tags; tags = tags->sym_parse_list) { find_units(ord, tags->sym_type); } if (sym->sym_type->type_base != sym) { find_units(ord, sym->sym_type); } } static void find_units(ord, typ) int ord; typeinfo_t *typ; { #ifndef CCPROTO typeinfo_t *t; symbol_t *basetype; int unit_ord; for (t = typ; t; t = t->type_next) { if (! t->_builtin) { basetype = t->type_base; if (basetype != NULL && !basetype->intrinsic && basetype->traversal_unit != ord) { basetype->traversal_unit = ord; get_basetype_unit_list(ord, basetype); unit_ord = FILE_ORD(basetype->sym_def); if (unit_ord != ord) { unit_dependency(ord, unit_ord); } } } } #endif } /* * Determine which Ada package need to be with'd * for the types of this symbol */ static void get_unit_list(sym) symbol_t *sym; { symbol_t *tags; int unit_ord; if (!auto_package) return; for (tags = sym->sym_tags; tags; tags = tags->sym_parse_list) { unit_ord = FILE_ORD(tags->sym_def); find_units(unit_ord, tags->sym_type); } unit_ord = FILE_ORD(sym->sym_def); find_units(unit_ord, sym->sym_type); } static void grok_decl(sym) symbol_t *sym; { typeinfo_t *typ, *ntyp; assert(sym != NULL); typ = sym->sym_type; assert(typ != NULL); assert(sym->sym_parse_list == NULL); if (typ->_typedef) { if (typ->type_kind == union_of || typ->type_kind == struct_of) { assert(typ->type_base != NULL); if (typ->type_base != sym) { sym->sym_tags = typ->type_base->sym_tags; } } else if (is_access(typ)) { ntyp = typ->type_next; assert(ntyp != NULL); all_types_gened(ntyp); typ->type_base = sym; } } #ifndef CCPROTO all_types_gened(typ); gen_tag_types(sym->sym_tags); get_unit_list(sym); #endif switch (sym->sym_kind) { case type_symbol: store_sym(sym); if (! sym->gened) { sym->gened = 1; gen_ada_type(sym); } break; case func_symbol: #ifndef CCPROTO if (! is_static_function(typ)) { #endif if (! decl_defined(sym)) { if (! sym->gened) { sym->gened = 1; gen_ada_func(sym); } } #ifndef CCPROTO } #endif break; case var_symbol: if (! typ->_static) { if (! decl_defined(sym)) { if (! sym->gened) { sym->gened = 1; gen_ada_var(sym); } } } break; case enum_literal: default: fatal(__FILE__,__LINE__,"Unhandled symbol kind %d", sym->sym_kind); break; } } void grok_declarations(list) symbol_t *list; { symbol_t *next; for (; list; list = next) { next = list->sym_parse_list; list->sym_parse_list = NULL; grok_decl(list); } } static void grok_enum_lits(tags, typ) symbol_t *tags; typeinfo_t *typ; { symbol_t *sym; int ord = 0; for (sym = tags; sym; sym = sym->sym_parse_list) { assert(sym->sym_type == NULL); sym->sym_type = typ; if (sym->sym_value.intval == 0xBAD) { sym->sym_value.intval = ord++; } else { ord = sym->sym_value.intval + 1; } } } static symbol_t* gen_enum_sym(id) node_t *id; { symbol_t *sym; char enum_name[2048]; assert(id != NULL); assert(id->node_kind == _Ident); enum_name[0] = ENUM_PREFIX; strcpy(&enum_name[1], id->node.id.name); id->node.id.name = new_string(enum_name); sym = new_sym(); sym->sym_type = typeof_enum(); sym->sym_kind = type_symbol; sym->sym_ident = id; #ifndef CCPROTO sym->sym_ada_name = ada_name(enum_name, FILE_ORD(sym->sym_def)); #endif sym->sym_def = id->node_def; return sym; } static void add_tags(decls, tags) symbol_t *decls, *tags; { symbol_t *sym; for (sym = decls; sym; sym = sym->sym_parse_list) { assert(sym->sym_tags == NULL); sym->sym_tags = tags; } } static void grok_sizeof_struct(styp, fields) typeinfo_t *styp; symbol_t *fields; { symbol_t *sym; typeinfo_t *typ, *ftype; int min = 0; int aggsize = 0; int bitsize = 0; int width, tmp; for (sym = fields; sym; sym = sym->sym_parse_list) { typ = sym->sym_type; assert(typ != NULL); if (typ->type_kind == field_type) { width = typ->_sizeof; ftype = typ->type_next; assert(ftype != NULL); if (ftype->_sizeof > min) { min = ftype->_sizeof; } align_field: tmp = alignto(aggsize, ftype->_alignof); if (tmp != aggsize) { aggsize = tmp; bitsize = 0; } tmp = bitsize + width; if (tmp > ftype->_sizeof * BITS_PER_BYTE) { aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE; bitsize = 0; goto align_field; } sym->bitoffset = aggsize * BITS_PER_BYTE + bitsize; typ->_alignof = bitsize; bitsize += width; } else { if (bitsize != 0) { aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE; bitsize = 0; } aggsize = alignto(aggsize, typ->_alignof); sym->bitoffset = aggsize * BITS_PER_BYTE; aggsize += typ->_sizeof; } } if (bitsize != 0) { aggsize += (bitsize + BITS_PER_BYTE - 1) / BITS_PER_BYTE; } if (aggsize < min) { aggsize = min; } styp->_sizeof = aggsize; set_hash_for_type(styp); } static void grok_sizeof_union(utyp, fields) typeinfo_t *utyp; symbol_t *fields; { symbol_t *sym; typeinfo_t *typ; int aggsize = 0; for (sym = fields; sym; sym = sym->sym_parse_list) { typ = sym->sym_type; assert(typ != NULL); assert(typ->type_kind != field_type); if (typ->_sizeof > aggsize) { aggsize = typ->_sizeof; } } utyp->_sizeof = aggsize; set_hash_for_type(utyp); } static void grok_alignof_record(rtyp, fields) typeinfo_t *rtyp; symbol_t *fields; { symbol_t *sym; typeinfo_t *typ; int max = 0; for (sym = fields; sym; sym = sym->sym_parse_list) { typ = sym->sym_type; assert(typ != NULL); if (typ->type_kind == field_type) { typ = typ->type_next; assert(typ != NULL); } if (typ->_alignof > max) { max = typ->_alignof; } } rtyp->_alignof = max; set_hash_for_type(rtyp); } static void grok_type(typ) typeinfo_t *typ; { if (typ == NULL) return; switch (decl_class(typ)) { case pointer_decl: typ->_sizeof = SIZEOF_ADDRESS; typ->_alignof = ALIGNOF_ADDRESS; if (is_function_pointer(typ)) { grok_type(typ->type_next->type_next); } else { grok_type(typ->type_next); } set_hash_for_type(typ); break; case int_decl: #ifdef SIZEOF_LONG_LONG if (typ->_long_long) { typ->_sizeof = SIZEOF_LONG_LONG; typ->_alignof = ALIGNOF_LONG_LONG; typ->_short = 0; typ->_long = 0; set_hash_for_type(typ); return; } #endif if (typ->_long) { typ->_sizeof = SIZEOF_LONG; typ->_alignof = ALIGNOF_LONG; typ->_short = 0; typ->_long_long = 0; set_hash_for_type(typ); return; } if (typ->_short) { typ->_sizeof = SIZEOF_SHORT; typ->_alignof = ALIGNOF_SHORT; typ->_long_long = 0; set_hash_for_type(typ); return; } break; case fp_decl: #ifdef SIZEOF_LONG_DOUBLE if (typ->_long) { if (typ->_sizeof == SIZEOF_DOUBLE&&typ->_alignof == ALIGNOF_DOUBLE){ typ->_sizeof = SIZEOF_LONG_DOUBLE; typ->_alignof = ALIGNOF_LONG_DOUBLE; set_hash_for_type(typ); return; } } #endif break; case func_decl: assert(0); break; case enum_decl: typ->_sizeof = SIZEOF_INT; typ->_alignof = ALIGNOF_INT; set_hash_for_type(typ); break; case array_decl: case struct_decl: set_hash_for_type(typ); break; default: assert(0); break; } } static symbol_t* gen_rec_sym(id, typ) node_t *id; typeinfo_t *typ; { symbol_t *sym; char rec_name[2048]; assert(id != NULL); assert(id->node_kind == _Ident); rec_name[0] = (typ->type_kind == struct_of) ? STRUCT_PREFIX : UNION_PREFIX; strcpy(&rec_name[1], id->node.id.name); id->node.id.name = new_string(rec_name); sym = new_sym(); sym->sym_type = typ; sym->sym_kind = type_symbol; sym->sym_ident = id; #ifndef CCPROTO sym->sym_ada_name = ada_name(rec_name, FILE_ORD(sym->sym_def)); #endif sym->sym_def = id->node_def; typ->type_base = sym; return sym; } symbol_t* grok_enumerator(id, val) node_t *id, *val; { symbol_t *sym; assert(id != NULL); assert(id->node_kind == _Ident); assert(id->node.id.name != NULL); sym = new_sym(); sym->sym_ident = id; #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def)); #endif if (val == NULL) { sym->sym_value.intval = 0xBAD; } else { reduce_node(val); if (val->node_kind == _Int_Number) { sym->sym_value.intval = val->node.ival; } else { warning(NODE_FNAME(val), NODE_FLINE(val), "Enum literal value ignored"); sym->sym_value.intval = 0xBAD; } } store_sym(sym); return sym; } static char* gen_type_name(prefix) int prefix; { char name[256]; #ifdef CCPROTO name[0] = prefix; name[1] = 0; #else sprintf(name, "%c%s%d%s", prefix, OTHER_TYPE_PREFIX, next_anonymous_ord(), TYPE_POSTFIX); #endif return new_string(name); } static char* add_prefix(name, prefix, buf, len) char *name, *buf; int prefix, len; { char *result; int nlen; assert(name != NULL); nlen = strlen(name) + 2; if (buf == NULL || nlen > len) { result = (char*) malloc(strlen(name)+2); } else { result = buf; } assert(result != NULL); result[0] = prefix; strcpy(&result[1], name); return result; } symbol_t* anonymous_enum(literals) symbol_t *literals; { symbol_t *sym; assert(literals != NULL); sym = new_sym(); sym->sym_type = typeof_enum(); sym->sym_type->type_base = sym; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, gen_type_name(ENUM_PREFIX)); #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def)); #endif sym->_created_name = 1; grok_enum_lits(literals, sym->sym_type); add_tags(sym, literals); return sym; } symbol_t* named_enum(id, literals) node_t *id; symbol_t *literals; { symbol_t *sym; char buf[1024]; assert(id != NULL); assert(literals != NULL); assert(id->node_kind == _Ident); buf[0] = ENUM_PREFIX; strcpy(&buf[1], id->node.id.name); sym = find_sym(buf); if (sym == NULL) { sym = new_sym(); sym->sym_type = typeof_enum(); sym->sym_type->type_base = sym; sym->sym_ident = new_node(_Ident, new_string(buf)); #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def)); #endif sym->sym_kind = type_symbol; store_sym(sym); } else { sym->_created_by_reference = 0; } sym->sym_def = id->node_def; grok_enum_lits(literals, sym->sym_type); add_tags(sym, literals); return sym; } symbol_t* enum_reference(id) node_t *id; { char buf[256]; char *name; symbol_t *sym; assert(id != NULL); assert(id->node_kind == _Ident); name = add_prefix(id->node.id.name, ENUM_PREFIX, buf, sizeof(buf)); sym = find_sym(name); if (sym == NULL || !is_typedef(sym)) { sym = new_sym(); sym->sym_type = typeof_enum(); sym->sym_type->type_base = sym; sym->sym_kind = type_symbol; if (name != buf) { id->node.id.name = name; } else { id->node.id.name = new_string(name); } sym->sym_ident = id; #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def)); #endif sym->_created_by_reference = 1; store_sym(sym); } else { if (name != buf) { free(name); } } return sym; } static char* anonymous_rec_name(is_union) int is_union; { return gen_type_name(is_union ? UNION_PREFIX : STRUCT_PREFIX); } static symbol_t* delete_unamed_fields(tags) symbol_t *tags; { symbol_t *head = NULL; symbol_t *last = NULL; if (tags == NULL) return NULL; for (; tags; tags = tags->sym_parse_list) { if (tags->sym_ident == NULL) { if (head != NULL) { last->sym_parse_list = tags->sym_parse_list; } } else { if (head == NULL) { head = tags; } else { last->sym_parse_list = tags; } last = tags; } } return head; } symbol_t* anonymous_rec(is_union, tags) int is_union; symbol_t *tags; { symbol_t *sym; typeinfo_t *rtyp; assert(tags != NULL); rtyp = typeof_rec(is_union); sym = new_sym(); sym->sym_type = rtyp; sym->sym_kind = type_symbol; sym->sym_ident = new_node(_Ident, anonymous_rec_name(is_union)); #ifndef CCPROTO sym->sym_ada_name = ada_name(sym->sym_ident->node.id.name, FILE_ORD(sym->sym_def)); #endif sym->sym_tags = tags; rtyp->type_base = sym; if (is_union) { grok_sizeof_union(rtyp, tags); } else { grok_sizeof_struct(rtyp, tags); tags = delete_unamed_fields(tags); sym->sym_tags = tags; } grok_alignof_record(rtyp, tags); return sym; } symbol_t* named_rec(is_union, id, tags) int is_union; node_t *id; symbol_t *tags; { symbol_t *sym; typeinfo_t *rtyp; char buf[1024]; assert(id != NULL); assert(id->node_kind == _Ident); assert(tags != NULL); buf[0] = is_union ? UNION_PREFIX : STRUCT_PREFIX; strcpy(&buf[1], id->node.id.name); sym = find_sym(buf); if (sym == NULL) { rtyp = typeof_rec(is_union); sym = gen_rec_sym(id, rtyp); store_sym(sym); } else { sym->_created_by_reference = 0; rtyp = sym->sym_type; } sym->sym_tags = tags; if (is_union) { grok_sizeof_union(rtyp, tags); } else { grok_sizeof_struct(rtyp, tags); tags = delete_unamed_fields(tags); sym->sym_tags = tags; } grok_alignof_record(rtyp, tags); return sym; } symbol_t* rec_reference(is_union, id) int is_union; node_t *id; { symbol_t *sym; typeinfo_t *rtyp; char buf[1024]; assert(id != NULL); assert(id->node_kind == _Ident); buf[0] = is_union ? UNION_PREFIX : STRUCT_PREFIX; strcpy(&buf[1], id->node.id.name); sym = find_sym(buf); if (sym == NULL) { rtyp = typeof_rec(is_union); sym = gen_rec_sym(id, rtyp); sym->_created_by_reference = 1; store_sym(sym); } return sym; } static int no_typemods(typ) typeinfo_t *typ; { for (; typ; typ = typ->type_next) { if (typ->type_kind == typemodifier) { return 0; } } return 1; } symbol_t* novar_declaration(tlist) typeinfo_t *tlist; { symbol_t *result = NULL; assert(tlist != NULL); tlist = typeof_typespec(tlist); assert(no_typemods(tlist)); switch (decl_class(tlist)) { case int_decl: return NULL; case enum_decl: case struct_decl: assert(tlist->type_base != NULL); return tlist->type_base; case pointer_decl: case fp_decl: case func_decl: case array_decl: break; default: assert(0); break; } assert(0); return result; } symbol_t* var_declaration(tlist, vlist) typeinfo_t *tlist; node_t *vlist; { symbol_t *decl_list; assert(tlist != NULL); assert(vlist != NULL); tlist = typeof_typespec(tlist); assert(no_typemods(tlist)); grok_type(tlist); decl_list = grok_decl_list(tlist, vlist, 1); return set_symbol_kind(decl_list); } symbol_t* function_spec(tlist, f) typeinfo_t *tlist; node_t *f; { symbol_t *fdecl; assert(f != NULL); if (tlist == NULL) { tlist = typeof_int(0); } else { tlist = typeof_typespec(tlist); } assert(no_typemods(tlist)); grok_type(tlist); fdecl = grok_decl_list(tlist, f, 1); assert(fdecl != NULL); fdecl->sym_kind = func_symbol; return fdecl; } static void set_field_names(tags) symbol_t *tags; { #ifndef CCPROTO for (; tags; tags = tags->sym_parse_list) { if (tags->sym_ada_name == NULL) { if (tags->sym_ident != NULL) { tags->sym_ada_name = ada_name(tags->sym_ident->node.id.name, FILE_ORD(tags->sym_def)); } } } #endif } symbol_t* field_declaration(tlist, vlist) typeinfo_t *tlist; node_t *vlist; { symbol_t *decl_list; assert(tlist != NULL); assert(vlist != NULL); tlist = typeof_typespec(tlist); assert(no_typemods(tlist)); grok_type(tlist); decl_list = grok_decl_list(tlist, vlist, 0); set_field_names(decl_list); #ifndef CCPROTO gen_tag_types(decl_list); #endif return set_symbol_kind(decl_list); } void typed_external_decl(syms) symbol_t *syms; { symbol_t *next; for (; syms; syms = next) { next = syms->sym_parse_list; syms->sym_parse_list = NULL; grok_decl(syms); } } static char* next_param_name() { char buf[48]; sprintf(buf, "p%d", next_param()); return new_string(buf); } symbol_t* noname_simple_param(typ) typeinfo_t *typ; { symbol_t *sym; char *name; assert(typ != NULL); name = next_param_name(); typ = typeof_typespec(typ); assert(no_typemods(typ)); grok_type(typ); sym = new_sym(); sym->sym_ident = new_node(_Ident, name); #ifndef CCPROTO sym->sym_ada_name = name; #endif sym->sym_type = typ; sym->sym_kind = param_symbol; return sym; } symbol_t* noname_abstract_param(typ, adecl) typeinfo_t *typ; node_t *adecl; { symbol_t *sym; char *name; assert(typ != NULL); assert(adecl != NULL); name = next_param_name(); typ = typeof_typespec(typ); assert(no_typemods(typ)); grok_type(typ); sym = grok_decl_list(typ, adecl, 0); sym->sym_ident = new_node(_Ident,name); #ifndef CCPROTO sym->sym_ada_name = name; #endif sym->sym_kind = param_symbol; return sym; } symbol_t* named_abstract_param(typ, adecl) typeinfo_t *typ; node_t *adecl; { symbol_t *sym; assert(typ != NULL); assert(adecl != NULL); next_param(); typ = typeof_typespec(typ); assert(no_typemods(typ)); grok_type(typ); sym = grok_decl_list(typ, adecl, 0); sym->sym_kind = param_symbol; return sym; } typeinfo_t* noname_type(typ, adecl) typeinfo_t *typ; node_t *adecl; { symbol_t *sym; assert(typ != NULL); assert(adecl != NULL); typ = typeof_typespec(typ); assert(no_typemods(typ)); grok_type(typ); sym = grok_decl_list(typ, adecl, 0); return sym->sym_type; } static void KnR_tag_type(p, params) symbol_t *p, *params; { for (; params; params = params->sym_parse_list) { if (!strcmp(p->sym_ident->node.id.name, params->sym_ident->node.id.name)) { p->sym_type = params->sym_type; return; } } } void KnR_params(func, params) symbol_t *func, *params; { symbol_t *tags; assert(func != NULL); assert(params != NULL); for (tags = func->sym_tags; tags; tags = tags->sym_parse_list) { KnR_tag_type(tags, params); } } void function_def(f) symbol_t *f; { symbol_t *dup; assert(f != NULL); #ifndef CCPROTO if (is_static_function(f->sym_type)) { return; } #endif assert(f->sym_ident != NULL); assert(f->sym_ident->node_kind == _Ident); assert(f->sym_ident->node.id.name != NULL); dup = find_sym(f->sym_ident->node.id.name); if (dup == NULL) { grok_decl(f); return; } if (dup->sym_tags == NULL && f->sym_tags != NULL) { /* Must be K&R crap */ dup->sym_tags = f->sym_tags; #ifndef CCPROTO gen_tag_types(dup->sym_tags); #endif } } symbol_t* elipsis_arg() { static symbol_t varg; varg.var_params = 1; return &varg; }