X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftr%2Ftype.c;h=32984547d4301b60d25c665b22cc45045043253a;hb=e04bce85ae3e855b372708e93b2a9794c4819ff2;hp=967397c6e1c7ad504887ebf713c84a95f12b50d6;hpb=6c0d7102d4c915d93dfa1608bffa885716b09a3f;p=libfirm diff --git a/ir/tr/type.c b/ir/tr/type.c index 967397c6e..32984547d 100644 --- a/ir/tr/type.c +++ b/ir/tr/type.c @@ -1,9 +1,21 @@ +/* + * Project: libFIRM + * File name: ir/tr/type.c + * Purpose: Representation of types. + * Author: Goetz Lindenmaier + * Modified by: + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 2001-2003 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ + /** * * file type.c - implementation of the datastructure to hold * type information. * (C) 2001 by Universitaet Karlsruhe - * Martin Trapp, Christian Schaefer, Goetz Lindenmaier + * Goetz Lindenmaier * * This module supplies a datastructure to represent all types * known in the compiled program. This includes types specified @@ -23,7 +35,6 @@ * @see type_t.h type tpop */ -/* $Id$ */ #ifdef HAVE_CONFIG_H # include #endif @@ -35,7 +46,7 @@ # include "type_t.h" # include "tpop_t.h" # include "irprog_t.h" -# include "typegmod_t.h" +# include "typegmod.h" # include "array.h" # include "irprog.h" # include "mangle.h" @@ -46,6 +57,10 @@ /** TYPE **/ /*******************************************************************/ +type *none_type; type *get_none_type(void) { return none_type; } +type *unknown_type; type *get_unknown_type(void) { return unknown_type; } + + #ifdef DEBUG_libfirm /** Returns a new, unique number to number nodes or the like. */ int get_irp_new_node_nr(void); @@ -56,8 +71,18 @@ 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)); + value_params_suffix = new_id_from_str(VALUE_PARAMS_SUFFIX); + value_ress_suffix = new_id_from_str(VALUE_RESS_SUFFIX); + + /* construct none and unknown type. */ + none_type = new_type(tpop_none, mode_BAD, new_id_from_str("type_none")); + set_type_size (none_type, 0); + set_type_state (none_type, layout_fixed); + remove_irp_type(none_type); + unknown_type = new_type(tpop_unknown, mode_ANY, new_id_from_str("type_unknown")); + set_type_size (unknown_type, 0); + set_type_state (unknown_type, layout_fixed); + remove_irp_type(unknown_type); } unsigned long type_visited; @@ -65,17 +90,6 @@ INLINE void set_master_type_visited(unsigned long val) { type_visited = val; } INLINE unsigned long get_master_type_visited() { return type_visited; } INLINE void inc_master_type_visited() { type_visited++; } -void free_type(type *tp) { - /* Remove from list of all types */ - remove_irp_type(tp); - /* Free the attributes of the type. */ - free_type_attrs(tp); - /* Free entities automatically allocated with the type */ - if (is_array_type(tp)) - free_entity(get_array_element_entity(tp)); - /* And now the type itself... */ - free(tp); -} INLINE type * new_type(tp_op *type_op, ir_mode *mode, ident* name) { @@ -104,6 +118,35 @@ new_type(tp_op *type_op, ir_mode *mode, ident* name) { return res; } +void free_type(type *tp) { + if ((get_type_tpop(tp) == tpop_none) || (get_type_tpop(tp) == tpop_unknown)) + return; + /* Remove from list of all types */ + remove_irp_type(tp); + /* Free the attributes of the type. */ + free_type_attrs(tp); + /* Free entities automatically allocated with the type */ + if (is_array_type(tp)) + free_entity(get_array_element_entity(tp)); + /* And now the type itself... */ + tp->kind = k_BAD; + free(tp); +} + +void free_type_entities(type *tp) { + switch(get_type_tpop_code(tp)) { + case tpo_class: { free_class_entities(tp); } break; + case tpo_struct: { free_struct_entities(tp); } break; + case tpo_method: { free_method_entities(tp); } break; + case tpo_union: { free_union_entities(tp); } break; + case tpo_array: { free_array_entities(tp); } break; + case tpo_enumeration: { free_enumeration_entities(tp); } break; + case tpo_pointer: { free_pointer_entities(tp); } break; + case tpo_primitive: { free_primitive_entities(tp); } break; + default: break; + } +} + void free_type_attrs(type *tp) { switch(get_type_tpop_code(tp)) { case tpo_class: { free_class_attrs(tp); } break; @@ -143,7 +186,7 @@ ident* get_type_tpop_nameid(type *tp) { const char* get_type_tpop_name(type *tp) { assert(tp && tp->kind == k_type); - return id_to_str(tp->type_op->name); + return get_id_str(tp->type_op->name); } tp_opcode get_type_tpop_code(type *tp) { @@ -159,12 +202,16 @@ ir_mode* get_type_mode(type *tp) { void set_type_mode(type *tp, ir_mode* m) { assert(tp && tp->kind == k_type); - assert(((tp->type_op != type_primitive) || mode_is_data(m)) && + assert(((tp->type_op != type_primitive) || mode_is_data(m)) && /* Modes of primitives must be data */ - ((tp->type_op != type_enumeration) || mode_is_int(m))); + ((tp->type_op != type_enumeration) || mode_is_int(m)) && /* Modes of enumerations must be integers */ + ((tp->type_op != type_pointer) || mode_is_reference(m)) ); + /* Modes of pointers must be references. */ - if ((tp->type_op == type_primitive) || (tp->type_op == type_enumeration)) { + if ((tp->type_op == type_primitive) || + (tp->type_op == type_enumeration) || + (tp->type_op == type_pointer) ) { /* For pointer, primitive and enumeration size depends on the mode. */ assert((get_mode_size_bytes(m) != -1) && "unorthodox modes not implemented"); tp->size = get_mode_size_bytes(m); @@ -189,13 +236,13 @@ get_type_nr(type *tp) { #ifdef DEBUG_libfirm return tp->nr; #else - return 0; + return (long)tp; #endif } const char* get_type_name(type *tp) { assert(tp && tp->kind == k_type); - return (id_to_str(tp->name)); + return (get_id_str(tp->name)); } int get_type_size(type *tp) { @@ -239,8 +286,10 @@ set_type_state(type *tp, type_state state) { 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); + /* TR ?? assert(is_method_type(get_entity_type(get_class_member(tp, i))) || - (get_entity_allocation(get_class_member(tp, i)) == automatic_allocated)); + (get_entity_allocation(get_class_member(tp, i)) == allocation_automatic)); + */ } } break; case tpo_struct: @@ -248,7 +297,7 @@ set_type_state(type *tp, type_state state) { 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)); + assert((get_entity_allocation(get_struct_member(tp, i)) == allocation_automatic)); } } break; case tpo_union: @@ -561,11 +610,11 @@ INLINE type *new_type_class (ident *name) { res = new_type(type_class, NULL, name); - res->attr.ca.members = NEW_ARR_F (entity *, 1); - res->attr.ca.subtypes = NEW_ARR_F (type *, 1); - res->attr.ca.supertypes = NEW_ARR_F (type *, 1); - res->attr.ca.peculiarity = existent; - res->attr.ca.dfn = 0; + res->attr.ca.members = NEW_ARR_F (entity *, 1); + res->attr.ca.subtypes = NEW_ARR_F (type *, 1); + res->attr.ca.supertypes = NEW_ARR_F (type *, 1); + res->attr.ca.peculiarity = peculiarity_existent; + res->attr.ca.dfn = 0; return res; } @@ -574,6 +623,14 @@ type *new_d_type_class (ident *name, dbg_info* db) { set_type_dbg_info(res, db); return res; } + +INLINE void free_class_entities(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)); +} + INLINE void free_class_attrs(type *clss) { assert(clss && (clss->type_op == type_class)); DEL_ARR_F(clss->attr.ca.members); @@ -713,13 +770,21 @@ void remove_class_supertype(type *clss, type *supertype) { } } +char *get_peculiarity_string(peculiarity p) { + if (p == peculiarity_description) + return "peculiarity_description"; + if (p == peculiarity_inherited) + return "peculiarity_inherited"; + return "peculiarity_existent"; +} + INLINE peculiarity get_class_peculiarity (type *clss) { assert(clss && (clss->type_op == type_class)); return clss->attr.ca.peculiarity; } INLINE void set_class_peculiarity (type *clss, peculiarity pec) { assert(clss && (clss->type_op == type_class)); - assert(pec != inherited); /* There is no inheritance of types in libFirm. */ + assert(pec != peculiarity_inherited); /* There is no inheritance of types in libFirm. */ clss->attr.ca.peculiarity = pec; } @@ -769,6 +834,12 @@ type *new_d_type_struct (ident *name, dbg_info* db) { set_type_dbg_info(res, db); return res; } +INLINE void free_struct_entities (type *strct) { + int i; + assert(strct && (strct->type_op == type_struct)); + for (i = get_struct_n_members(strct)-1; i >= 0; --i) + free_entity(get_struct_member(strct, i)); +} INLINE void free_struct_attrs (type *strct) { assert(strct && (strct->type_op == type_struct)); DEL_ARR_F(strct->attr.sa.members); @@ -847,7 +918,7 @@ INLINE type *new_type_method (ident *name, int n_param, int n_res) { 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; + res->attr.ma.variadicity = variadicity_non_variadic; return res; } @@ -858,10 +929,22 @@ type *new_d_type_method (ident *name, int n_param, int n_res, dbg_info* db) { return res; } +INLINE void free_method_entities(type *method) { + assert(method && (method->type_op == type_method)); +} +/* Attention: also frees entities in value parameter subtypes! */ 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); + if (method->attr.ma.value_params) { + free_type_entities(method->attr.ma.value_params); + free_type(method->attr.ma.value_params); + } + if (method->attr.ma.value_ress) { + free_type_entities(method->attr.ma.value_ress); + free_type(method->attr.ma.value_ress); + } } /* manipulate private fields of method. */ @@ -870,9 +953,12 @@ int get_method_n_params (type *method) { return method->attr.ma.n_params; } type *get_method_param_type(type *method, int pos) { + type *res; assert(method && (method->type_op == type_method)); assert(pos >= 0 && pos < get_method_n_params(method)); - return method->attr.ma.param_type[pos] = skip_tid(method->attr.ma.param_type[pos]); + res = method->attr.ma.param_type[pos]; + assert(res != NULL && "empty method param type"); + return method->attr.ma.param_type[pos] = skip_tid(res); } void set_method_param_type(type *method, int pos, type* tp) { assert(method && (method->type_op == type_method)); @@ -893,19 +979,29 @@ entity *get_method_value_param_ent(type *method, int pos) { 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) + 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); } +type *get_method_value_res_type(type *method) { + assert(method && (method->type_op == type_method)); + return method->attr.ma.value_params; +} + + int get_method_n_ress (type *method) { assert(method && (method->type_op == type_method)); return method->attr.ma.n_res; } type *get_method_res_type(type *method, int pos) { + type *res; assert(method && (method->type_op == type_method)); assert(pos >= 0 && pos < get_method_n_ress(method)); - return method->attr.ma.res_type[pos] = skip_tid(method->attr.ma.res_type[pos]); + res = method->attr.ma.res_type[pos]; + assert(res != NULL && "empty method return type"); + return method->attr.ma.res_type[pos] = skip_tid(res); } void set_method_res_type(type *method, int pos, type* tp) { assert(method && (method->type_op == type_method)); @@ -932,6 +1028,19 @@ entity *get_method_value_res_ent(type *method, int pos) { return get_struct_member(method->attr.ma.value_ress, pos); } +/* Returns the null-terminated name of this variadicity. */ +const char *get_variadicity_name(variadicity vari) +{ +#define X(a) case a: return #a + switch (vari) { + X(variadicity_non_variadic); + X(variadicity_variadic); + default: + return "BAD VALUE"; + } +#undef X +} + variadicity get_method_variadicity(type *method) { assert(method && (method->type_op == type_method)); @@ -968,6 +1077,12 @@ type *new_d_type_union (ident *name, dbg_info* db) { set_type_dbg_info(res, db); return res; } +INLINE void free_union_entities (type *uni) { + int i; + assert(uni && (uni->type_op == type_union)); + for (i = get_union_n_members(uni)-1; i >= 0; --i) + free_entity(get_union_member(uni, i)); +} INLINE void free_union_attrs (type *uni) { assert(uni && (uni->type_op == type_union)); DEL_ARR_F(uni->attr.ua.members); @@ -996,7 +1111,7 @@ ident *get_union_delim_nameid (type *uni, int pos) { const char *get_union_delim_name (type *uni, int pos) { assert(uni && (uni->type_op == type_union)); assert(pos >= 0 && pos < get_union_n_types(uni)); - return id_to_str(uni->attr.ua.delim_names[pos]); + return get_id_str(uni->attr.ua.delim_names[pos]); } void set_union_delim_nameid (type *uni, int pos, ident *id) { assert(uni && (uni->type_op == type_union)); @@ -1050,18 +1165,23 @@ 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(mode_Iu); + res->attr.aa.upper_bound[i] = new_Unknown(mode_Iu); 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); @@ -1074,6 +1194,9 @@ type *new_d_type_array (ident *name, int n_dimensions, return res; } +INLINE void free_array_entities (type *array) { + assert(array && (array->type_op == type_array)); +} INLINE void free_array_attrs (type *array) { assert(array && (array->type_op == type_array)); free(array->attr.aa.lower_bound); @@ -1090,6 +1213,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; } @@ -1106,6 +1232,7 @@ set_array_bounds_int (type *array, int dimension, int lower_bound, 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) { @@ -1118,6 +1245,7 @@ void set_array_lower_bound_int (type *array, int dimension, int lower_bound) { 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) { @@ -1127,10 +1255,18 @@ void set_array_upper_bound_int (type *array, int dimension, int 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]; @@ -1182,12 +1318,10 @@ INLINE type *new_type_enumeration (ident *name, int n_enums) { int i; res = new_type(type_enumeration, NULL, name); res->attr.ea.n_enums = n_enums; - res->attr.ea.enumer = (tarval **) xmalloc (sizeof (tarval *) * n_enums); - res->attr.ea.enum_nameid = (ident **) xmalloc (sizeof (ident *) * n_enums); - for (i = 0; i < n_enums; i++) { - res->attr.ea.enumer[i] = NULL; - res->attr.ea.enum_nameid = NULL; - } + res->attr.ea.enumer = (tarval **)xmalloc(sizeof(res->attr.ea.enumer[0]) * n_enums); + res->attr.ea.enum_nameid = (ident **)xmalloc(sizeof(res->attr.ea.enum_nameid[0]) * n_enums); + memset(res->attr.ea.enumer, 0, sizeof(res->attr.ea.enumer[0]) * n_enums); + memset(res->attr.ea.enum_nameid, 0, sizeof(res->attr.ea.enum_nameid[0]) * n_enums); return res; } type *new_d_type_enumeration (ident *name, int n_enums, dbg_info* db) { @@ -1196,6 +1330,9 @@ type *new_d_type_enumeration (ident *name, int n_enums, dbg_info* db) { return res; } +INLINE void free_enumeration_entities(type *enumeration) { + assert(enumeration && (enumeration->type_op == type_enumeration)); +} INLINE void free_enumeration_attrs(type *enumeration) { assert(enumeration && (enumeration->type_op == type_enumeration)); free(enumeration->attr.ea.enumer); @@ -1230,7 +1367,7 @@ ident *get_enumeration_nameid (type *enumeration, int pos) { const char *get_enumeration_name(type *enumeration, int pos) { assert(enumeration && (enumeration->type_op == type_enumeration)); assert(pos >= 0 && pos < get_enumeration_n_enums(enumeration)); - return id_to_str(enumeration->attr.ea.enum_nameid[pos]); + return get_id_str(enumeration->attr.ea.enum_nameid[pos]); } /* typecheck */ @@ -1259,6 +1396,9 @@ type *new_d_type_pointer (ident *name, type *points_to, ir_mode *ptr_mode, dbg_i set_type_dbg_info(res, db); return res; } +INLINE void free_pointer_entities (type *pointer) { + assert(pointer && (pointer->type_op == type_pointer)); +} INLINE void free_pointer_attrs (type *pointer) { assert(pointer && (pointer->type_op == type_pointer)); } @@ -1278,6 +1418,20 @@ bool is_pointer_type (type *pointer) { if (pointer->type_op == type_pointer) return 1; else return 0; } +/* Returns the first pointer type that has as points_to tp. + * Not efficient: O(#types). + * If not found returns unknown_type. */ +type *find_pointer_type_to_type (type *tp) { + int i; + for (i = 0; i < get_irp_n_types(); ++i) { + type *found = get_irp_type(i); + if (is_pointer_type(found) && get_pointer_points_to_type(found) == tp) + return (found); + } + return unknown_type; +} + + /*******************************************************************/ /** TYPE_PRIMITIVE **/ @@ -1298,6 +1452,9 @@ type *new_d_type_primitive (ident *name, ir_mode *mode, dbg_info* db) { set_type_dbg_info(res, db); return res; } +INLINE void free_primitive_entities (type *primitive) { + assert(primitive && (primitive->type_op == type_primitive)); +} INLINE void free_primitive_attrs (type *primitive) { assert(primitive && (primitive->type_op == type_primitive)); }