-/* Checks whether two types are structural equal.*/
-int equal_type(ir_type *typ1, ir_type *typ2) {
- entity **m;
- ir_type **t;
- int i, j;
-
- if (typ1 == typ2) return 1;
-
- if ((get_type_tpop_code(typ1) != get_type_tpop_code(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 0;
- if ((get_type_state(typ1) == layout_fixed) &&
- (get_type_size_bits(typ1) != get_type_size_bits(typ2)))
- return 0;
-
- switch (get_type_tpop_code(typ1)) {
- case tpo_class: {
- if (get_class_n_members(typ1) != get_class_n_members(typ2)) return 0;
- if (get_class_n_subtypes(typ1) != get_class_n_subtypes(typ2)) return 0;
- if (get_class_n_supertypes(typ1) != get_class_n_supertypes(typ2)) return 0;
- if (get_class_peculiarity(typ1) != get_class_peculiarity(typ2)) return 0;
- /** Compare the members **/
- m = alloca(sizeof(entity *) * get_class_n_members(typ1));
- memset(m, 0, sizeof(entity *) * get_class_n_members(typ1));
- /* First sort the members of typ2 */
- for (i = 0; i < get_class_n_members(typ1); i++) {
- entity *e1 = get_class_member(typ1, i);
- for (j = 0; j < get_class_n_members(typ2); j++) {
- entity *e2 = get_class_member(typ2, j);
- if (get_entity_name(e1) == get_entity_name(e2))
- m[i] = e2;
- }
- }
- for (i = 0; i < get_class_n_members(typ1); i++) {
- if (!m[i] || /* Found no counterpart */
- !equal_entity(get_class_member(typ1, i), m[i]))
- return 0;
- }
- /** Compare the supertypes **/
- t = alloca(sizeof(entity *) * get_class_n_supertypes(typ1));
- memset(t, 0, sizeof(entity *) * get_class_n_supertypes(typ1));
- /* First sort the supertypes of typ2 */
- for (i = 0; i < get_class_n_supertypes(typ1); i++) {
- ir_type *t1 = get_class_supertype(typ1, i);
- for (j = 0; j < get_class_n_supertypes(typ2); j++) {
- ir_type *t2 = get_class_supertype(typ2, j);
- if (get_type_ident(t2) == get_type_ident(t1))
- t[i] = t2;
- }
- }
- for (i = 0; i < get_class_n_supertypes(typ1); i++) {
- if (!t[i] || /* Found no counterpart */
- get_class_supertype(typ1, i) != t[i])
- return 0;
- }
- } break;
- case tpo_struct: {
- if (get_struct_n_members(typ1) != get_struct_n_members(typ2)) return 0;
- m = alloca(sizeof(entity *) * get_struct_n_members(typ1));
- memset(m, 0, sizeof(entity *) * get_struct_n_members(typ1));
- /* First sort the members of lt */
- for (i = 0; i < get_struct_n_members(typ1); i++) {
- entity *e1 = get_struct_member(typ1, i);
- for (j = 0; j < get_struct_n_members(typ2); j++) {
- entity *e2 = get_struct_member(typ2, j);
- if (get_entity_name(e1) == get_entity_name(e2))
- m[i] = e2;
- }
- }
- for (i = 0; i < get_struct_n_members(typ1); i++) {
- if (!m[i] || /* Found no counterpart */
- !equal_entity(get_struct_member(typ1, i), m[i]))
- return 0;
- }
- } break;
- case tpo_method: {
- int n_param1, n_param2;
-
- if (get_method_variadicity(typ1) != get_method_variadicity(typ2)) return 0;
- if (get_method_n_ress(typ1) != get_method_n_ress(typ2)) return 0;
- if (get_method_calling_convention(typ1) !=
- get_method_calling_convention(typ2)) return 0;
-
- if (get_method_variadicity(typ1) == variadicity_non_variadic) {
- n_param1 = get_method_n_params(typ1);
- n_param2 = get_method_n_params(typ2);
- }
- else {
- n_param1 = get_method_first_variadic_param_index(typ1);
- n_param2 = get_method_first_variadic_param_index(typ2);
- }
-
- if (n_param1 != n_param2) return 0;
-
- for (i = 0; i < n_param1; i++) {
- if (!equal_type(get_method_param_type(typ1, i), get_method_param_type(typ2, i)))
- return 0;
- }
- for (i = 0; i < get_method_n_ress(typ1); i++) {
- if (!equal_type(get_method_res_type(typ1, i), get_method_res_type(typ2, i)))
- return 0;
- }
- } break;
- case tpo_union: {
- if (get_union_n_members(typ1) != get_union_n_members(typ2)) return 0;
- m = alloca(sizeof(entity *) * get_union_n_members(typ1));
- memset(m, 0, sizeof(entity *) * get_union_n_members(typ1));
- /* First sort the members of lt */
- for (i = 0; i < get_union_n_members(typ1); i++) {
- entity *e1 = get_union_member(typ1, i);
- for (j = 0; j < get_union_n_members(typ2); j++) {
- entity *e2 = get_union_member(typ2, j);
- if (get_entity_name(e1) == get_entity_name(e2))
- m[i] = e2;
- }
- }
- for (i = 0; i < get_union_n_members(typ1); i++) {
- if (!m[i] || /* Found no counterpart */
- !equal_entity(get_union_member(typ1, i), m[i]))
- return 0;
- }
- } break;
- case tpo_array: {
- if (get_array_n_dimensions(typ1) != get_array_n_dimensions(typ2))
- return 0;
- if (!equal_type(get_array_element_type(typ1), get_array_element_type(typ2)))
- return 0;
- for(i = 0; i < get_array_n_dimensions(typ1); i++) {
- if (get_array_lower_bound(typ1, i) != get_array_lower_bound(typ2, i) ||
- get_array_upper_bound(typ1, i) != get_array_upper_bound(typ2, i))
- return 0;
- if (get_array_order(typ1, i) != get_array_order(typ2, i))
- assert(0 && "type compare with different dimension orders not implemented");
- }
- } break;
- case tpo_enumeration: {
- assert(0 && "enumerations not implemented");
- } break;
- case tpo_pointer: {
- if (get_pointer_points_to_type(typ1) != get_pointer_points_to_type(typ2))
- return 0;
- } break;
- case tpo_primitive: {
- } break;
- default: break;
- }
- return 1;
-}
-
-/* Checks whether two types are structural comparable. */
-int smaller_type (ir_type *st, ir_type *lt) {
- entity **m;
- int i, j;
-
- if (st == lt) return 1;
-
- if (get_type_tpop_code(st) != get_type_tpop_code(lt))
- return 0;
-
- switch(get_type_tpop_code(st)) {
- case tpo_class: {
- return is_SubClass_of(st, lt);
- } break;
- case tpo_struct: {
- if (get_struct_n_members(st) != get_struct_n_members(lt)) return 0;
- m = alloca(sizeof(entity *) * get_struct_n_members(st));
- memset(m, 0, sizeof(entity *) * get_struct_n_members(st));
- /* First sort the members of lt */
- for (i = 0; i < get_struct_n_members(st); i++) {
- entity *se = get_struct_member(st, i);
- for (j = 0; j < get_struct_n_members(lt); j++) {
- entity *le = get_struct_member(lt, j);
- if (get_entity_name(le) == get_entity_name(se))
- m[i] = le;
- }
- }
- for (i = 0; i < get_struct_n_members(st); i++) {
- if (!m[i] || /* Found no counterpart */
- !smaller_type(get_entity_type(get_struct_member(st, i)),
- get_entity_type(m[i])))
- return 0;
- }
- } break;
- case tpo_method: {
- int n_param1, n_param2;
-
- /** FIXME: is this still 1? */
- if (get_method_variadicity(st) != get_method_variadicity(lt)) return 0;
- if (get_method_n_ress(st) != get_method_n_ress(lt)) return 0;
- if (get_method_calling_convention(st) !=
- get_method_calling_convention(lt)) return 0;
-
- if (get_method_variadicity(st) == variadicity_non_variadic) {
- n_param1 = get_method_n_params(st);
- n_param2 = get_method_n_params(lt);
- }
- else {
- n_param1 = get_method_first_variadic_param_index(st);
- n_param2 = get_method_first_variadic_param_index(lt);
- }
-
- if (n_param1 != n_param2) return 0;
-
- for (i = 0; i < get_method_n_params(st); i++) {
- if (!smaller_type(get_method_param_type(st, i), get_method_param_type(lt, i)))
- return 0;
- }
- for (i = 0; i < get_method_n_ress(st); i++) {
- if (!smaller_type(get_method_res_type(st, i), get_method_res_type(lt, i)))
- return 0;
- }
- } break;
- case tpo_union: {
- if (get_union_n_members(st) != get_union_n_members(lt)) return 0;
- m = alloca(sizeof(entity *) * get_union_n_members(st));
- memset(m, 0, sizeof(entity *) * get_union_n_members(st));
- /* First sort the members of lt */
- for (i = 0; i < get_union_n_members(st); i++) {
- entity *se = get_union_member(st, i);
- for (j = 0; j < get_union_n_members(lt); j++) {
- entity *le = get_union_member(lt, j);
- if (get_entity_name(le) == get_entity_name(se))
- m[i] = le;
- }
- }
- for (i = 0; i < get_union_n_members(st); i++) {
- if (!m[i] || /* Found no counterpart */
- !smaller_type(get_entity_type(get_union_member(st, i)),
- get_entity_type(m[i])))
- return 0;
- }
- } break;
- case tpo_array: {
- ir_type *set, *let; /* small/large elt. ir_type */
- if (get_array_n_dimensions(st) != get_array_n_dimensions(lt))
- return 0;
- set = get_array_element_type(st);
- let = get_array_element_type(lt);
- if (set != let) {
- /* If the element types are different, set must be convertible
- to let, and they must have the same size so that address
- computations work out. To have a size the layout must
- be fixed. */
- if ((get_type_state(set) != layout_fixed) ||
- (get_type_state(let) != layout_fixed))
- return 0;
- if (!smaller_type(set, let) ||
- get_type_size_bits(set) != get_type_size_bits(let))
- return 0;
- }
- for(i = 0; i < get_array_n_dimensions(st); i++) {
- if (get_array_lower_bound(lt, i))
- if(get_array_lower_bound(st, i) != get_array_lower_bound(lt, i))
- return 0;
- if (get_array_upper_bound(lt, i))
- if(get_array_upper_bound(st, i) != get_array_upper_bound(lt, i))
- return 0;
- }
- } break;
- case tpo_enumeration: {
- assert(0 && "enumerations not implemented");
- } break;
- case tpo_pointer: {
- if (!smaller_type(get_pointer_points_to_type(st),
- get_pointer_points_to_type(lt)))
- return 0;
- } break;
- case tpo_primitive: {
- if (!smaller_mode(get_type_mode(st), get_type_mode(lt)))
- return 0;
- } break;
- default: break;
- }
- return 1;
-}
-
-/*-----------------------------------------------------------------*/
-/* TYPE_CLASS */
-/*-----------------------------------------------------------------*/
-
-/* create a new class ir_type */
-ir_type *new_d_type_class (ident *name, dbg_info *db) {
- ir_type *res;
-
- res = new_type(type_class, NULL, name, db);
-
- res->attr.ca.members = NEW_ARR_F (entity *, 0);
- 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;
-}
-
-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) {
- assert(clss && (clss->type_op == type_class));
- DEL_ARR_F(clss->attr.ca.members);
- DEL_ARR_F(clss->attr.ca.subtypes);
- DEL_ARR_F(clss->attr.ca.supertypes);
-}
-
-/* manipulate private fields of class type */
-void add_class_member (ir_type *clss, entity *member) {
- assert(clss && (clss->type_op == type_class));
- assert(clss != get_entity_type(member) && "recursive type");
- ARR_APP1 (entity *, clss->attr.ca.members, member);
-}
-
-int (get_class_n_members) (const ir_type *clss) {
- return _get_class_n_members(clss);
-}
-
-int get_class_member_index(const ir_type *clss, entity *mem) {
- int i, n;
- assert(clss && (clss->type_op == type_class));
- for (i = 0, n = get_class_n_members(clss); i < n; ++i)
- if (get_class_member(clss, i) == mem)
- return i;
- return -1;
-}
-
-entity *(get_class_member) (const ir_type *clss, int pos) {
- return _get_class_member(clss, pos);
-}
-
-entity *get_class_member_by_name(ir_type *clss, ident *name) {
- int i, n_mem;
- assert(clss && (clss->type_op == type_class));
- n_mem = get_class_n_members(clss);
- for (i = 0; i < n_mem; ++i) {
- entity *mem = get_class_member(clss, i);
- if (get_entity_ident(mem) == name) return mem;
- }
- return NULL;
-}
-
-void set_class_member (ir_type *clss, entity *member, int pos) {
- assert(clss && (clss->type_op == type_class));
- assert(pos >= 0 && pos < get_class_n_members(clss));
- clss->attr.ca.members[pos] = member;
-}
-void set_class_members (ir_type *clss, entity **members, int arity) {
- int i;
- assert(clss && (clss->type_op == type_class));
- DEL_ARR_F(clss->attr.ca.members);
- clss->attr.ca.members = NEW_ARR_F (entity *, 0);
- for (i = 0; i < arity; i++) {
- set_entity_owner(members[i], clss);
- ARR_APP1 (entity *, clss->attr.ca.members, members[i]);
- }
-}
-void remove_class_member(ir_type *clss, entity *member) {
- int i;
- assert(clss && (clss->type_op == type_class));
- for (i = 0; i < (ARR_LEN (clss->attr.ca.members)); i++) {
- if (clss->attr.ca.members[i] == member) {
- for (; i < (ARR_LEN (clss->attr.ca.members)) - 1; i++)
- clss->attr.ca.members[i] = clss->attr.ca.members[i + 1];
- ARR_SETLEN(entity*, clss->attr.ca.members, ARR_LEN(clss->attr.ca.members) - 1);
- break;
- }
- }
-}
-
-void add_class_subtype (ir_type *clss, ir_type *subtype) {
- int i;
- assert(clss && (clss->type_op == type_class));
- ARR_APP1 (ir_type *, clss->attr.ca.subtypes, subtype);
- for (i = 0; i < get_class_n_supertypes(subtype); i++)
- if (get_class_supertype(subtype, i) == clss)
- /* Class already registered */
- return;
- ARR_APP1 (ir_type *, subtype->attr.ca.supertypes, clss);
-}
-int get_class_n_subtypes (const ir_type *clss) {
- assert(clss && (clss->type_op == type_class));
- return (ARR_LEN (clss->attr.ca.subtypes));
-}
-ir_type *get_class_subtype (ir_type *clss, int pos) {
- assert(clss && (clss->type_op == type_class));
- assert(pos >= 0 && pos < get_class_n_subtypes(clss));
- return clss->attr.ca.subtypes[pos] = skip_tid(clss->attr.ca.subtypes[pos]);
-}
-int get_class_subtype_index(ir_type *clss, const ir_type *subclass) {
- int i, n_subtypes = get_class_n_subtypes(clss);
- assert(is_Class_type(subclass));
- for (i = 0; i < n_subtypes; ++i) {
- if (get_class_subtype(clss, i) == subclass) return i;
- }
- return -1;
-}
-void set_class_subtype (ir_type *clss, ir_type *subtype, int pos) {
- assert(clss && (clss->type_op == type_class));
- assert(pos >= 0 && pos < get_class_n_subtypes(clss));
- clss->attr.ca.subtypes[pos] = subtype;
-}
-void remove_class_subtype(ir_type *clss, ir_type *subtype) {
- int i;
- assert(clss && (clss->type_op == type_class));
- for (i = 0; i < (ARR_LEN (clss->attr.ca.subtypes)); i++)
- if (clss->attr.ca.subtypes[i] == subtype) {
- for (; i < (ARR_LEN (clss->attr.ca.subtypes))-1; i++)
- clss->attr.ca.subtypes[i] = clss->attr.ca.subtypes[i+1];
- ARR_SETLEN(entity*, clss->attr.ca.subtypes, ARR_LEN(clss->attr.ca.subtypes) - 1);
- break;
- }
-}
-
-void add_class_supertype (ir_type *clss, ir_type *supertype) {
- int i;
- assert(clss && (clss->type_op == type_class));
- assert(supertype && (supertype -> type_op == type_class));
- ARR_APP1 (ir_type *, clss->attr.ca.supertypes, supertype);
- for (i = get_class_n_subtypes(supertype) - 1; i >= 0; --i)
- if (get_class_subtype(supertype, i) == clss)
- /* Class already registered */
- return;
- ARR_APP1 (ir_type *, supertype->attr.ca.subtypes, clss);
-}
-int get_class_n_supertypes (const ir_type *clss) {
- assert(clss && (clss->type_op == type_class));
- return (ARR_LEN (clss->attr.ca.supertypes));
-}
-int get_class_supertype_index(ir_type *clss, ir_type *super_clss) {
- int i, n_supertypes = get_class_n_supertypes(clss);
- assert(super_clss && (super_clss->type_op == type_class));
- for (i = 0; i < n_supertypes; i++)
- if (get_class_supertype(clss, i) == super_clss)
- return i;
- return -1;
-}
-ir_type *get_class_supertype (ir_type *clss, int pos) {
- assert(clss && (clss->type_op == type_class));
- assert(pos >= 0 && pos < get_class_n_supertypes(clss));
- return clss->attr.ca.supertypes[pos] = skip_tid(clss->attr.ca.supertypes[pos]);
-}
-void set_class_supertype (ir_type *clss, ir_type *supertype, int pos) {
- assert(clss && (clss->type_op == type_class));
- assert(pos >= 0 && pos < get_class_n_supertypes(clss));
- clss->attr.ca.supertypes[pos] = supertype;
-}
-void remove_class_supertype(ir_type *clss, ir_type *supertype) {
- int i;
- assert(clss && (clss->type_op == type_class));
- for (i = 0; i < (ARR_LEN (clss->attr.ca.supertypes)); i++)
- if (clss->attr.ca.supertypes[i] == supertype) {
- for(; i < (ARR_LEN (clss->attr.ca.supertypes))-1; i++)
- clss->attr.ca.supertypes[i] = clss->attr.ca.supertypes[i+1];
- ARR_SETLEN(entity*, clss->attr.ca.supertypes, ARR_LEN(clss->attr.ca.supertypes) - 1);
- 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
- switch (p) {
- X(peculiarity_description);
- X(peculiarity_inherited);
- X(peculiarity_existent);
- }
-#undef X
- return "invalid peculiarity";