📄 types.cc
字号:
upper_bound().add_to_annote(an); return an;}/* * Read the array_type fields from an annotation. */voidarray_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); unsigned elemt_id = an->immeds()->pop().unsigned_int(); low = array_bound(an, symtab); uppr = array_bound(an, symtab); elemt = symtab->lookup_type_id(elemt_id); assert_msg(elemt, ("array_type::cvt_from_annote - type ID %u not found", elemt_id));}type_node *array_type::clone_internal(void){ return clone();}/* * Help print an array_type. Show the bounds and the element type. */voidarray_type::print_helper (FILE *f, int /* depth */){ fputc('[', f); lower_bound().print(f); fputs("..", f); upper_bound().print(f); fputs("] of ", f); assert_msg(elem_type(), ("array_type::print - missing element type")); elem_type()->print(f);}/* * Make a copy of an array_type. The element type is not copied. */type_node *array_type::copy (){ array_type *result = new array_type(elem_type()); result->set_lower_bound(lower_bound()); result->set_upper_bound(upper_bound()); return result;}array_type *array_type::clone(void){ array_type *result = new array_type(elem_type()->clone(), lower_bound(), upper_bound()); copy_annotes(result); return result;}/* * Check if this type is compatible with another type_node. Array types * should never need to be compared but this method does something reasonable * just in case. */booleanarray_type::compatible (type_node *t){ if (!t) return FALSE; return is_same(t->unqual());}/* * Check if an array_type is equivalent to another type_node. */booleanarray_type::is_same (type_node *t){ if (!type_node::is_same(t)) return FALSE; array_type *at = (array_type *)t; if (lower_bound() != at->lower_bound()) return FALSE; if (upper_bound() != at->upper_bound()) return FALSE; if (!elem_type() || !elem_type()->is_same(at->elem_type())) return FALSE; return TRUE;}/*****************************************************************************//* * Create a new func_type. The argument information is assumed * unknown. */func_type::func_type (type_node *r) : ret(r), nargs(0), argts(NULL), vargs(FALSE), arg_info(FALSE){ set_op(TYPE_FUNC);}/* * Create a new func_type. The argument array is allocated and initialized. * The individual argument types must be set separately. */func_type::func_type (type_node *r, unsigned n, boolean varargs, boolean know_args) : ret(r), nargs(n), argts(0), vargs(varargs), arg_info(know_args){ assert(know_args || ((n == 0) && (!varargs))); set_op(TYPE_FUNC); if (nargs == 0) { argts = NULL; } else { argts = new type_node*[nargs]; for (unsigned i = 0; i < nargs; i++) { argts[i] = NULL; } }}func_type::func_type (boolean varargs, type_node *r) : ret(r), nargs(0), argts(0), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC);}func_type::func_type (type_node *r, type_node *arg, boolean varargs) : ret(r), nargs(1), argts(new type_node *[1]), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC); argts[0] = arg;}func_type::func_type (type_node *r, type_node *arg1, type_node *arg2, boolean varargs) : ret(r), nargs(2), argts(new type_node*[2]), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC); argts[0] = arg1; argts[1] = arg2;}func_type::func_type (type_node *r, type_node *arg1, type_node *arg2, type_node *arg3, boolean varargs) : ret(r), nargs(3), argts(new type_node*[3]), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC); argts[0] = arg1; argts[1] = arg2; argts[2] = arg3;}func_type::func_type (type_node *r, type_node *arg1, type_node *arg2, type_node *arg3, type_node *arg4, boolean varargs) : ret(r), nargs(4), argts(new type_node*[4]), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC); argts[0] = arg1; argts[1] = arg2; argts[2] = arg3; argts[3] = arg4;}func_type::func_type (type_node *r, type_node *arg1, type_node *arg2, type_node *arg3, type_node *arg4, type_node *arg5, boolean varargs) : ret(r), nargs(5), argts(new type_node*[5]), vargs(varargs), arg_info(TRUE){ set_op(TYPE_FUNC); argts[0] = arg1; argts[1] = arg2; argts[2] = arg3; argts[3] = arg4; argts[4] = arg5;}func_type::~func_type (){ if (argts) delete[] argts;}/* * Check if an argument number is valid. */voidfunc_type::check_range (unsigned n){ assert_msg(n < num_args(), ((num_args() > 0) ? (char *) "func_type: argument number %u out of range 0 to %u" : (char *) "func_type: argument number %u is invalid for function " "type with zero arguments", n, num_args() - 1));}/* * Change the number of arguments. If the number is larger than before, * the argument type array is reallocated. */voidfunc_type::set_num_args (unsigned n){ if ((n > 0) && !args_known()) set_args_known(); if (n <= nargs) { nargs = n; return; } type_node **new_args = new type_node*[n]; /* copy the old arguments (as much as possible) */ unsigned i; for (i = 0; (i < nargs) && (i < n); i++) { new_args[i] = argts[i]; } /* initialize any new arg fields */ for (unsigned j = nargs; j < n; j++) { new_args[i] = NULL; } nargs = n; if (argts != NULL) delete[] argts; argts = new_args;}/* * Set the argument information to be unknown. */voidfunc_type::set_args_unknown (void){ set_num_args(0); set_varargs(FALSE); arg_info = FALSE;}/* * Set one of the argument types. The argument number must be valid or an * error will occur. */voidfunc_type::set_arg_type (unsigned n, type_node *t){ check_range(n); argts[n] = t;}type_node *func_type::ref_type (unsigned num){ if (num == 0) return return_type(); else return arg_type(num - 1);}voidfunc_type::set_ref_type (unsigned num, type_node *new_type){ if (num == 0) set_return_type(new_type); else set_arg_type(num - 1, new_type);}/* * Write the func_type fields onto an annotation. */annote *func_type::cvt_to_annote (){ annote *an = new annote(k_func_type); cvt_to_annote_base(an); assert_msg(return_type(), ("func_type::cvt_to_annote - missing return type")); if (write_scope != NULL) return_type()->write_check(); unsigned ret_id = return_type()->type_id(); an->immeds()->append(immed(ret_id)); an->immeds()->append(immed(num_args())); unsigned arg_flag = ((unsigned)(has_varargs())) | (((unsigned)(!args_known())) << 1); an->immeds()->append(immed(arg_flag)); for (unsigned i = 0; i < num_args(); i++) { assert_msg(arg_type(i), ("func_type::cvt_to_annote - missing type for " "argument %u", i)); if (write_scope != NULL) arg_type(i)->write_check(); unsigned arg_id = arg_type(i)->type_id(); an->immeds()->append(immed(arg_id)); } return an;}/* * Read the func_type fields from an annotation. */voidfunc_type::cvt_from_annote (annote *an, base_symtab *symtab){ type_node::cvt_from_annote(an, symtab); unsigned ret_id = an->immeds()->pop().unsigned_int(); ret = symtab->lookup_type_id(ret_id); assert_msg(ret, ("func_type::cvt_from_annote - type ID %u not found", ret_id)); nargs = an->immeds()->pop().unsigned_int(); unsigned arg_flags = an->immeds()->pop().unsigned_int(); vargs = (arg_flags & 0x1); if (nargs == (unsigned)-1) { /* old-style format, for backward compatibility */ nargs = 0; arg_info = FALSE; } else { arg_info = !((arg_flags & 0x2) >> 1); } argts = new type_node*[num_args()]; for (unsigned i = 0; i < num_args(); i++) { unsigned arg_id = an->immeds()->pop().unsigned_int(); argts[i] = symtab->lookup_type_id(arg_id); assert_msg(argts[i], ("func_type::cvt_from_annote - type ID %u not " "found", arg_id)); }}type_node *func_type::clone_internal(void){ return clone();}/* * Help print a func_type. Show the argument types, including "..." if * the function has a variable argument list, and the return type. */voidfunc_type::print_helper (FILE *f, int /* depth */){ /* print the argument types */ fputs("(", f); if (args_known()) { unsigned n; for (n = 0; n + 1 < num_args(); n++) { if(arg_type(n)) { arg_type(n)->print(f); } else { fputs("<<MISSING TYPE>>", f); } fputs(", ", f); } if (num_args() > 0) { if(arg_type(n)) { arg_type(n)->print(f); } else { fputs("<<MISSING TYPE>>", f); } } if (has_varargs()) { if (num_args() > 0) fputs(", ", f); fputs("...", f); } } else { fputs("??", f); } fputs(") returns ", f); if(return_type()) { return_type()->print(f); } else { fputs("<<MISSING RETURN TYPE>>", f); }}/* * Make a copy of a func_type. The return and argument types are not copied. */type_node *func_type::copy (){ /* create new func_type */ func_type *result = new func_type(return_type(), num_args(), has_varargs(), args_known()); /* set the argument types */ for (unsigned n = 0; n < num_args(); n++) { result->set_arg_type(n, arg_type(n)); } return result;}func_type *func_type::clone(void){ func_type *result = new func_type(return_type()->clone(), num_args(), has_varargs(), args_known()); for (unsigned n = 0; n < num_args(); n++) { result->set_arg_type(n, arg_type(n)->clone()); } copy_annotes(result); return result;}/* * Check if this type is compatible with another type_node. Function types * should never need to be compared but this method does something reasonable * just in case. */booleanfunc_type::compatible (type_node *t){ if (!t) return FALSE; return is_same(t->unqual());}/* * Check if this func_type is equivalent to another type_node. */booleanfunc_type::is_same (type_node *t){ if (!type_node::is_same(t)) return FALSE; func_type *ft = (func_type *)t; if (args_known() != ft->args_known()) return FALSE; if (num_args() != ft->num_args()) return FALSE; if (!return_type() || !return_type()->is_same(ft->return_type())) return FALSE; if (has_varargs() != ft->has_varargs()) return FALSE; /* compare the argument types */ for (unsigned n = 0; n < num_args(); n++) { if (!arg_type(n) || !arg_type(n)->is_same(ft->arg_type(n))) return FALSE; } return TRUE;}/*****************************************************************************//* * Create a new struct_type. The field arrays are allocated and initialized, * but the individual field names, types, and offset must be set separately. */struct_type::struct_type (type_ops o, int s, char *nm, unsigned n) : my_name(0), sz(s), ntypes(n), types(new type_node*[n]), names(new char*[n]), offsets(new int[n]){ assert_msg((o == TYPE_GROUP) || (o == TYPE_STRUCT) || (o == TYPE_UNION), ("attempt to create struct of non-struct type")); set_op(o); set_name(nm); /* initialize the fields */ for (unsigned i = 0; i < ntypes; i++) { types[i] = NULL; names[i] = NULL; offsets[i] = 0; }}struct_type::~struct_type (){ if (types) delete[] types; if (names) delete[] names; if (offsets) delete[] offsets;}/* * Check if a field number is valid. */voidstruct_type::check_range (unsigned n){ assert_msg(n < num_fields(), ((num_fields() > 0) ? (char *) "struct_type: field number %u out of range 0 to %u" : (char *) "struct_type: field number %u is invalid for structure " "type with zero fields", n, num_fields() - 1));}/* * Change the number of fields. If the number is larger than before, the * field arrays are reallocated. */voidstruct_type::set_num_fields (unsigned n){ if (n <= ntypes) { ntypes = n; return; } type_node **new_types = new type_node*[n]; char **new_names = new char*[n]; int *new_offsets = new int[n]; /* copy the old fields (as much as possible) */ unsigned i; for (i = 0; (i < ntypes) && (i < n); i++) { new_types[i] = types[i]; new_names[i] = names[i]; new_offsets[i] = offsets[i]; } /* initialize any new fields */ for (unsigned j = ntypes; j < n; j++) { new_types[i] = NULL; new_names[i] = NULL; new_offsets[i] = 0; } ntypes = n; delete[] types; delete[] names; delete[] offsets; types = new_types; names = new_names; offsets = new_offsets;}/* * Set the name of a struct_type. Make sure that it is entered in the * lexicon. */voidstruct_type::set_name (char *nm){ my_name = nm ? lexicon->enter(nm)->sp : NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -