X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Ftr%2Ftype.c;h=10640e56198571f3634b2e6d5358719db6c2ed07;hb=760356ab155a0d884324c867a1f9a78a79c0b5a3;hp=3088528659320d664c84bef918b8e9660c634562;hpb=677f67f9b487e35b983148f48b933d54ee383db6;p=libfirm diff --git a/ir/tr/type.c b/ir/tr/type.c index 308852865..10640e561 100644 --- a/ir/tr/type.c +++ b/ir/tr/type.c @@ -1,14 +1,10 @@ -/****h* libfirm/type.c +/** * - * NAME * file type.c - implementation of the datastructure to hold * type information. - * COPYRIGHT * (C) 2001 by Universitaet Karlsruhe - * AUTHORS * Martin Trapp, Christian Schaefer, Goetz Lindenmaier * - * NOTES * This module supplies a datastructure to represent all types * known in the compiled program. This includes types specified * in the program as well as types defined by the language. In the @@ -24,18 +20,21 @@ * on the level of the programming language, modes at the level of * the target processor. * - * SEE ALSO - * type_t.h type tpop - ***** + * @see type_t.h type tpop */ /* $Id$ */ +#ifdef HAVE_CONFIG_H +# include +#endif + # include # include # include # include "type_t.h" # include "tpop_t.h" +# include "irprog_t.h" # include "typegmod_t.h" # include "array.h" # include "irprog.h" @@ -47,6 +46,20 @@ /** 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; + +void init_type(void) { + value_params_suffix = id_from_str(VALUE_PARAMS_SUFFIX, strlen(VALUE_PARAMS_SUFFIX)); + value_ress_suffix = id_from_str(VALUE_RESS_SUFFIX, strlen(VALUE_RESS_SUFFIX)); +} + unsigned long type_visited; INLINE void set_master_type_visited(unsigned long val) { type_visited = val; } INLINE unsigned long get_master_type_visited() { return type_visited; } @@ -70,6 +83,7 @@ new_type(tp_op *type_op, ir_mode *mode, ident* name) { int node_size ; assert(type_op != type_id); + assert(!id_contains_char(name, ' ') && "type name should not contain spaces"); node_size = offsetof (type, attr) + type_op->attr_size; res = (type *) xmalloc (node_size); @@ -83,6 +97,9 @@ new_type(tp_op *type_op, ir_mode *mode, ident* name) { res->size = -1; res->visit = 0; res -> link = NULL; +#ifdef DEBUG_libfirm + res->nr = get_irp_new_node_nr(); +#endif return res; } @@ -149,7 +166,8 @@ void set_type_mode(type *tp, ir_mode* m) { if ((tp->type_op == type_primitive) || (tp->type_op == type_enumeration)) { /* For pointer, primitive and enumeration size depends on the mode. */ - tp->size = get_mode_size(m); + assert((get_mode_size_bytes(m) != -1) && "unorthodox modes not implemented"); + tp->size = get_mode_size_bytes(m); tp->mode = m; } } @@ -164,6 +182,17 @@ void set_type_ident(type *tp, ident* id) { tp->name = id; } +/* Outputs a unique number for this node */ +INLINE long +get_type_nr(type *tp) { + assert(tp); +#ifdef DEBUG_libfirm + return tp->nr; +#else + return 0; +#endif +} + const char* get_type_name(type *tp) { assert(tp && tp->kind == k_type); return (id_to_str(tp->name)); @@ -194,7 +223,7 @@ void set_type_state(type *tp, type_state state) { assert(tp && tp->kind == k_type); - if ((tp->type_op == type_pointer) && (tp->type_op == type_primitive) && + if ((tp->type_op == type_pointer) || (tp->type_op == type_primitive) || (tp->type_op == type_method)) return; @@ -207,15 +236,16 @@ set_type_state(type *tp, type_state state) { assert(get_type_size(tp) > -1); if (tp != get_glob_type()) for (i = 0; i < get_class_n_members(tp); i++) { + if (get_entity_offset(get_class_member(tp, i)) <= -1) + { DDMT(tp); DDME(get_class_member(tp, i)); } assert(get_entity_offset(get_class_member(tp, i)) > -1); assert(is_method_type(get_entity_type(get_class_member(tp, i))) || (get_entity_allocation(get_class_member(tp, i)) == automatic_allocated)); - /* @@@ lowerfirm geht nicht durch */ } } break; case tpo_struct: { - /* assert(get_type_size(tp) > -1); @@@ lowerfirm geht nicht durch */ + assert(get_type_size(tp) > -1); for (i = 0; i < get_struct_n_members(tp); i++) { assert(get_entity_offset(get_struct_member(tp, i)) > -1); assert((get_entity_allocation(get_struct_member(tp, i)) == automatic_allocated)); @@ -256,6 +286,16 @@ void mark_type_visited(type *tp) { assert(tp->visit < type_visited); tp->visit = type_visited; } +/* @@@ name clash with master flag +bool type_visited(type *tp) { + assert(tp && tp->kind == k_type); + return tp->visit >= type_visited; + }*/ +bool type_not_visited(type *tp) { + assert(tp && tp->kind == k_type); + return tp->visit < type_visited; +} + int is_type (void *thing) { assert(thing); @@ -274,7 +314,7 @@ bool equal_type(type *typ1, type *typ2) { if (typ1 == typ2) return true; if ((get_type_tpop_code(typ1) != get_type_tpop_code(typ2)) || - (get_type_name(typ1) != get_type_name(typ2)) || + (get_type_ident(typ1) != get_type_ident(typ2)) || (get_type_mode(typ1) != get_type_mode(typ2)) || (get_type_state(typ1) != get_type_state(typ2))) return false; @@ -313,7 +353,7 @@ bool equal_type(type *typ1, type *typ2) { type *t1 = get_class_supertype(typ1, i); for (j = 0; j < get_class_n_supertypes(typ2); j++) { type *t2 = get_class_supertype(typ2, j); - if (get_type_name(t2) == get_type_name(t1)) + if (get_type_ident(t2) == get_type_ident(t1)) t[i] = t2; } } @@ -343,6 +383,7 @@ bool equal_type(type *typ1, type *typ2) { } } break; case tpo_method: { + if (get_method_variadicity(typ1) != get_method_variadicity(typ2)) return false; if (get_method_n_params(typ1) != get_method_n_params(typ2)) return false; if (get_method_n_ress(typ1) != get_method_n_ress(typ2)) return false; for (i = 0; i < get_method_n_params(typ1); i++) { @@ -374,7 +415,6 @@ bool equal_type(type *typ1, type *typ2) { } } break; case tpo_array: { - type *set, *let; /* small/large elt. type */ if (get_array_n_dimensions(typ1) != get_array_n_dimensions(typ2)) return false; if (!equal_type(get_array_element_type(typ1), get_array_element_type(typ2))) @@ -435,6 +475,7 @@ bool smaller_type (type *st, type *lt) { } } break; case tpo_method: { + if (get_method_variadicity(st) != get_method_variadicity(lt)) return false; if (get_method_n_params(st) != get_method_n_params(lt)) return false; if (get_method_n_ress(st) != get_method_n_ress(lt)) return false; for (i = 0; i < get_method_n_params(st); i++) { @@ -549,6 +590,14 @@ int get_class_n_members (type *clss) { assert(clss && (clss->type_op == type_class)); return (ARR_LEN (clss->attr.ca.members))-1; } +int get_class_member_index(type *clss, entity *mem) { + int i; + assert(clss && (clss->type_op == type_class)); + for (i = 0; i < get_class_n_members(clss); i++) + if (get_class_member(clss, i) == mem) + return i; + return -1; +} entity *get_class_member (type *clss, int pos) { assert(clss && (clss->type_op == type_class)); assert(pos >= 0 && pos < get_class_n_members(clss)); @@ -633,6 +682,15 @@ int get_class_n_supertypes (type *clss) { assert(clss && (clss->type_op == type_class)); return (ARR_LEN (clss->attr.ca.supertypes))-1; } +int get_class_supertype_index(type *clss, type *super_clss) { + int i; + assert(clss && (clss->type_op == type_class)); + assert(super_clss && (super_clss->type_op == type_class)); + for (i = 0; i < get_class_n_supertypes(clss); i++) + if (get_class_supertype(clss, i) == super_clss) + return i; + return -1; +} type *get_class_supertype (type *clss, int pos) { assert(clss && (clss->type_op == type_class)); assert(pos >= 0 && pos < get_class_n_supertypes(clss)); @@ -760,29 +818,52 @@ bool is_struct_type(type *strct) { /** TYPE_METHOD **/ /*******************************************************************/ +/* Lazy construction of value argument / result representation. */ +static INLINE type * +build_value_type(ident *name, int len, type **tps) { + int i; + type *res = new_type_struct(name); + /* Remove type from type list. Must be treated differently than other types. */ + remove_irp_type_from_list(res); + for (i = 0; i < len; i++) { + type *elt_type = res; /* use res as default if corresponding type is not yet set. */ + if (tps[i]) elt_type = tps[i]; + new_entity(res, mangle_u(name, get_type_ident(elt_type)), elt_type); + } + return res; +} + /* Create a new method type. N_param is the number of parameters, n_res the number of results. */ INLINE type *new_type_method (ident *name, int n_param, int n_res) { type *res; - res = new_type(type_method, mode_p, name); + res = new_type(type_method, mode_P_mach, name); res->state = layout_fixed; - res->size = get_mode_size(mode_p); - res->attr.ma.n_params = n_param; - res->attr.ma.param_type = (type **) xmalloc (sizeof (type *) * n_param); - res->attr.ma.n_res = n_res; - res->attr.ma.res_type = (type **) xmalloc (sizeof (type *) * n_res); + assert((get_mode_size_bytes(mode_P_mach) != -1) && "unorthodox modes not implemented"); + res->size = get_mode_size_bytes(mode_P_mach); + res->attr.ma.n_params = n_param; + res->attr.ma.param_type = (type **) xmalloc (sizeof (type *) * n_param); + res->attr.ma.value_params = NULL; + res->attr.ma.n_res = n_res; + res->attr.ma.res_type = (type **) xmalloc (sizeof (type *) * n_res); + res->attr.ma.value_ress = NULL; + res->attr.ma.variadicity = non_variadic; + return res; } + type *new_d_type_method (ident *name, int n_param, int n_res, dbg_info* db) { type *res = new_type_method (name, n_param, n_res); set_type_dbg_info(res, db); return res; } + INLINE void free_method_attrs(type *method) { assert(method && (method->type_op == type_method)); free(method->attr.ma.param_type); free(method->attr.ma.res_type); } + /* manipulate private fields of method. */ int get_method_n_params (type *method) { assert(method && (method->type_op == type_method)); @@ -797,6 +878,24 @@ void set_method_param_type(type *method, int pos, type* tp) { assert(method && (method->type_op == type_method)); assert(pos >= 0 && pos < get_method_n_params(method)); method->attr.ma.param_type[pos] = tp; + /* If information constructed set pass-by-value representation. */ + if (method->attr.ma.value_params) { + assert(get_method_n_params(method) == get_struct_n_members(method->attr.ma.value_params)); + set_entity_type(get_struct_member(method->attr.ma.value_params, pos), tp); + } +} +/* Returns an entity that represents the copied value argument. Only necessary + for compounds passed by value. */ +entity *get_method_value_param_ent(type *method, int pos) { + assert(method && (method->type_op == type_method)); + assert(pos >= 0 && pos < get_method_n_params(method)); + if (!method->attr.ma.value_params) + method->attr.ma.value_params + = build_value_type(mangle_u(get_type_ident(method), value_params_suffix), + get_method_n_params(method), method->attr.ma.param_type); + assert((get_entity_type(get_struct_member(method->attr.ma.value_params, pos)) != method->attr.ma.value_params) + && "param type not yet set"); + return get_struct_member(method->attr.ma.value_params, pos); } int get_method_n_ress (type *method) { @@ -811,7 +910,38 @@ type *get_method_res_type(type *method, int pos) { void set_method_res_type(type *method, int pos, type* tp) { assert(method && (method->type_op == type_method)); assert(pos >= 0 && pos < get_method_n_ress(method)); + /* set the result type */ method->attr.ma.res_type[pos] = tp; + /* If information constructed set pass-by-value representation. */ + if (method->attr.ma.value_ress) { + assert(get_method_n_ress(method) == get_struct_n_members(method->attr.ma.value_ress)); + set_entity_type(get_struct_member(method->attr.ma.value_ress, pos), tp); + } +} +/* Returns an entity that represents the copied value result. Only necessary + for compounds passed by value. */ +entity *get_method_value_res_ent(type *method, int pos) { + assert(method && (method->type_op == type_method)); + assert(pos >= 0 && pos < get_method_n_ress(method)); + if (!method->attr.ma.value_ress) + method->attr.ma.value_ress + = build_value_type(mangle_u(get_type_ident(method), value_ress_suffix), + get_method_n_ress(method), method->attr.ma.res_type); + assert((get_entity_type(get_struct_member(method->attr.ma.value_ress, pos)) != method->attr.ma.value_ress) + && "result type not yet set"); + return get_struct_member(method->attr.ma.value_ress, pos); +} + +variadicity get_method_variadicity(type *method) +{ + assert(method && (method->type_op == type_method)); + return method->attr.ma.variadicity; +} + +void set_method_variadicity(type *method, variadicity vari) +{ + assert(method && (method->type_op == type_method)); + method->attr.ma.variadicity = vari; } /* typecheck */ @@ -819,7 +949,6 @@ bool is_method_type (type *method) { assert(method); if (method->type_op == type_method) return 1; else return 0; } -/*****/ /*******************************************************************/ /** TYPE_UNION **/ @@ -921,20 +1050,26 @@ INLINE type *new_type_array (ident *name, int n_dimensions, type *element_type) { type *res; int i; + ir_graph *rem = current_ir_graph; assert(!is_method_type(element_type)); + res = new_type(type_array, NULL, name); res->attr.aa.n_dimensions = n_dimensions; res->attr.aa.lower_bound = (ir_node **) xmalloc (sizeof (ir_node *) * n_dimensions); res->attr.aa.upper_bound = (ir_node **) xmalloc (sizeof (ir_node *) * n_dimensions); res->attr.aa.order = (int *) xmalloc (sizeof (int) * n_dimensions); + current_ir_graph = get_const_code_irg(); for (i = 0; i < n_dimensions; i++) { - res->attr.aa.lower_bound[i] = NULL; - res->attr.aa.upper_bound[i] = NULL; + res->attr.aa.lower_bound[i] = new_Unknown(); + res->attr.aa.upper_bound[i] = new_Unknown(); res->attr.aa.order[i] = i; } + current_ir_graph = rem; + res->attr.aa.element_type = element_type; new_entity(res, mangle_u(name, id_from_str("elem_ent", 8)), element_type); + return res; } type *new_d_type_array (ident *name, int n_dimensions, @@ -960,6 +1095,9 @@ INLINE void set_array_bounds (type *array, int dimension, ir_node * lower_bound, ir_node * upper_bound) { assert(array && (array->type_op == type_array)); + assert(lower_bound && "lower_bound node may not be NULL."); + assert(upper_bound && "upper_bound node may not be NULL."); + assert(dimension < array->attr.aa.n_dimensions && dimension >= 0); array->attr.aa.lower_bound[dimension] = lower_bound; array->attr.aa.upper_bound[dimension] = upper_bound; } @@ -969,38 +1107,48 @@ set_array_bounds_int (type *array, int dimension, int lower_bound, ir_graph *rem = current_ir_graph; current_ir_graph = get_const_code_irg(); set_array_bounds (array, dimension, - new_Const(mode_I, tarval_from_long (mode_I, lower_bound)), - new_Const(mode_I, tarval_from_long (mode_I, upper_bound))); + new_Const(mode_Iu, new_tarval_from_long (lower_bound, mode_Iu)), + new_Const(mode_Iu, new_tarval_from_long (upper_bound, mode_Iu ))); current_ir_graph = rem; } INLINE void set_array_lower_bound (type *array, int dimension, ir_node * lower_bound) { assert(array && (array->type_op == type_array)); + assert(lower_bound && "lower_bound node may not be NULL."); array->attr.aa.lower_bound[dimension] = lower_bound; } void set_array_lower_bound_int (type *array, int dimension, int lower_bound) { ir_graph *rem = current_ir_graph; current_ir_graph = get_const_code_irg(); set_array_lower_bound (array, dimension, - new_Const(mode_I, tarval_from_long (mode_I, lower_bound))); + new_Const(mode_Iu, new_tarval_from_long (lower_bound, mode_Iu))); current_ir_graph = rem; } INLINE void set_array_upper_bound (type *array, int dimension, ir_node * upper_bound) { assert(array && (array->type_op == type_array)); + assert(upper_bound && "upper_bound node may not be NULL."); array->attr.aa.upper_bound[dimension] = upper_bound; } void set_array_upper_bound_int (type *array, int dimension, int upper_bound) { ir_graph *rem = current_ir_graph; current_ir_graph = get_const_code_irg(); set_array_upper_bound (array, dimension, - new_Const(mode_I, tarval_from_long (mode_I, upper_bound))); + new_Const(mode_Iu, new_tarval_from_long (upper_bound, mode_Iu))); current_ir_graph = rem; } +int has_array_lower_bound (type *array, int dimension) { + assert(array && (array->type_op == type_array)); + return (get_irn_op(array->attr.aa.lower_bound[dimension]) != op_Unknown); +} ir_node * get_array_lower_bound (type *array, int dimension) { assert(array && (array->type_op == type_array)); return array->attr.aa.lower_bound[dimension]; } +int has_array_upper_bound (type *array, int dimension) { + assert(array && (array->type_op == type_array)); + return (get_irn_op(array->attr.aa.upper_bound[dimension]) != op_Unknown); +} ir_node * get_array_upper_bound (type *array, int dimension) { assert(array && (array->type_op == type_array)); return array->attr.aa.upper_bound[dimension]; @@ -1114,16 +1262,18 @@ bool is_enumeration_type (type *enumeration) { /*******************************************************************/ /* Create a new type pointer */ -INLINE type *new_type_pointer (ident *name, type *points_to) { +INLINE type *new_type_pointer_mode (ident *name, type *points_to, ir_mode *ptr_mode) { type *res; - res = new_type(type_pointer, mode_p, name); + assert(mode_is_reference(ptr_mode)); + res = new_type(type_pointer, ptr_mode, name); res->attr.pa.points_to = points_to; - res->size = get_mode_size(res->mode); + assert((get_mode_size_bytes(res->mode) != -1) && "unorthodox modes not implemented"); + res->size = get_mode_size_bytes(res->mode); res->state = layout_fixed; return res; } -type *new_d_type_pointer (ident *name, type *points_to, dbg_info* db) { - type *res = new_type_pointer (name, points_to); +type *new_d_type_pointer (ident *name, type *points_to, ir_mode *ptr_mode, dbg_info* db) { + type *res = new_type_pointer_mode (name, points_to, ptr_mode); set_type_dbg_info(res, db); return res; } @@ -1154,9 +1304,10 @@ bool is_pointer_type (type *pointer) { /* create a new type primitive */ INLINE type *new_type_primitive (ident *name, ir_mode *mode) { type *res; - /* @@@ assert( mode_is_data(mode) && (!mode == mode_p)); */ + /* @@@ assert( mode_is_data(mode) && (!mode_is_reference(mode))); */ res = new_type(type_primitive, mode, name); - res->size = get_mode_size(mode); + assert((get_mode_size_bytes(mode) != -1) && "unorthodox modes not implemented"); + res->size = get_mode_size_bytes(mode); res->state = layout_fixed; return res; } @@ -1185,6 +1336,49 @@ INLINE int is_atomic_type(type *tp) { return (is_primitive_type(tp) || is_pointer_type(tp) || is_enumeration_type(tp)); } + +/* + * Gets the number of elements in a firm compound type. + */ +int get_compound_n_members(type *tp) +{ + int res = 0; + + if (is_struct_type(tp)) + res = get_struct_n_members(tp); + else if (is_class_type(tp)) + res = get_class_n_members(tp); + else if (is_union_type(tp)) + res = get_union_n_members(tp); + else + assert(0 && "need struct, union or class for member count"); + + return res; +} + +/* + * Gets the member of a firm compound type at position pos. + */ +entity *get_compound_member(type *tp, int pos) +{ + entity *res; + + if (is_struct_type(tp)) + res = get_struct_member(tp, pos); + else if (is_class_type(tp)) + res = get_class_member(tp, pos); + else if (is_union_type(tp)) + res = get_union_member(tp, pos); + else + { + assert(0 && "need struct, union or class to get a member"); + res=NULL; + } + + return res; +} + + INLINE int is_compound_type(type *tp) { assert(tp && tp->kind == k_type); return (is_class_type(tp) || is_struct_type(tp) ||