📄 types.cc
字号:
/* Implementation of High-Level Types *//* Copyright (c) 1994 Stanford University All rights reserved. This software is provided under the terms described in the "suif_copyright.h" include file. */#include <suif_copyright.h>#define _MODULE_ "libsuif.a"#pragma implementation "types.h"#define RCS_BASE_FILE types_cc#include "suif1.h"#include "suif_internal.h"RCS_BASE( "$Id: types.cc,v 1.2 1999/08/25 03:29:19 brm Exp $")/* predefined types */type_node *type_error = NULL;type_node *type_v0 = NULL;type_node *type_s8 = NULL;type_node *type_s16 = NULL;type_node *type_s32 = NULL;type_node *type_s64 = NULL;type_node *type_u8 = NULL;type_node *type_u16 = NULL;type_node *type_u32 = NULL;type_node *type_u64 = NULL;type_node *type_f32 = NULL;type_node *type_f64 = NULL;type_node *type_f128 = NULL;/* portable types */type_node *type_void = NULL;type_node *type_ptr = NULL;type_node *type_char = NULL;type_node *type_signed_char = NULL;type_node *type_unsigned_char = NULL;type_node *type_signed_short = NULL;type_node *type_unsigned_short = NULL;type_node *type_signed = NULL; /* int */type_node *type_unsigned = NULL; /* int */type_node *type_signed_long = NULL;type_node *type_unsigned_long = NULL;type_node *type_signed_longlong = NULL;type_node *type_unsigned_longlong = NULL;type_node *type_ptr_diff = NULL;type_node *type_float = NULL;type_node *type_double = NULL;type_node *type_longdouble = NULL;type_node::type_node () : oper(TYPE_VOID), table(0), id(0){}voidtype_node::clear_type_id (){ if (parent() != NULL) parent()->register_type_id_change(this, 0); set_type_id(0);}/* * Check if a type is a group, a structure, a union, or an enumeration. * These are all of the named type classes. */booleantype_node::is_named (){ if (op() == TYPE_GROUP) return TRUE; if (op() == TYPE_STRUCT) return TRUE; if (op() == TYPE_UNION) return TRUE; if (op() == TYPE_ENUM) return TRUE; return FALSE;}/* * Check if a type is scalar. This rules out everything except integers, * floats, pointers, and enumerations. */booleantype_node::is_scalar (){ type_node *t = unqual(); if ((t->op() == TYPE_INT) || (t->op() == TYPE_FLOAT) || (t->op() == TYPE_PTR) || (t->op() == TYPE_ENUM)) { return TRUE; } return FALSE;}/* * Compare the base class fields for two type_nodes. This is not called * directly by users but may be used in the derived "is_same" methods. */booleantype_node::is_same (type_node *t){ if (!t) return FALSE; if (op() != t->op()) return FALSE; if (!is_same_annotes(t)) return FALSE; return TRUE;}/* * Check if another type node has the same annotations. Structured * annotations are automatically flattened so they can be compared. * Unregistered annotations are ignored. Note that this method assumes * that the annotation order is significant. */booleantype_node::is_same_annotes (type_node *t){ /* compare the annotations */ if (are_annotations() != t->are_annotations()) return FALSE; if (!are_annotations()) return TRUE; if (annotes()->count() != t->annotes()->count()) return FALSE; annote_list_iter anli(annotes()); annote_list_iter t_anli(t->annotes()); while (!anli.is_empty()) { assert(!t_anli.is_empty()); annote *an = anli.step(); annote *t_an = t_anli.step(); /* compare the annotation names */ if (an->name() != t_an->name()) return FALSE; immed_list *iml = an->immeds(); immed_list *t_iml = t_an->immeds(); /* ignore unregistered annotations */ if (!iml) continue; boolean no_diff = TRUE; /* check if the immed lists are the same length */ if (iml->count() != t_iml->count()) { no_diff = FALSE; } else { /* compare the immeds */ immed_list_iter imli(iml); immed_list_iter t_imli(t_iml); while (!imli.is_empty()) { assert(!t_imli.is_empty()); if (imli.step() != t_imli.step()) { no_diff = FALSE; break; } } } if (an->is_structured()) { delete iml; delete t_iml; } if (!no_diff) return FALSE; } return TRUE;}/* * Try to find the specified modifier type. Return NULL if it does * not exist. */modifier_type *type_node::find_modifier (type_ops mod){ if (!is_modifier()) return NULL; modifier_type *mt = (modifier_type *)this; if (op() == mod) return mt; return mt->base()->find_modifier(mod);}/* * Return a type which is a pointer to this type. If this type is * installed, the pointer type will be installed in the same place. * If this type is not installed, the pointer type will not be * installed. */ptr_type *type_node::ptr_to(void){ ptr_type *result = new ptr_type(this); if (parent() != NULL) result = (ptr_type *)(parent()->install_type(result)); return result;}/* * Print a type (short version) -- just use the type ID number. */voidtype_node::print (FILE *f){ fputs("t:", f); print_id_number(f, type_id());}/* * Print the type id, operator, and size. This abbreviated form is used * when printing the result_types of instructions. */voidtype_node::print_abbrev (FILE *f){ /* print the type_id number */ print(f); fputs(" (", f); switch (unqual()->op()) { case TYPE_INT: { base_type *bt = (base_type *)unqual(); if (bt->is_signed()) { putc('i', f); } else { putc('u', f); } break; } case TYPE_FLOAT: { putc('f', f); break; } case TYPE_VOID: { putc('v', f); break; } case TYPE_PTR: { putc('p', f); break; } case TYPE_ARRAY: { putc('a', f); break; } case TYPE_FUNC: { putc('n', f); break; } case TYPE_GROUP: { putc('g', f); break; } case TYPE_STRUCT: { putc('s', f); break; } case TYPE_UNION: { putc('n', f); break; } case TYPE_ENUM: { putc('e', f); break; } default: { assert_msg(FALSE, ("type_node::print_abbrev - invalid operator")); } } fprintf(f, ".%d)", size());}/* * Print all of the type information. This method is used for printing * symtabs. This handles the fields shared by all type_nodes and the * print_helper virtual function is used to print fields specific to the * derived classes. */voidtype_node::print_full (FILE *f, int depth){ suif_indent(f, depth); /* print the ID number */ print(f); switch (op()) { case TYPE_INT: { fputs(": int ", f); break; } case TYPE_FLOAT: { fputs(": float ", f); break; } case TYPE_VOID: { fputs(": void ", f); break; } case TYPE_PTR: { fputs(": ptr ", f); break; } case TYPE_ARRAY: { fputs(": array ", f); break; } case TYPE_FUNC: { fputs(": function ", f); break; } case TYPE_GROUP: { fputs(": group ", f); break; } case TYPE_STRUCT: { fputs(": struct ", f); break; } case TYPE_UNION: { fputs(": union ", f); break; } case TYPE_ENUM: { fputs(": enum ", f); break; } case TYPE_CONST: { fputs(": const ", f); break; } case TYPE_VOLATILE: { fputs(": volatile ", f); break; } case TYPE_CALL_BY_REF: { fputs(": call-by-ref ", f); break; } case TYPE_NULL: { fputs(": null ", f); break; } default: { assert_msg(FALSE, ("type_node::print - invalid operator")); } } /* print any fields specific to the type kind */ print_helper(f, depth); print_annotes(f, depth+1); putc('\n', f);}/* * Read a type_node from an input stream. The type_node must have already * been created in the symtab or one of its ancestors. */type_node *type_node::read (in_stream *is, base_symtab *symtab){ unsigned i = is->read_int(); type_node *result = symtab->lookup_type_id(i); assert_msg(result, ("type_node::read - type ID %u not found", i)); return result;}/* * Write a type_node to an output stream. The type_node must have a * non-zero ID number assigned before it can be written out. */voidtype_node::write (out_stream *os){ write_check(); os->write_int(id);}voidtype_node::write_check (void){ assert(write_scope != NULL); assert_msg(type_id() != 0, ("attempt to write reference to type with no type_id")); assert_msg(write_scope->is_visible(this), ("attempt to write reference to type #%u used outside its " "scope", id));}/* * Create a type_node from an annotation created by type_node::cvt_to_annote. * This function calls the appropriate constructor based on the name * of the annotation. This function only creates the type_nodes; it * doesn't read the details of the types (except the ID numbers) from * the annotations because there may be references to type_nodes that * haven't yet been created. */type_node *type_node::scan_from_annote (annote *an){ type_node *result = NULL; if (an->name() == k_int_type) { result = new base_type; result->set_op(TYPE_INT); } else if (an->name() == k_float_type) { result = new base_type; result->set_op(TYPE_FLOAT); } else if (an->name() == k_void_type) { result = new base_type; result->set_op(TYPE_VOID); } else if (an->name() == k_ptr_type) { result = new ptr_type; result->set_op(TYPE_PTR); } else if (an->name() == k_array_type) { result = new array_type; result->set_op(TYPE_ARRAY); } else if (an->name() == k_func_type) { result = new func_type; result->set_op(TYPE_FUNC); } else if (an->name() == k_group_type) { result = new struct_type; result->set_op(TYPE_GROUP); } else if (an->name() == k_struct_type) { result = new struct_type; result->set_op(TYPE_STRUCT); } else if (an->name() == k_union_type) { result = new struct_type; result->set_op(TYPE_UNION); } else if (an->name() == k_enum_type) { result = new enum_type; result->set_op(TYPE_ENUM); } else if (an->name() == k_const_type) { result = new modifier_type; result->set_op(TYPE_CONST); } else if (an->name() == k_volatile_type) { result = new modifier_type; result->set_op(TYPE_VOLATILE); } else if (an->name() == k_call_by_ref_type) { result = new modifier_type; result->set_op(TYPE_CALL_BY_REF); } else if (an->name() == k_null_type) { result = new modifier_type; result->set_op(TYPE_NULL); } assert_msg(result, ("type_node::scan_from_annote: unknown type kind")); /* get the ID number */ result->id = (*an->immeds())[0].unsigned_int(); return result;}/* * Read the shared type_node fields from an annotation. This function is * called by the cvt_from_annote functions in the derived classes. Since * the ID number has already been read by scan_from_annote, it is just * checked here. */voidtype_node::cvt_from_annote (annote *an, base_symtab *){ assert(id == an->immeds()->pop().unsigned_int());}/* * Write the shared type_node fields onto an annotation. This function is * called by the cvt_to_annote functions to append to the annotation the * fields shared by all type_nodes. */voidtype_node::cvt_to_annote_base (annote *an){ an->immeds()->append(immed(id));}/* * Check if a type_node has been cloned, and if so, return its replacement. * Otherwise, just return this type_node. */type_node *type_node::clone_helper (replacements *r){ /* check if this type has been replaced */ type_node_list_iter old_tnli(&r->oldtypes); type_node_list_iter new_tnli(&r->newtypes); while (!old_tnli.is_empty()) { assert(!new_tnli.is_empty()); type_node *old_tn = old_tnli.step(); type_node *new_tn = new_tnli.step(); /* return the replacement */ if (old_tn == this) return new_tn; } return this;}/*****************************************************************************//* * Create a modifier type. */modifier_type::modifier_type (type_ops o, type_node *t) : type_node(), typ(t){ assert_msg((o == TYPE_CONST) || (o == TYPE_VOLATILE) || (o == TYPE_CALL_BY_REF) || (o == TYPE_NULL), ("attempt to create modifier_type with invalid operator")); set_op(o);}/* * Return the type size. Modifiers have no effect on the size. */intmodifier_type::size (){ if (!base()) return 0; return base()->size();}/* * Unqualify a type (remove the modifiers). Since we know this is a * modifier, we can just skip to the base type. */type_node *modifier_type::unqual (){ if (!base()) return NULL; return base()->unqual();}/* * Virtual methods to check for the various modifiers. The default return * value for these methods is FALSE. */booleanmodifier_type::is_const (){ if (op() == TYPE_CONST) return TRUE; if (base()) return base()->is_const(); return FALSE;}booleanmodifier_type::is_volatile (){ if (op() == TYPE_VOLATILE) return TRUE; if (base()) return base()->is_volatile(); return FALSE;}booleanmodifier_type::is_call_by_ref (){ if (op() == TYPE_CALL_BY_REF) return TRUE; if (base()) return base()->is_call_by_ref(); return FALSE;}type_node *modifier_type::ref_type (unsigned num){ assert(num == 0); return base();}voidmodifier_type::set_ref_type (unsigned num, type_node *new_type){ assert(num == 0); set_base(new_type);}/* * Help print a modifier type. Just print the base type. */voidmodifier_type::print_helper (FILE *f, int /* depth */){ assert_msg(base(), ("modifier_type::print_helper - missing base type")); base()->print(f);}/* * Make a copy of a modifier_type. (This isn't very useful!) */type_node *modifier_type::copy (){ modifier_type *result = new modifier_type(op(), base()); return result;}modifier_type *modifier_type::clone(void){ modifier_type *result = new modifier_type(op(), base()->clone()); copy_annotes(result); return result;}/* * Check if this type is the same as another type_node. The modifiers * may be in any order, so the "is_same_helper" method is used to check
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -