📄 ctree.cc
字号:
/* file "ctree.cc" *//* 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>/* * Implementation of the C abstract syntax tree class. */#pragma implementation "ctree.h"#include "s2c.h"#include <string.h>/* * This is the table of ctree operators, their associativity, * commutivity, and printable representation. */static type_node *op_type_conv(type_node *the_type);static type_node *usual_arith_conv(type_node *type_1, type_node *type_2);static type_node *integral_promotions(type_node *the_type);static enum C_types c_int_promotions(enum C_types c_type, boolean *is_signed);static boolean assign_convert_implicit(type_node *dest_type, type_node *source_type);static boolean call_convert_implicit(type_node *dest_type, type_node *source_type);static enum C_types get_c_arith_type(type_node *the_type);struct _ctree_oper_attr ctree_oper_attr[] = { { 16, ctree_leftassoc, 0, "" }, { 15, ctree_leftassoc, 0, "int" }, { 15, ctree_leftassoc, 0, "char" }, { 15, ctree_leftassoc, 0, "float" }, { 15, ctree_leftassoc, 0, "enum" }, { 15, ctree_leftassoc, 0, "string" }, { 15, ctree_leftassoc, 0, "symbol" }, { 15, ctree_leftassoc, 0, "funcdecl" }, { 15, ctree_leftassoc, 0, "vardecl" }, { 15, ctree_leftassoc, 0, "vardef" }, { 15, ctree_leftassoc, 0, "typedecl" }, { 15, ctree_leftassoc, 0, "forward typedecl" }, { 15, ctree_leftassoc, 0, "goto" }, { 15, ctree_leftassoc, 0, "break" }, { 15, ctree_leftassoc, 0, "continue" }, { 15, ctree_leftassoc, 0, "return" }, { 15, ctree_leftassoc, 0, "label" }, { 15, ctree_leftassoc, 0, "case" }, { 15, ctree_leftassoc, 0, "default" }, { 15, ctree_leftassoc, 0, "for" }, { 15, ctree_leftassoc, 0, "if" }, { 15, ctree_leftassoc, 0, "do" }, { 15, ctree_leftassoc, 0, "switch" }, { 15, ctree_leftassoc, 0, "{" }, { 14, ctree_leftassoc, 0, "->" }, { 14, ctree_leftassoc, 0, "." }, { 14, ctree_leftassoc, 0, "[]" }, { 14, ctree_leftassoc, 0, "CALL" }, { 14, ctree_leftassoc, 0, "macro" }, { 13, ctree_leftassoc, 0, "++" }, { 13, ctree_leftassoc, 0, "++" }, { 13, ctree_leftassoc, 0, "--" }, { 13, ctree_leftassoc, 0, "--" }, { 13, ctree_leftassoc, 0, "~" }, { 13, ctree_leftassoc, 0, "!" }, { 13, ctree_leftassoc, 0, "-" }, { 13, ctree_leftassoc, 0, "&" }, { 13, ctree_leftassoc, 0, "*" }, { 13, ctree_leftassoc, 0, "()" }, { 12, ctree_leftassoc, 1, "*" }, { 12, ctree_leftassoc, 0, "/" }, { 12, ctree_leftassoc, 0, "%" }, { 11, ctree_leftassoc, 1, "+" }, { 11, ctree_leftassoc, 0, "-" }, { 10, ctree_leftassoc, 0, "<<" }, { 10, ctree_leftassoc, 0, ">>" }, { 9, ctree_leftassoc, 0, "<" }, { 9, ctree_leftassoc, 0, "<=" }, { 9, ctree_leftassoc, 0, ">" }, { 9, ctree_leftassoc, 0, ">=" }, { 8, ctree_leftassoc, 0, "==" }, { 8, ctree_leftassoc, 0, "!=" }, { 7, ctree_leftassoc, 0, "&" }, { 6, ctree_leftassoc, 0, "^" }, { 5, ctree_leftassoc, 0, "|" }, { 4, ctree_leftassoc, 1, "&&" }, { 3, ctree_leftassoc, 1, "||" }, { 2, ctree_leftassoc, 0, "?:" }, { 1, ctree_leftassoc, 0, "=" }, { 1, ctree_leftassoc, 0, "+=" }, { 1, ctree_leftassoc, 0, "-=" }, { 0, ctree_leftassoc, 1, "," }, { 0, ctree_leftassoc, 1, ";" },};#define grandchild(i,j) ((ctree*)(*(child(i)->children))[j])/* * Convert a SUIF op to a ctree op. */ctree_op ctree::ctree_io_to_op(if_ops n){ switch (n) { case io_add: return ctree_add; case io_sub: return ctree_sub; case io_neg: return ctree_neg; case io_mul: return ctree_mult; case io_div: return ctree_div; case io_rem: return ctree_mod; case io_not: return ctree_compl; case io_and: return ctree_bitand; case io_ior: return ctree_bitor; case io_xor: return ctree_bitxor; case io_asr: case io_lsr: return ctree_rshift; case io_lsl: return ctree_lshift; case io_cvt: return ctree_conv; case io_lod: return ctree_deref; case io_seq: return ctree_eq; case io_sne: return ctree_neq; case io_sl: return ctree_lt; case io_sle: return ctree_lte; default: assert(FALSE); } assert(FALSE); return ctree_semi;}/* * Indent for readability. */static void ctree_indent(io_class* out, int n){ for (int i=0; i<n; i++) out->printf(" ");}/* * ctree constructors. */ctree::ctree(void){ op = ctree_semi; type = type_error; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop){ op = theop; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop, boolean is_foldable, type_node *thetype){ op = theop; type = thetype; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = is_foldable; comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop, type_node *thetype, const i_integer &val){ op = theop; type = thetype; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; set_integer_val(val); comments = NULL; comment_space = 0;}ctree::ctree(type_node *thetype, immed float_immed){ op = ctree_floatconst; type = thetype; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; set_float_val(float_immed); comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop, char *val){ op = theop; type = NULL; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; leafval.s = val; comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop, char *val, type_node *the_type){ op = theop; type = the_type; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; leafval.s = val; comments = NULL; comment_space = 0;}ctree::ctree(ctree_op theop, sym_node *val, type_node *t){ op = theop; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; leafval.y = val; type = t; comments = NULL; comment_space = 0; if ((theop == ctree_vardecl) || (theop == ctree_vardef) || (theop == ctree_funcdecl) || (theop == ctree_funcdef) || (theop == ctree_label)) { add_object_comments(val); }}ctree::ctree(ctree_op theop, type_node *val){ op = theop; children = new ctree_list; cached_child = NULL; cached_size = 0; foldable = FALSE; leafval.t = val; comments = NULL; comment_space = 0;}/* * ctree destructor */ctree::~ctree(){ for (int i=0; i<N(); i++) delete child(i); delete children; if (comments != NULL) delete[] comments;}/* * Return number of elements. This value is cached because recalculating it * requires iterating through the entire list of children. */int ctree::N(void) { if (cached_size == 0) cached_size = children->count(); return cached_size; }/* * Return child number n. * * The method of iterating through children used all over the code is a loop * of the form: * * for (int i=0; i<N(); i++) * <function>(child(i)); * * If ctree:child() and ctree::N() just called the corresponding functions on * the ``children'' list every time, this would be an N^2 operation where N is * the size of the list. This was the original approach, but it turns out * that large lists sometimes occur and lead to unacceptable performance. * In particular, some Fortran benchmarks have arrays of 150,000 or more * elements initialized, leading to comma lists of that many elements. N^2 * performance is unacceptable in that case; the program can run all night and * not finish. * * To fix this problem, both the last values of N() and the element of the * list used by child() are cached. Then the performance for this typical * iteration becomes linear. */ctree *ctree::child(int n) { if ((cached_child == NULL) || (cached_child_num > n)) { cached_child = children->head(); cached_child_num = 0; } while (cached_child_num < n) { assert(cached_child != NULL); cached_child = cached_child->next(); ++cached_child_num; } assert(cached_child != NULL); return cached_child->contents; }i_integer ctree::integer_val(void) const { if (leafval.i.is_c_int) return leafval.i.u.i; else return immed_to_ii(immed(im_extended_int, leafval.i.u.str)); }void ctree::set_integer_val(const i_integer &new_value) { if (new_value.is_c_int()) { leafval.i.is_c_int = TRUE; leafval.i.u.i = new_value.c_int(); } else { leafval.i.is_c_int = FALSE; immed the_immed = ii_to_immed(new_value); assert(the_immed.kind() == im_extended_int); leafval.i.u.str = the_immed.ext_integer(); } }immed ctree::float_val(void) const { assert(op == ctree_floatconst); if (leafval.f.is_c_double) return immed(leafval.f.u.f); else return immed(im_extended_float, leafval.f.u.str); }void ctree::set_float_val(immed new_value) { assert(op == ctree_floatconst); if (new_value.is_flt()) { leafval.f.is_c_double = TRUE; leafval.f.u.f = new_value.flt(); } else if (new_value.is_ext_flt()) { leafval.f.is_c_double = FALSE; leafval.f.u.str = new_value.ext_flt(); } else { assert(FALSE); } }void ctree::replace_child(int child_num, ctree *new_child) { if ((cached_child == NULL) || (cached_child_num > child_num)) { cached_child = children->head(); cached_child_num = 0; } while (cached_child_num < child_num) { assert(cached_child != NULL); cached_child = cached_child->next(); ++cached_child_num; } assert(cached_child != NULL); cached_child->contents = new_child; }void ctree::add_comment(char *comment) { if (comments != NULL) { for (int space_num = 0; space_num + 1 < comment_space; ++space_num) { if (comments[space_num] == NULL) { comments[space_num] = comment; comments[space_num + 1] = NULL; return; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -