+void (set_type_visited)(ir_type *tp, ir_visited_t num)
+{
+ _set_type_visited(tp, num);
+}
+
+void (mark_type_visited)(ir_type *tp)
+{
+ _mark_type_visited(tp);
+}
+
+int (type_visited)(const ir_type *tp)
+{
+ return _type_visited(tp);
+}
+
+int (type_not_visited)(const ir_type *tp)
+{
+ return _type_not_visited(tp);
+}
+
+type_dbg_info *(get_type_dbg_info)(const ir_type *tp)
+{
+ return _get_type_dbg_info(tp);
+}
+
+void (set_type_dbg_info)(ir_type *tp, type_dbg_info *db)
+{
+ _set_type_dbg_info(tp, db);
+}
+
+int (is_type)(const void *thing)
+{
+ return _is_type(thing);
+}
+
+/* Checks whether two types are structural equal.*/
+int equal_type(ir_type *typ1, ir_type *typ2)
+{
+ ir_entity **m;
+ ir_type **t;
+ int i, j;
+
+ if (typ1 == typ2) return 1;
+
+ if ((get_type_tpop_code(typ1) != get_type_tpop_code(typ2)) ||
+ typ1->name != typ2->name ||
+ (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_bytes(typ1) != get_type_size_bytes(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 = ALLOCANZ(ir_entity*, get_class_n_members(typ1));
+ /* First sort the members of typ2 */
+ for (i = 0; i < get_class_n_members(typ1); i++) {
+ ir_entity *e1 = get_class_member(typ1, i);
+ for (j = 0; j < get_class_n_members(typ2); j++) {
+ ir_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] || get_class_member(typ1, i) != m[i])
+ return 0;
+ }
+ /** Compare the supertypes **/
+ t = ALLOCANZ(ir_type*, 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 (t2->name == t1->name)
+ 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 = ALLOCANZ(ir_entity*, get_struct_n_members(typ1));
+ /* First sort the members of lt */
+ for (i = 0; i < get_struct_n_members(typ1); i++) {
+ ir_entity *e1 = get_struct_member(typ1, i);
+ for (j = 0; j < get_struct_n_members(typ2); j++) {
+ ir_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] || 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 = ALLOCANZ(ir_entity*, get_union_n_members(typ1));
+ /* First sort the members of lt */
+ for (i = 0; i < get_union_n_members(typ1); i++) {
+ ir_entity *e1 = get_union_member(typ1, i);
+ for (j = 0; j < get_union_n_members(typ2); j++) {
+ ir_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] || 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;
+}
+
+int smaller_type(ir_type *st, ir_type *lt)
+{
+ ir_entity **m;
+ int i, j, n_st_members;
+
+ 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);
+
+ case tpo_struct:
+ n_st_members = get_struct_n_members(st);
+ if (n_st_members != get_struct_n_members(lt))
+ return 0;
+
+ m = ALLOCANZ(ir_entity*, n_st_members);
+ /* First sort the members of lt */
+ for (i = 0; i < n_st_members; ++i) {
+ ir_entity *se = get_struct_member(st, i);
+ int n = get_struct_n_members(lt);
+ for (j = 0; j < n; ++j) {
+ ir_entity *le = get_struct_member(lt, j);
+ if (get_entity_name(le) == get_entity_name(se))
+ m[i] = le;
+ }
+ }
+ for (i = 0; i < n_st_members; 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:
+ n_st_members = get_union_n_members(st);
+ if (n_st_members != get_union_n_members(lt)) return 0;
+ m = ALLOCANZ(ir_entity*, n_st_members);
+ /* First sort the members of lt */
+ for (i = 0; i < n_st_members; ++i) {
+ ir_entity *se = get_union_member(st, i);
+ int n = get_union_n_members(lt);
+ for (j = 0; j < n; ++j) {
+ ir_entity *le = get_union_member(lt, j);
+ if (get_entity_name(le) == get_entity_name(se))
+ m[i] = le;
+ }
+ }
+ for (i = 0; i < n_st_members; ++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_bytes(set) != get_type_size_bytes(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;
+}
+
+
+ir_type *new_d_type_class(ident *name, type_dbg_info *db)
+{
+ ir_type *res;
+
+ res = new_type(type_class, NULL, db);
+ res->name = name;
+
+ res->attr.ca.members = NEW_ARR_F (ir_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.vtable_size = 0;
+ res->attr.ca.clss_flags = cf_none;
+ 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);
+}
+
+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);
+}
+
+ident *get_class_ident(const ir_type *clss)
+{
+ assert(clss->type_op == type_class);
+ return clss->name;
+}
+
+const char *get_class_name(const ir_type *clss)
+{
+ if (get_class_ident(clss) == NULL)
+ return NULL;
+ return get_id_str(get_class_ident(clss));
+}
+
+void add_class_member(ir_type *clss, ir_entity *member)
+{
+ assert(clss && (clss->type_op == type_class));
+ assert(clss != get_entity_type(member) && "recursive type");
+ ARR_APP1 (ir_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, ir_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;
+}
+
+ir_entity *(get_class_member)(const ir_type *clss, int pos)
+{
+ return _get_class_member(clss, pos);
+}
+
+ir_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) {
+ ir_entity *mem = get_class_member(clss, i);
+ if (get_entity_ident(mem) == name) return mem;
+ }
+ return NULL;
+}
+
+void set_class_member(ir_type *clss, ir_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, ir_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(ir_entity *, 0);
+ for (i = 0; i < arity; ++i) {
+ set_entity_owner(members[i], clss);
+ ARR_APP1(ir_entity *, clss->attr.ca.members, members[i]);
+ }
+}
+
+void remove_class_member(ir_type *clss, ir_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(ir_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];
+}
+
+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(ir_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];
+}
+
+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(ir_entity*, clss->attr.ca.supertypes, ARR_LEN(clss->attr.ca.supertypes) - 1);
+ break;
+ }
+}
+
+ir_entity *get_class_type_info(const ir_type *clss)
+{
+ return clss->attr.ca.type_info;
+}
+
+void set_class_type_info(ir_type *clss, ir_entity *ent)
+{
+ clss->attr.ca.type_info = ent;
+ if (ent)
+ ent->repr_class = clss;
+}
+
+ir_peculiarity get_class_peculiarity(const ir_type *clss)
+{
+ assert(clss && (clss->type_op == type_class));
+ return clss->attr.ca.peculiarity;
+}
+
+void set_class_peculiarity(ir_type *clss, ir_peculiarity pec)
+{
+ assert(clss && (clss->type_op == type_class));
+ assert(pec != peculiarity_inherited); /* There is no inheritance of types in libFirm. */
+ clss->attr.ca.peculiarity = pec;
+}
+
+unsigned (get_class_vtable_size)(const ir_type *clss)
+{
+ return _get_class_vtable_size(clss);
+}
+
+void (set_class_vtable_size)(ir_type *clss, unsigned size)
+{
+ _set_class_vtable_size(clss, size);
+}
+
+int (is_class_final)(const ir_type *clss)
+{
+ return _is_class_final(clss);
+}
+
+void (set_class_final)(ir_type *clss, int flag)
+{
+ _set_class_final(clss, flag);
+}
+
+int (is_class_interface)(const ir_type *clss)
+{
+ return _is_class_interface(clss);
+}
+
+void (set_class_interface)(ir_type *clss, int flag)
+{
+ _set_class_interface(clss, flag);
+}
+
+int (is_class_abstract)(const ir_type *clss)
+{
+ return _is_class_abstract(clss);
+}
+
+void (set_class_abstract)(ir_type *clss, int final)
+{
+ _set_class_abstract(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);
+}
+
+int (is_Class_type)(const ir_type *clss)
+{
+ return _is_class_type(clss);
+}
+
+void set_class_mode(ir_type *tp, ir_mode *mode)
+{
+ /* for classes and structs we allow to set a mode if the layout is fixed AND the size matches */
+ assert(get_type_state(tp) == layout_fixed &&
+ tp->size == get_mode_size_bytes(mode) && "mode don't match class layout");
+ tp->mode = mode;
+}
+
+void set_class_size(ir_type *tp, unsigned size)
+{
+ tp->size = size;
+}
+
+
+ir_type *new_d_type_struct(ident *name, type_dbg_info *db)
+{
+ ir_type *res = new_type(type_struct, NULL, db);
+ res->name = name;
+
+ res->attr.sa.members = NEW_ARR_F(ir_entity *, 0);
+ hook_new_type(res);
+ return res;
+}
+
+ir_type *new_type_struct(ident *name)
+{
+ return new_d_type_struct (name, NULL);
+}
+
+void free_struct_entities(ir_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));
+}
+
+void free_struct_attrs(ir_type *strct)
+{
+ assert(strct && (strct->type_op == type_struct));
+ DEL_ARR_F(strct->attr.sa.members);
+}
+
+ident *get_struct_ident(const ir_type *strct)
+{
+ assert(strct->type_op == type_struct);
+ return strct->name;
+}
+
+const char *get_struct_name(const ir_type *strct)
+{
+ if (get_struct_ident(strct) == NULL)
+ return NULL;
+ return get_id_str(get_struct_ident(strct));
+}
+
+int get_struct_n_members(const ir_type *strct)
+{
+ assert(strct && (strct->type_op == type_struct));
+ return ARR_LEN(strct->attr.sa.members);
+}
+
+void add_struct_member(ir_type *strct, ir_entity *member)
+{
+ assert(strct && (strct->type_op == type_struct));
+ assert(get_type_tpop(get_entity_type(member)) != type_method);
+ assert(strct != get_entity_type(member) && "recursive type");
+ ARR_APP1 (ir_entity *, strct->attr.sa.members, member);
+}
+
+ir_entity *get_struct_member(const ir_type *strct, int pos)
+{
+ assert(strct && (strct->type_op == type_struct));
+ assert(pos >= 0 && pos < get_struct_n_members(strct));
+ return strct->attr.sa.members[pos];
+}
+
+int get_struct_member_index(const ir_type *strct, ir_entity *mem)
+{
+ int i, n;
+ assert(strct && (strct->type_op == type_struct));
+ for (i = 0, n = get_struct_n_members(strct); i < n; ++i)
+ if (get_struct_member(strct, i) == mem)
+ return i;
+ return -1;
+}
+
+void set_struct_member(ir_type *strct, int pos, ir_entity *member)
+{
+ assert(strct && (strct->type_op == type_struct));
+ assert(pos >= 0 && pos < get_struct_n_members(strct));
+ assert(get_entity_type(member)->type_op != type_method);/* @@@ lowerfirm !!*/
+ strct->attr.sa.members[pos] = member;
+}
+
+void remove_struct_member(ir_type *strct, ir_entity *member)
+{
+ int i;
+ assert(strct && (strct->type_op == type_struct));
+ for (i = 0; i < (ARR_LEN (strct->attr.sa.members)); i++)
+ if (strct->attr.sa.members[i] == member) {
+ for (; i < (ARR_LEN (strct->attr.sa.members))-1; i++)
+ strct->attr.sa.members[i] = strct->attr.sa.members[i+1];
+ ARR_SETLEN(ir_entity*, strct->attr.sa.members, ARR_LEN(strct->attr.sa.members) - 1);
+ break;
+ }
+}
+
+int (is_Struct_type)(const ir_type *strct)
+{
+ return _is_struct_type(strct);
+}
+
+void set_struct_mode(ir_type *tp, ir_mode *mode)
+{
+ /* for classes and structs we allow to set a mode if the layout is fixed AND the size matches */
+ assert(get_type_state(tp) == layout_fixed &&
+ tp->size == get_mode_size_bytes(mode) && "mode don't match struct layout");
+ tp->mode = mode;
+}
+
+void set_struct_size(ir_type *tp, unsigned size)
+{
+ tp->size = size;
+}
+
+
+/**
+ * Lazy construction of value argument / result representation.
+ * Constructs a struct type and its member. The types of the members
+ * are passed in the argument list.
+ *
+ * @param name name of the type constructed
+ * @param len number of fields
+ * @param tps array of field types with length len
+ */
+static ir_type *build_value_type(char const* name, int len, tp_ent_pair *tps)
+{
+ int i;
+ ir_type *res = new_type_struct(new_id_from_str(name));
+ res->flags |= tf_value_param_type;
+ /* Remove type from type list. Must be treated differently than other types. */
+ remove_irp_type(res);
+ for (i = 0; i < len; i++) {
+ ident *id = tps[i].param_name;
+
+ /* use res as default if corresponding type is not yet set. */
+ ir_type *elt_type = tps[i].tp ? tps[i].tp : res;
+
+ /* use the parameter name if specified */
+ if (id == NULL) {
+ id = new_id_from_str("elt");
+ }
+ tps[i].ent = new_entity(res, id, elt_type);
+ set_entity_allocation(tps[i].ent, allocation_parameter);
+ }
+ return res;
+}
+
+ir_type *new_d_type_method(int n_param, int n_res, type_dbg_info *db)
+{
+ ir_type *res;
+
+ assert((get_mode_size_bits(mode_P_code) % 8 == 0) && "unorthodox modes not implemented");
+ res = new_type(type_method, mode_P_code, db);
+ res->flags |= tf_layout_fixed;
+ res->size = get_mode_size_bytes(mode_P_code);
+ res->attr.ma.n_params = n_param;
+ res->attr.ma.params = XMALLOCNZ(tp_ent_pair, n_param);
+ res->attr.ma.value_params = NULL;
+ res->attr.ma.n_res = n_res;
+ res->attr.ma.res_type = XMALLOCNZ(tp_ent_pair, n_res);
+ 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;
+}
+
+ir_type *new_type_method(int n_param, int n_res)
+{
+ return new_d_type_method(n_param, n_res, NULL);
+}
+
+ir_type *clone_type_method(ir_type *tp)
+{
+ ir_type *res;
+ ir_mode *mode;
+ int n_params, n_res;
+ type_dbg_info *db;
+
+ assert(is_Method_type(tp));
+
+ mode = tp->mode;
+ n_params = tp->attr.ma.n_params;
+ n_res = tp->attr.ma.n_res;
+ db = tp->dbi;
+
+ res = new_type(type_method, mode, db);
+
+ res->flags = tp->flags;
+ res->assoc_type = tp->assoc_type;
+ res->size = tp->size;
+ res->attr.ma.n_params = n_params;
+ res->attr.ma.params = XMALLOCN(tp_ent_pair, n_params);
+ memcpy(res->attr.ma.params, tp->attr.ma.params, n_params * sizeof(res->attr.ma.params[0]));
+ res->attr.ma.value_params = tp->attr.ma.value_params;
+ res->attr.ma.n_res = n_res;
+ res->attr.ma.res_type = XMALLOCN(tp_ent_pair, n_res);
+ memcpy(res->attr.ma.res_type, tp->attr.ma.res_type, n_res * sizeof(res->attr.ma.res_type[0]));
+ res->attr.ma.value_ress = tp->attr.ma.value_ress;
+ res->attr.ma.variadicity = tp->attr.ma.variadicity;
+ res->attr.ma.first_variadic_param = tp->attr.ma.first_variadic_param;
+ res->attr.ma.additional_properties = tp->attr.ma.additional_properties;
+ res->attr.ma.irg_calling_conv = tp->attr.ma.irg_calling_conv;
+ hook_new_type(res);
+ return res;
+}
+
+void free_method_entities(ir_type *method)
+{
+ (void) method;
+ assert(method && (method->type_op == type_method));
+}
+
+void free_method_attrs(ir_type *method)
+{
+ assert(method && (method->type_op == type_method));
+ free(method->attr.ma.params);
+ free(method->attr.ma.res_type);
+ /* cannot free it yet, type could be cloned ...
+ 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);
+ }
+}
+
+int (get_method_n_params)(const ir_type *method)
+{
+ return _get_method_n_params(method);
+}
+
+ir_type *get_method_param_type(ir_type *method, int pos)
+{
+ ir_type *res;
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_params(method));
+ res = method->attr.ma.params[pos].tp;
+ assert(res != NULL && "empty method param type");
+ return res;
+}
+
+void set_method_param_type(ir_type *method, int pos, ir_type *tp)
+{
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_params(method));
+ method->attr.ma.params[pos].tp = 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);
+ }
+}
+
+ident *get_method_param_ident(ir_type *method, int pos)
+{
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_params(method));
+ return method->attr.ma.params[pos].param_name;
+}
+
+const char *get_method_param_name(ir_type *method, int pos)
+{
+ ident *id = get_method_param_ident(method, pos);
+ return id ? get_id_str(id) : NULL;
+}
+
+void set_method_param_ident(ir_type *method, int pos, ident *id)
+{
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_params(method));
+ method->attr.ma.params[pos].param_name = id;
+}
+
+ir_entity *get_method_value_param_ent(ir_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) {
+ /* parameter value type not created yet, build */
+ method->attr.ma.value_params = build_value_type("<value param>",
+ get_method_n_params(method), method->attr.ma.params);
+ }
+ /*
+ * build_value_type() sets the method->attr.ma.value_params type as default if
+ * no type is set!
+ */
+ assert((get_entity_type(method->attr.ma.params[pos].ent) != method->attr.ma.value_params)
+ && "param type not yet set");
+ return method->attr.ma.params[pos].ent;
+}
+
+void set_method_value_param_type(ir_type *method, ir_type *tp)
+{
+ int i, n;
+
+ assert(method && (method->type_op == type_method));
+ assert(is_value_param_type(tp));
+ assert(get_method_n_params(method) == get_struct_n_members(tp));
+
+ method->attr.ma.value_params = tp;
+
+ n = get_struct_n_members(tp);
+ for (i = 0; i < n; i++) {
+ ir_entity *ent = get_struct_member(tp, i);
+ method->attr.ma.params[i].ent = ent;
+ }
+}
+
+ir_type *get_method_value_param_type(const ir_type *method)
+{
+ assert(method && (method->type_op == type_method));
+ return method->attr.ma.value_params;
+}
+
+int (get_method_n_ress)(const ir_type *method)
+{
+ return _get_method_n_ress(method);
+}
+
+ir_type *get_method_res_type(ir_type *method, int pos)
+{
+ ir_type *res;
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_ress(method));
+ res = method->attr.ma.res_type[pos].tp;
+ assert(res != NULL && "empty method return type");
+ return res;
+}
+
+void set_method_res_type(ir_type *method, int pos, ir_type *tp)
+{
+ assert(method && (method->type_op == type_method));
+ assert(pos >= 0 && pos < get_method_n_ress(method));
+ /* set the result ir_type */
+ method->attr.ma.res_type[pos].tp = 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);
+ }
+}