X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftr%2Ftype.c;h=32880488ccf0ab1bdc0479d8db2fd243f0813be4;hb=d2dc2564b47d9c113d7e6e598574e9733627fcca;hp=26ddf7cf3cdcb9b27a421b8a40892d0e5f9dc020;hpb=134ecab995321db5c61c0fbf71c9b6916f911a9b;p=libfirm diff --git a/ir/tr/type.c b/ir/tr/type.c index 26ddf7cf3..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) { @@ -1134,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])); @@ -1144,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; @@ -1514,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 */ @@ -1737,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; } @@ -1783,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); @@ -1803,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; } @@ -1889,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. */ @@ -1897,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); @@ -1905,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; +}