X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftr%2Ftype.c;h=32880488ccf0ab1bdc0479d8db2fd243f0813be4;hb=d2dc2564b47d9c113d7e6e598574e9733627fcca;hp=6ebb8936da7fc28e131366fa0a0b54473e667611;hpb=1838facc84fbc7a6fceab043371c93e244c5c204;p=libfirm diff --git a/ir/tr/type.c b/ir/tr/type.c index 6ebb8936d..32880488c 100644 --- a/ir/tr/type.c +++ b/ir/tr/type.c @@ -17,8 +17,8 @@ * Implementation of the datastructure to hold * type information. * - * (C) 2001-2005 by Universitaet Karlsruhe - * Goetz Lindenmaier + * (C) 2001-2006 by Universitaet Karlsruhe + * Goetz Lindenmaier, Michael Beck * * This module supplies a datastructure to represent all types * known in the compiled program. This includes types specified @@ -67,6 +67,7 @@ # include "mangle.h" # include "tv_t.h" # include "irhooks.h" +# include "irtools.h" # include "array.h" @@ -78,11 +79,6 @@ ir_type *firm_none_type; ir_type *get_none_type(void) { return firm_none_t ir_type *firm_unknown_type; ir_type *get_unknown_type(void) { return firm_unknown_type; } -#ifdef DEBUG_libfirm -/* Returns a new, unique number to number nodes or the like. */ -int get_irp_new_node_nr(void); -#endif - /* Suffixes added to types used for pass-by-value representations. */ static ident *value_params_suffix = NULL; static ident *value_ress_suffix = NULL; @@ -141,13 +137,13 @@ new_type(tp_op *type_op, ir_mode *mode, ident *name, dbg_info *db) { res->mode = mode; res->name = name; res->visibility = visibility_external_allocated; - res->frame_type = 0; - res->state = layout_undefined; + res->flags = tf_none; res->size = -1; res->align = -1; res->visit = 0; res->link = NULL; res->dbi = db; + res->assoc_type = NULL; #ifdef DEBUG_libfirm res->nr = get_irp_new_node_nr(); #endif /* defined DEBUG_libfirm */ @@ -241,7 +237,7 @@ long get_type_nr(const ir_type *tp) { #ifdef DEBUG_libfirm return tp->nr; #else - return (long)tp; + return (long)PTR_TO_INT(tp); #endif } @@ -365,6 +361,7 @@ int get_type_alignment_bits(ir_type *tp) { void set_type_alignment_bits(ir_type *tp, int align) { assert(tp && tp->kind == k_type); + assert((align == -1 || (align & (align - 1)) == 0) && "type alignment not power of two"); /* Methods don't have an alignment. */ if (tp->type_op != type_method) { tp->align = align; @@ -373,7 +370,11 @@ set_type_alignment_bits(ir_type *tp, int align) { void set_type_alignment_bytes(ir_type *tp, int align) { - set_type_alignment_bits(tp, 8*align); + if (align == -1) { + set_type_alignment_bits(tp, -1); + } else { + set_type_alignment_bits(tp, 8*align); + } } /* Returns a human readable string for the enum entry. */ @@ -445,7 +446,10 @@ set_type_state(ir_type *tp, type_state state) { default: break; } /* switch (tp) */ } - tp->state = state; + if (state == layout_fixed) + tp->flags |= tf_layout_fixed; + else + tp->flags &= tf_layout_fixed; } unsigned long (get_type_visited)(const ir_type *tp) { @@ -765,6 +769,8 @@ ir_type *new_d_type_class (ident *name, dbg_info *db) { res->attr.ca.subtypes = NEW_ARR_F (ir_type *, 0); res->attr.ca.supertypes = NEW_ARR_F (ir_type *, 0); res->attr.ca.peculiarity = peculiarity_existent; + res->attr.ca.type_info = NULL; + res->attr.ca.final = 0; res->attr.ca.dfn = 0; hook_new_type(res); return res; @@ -774,11 +780,13 @@ ir_type *new_type_class (ident *name) { return new_d_type_class (name, NULL); } +/* free all entities of a class */ void free_class_entities(ir_type *clss) { int i; assert(clss && (clss->type_op == type_class)); for (i = get_class_n_members(clss) - 1; i >= 0; --i) free_entity(get_class_member(clss, i)); + /* do NOT free the type info here. It belongs to another class */ } void free_class_attrs(ir_type *clss) { @@ -799,10 +807,10 @@ int (get_class_n_members) (const ir_type *clss) { return _get_class_n_members(clss); } -int get_class_member_index(ir_type *clss, entity *mem) { - int i; +int get_class_member_index(const ir_type *clss, entity *mem) { + int i, n; assert(clss && (clss->type_op == type_class)); - for (i = 0; i < get_class_n_members(clss); i++) + for (i = 0, n = get_class_n_members(clss); i < n; ++i) if (get_class_member(clss, i) == mem) return i; return -1; @@ -939,6 +947,12 @@ void remove_class_supertype(ir_type *clss, ir_type *supertype) { break; } } +entity *get_class_type_info(const ir_type *clss) { + return clss->attr.ca.type_info; +} +void set_class_type_info(ir_type *clss, entity *ent) { + clss->attr.ca.type_info = ent; +} const char *get_peculiarity_string(peculiarity p) { #define X(a) case a: return #a @@ -962,13 +976,19 @@ void set_class_peculiarity (ir_type *clss, peculiarity pec) { clss->attr.ca.peculiarity = pec; } -void set_class_dfn (ir_type *clss, int dfn) -{ - clss->attr.ca.dfn = dfn; +int (is_class_final)(const ir_type *clss) { + return _is_class_final(clss); } -int get_class_dfn (const ir_type *clss) -{ +void (set_class_final)(ir_type *clss, int final) { + _set_class_final(clss, final); +} + +void set_class_dfn (ir_type *clss, int dfn) { + clss->attr.ca.dfn = dfn; +} + +int get_class_dfn (const ir_type *clss) { return (clss->attr.ca.dfn); } @@ -1038,10 +1058,10 @@ entity *get_struct_member (const ir_type *strct, int pos) { return strct->attr.sa.members[pos]; } -int get_struct_member_index(ir_type *strct, entity *mem) { - int i; +int get_struct_member_index(const ir_type *strct, entity *mem) { + int i, n; assert(strct && (strct->type_op == type_struct)); - for (i = 0; i < get_struct_n_members(strct); i++) + for (i = 0, n = get_struct_n_members(strct); i < n; ++i) if (get_struct_member(strct, i) == mem) return i; return -1; @@ -1118,7 +1138,7 @@ ir_type *new_d_type_method(ident *name, int n_param, int n_res, dbg_info *db) { assert((get_mode_size_bytes(mode_P_code) != -1) && "unorthodox modes not implemented"); res = new_type(type_method, mode_P_code, name, db); - res->state = layout_fixed; + res->flags |= tf_layout_fixed; res->size = get_mode_size_bits(mode_P_code); res->attr.ma.n_params = n_param; res->attr.ma.param_type = xcalloc(n_param, sizeof(res->attr.ma.param_type[0])); @@ -1128,6 +1148,7 @@ ir_type *new_d_type_method(ident *name, int n_param, int n_res, dbg_info *db) { res->attr.ma.value_ress = NULL; res->attr.ma.variadicity = variadicity_non_variadic; res->attr.ma.first_variadic_param = -1; + res->attr.ma.additional_properties = mtp_no_property; res->attr.ma.irg_calling_conv = default_cc_mask; hook_new_type(res); return res; @@ -1379,7 +1400,7 @@ ir_type *new_d_type_union(ident *name, dbg_info *db) { return res; } -type *new_type_union(ident *name) { +ir_type *new_type_union(ident *name) { return new_d_type_union(name, NULL); } @@ -1410,6 +1431,14 @@ entity *get_union_member (const ir_type *uni, int pos) { assert(pos >= 0 && pos < get_union_n_members(uni)); return uni->attr.ua.members[pos]; } +int get_union_member_index(const ir_type *uni, entity *mem) { + int i, n; + assert(uni && (uni->type_op == type_union)); + for (i = 0, n = get_union_n_members(uni); i < n; ++i) + if (get_union_member(uni, i) == mem) + return i; + return -1; +} void set_union_member (ir_type *uni, int pos, entity *member) { assert(uni && (uni->type_op == type_union)); assert(pos >= 0 && pos < get_union_n_members(uni)); @@ -1490,6 +1519,7 @@ void free_array_attrs (ir_type *array) { assert(array && (array->type_op == type_array)); free(array->attr.aa.lower_bound); free(array->attr.aa.upper_bound); + free(array->attr.aa.order); } /* manipulate private fields of array ir_type */ @@ -1713,7 +1743,7 @@ ir_type *new_d_type_pointer(ident *name, ir_type *points_to, ir_mode *ptr_mode, res->attr.pa.points_to = points_to; assert((get_mode_size_bytes(res->mode) != -1) && "unorthodox modes not implemented"); res->size = get_mode_size_bits(res->mode); - res->state = layout_fixed; + res->flags |= tf_layout_fixed; hook_new_type(res); return res; } @@ -1759,8 +1789,8 @@ void set_pointer_mode(ir_type *tp, ir_mode *mode) { * Not efficient: O(#types). * If not found returns firm_unknown_type. */ ir_type *find_pointer_type_to_type (ir_type *tp) { - int i; - for (i = 0; i < get_irp_n_types(); ++i) { + int i, n = get_irp_n_types(); + for (i = 0; i < n; ++i) { ir_type *found = get_irp_type(i); if (is_Pointer_type(found) && get_pointer_points_to_type(found) == tp) return (found); @@ -1779,7 +1809,7 @@ ir_type *new_d_type_primitive(ident *name, ir_mode *mode, dbg_info *db) { /* @@@ assert( mode_is_data(mode) && (!mode_is_reference(mode))); */ res = new_type(type_primitive, mode, name, db); res->size = get_mode_size_bits(mode); - res->state = layout_fixed; + res->flags |= tf_layout_fixed; hook_new_type(res); return res; } @@ -1844,6 +1874,20 @@ entity *get_compound_member(const ir_type *tp, int pos) return res; } +/* Returns index of member in tp, -1 if not contained. */ +int get_compound_member_index(const ir_type *tp, entity *member) +{ + const tp_op *op = get_type_tpop(tp); + int index = -1; + + if (op->ops.get_member_index) + index = op->ops.get_member_index(tp, member); + else + assert(0 && "no members in this type"); + + return index; +} + int is_compound_type(const ir_type *tp) { assert(tp && tp->kind == k_type); return tp->type_op->flags & TP_OP_FLAG_COMPOUND; @@ -1851,7 +1895,12 @@ int is_compound_type(const ir_type *tp) { /* Checks, whether a type is a frame ir_type */ int is_frame_type(const ir_type *tp) { - return tp->frame_type; + return tp->flags & tf_frame_type; +} + +/* Checks, whether a type is a lowered ir_type */ +int is_lowered_type(const ir_type *tp) { + return tp->flags & tf_lowered_type; } /* Makes a new frame type. */ @@ -1859,7 +1908,7 @@ ir_type *new_type_frame(ident *name) { ir_type *res = new_type_class(name); - res->frame_type = 1; + res->flags |= tf_frame_type; /* Remove type from type list. Must be treated differently than other types. */ remove_irp_type(res); @@ -1867,7 +1916,80 @@ ir_type *new_type_frame(ident *name) return res; } +/* Sets a lowered type for a type. This sets both associations. */ +void set_lowered_type(ir_type *tp, ir_type *lowered_type) { + assert(is_type(tp) && is_type(lowered_type)); + lowered_type->flags |= tf_lowered_type; + tp->assoc_type = lowered_type; + lowered_type->assoc_type = tp; +} + +/* + * Gets the lowered/unlowered type of a type or NULL if this type + * has no lowered/unlowered one. + */ +ir_type *get_associated_type(const ir_type *tp) { + return tp->assoc_type; +} + /* set the type size for the unknown and none ir_type */ void set_default_size_bits(ir_type *tp, int size) { tp->size = size; } + +/* + * Allocate an area of size bytes aligned at alignment + * at the start or the end of a frame type. + * The frame type must have already an fixed layout. + */ +entity *frame_alloc_area(type *frame_type, int size, int alignment, int at_start) +{ + entity *area; + ir_type *tp; + ident *name; + char buf[32]; + int frame_align, i, offset, frame_size; + static unsigned area_cnt = 0; + static ir_type *a_byte = NULL; + + assert(is_frame_type(frame_type)); + assert(get_type_state(frame_type) == layout_fixed); + + if (! a_byte) + a_byte = new_type_primitive(new_id_from_chars("byte", 4), mode_Bu); + + snprintf(buf, sizeof(buf), "area%u", area_cnt++); + name = new_id_from_str(buf); + + /* align the size */ + frame_align = get_type_alignment_bytes(frame_type); + size = (size + frame_align - 1) & -frame_align; + + tp = new_type_array(mangle_u(get_type_ident(frame_type), name), 1, a_byte); + set_array_bounds_int(tp, 0, 0, size); + set_type_alignment_bytes(tp, alignment); + + frame_size = get_type_size_bytes(frame_type); + if (at_start) { + /* fix all offsets so far */ + for (i = get_class_n_members(frame_type) - 1; i >= 0; --i) { + entity *ent = get_class_member(frame_type, i); + + set_entity_offset_bytes(ent, get_entity_offset_bytes(ent) + size); + } + /* calculate offset and new type size */ + offset = 0; + frame_size += size; + } + else { + /* calculate offset and new type size */ + offset = (frame_size + alignment - 1) & -alignment; + frame_size = offset + size; + } + + area = new_entity(frame_type, name, tp); + set_entity_offset_bytes(area, offset); + set_type_size_bytes(frame_type, frame_size); + + return area; +}