+
+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));
+}
+
+size_t get_struct_n_members(const ir_type *strct)
+{
+ assert(strct->type_op == type_struct);
+ return ARR_LEN(strct->attr.sa.members);
+}
+
+static 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, size_t pos)
+{
+ assert(strct && (strct->type_op == type_struct));
+ assert(pos < get_struct_n_members(strct));
+ return strct->attr.sa.members[pos];
+}
+
+size_t get_struct_member_index(const ir_type *strct, ir_entity *mem)
+{
+ size_t 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 (size_t)-1;
+}
+
+static void remove_struct_member(ir_type *strct, ir_entity *member)
+{
+ size_t 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(size_t n_param, size_t 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;
+ hook_new_type(res);
+ return res;
+}
+
+ir_type *new_type_method(size_t n_param, size_t 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;
+ size_t n_params;
+ size_t 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);
+ }
+}
+
+size_t (get_method_n_params)(const ir_type *method)
+{
+ return _get_method_n_params(method);
+}
+
+ir_type *get_method_param_type(ir_type *method, size_t pos)
+{
+ ir_type *res;
+ assert(method->type_op == type_method);
+ assert(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, size_t pos, ir_type *tp)
+{
+ assert(method->type_op == type_method);
+ assert(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, size_t pos)
+{
+ assert(method->type_op == type_method);
+ assert(pos < get_method_n_params(method));
+ return method->attr.ma.params[pos].param_name;
+}
+
+const char *get_method_param_name(ir_type *method, size_t pos)
+{
+ ident *id = get_method_param_ident(method, pos);
+ return id ? get_id_str(id) : NULL;
+}
+
+void set_method_param_ident(ir_type *method, size_t pos, ident *id)
+{
+ assert(method->type_op == type_method);
+ assert(pos < get_method_n_params(method));
+ method->attr.ma.params[pos].param_name = id;
+}
+
+ir_entity *get_method_value_param_ent(ir_type *method, size_t pos)
+{
+ assert(method && (method->type_op == type_method));
+ assert(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)
+{
+ size_t i;
+ size_t 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;
+}
+
+size_t (get_method_n_ress)(const ir_type *method)
+{
+ return _get_method_n_ress(method);
+}
+
+ir_type *get_method_res_type(ir_type *method, size_t pos)
+{
+ ir_type *res;
+ assert(method->type_op == type_method);
+ assert(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, size_t pos, ir_type *tp)
+{
+ assert(method->type_op == type_method);
+ assert(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);
+ }
+}
+
+ir_entity *get_method_value_res_ent(ir_type *method, size_t pos)
+{
+ assert(method->type_op == type_method);
+ assert(pos < get_method_n_ress(method));
+
+ if (!method->attr.ma.value_ress) {
+ /* result value type not created yet, build */
+ method->attr.ma.value_ress = build_value_type("<value result>",
+ get_method_n_ress(method), method->attr.ma.res_type);
+ }
+ /*
+ * build_value_type() sets the method->attr.ma.value_ress type as default if
+ * no type is set!
+ */
+ assert((get_entity_type(method->attr.ma.res_type[pos].ent) != method->attr.ma.value_ress)
+ && "result type not yet set");
+
+ return method->attr.ma.res_type[pos].ent;
+}
+
+ir_type *get_method_value_res_type(const ir_type *method)
+{
+ assert(method->type_op == type_method);
+ return method->attr.ma.value_ress;
+}
+
+const char *get_variadicity_name(ir_variadicity vari)
+{
+#define X(a) case a: return #a
+ switch (vari) {
+ X(variadicity_non_variadic);
+ X(variadicity_variadic);
+ default:
+ return "BAD VALUE";
+ }
+#undef X
+}
+
+ir_variadicity get_method_variadicity(const ir_type *method)
+{
+ assert(method && (method->type_op == type_method));
+ return method->attr.ma.variadicity;
+}
+
+void set_method_variadicity(ir_type *method, ir_variadicity vari)
+{
+ assert(method && (method->type_op == type_method));
+ method->attr.ma.variadicity = vari;
+}
+
+size_t get_method_first_variadic_param_index(const ir_type *method)
+{
+ assert(method->type_op == type_method);
+
+ if (method->attr.ma.variadicity == variadicity_non_variadic)
+ return (size_t)-1;
+
+ if (method->attr.ma.first_variadic_param == (size_t)-1)
+ return get_method_n_params(method);
+ return method->attr.ma.first_variadic_param;
+}
+
+void set_method_first_variadic_param_index(ir_type *method, size_t index)
+{
+ assert(method->type_op == type_method);
+ assert(index <= get_method_n_params(method));
+
+ method->attr.ma.first_variadic_param = index;
+}
+
+mtp_additional_properties (get_method_additional_properties)(const ir_type *method)
+{
+ return _get_method_additional_properties(method);
+}
+
+void (set_method_additional_properties)(ir_type *method, mtp_additional_properties mask)
+{
+ _set_method_additional_properties(method, mask);
+}
+
+void (add_method_additional_properties)(ir_type *method,
+ mtp_additional_properties flag)
+{
+ _add_method_additional_properties(method, flag);
+}
+
+unsigned (get_method_calling_convention)(const ir_type *method)
+{
+ return _get_method_calling_convention(method);
+}
+
+void (set_method_calling_convention)(ir_type *method, unsigned cc_mask)
+{
+ _set_method_calling_convention(method, cc_mask);
+}
+
+unsigned get_method_n_regparams(ir_type *method)
+{
+ unsigned cc = get_method_calling_convention(method);
+ assert(IS_FASTCALL(cc));
+
+ return cc & ~cc_bits;
+}
+
+void set_method_n_regparams(ir_type *method, unsigned n_regs)
+{
+ unsigned cc = get_method_calling_convention(method);
+ assert(IS_FASTCALL(cc));
+
+ set_method_calling_convention(method, (cc & cc_bits) | (n_regs & ~cc_bits));
+}
+
+int (is_Method_type)(const ir_type *method)
+{
+ return _is_method_type(method);
+}
+
+
+ir_type *new_d_type_union(ident *name, type_dbg_info *db)
+{
+ ir_type *res = new_type(type_union, NULL, db);
+ res->name = name;
+
+ res->attr.ua.members = NEW_ARR_F(ir_entity *, 0);
+ hook_new_type(res);
+ return res;
+}
+
+ir_type *new_type_union(ident *name)
+{
+ return new_d_type_union(name, NULL);
+}
+
+void free_union_entities(ir_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));
+}
+
+void free_union_attrs (ir_type *uni)
+{
+ assert(uni && (uni->type_op == type_union));
+ DEL_ARR_F(uni->attr.ua.members);
+}
+
+ident *get_union_ident(const ir_type *uni)
+{
+ assert(uni->type_op == type_union);
+ return uni->name;
+}
+
+const char *get_union_name(const ir_type *uni)
+{
+ if (get_union_ident(uni) == NULL)
+ return NULL;
+ return get_id_str(get_union_ident(uni));
+}
+
+size_t get_union_n_members(const ir_type *uni)
+{
+ assert(uni->type_op == type_union);
+ return ARR_LEN(uni->attr.ua.members);
+}
+
+static void add_union_member(ir_type *uni, ir_entity *member)
+{
+ assert(uni->type_op == type_union);
+ assert(uni != get_entity_type(member) && "recursive type");
+ ARR_APP1(ir_entity *, uni->attr.ua.members, member);
+}
+
+ir_entity *get_union_member(const ir_type *uni, size_t pos)
+{
+ assert(uni->type_op == type_union);
+ assert(pos < get_union_n_members(uni));
+ return uni->attr.ua.members[pos];
+}
+
+size_t get_union_member_index(const ir_type *uni, ir_entity *mem)
+{
+ size_t i, n;
+ assert(uni && (uni->type_op == type_union));
+ for (i = 0, n = get_union_n_members(uni); i < n; ++i) {
+ if (get_union_member(uni, i) == mem)
+ return i;
+ }
+ return (size_t)-1;
+}
+
+static void remove_union_member(ir_type *uni, ir_entity *member)
+{
+ size_t i;
+ assert(uni && (uni->type_op == type_union));
+ for (i = 0; i < ARR_LEN(uni->attr.ua.members); ++i) {
+ if (uni->attr.ua.members[i] == member) {
+ for (; i < ARR_LEN(uni->attr.ua.members) - 1; i++)
+ uni->attr.ua.members[i] = uni->attr.ua.members[i+1];
+ ARR_SETLEN(ir_entity*, uni->attr.ua.members, ARR_LEN(uni->attr.ua.members) - 1);
+ break;
+ }
+ }
+}
+
+int (is_Union_type)(const ir_type *uni)
+{
+ return _is_union_type(uni);
+}
+
+void set_union_size(ir_type *tp, unsigned size)
+{
+ tp->size = size;
+}
+
+
+
+ir_type *new_d_type_array(int n_dimensions, ir_type *element_type,
+ type_dbg_info *db)
+{
+ ir_type *res;
+ int i;
+ ir_node *unk;
+ ir_graph *irg = get_const_code_irg();
+
+ assert(!is_Method_type(element_type));
+
+ res = new_type(type_array, NULL, db);
+ res->attr.aa.n_dimensions = n_dimensions;
+ res->attr.aa.lower_bound = XMALLOCNZ(ir_node*, n_dimensions);
+ res->attr.aa.upper_bound = XMALLOCNZ(ir_node*, n_dimensions);
+ res->attr.aa.order = XMALLOCNZ(int, n_dimensions);
+
+ unk = new_r_Unknown(irg, mode_Iu);
+ for (i = 0; i < n_dimensions; i++) {
+ res->attr.aa.lower_bound[i] =
+ res->attr.aa.upper_bound[i] = unk;
+ res->attr.aa.order[i] = i;
+ }
+
+ res->attr.aa.element_type = element_type;
+ res->attr.aa.element_ent
+ = new_entity(NULL, new_id_from_chars("elem_ent", 8), element_type);
+ res->attr.aa.element_ent->owner = res;
+
+ hook_new_type(res);
+ return res;
+}
+
+ir_type *new_type_array(int n_dimensions, ir_type *element_type)
+{
+ return new_d_type_array(n_dimensions, element_type, NULL);
+}
+
+void free_array_automatic_entities(ir_type *array)
+{
+ assert(array && (array->type_op == type_array));
+ free_entity(get_array_element_entity(array));
+}
+
+void free_array_entities(ir_type *array)
+{
+ (void) array;
+ assert(array->type_op == type_array);
+}
+
+void free_array_attrs(ir_type *array)
+{
+ assert(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 */
+size_t get_array_n_dimensions(const ir_type *array)
+{
+ assert(array->type_op == type_array);
+ return array->attr.aa.n_dimensions;
+}
+
+void set_array_bounds(ir_type *array, size_t 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);
+ array->attr.aa.lower_bound[dimension] = lower_bound;
+ array->attr.aa.upper_bound[dimension] = upper_bound;
+}
+
+void set_array_bounds_int(ir_type *array, size_t dimension, int lower_bound,
+ int upper_bound)
+{
+ ir_graph *irg = get_const_code_irg();
+ set_array_bounds(array, dimension,
+ new_r_Const_long(irg, mode_Iu, lower_bound),
+ new_r_Const_long(irg, mode_Iu, upper_bound));
+}
+
+void set_array_lower_bound(ir_type *array, size_t 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;