📄 types.cc
字号:
* for each possible modifier. */booleanmodifier_type::is_same (type_node *t){ if (!t) return FALSE; type_node *ut = unqual(); if (!ut || (!ut->is_same(t->unqual()))) return FALSE; if (is_same_helper(TYPE_CONST, t) && is_same_helper(TYPE_VOLATILE, t) && is_same_helper(TYPE_CALL_BY_REF, t) && is_same_helper(TYPE_NULL, t)) { return TRUE; } return FALSE;}booleanmodifier_type::is_same_helper (type_ops mod, type_node *t){ modifier_type *mt1 = find_modifier(mod); modifier_type *mt2 = t->find_modifier(mod); /* check if they are identical or both NULL */ if (mt1 == mt2) return TRUE; /* check if both types have the same modifier with the same annotations */ if (mt1 && mt2 && mt1->is_same_annotes(mt2)) return TRUE; return FALSE;}/* * Check if this type is compatible with another type_node. Modifiers * do not affect compatibility so they are ignored here. */booleanmodifier_type::compatible (type_node *t){ if (!t) return FALSE; type_node *ut = unqual(); if (!ut) return FALSE; return ut->compatible(t);}/* * Write the modifier_type fields onto an annotation. */annote *modifier_type::cvt_to_annote (){ annote *an; /* determine the annotation name from the type operator */ switch (op()) { case TYPE_CONST: { an = new annote(k_const_type); break; } case TYPE_VOLATILE: { an = new annote(k_volatile_type); break; } case TYPE_CALL_BY_REF: { an = new annote(k_call_by_ref_type); break; } case TYPE_NULL: { an = new annote(k_null_type); break; } default: { break; } } assert_msg(an, ("modifier_type::cvt_to_annote - invalid type operator")); cvt_to_annote_base(an); assert_msg(base(), ("modifier_type::cvt_to_annote - missing base type")); if (write_scope != NULL) base()->write_check(); unsigned base_id = base()->type_id(); an->immeds()->append(immed(base_id)); return an;}/* * Read the modifier_type fields from an annotation. */voidmodifier_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); unsigned base_id = an->immeds()->pop().unsigned_int(); typ = symtab->lookup_type_id(base_id); assert_msg(typ, ("modifier_type::cvt_from_annote - type ID %u not found", base_id));}type_node *modifier_type::clone_internal(void){ return clone();}/*****************************************************************************//* * Create a base type. */base_type::base_type (type_ops o, int s, boolean b) : sz(s), sgn(b){ assert_msg((o == TYPE_INT) || (o == TYPE_FLOAT) || (o == TYPE_VOID) || (o == TYPE_ENUM), ("attempt to create base_type with non-base operator")); set_op(o); if ((o == TYPE_INT) || (o == TYPE_ENUM)) { sgn = b; } else if (o == TYPE_VOID) { sgn = FALSE; } else { sgn = TRUE; }}/* * Write the base_type fields onto an annotation. */annote *base_type::cvt_to_annote (){ annote *an; /* determine the annotation name from the type operator */ switch (op()) { case TYPE_INT: { an = new annote(k_int_type); break; } case TYPE_FLOAT: { an = new annote(k_float_type); break;} case TYPE_VOID: { an = new annote(k_void_type); break; } default: { break; } } assert_msg(an, ("base_type::cvt_to_annote - invalid type operator")); cvt_to_annote_base(an); an->immeds()->append(immed(size())); an->immeds()->append(immed((int)is_signed())); return an;}/* * Read the base_type fields from an annotation. */voidbase_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); sz = an->immeds()->pop().integer(); sgn = (boolean)(an->immeds()->pop().integer());}type_node *base_type::clone_internal(void){ return clone();}/* * Help print a base_type. The only added fields to check are the * "is_signed" flag and the size. */voidbase_type::print_helper (FILE *f, int /* depth */){ if (op() == TYPE_INT) { if (is_signed()) { fputs("signed ", f); } else { fputs("unsigned ", f); } } fprintf(f, "%d", size());}/* * Make a copy of a base_type. */type_node *base_type::copy (){ base_type *result = new base_type(op(), size(), is_signed()); return result;}base_type *base_type::clone(void){ base_type *result = new base_type(op(), size(), is_signed()); copy_annotes(result); return result;}/* * Check if this type is compatible with another type_node. This is mostly * like "is_same" except that ENUMs may be compatible with INTs. */booleanbase_type::compatible (type_node *t){ t = t->unqual(); /* enums and ints may be compatible */ if ((t->op() == TYPE_ENUM) && (op() == TYPE_INT)) { enum_type *et = (enum_type *)t; if ((et->is_signed() == is_signed()) && (et->size() == size())) { return TRUE; } } if (t->op() != op()) return FALSE; base_type *bt = (base_type *)t; if (bt->size() != size()) return FALSE; if (bt->is_signed() != is_signed()) return FALSE; return TRUE;}/* * Check if this base_type is the same as another type_node. */booleanbase_type::is_same (type_node *t){ if (!type_node::is_same(t)) return FALSE; base_type *bt = (base_type *)t; if (bt->size() != size()) return FALSE; if (bt->is_signed() != is_signed()) return FALSE; return TRUE;}/*****************************************************************************//* * Create a new ptr_type. */ptr_type::ptr_type (type_node *r) : ref(r){ set_op(TYPE_PTR);}/* * Write the ptr_type fields onto an annotation. */annote *ptr_type::cvt_to_annote (){ annote *an = new annote(k_ptr_type); cvt_to_annote_base(an); assert_msg(ref_type(), ("ptr_type::cvt_to_annote - missing ref type")); if (write_scope != NULL) ref_type()->write_check(); unsigned ref_id = ref_type()->type_id(); an->immeds()->append(immed(ref_id)); return an;}/* * Read the ptr_type fields from an annotation. */voidptr_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); unsigned ref_id = an->immeds()->pop().unsigned_int(); ref = symtab->lookup_type_id(ref_id); assert_msg(ref, ("ptr_type::cvt_from_annote - type ID %u not found", ref_id));}type_node *ptr_type::clone_internal(void){ return clone();}/* * Help print a ptr_type. Just print the referent type. */voidptr_type::print_helper (FILE *f, int /* depth */){ fputs("to ", f); assert_msg(ref_type(), ("ptr_type::print - missing ref type")); ref_type()->print(f);}type_node *ptr_type::ref_type (unsigned num){ assert(num == 0); return ref_type();}voidptr_type::set_ref_type (unsigned num, type_node *new_type){ assert(num == 0); set_ref_type(new_type);}/* * Make a copy of a ptr_type. The referent type is not copied. */type_node *ptr_type::copy (){ ptr_type *result = new ptr_type(ref_type()); return result;}ptr_type *ptr_type::clone(void){ ptr_type *result = new ptr_type(ref_type()->clone()); copy_annotes(result); return result;}/* * Check if this type is compatible with another type_node. All pointers * are considered to be compatible with one another. */booleanptr_type::compatible (type_node *t){ if (!t || !(t = t->unqual())) return FALSE; if (t->op() != op()) return FALSE; return TRUE;}/* * Check if a ptr_type is equivalent to another type_node. */booleanptr_type::is_same (type_node *t){ if (!type_node::is_same(t)) return FALSE; ptr_type *pt = (ptr_type *)t; if (!ref_type() || !ref_type()->is_same(pt->ref_type())) return FALSE; return TRUE;}/*****************************************************************************//* * Global variable used for unknown array bounds. */const array_bound unknown_bound;/* * Retrieve a constant bound. An error occurs if the bound is not * a constant. */intarray_bound::constant () const{ assert_msg(is_constant(), ("array_bound::constant - bound is not constant")); return u.cnst;}/* * Retrieve a variable bound. An error occurs if the bound is not * a variable. */var_sym *array_bound::variable () const{ assert_msg(is_variable(), ("array_bound::variable - bound is not a variable")); return u.var;}/* * Print an array bound. Variables include the full chain_name from the * symbol table. If the bound is unknown, it is printed as an asterisk. */voidarray_bound::print (FILE *f){ if (is_constant()) { fprintf(f, "%d", constant()); } else if (is_variable()) { variable()->print(f); } else { fputc('*', f); }}/* * Array bound operators.... */array_bound &array_bound::operator= (const array_bound &b){ is_cnst = b.is_cnst; u = b.u; return *this;}booleanarray_bound::operator== (const array_bound &b){ if (is_unknown() && b.is_unknown()) return TRUE; if (is_constant() && b.is_constant()) return (constant() == b.constant()); if (is_variable() && b.is_variable()) return (variable() == b.variable()); return FALSE;}/* * Grab an array bound from the list of immeds in an annotation. * This is called by the array_type::cvt_from_annote function. */array_bound::array_bound (annote *an, base_symtab *symtab){ is_cnst = (boolean)(an->immeds()->pop().integer()); if (is_cnst) { u.cnst = an->immeds()->pop().integer(); } else { unsigned var_id = an->immeds()->pop().unsigned_int(); if (var_id == 0) { u.var = NULL; } else { u.var = (var_sym *)symtab->lookup_sym_id(var_id); assert_msg(u.var && u.var->is_var(), ("array_bound - variable ID (%u) not found", var_id)); } }}/* * Put an array bound on the list of immeds of an annotation. * This is called by the array_type::cvt_to_annote function. */voidarray_bound::add_to_annote (annote *an){ if (is_constant()) { an->immeds()->append(immed((int)TRUE)); an->immeds()->append(immed(constant())); } else if (is_variable()) { an->immeds()->append(immed((int)FALSE)); if (write_scope != NULL) variable()->write_check(); an->immeds()->append(immed(variable()->sym_id())); } else { an->immeds()->append(immed((int)FALSE)); an->immeds()->append(immed(0u)); }}/*****************************************************************************//* * Create a new array type. By default, the bounds are unknown. */array_type::array_type (type_node *elem, array_bound lb, array_bound ub) : elemt(elem), low(lb), uppr(ub){ set_op(TYPE_ARRAY); /* make sure constant bounds are valid */ if (lb.is_constant() && ub.is_constant()) { assert_msg(ub.constant() >= lb.constant(), ("array_type - upper bound smaller than lower bound")); }}/* * Check if the upper bound is unknown. As a consistency check, this * method also checks that if the upper bound is known, then the lower * bound must also be known. */booleanarray_type::are_bounds_unknown (){ if (upper_bound().is_unknown()) return TRUE; if (lower_bound().is_unknown()) { assert_msg(upper_bound().is_unknown(), ("array_type::are_bounds_unknown - " "only upper bound is known")); } return FALSE;}/* * Try to figure out the size (in bits) of an array. If the array bounds * are not constant, the result is zero. */intarray_type::size (){ if (!lower_bound().is_constant() || !upper_bound().is_constant() || !elem_type()) { return 0; } int lb = lower_bound().constant(); int ub = upper_bound().constant(); assert_msg(ub >= lb, ("array_type::size - " "upper bound smaller than lower bound")); return (ub - lb + 1) * elem_type()->size();}type_node *array_type::ref_type (unsigned num){ assert(num == 0); return elem_type();}voidarray_type::set_ref_type (unsigned num, type_node *new_type){ assert(num == 0); set_elem_type(new_type);}/* * Write the array_type fields onto an annotation. */annote *array_type::cvt_to_annote (){ annote *an = new annote(k_array_type); cvt_to_annote_base(an); assert_msg(elem_type(), ("array_type::cvt_to_annote - missing element type")); if (write_scope != NULL) elem_type()->write_check(); unsigned elemt_id = elem_type()->type_id(); an->immeds()->append(immed(elemt_id)); lower_bound().add_to_annote(an);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -