📄 types.cc
字号:
/* * Set the name of a particular field in a struct_type. Make sure that it * is entered in the lexicon. The field number must be valid or an error * will occur. */voidstruct_type::set_field_name (unsigned n, char *nm){ check_range(n); names[n] = nm ? lexicon->enter(nm)->sp : NULL;}/* * Set the type of a particular field in a struct_type. The field number * must be valid or an error will occur. */voidstruct_type::set_field_type (unsigned n, type_node *t){ check_range(n); types[n] = t;}/* * Set the offset of a particular field in a struct_type. The field number * must be valid or an error will occur. */voidstruct_type::set_offset (unsigned n, int o){ check_range(n); offsets[n] = o;}/* * Find a structure field from its offset. This relies upon the convention * that the fields are stored in order of increasing offsets. If no fields * match the offset exactly, the field containing the offset is returned and * the number of bits from the start of that field is returned in the "left" * parameter. This function is useless for TYPE_UNIONs since the fields all * have the same offset. */unsignedstruct_type::find_field_by_offset (int off, int& left){ unsigned closest_field = num_fields(); int distance = 0; for (unsigned field_num = 0; field_num < num_fields(); ++field_num) { if (offset(field_num) <= off) { if ((closest_field == num_fields()) || (distance > (off - offset(field_num)))) { distance = off - offset(field_num); closest_field = field_num; } } } if (closest_field != num_fields()) left = distance; return closest_field;}/* * Find a group, structure, or union field by name. Returns * "(unsigned)-1" if the field is not found. */unsignedstruct_type::find_field_by_name (char *nm){ char *nn = nm ? lexicon->enter(nm)->sp : NULL; for (unsigned i = 0; i < num_fields(); i++) { if (nn == field_name(i)) return i; } return (unsigned)-1;}type_node *struct_type::ref_type (unsigned num){ return field_type(num);}voidstruct_type::set_ref_type (unsigned num, type_node *new_type){ set_field_type(num, new_type);}/* * Write the struct_type fields onto an annotation. */annote *struct_type::cvt_to_annote (){ annote *an; if (op() == TYPE_GROUP) { an = new annote(k_group_type); } else if (op() == TYPE_STRUCT) { an = new annote(k_struct_type); } else { an = new annote(k_union_type); } cvt_to_annote_base(an); an->immeds()->append(immed(name())); an->immeds()->append(immed(size())); an->immeds()->append(immed(num_fields())); for (unsigned i = 0; i < num_fields(); i++) { assert_msg(field_type(i), ("struct_type::cvt_to_annote - missing type " "for field %u", i)); if (write_scope != NULL) field_type(i)->write_check(); unsigned field_id = field_type(i)->type_id(); an->immeds()->append(immed(field_name(i))); an->immeds()->append(immed(field_id)); an->immeds()->append(immed(offset(i))); } return an;}/* * Read the struct_type fields from an annotation. */voidstruct_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); my_name = an->immeds()->pop().string(); sz = an->immeds()->pop().integer(); ntypes = an->immeds()->pop().unsigned_int(); /* allocate storage for the aggregate's elements */ names = new char*[ntypes]; types = new type_node*[ntypes]; offsets = new int[ntypes]; for (unsigned i = 0; i < ntypes; i++) { names[i] = an->immeds()->pop().string(); unsigned field_id = an->immeds()->pop().unsigned_int(); types[i] = symtab->lookup_type_id(field_id); assert_msg(types[i], ("struct_type::cvt_from_annote - type ID %u not " "found", field_id)); offsets[i] = an->immeds()->pop().integer(); }}type_node *struct_type::clone_internal(void){ return clone();}/* * Help print a struct_type. This method includes all of the struct_type * fields. */voidstruct_type::print_helper (FILE *f, int depth){ fprintf(f, "%s (%d) { ", name(), size()); for (unsigned i = 0; i < num_fields(); i++) { putc('\n', f); suif_indent(f, depth+1); if(field_name(i)) { fprintf(f, "%s offset=%d ", field_name(i), offset(i)); if(field_type(i)) { field_type(i)->print(f); } else { fprintf(f, "<<MISSING TYPE>>"); } } else { fprintf(f, "<<MISSING FIELD>>"); } } if (num_fields() > 0) { putc('\n', f); suif_indent(f, depth); } putc('}', f);}/* * Make a copy of a struct_type. The field types are not copied. */type_node *struct_type::copy (){ struct_type *result = new struct_type(op(), size(), name(), num_fields()); /* set the field names, types, and offsets */ for (unsigned n = 0; n < num_fields(); n++) { result->set_field_name(n, field_name(n)); result->set_field_type(n, field_type(n)); result->set_offset(n, offset(n)); } return result;}struct_type *struct_type::clone(void){ annote *clone_annote = annotes()->peek_annote(k_clone); if (clone_annote != NULL) { immed_list *clone_immeds = clone_annote->immeds(); assert((clone_immeds->count() == 1) && ((*clone_immeds)[0].is_type())); type_node *result = (*clone_immeds)[0].type(); assert(result->is_struct()); return (struct_type *)result; } struct_type *result = new struct_type(op(), size(), name(), num_fields()); clone_annote = new annote(k_clone); clone_annote->immeds()->append(immed(result)); annotes()->push(clone_annote); for (unsigned n = 0; n < num_fields(); n++) { result->set_field_name(n, field_name(n)); result->set_field_type(n, field_type(n)->clone()); result->set_offset(n, offset(n)); } clone_annote = annotes()->get_annote(k_clone); assert(clone_annote != NULL); delete clone_annote; copy_annotes(result); return result;}/* * Modify the type of struct_type * No validation is done here */voidstruct_type::set_to_union() { set_op(TYPE_UNION);}voidstruct_type::set_to_struct() { set_op(TYPE_STRUCT);}voidstruct_type::set_to_group() { set_op(TYPE_GROUP);}/* * Check if this type is compatible with another type_node. Struct types * should never need to be compared but this method does something reasonable * just in case. */booleanstruct_type::compatible (type_node *t){ if (!t) return FALSE; return is_same(t->unqual());}/* * Compare struct_types. In SUIF, the types are the same only if * their pointers match. */booleanstruct_type::is_same (type_node *t){ return (t == (type_node *)this);}/*****************************************************************************//* * Create a new enum_type. The member arrays are allocated and initialized, * but the individual values must be set separately. */enum_type::enum_type (char *nm, int s, boolean b, unsigned n) : base_type(TYPE_ENUM, s, b), my_name(0), nvals(n), names(new char*[nvals]), vals(new int[nvals]){ set_name(nm); /* initialize the members */ for (unsigned i = 0; i < nvals; i++) { names[i] = NULL; vals[i] = 0; }}enum_type::~enum_type (){ if (names) delete[] names; if (vals) delete[] vals;}/* * Check if an enum_type member number is valid. */voidenum_type::check_range (unsigned n){ assert_msg(n < num_values(), ((num_values() > 0) ? (char *) "enum_type: member number %u out of range 0 to %u" : (char *) "enum_type: member number %u is invalid for enumerated " "type with zero members", n, num_values() - 1));}/* * Change the number of members in an enum_type. If the number is larger * than before, the member arrays are reallocated. */voidenum_type::set_num_values (unsigned n){ if (n <= nvals) { nvals = n; return; } char **new_names = new char*[n]; int *new_vals = new int[n]; /* copy the old values (as much as possible) */ unsigned i; for (i = 0; (i < nvals) && (i < n); i++) { new_names[i] = names[i]; new_vals[i] = vals[i]; } /* initialize any new values */ for (unsigned j = nvals; j < n; j++) { new_names[i] = NULL; new_vals[i] = 0; } nvals = n; delete[] names; delete[] vals; names = new_names; vals = new_vals;}/* * Set the name of an enum_type. Make sure it is entered in the lexicon. */voidenum_type::set_name (char *nm){ my_name = nm ? lexicon->enter(nm)->sp : NULL;}/* * Set the name of a particular member of an enum_type. Make sure it is * entered in the lexicon. The member number must be valid or an error will * occur. */voidenum_type::set_member (unsigned n, char *nm){ check_range(n); names[n] = nm ? lexicon->enter(nm)->sp : NULL;}/* * Set the value of a particular member of an enum_type. The member number * must be valid or an error will occur. */voidenum_type::set_value (unsigned n, int v){ check_range(n); assert_msg(is_signed() || (v >= 0), ("enum_type: negative member number not allowed in unsigned " "enumeration")); assert_msg((is_signed() && ((v >= 0) && ((v >> size() - 1) == 0)) || ((v < 0) && (~v >> size() - 1) == 0)) || (!is_signed() && ((v >> size()) == 0)), ("enum_type: member number doesn't fit in size allocated")); vals[n] = v;}/* * Search for a particular member of an enumerated type by either the * value or the name. If found, the index of the member is returned; * otherwise, "(unsigned)-1" is returned. */unsignedenum_type::find_member_by_value (int v){ for (unsigned i = 0; i < num_values(); i++) { if (value(i) == v) return i; } return (unsigned)-1;}unsignedenum_type::find_member_by_name (char *nm){ char *nn = nm ? lexicon->enter(nm)->sp : NULL; for (unsigned i = 0; i < num_values(); i++) { if (nn == member(i)) return i; } return (unsigned)-1;}/* * Write the enum_type fields onto an annotation. */annote *enum_type::cvt_to_annote (){ annote *an = new annote(k_enum_type); cvt_to_annote_base(an); an->immeds()->append(immed(name())); an->immeds()->append(immed(size())); an->immeds()->append(immed((int)is_signed())); an->immeds()->append(immed(num_values())); for (unsigned n = 0; n < num_values(); n++) { an->immeds()->append(immed(member(n))); an->immeds()->append(immed(value(n))); } return an;}/* * Read the enum_type fields from an annotation. */voidenum_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); my_name = an->immeds()->pop().string(); set_size(an->immeds()->pop().integer()); set_signed((boolean)(an->immeds()->pop().integer())); nvals = an->immeds()->pop().unsigned_int(); names = new char*[nvals]; vals = new int[nvals]; for (unsigned n = 0; n < nvals; n++) { names[n] = an->immeds()->pop().string(); vals[n] = an->immeds()->pop().integer(); }}type_node *enum_type::clone_internal(void){ return clone();}/* * Help print an enum_type. This method includes all of the enum_type * members. */voidenum_type::print_helper (FILE *f, int depth){ fputs(name(), f); if (is_signed()) { fputs(" signed", f); } else { fputs(" unsigned", f); } fprintf(f, " %d { ", size()); for (unsigned i = 0; i < num_values(); i++) { putc('\n', f); suif_indent(f, depth+1); fprintf(f, "%s = %d, ", member(i), value(i)); } if (num_values() > 0) { putc('\n', f); suif_indent(f, depth); } putc('}', f);}/* * Make a copy of an enum_type. */type_node *enum_type::copy (){ enum_type *result = new enum_type(name(), size(), is_signed(), num_values()); /* set the members and values */ for (unsigned n = 0; n < num_values(); n++) { result->set_member(n, member(n)); result->set_value(n, value(n)); } return result;}enum_type *enum_type::clone(void){ enum_type *result = new enum_type(name(), size(), is_signed(), num_values()); for (unsigned n = 0; n < num_values(); n++) { result->set_member(n, member(n)); result->set_value(n, value(n)); } copy_annotes(result); return result;}/* * Check if this type is compatible with another type_node. ENUM types * are compatible with INTs and other ENUMs of the same size and "signed- * ness". */booleanenum_type::compatible (type_node *t){ t = t->unqual(); if ((t->op() == TYPE_INT) || (t->op() == TYPE_ENUM)) { base_type *bt = (base_type *)t; if ((bt->is_signed() == is_signed()) && (bt->size() == size())) { return TRUE; } } return is_same(t);}/* * Compare enum_types (using name equivalence). */booleanenum_type::is_same (type_node *t){ return (t == (type_node *)this);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -