📄 simpl.c
字号:
/* @(#) simpl.c 1.7 1/27/86 17:49:27 */ /*ident "@(#)cfront:src/simpl.c 1.7" *//******************************************************************* C++ source for cfront, the C++ compiler front-end written in the computer science research center of Bell Labs Copyright (c) 1984 AT&T, Inc. All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.simpl.c: simplify the typechecked function remove: classes: class fct-calls operators value constructors and destructors new and delete operators (replace with function calls) initializers (turn them into statements) constant expressions (evaluate them) inline functions (expand the calls) enums (make const ints) unreachable code (delete it) make implicit coersions explicit in general you cannot simplify something twice*******************************************************************/#include "cfront.h"#include "size.h"#include <ctype.h>Pname new_fct;Pname del_fct;Pname vec_new_fct;Pname vec_del_fct;Pstmt del_list;Pstmt block_del_list;Pname ret_var;bit not_inl; // is the current function an inline?Pname curr_fct; // current functionPexpr init_list;Pexpr one;void simpl_init(){ Pname nw = new name(oper_name(NEW)); Pname dl = new name(oper_name(DELETE)); Pname vn = new name("_vec_new"); Pname vd = new name("_vec_delete"); new_fct = gtbl->insert(nw,0); /* void* operator new(long); */ delete nw; Pname a = new name; a->tp = long_type; new_fct->tp = new fct(Pvoid_type,a,1); new_fct->n_scope = EXTERN; PERM(new_fct); PERM(new_fct->tp); new_fct->use(); new_fct->dcl_print(0); del_fct = gtbl->insert(dl,0); /* void operator delete(void*); */ delete dl; a = new name; a->tp = Pvoid_type; del_fct->tp = new fct(void_type,a,1); del_fct->n_scope = EXTERN; PERM(del_fct); PERM(del_fct->tp); del_fct->use(); del_fct->dcl_print(0); a = new name; a->tp = Pvoid_type; Pname al = a; a = new name; a->tp = int_type; a->n_list = al; al = a; a = new name; a->tp = int_type; a->n_list = al; al = a; a = new name; a->tp = Pvoid_type; a->n_list = al; al = a; /* (Pvoid, int, int, Pvoid) */ vec_new_fct = gtbl->insert(vn,0); delete vn; vec_new_fct->tp = new fct(Pvoid_type,al,1); vec_new_fct->n_scope = EXTERN; PERM(vec_new_fct); PERM(vec_new_fct->tp); vec_new_fct->use(); vec_new_fct->dcl_print(0); a = new name; a->tp = int_type; al = a; a = new name; a->tp = Pvoid_type; a->n_list = al; al = a; a = new name; a->tp = int_type; a->n_list = al; al = a; a = new name; a->tp = int_type; a->n_list = al; al = a; a = new name; a->tp = Pvoid_type; a->n_list = al; al = a; /* (Pvoid, int, int, Pvoid, int) */ vec_del_fct = gtbl->insert(vd,0); delete vd; vec_del_fct->tp = new fct(void_type,al,1); vec_del_fct->n_scope = EXTERN; PERM(vec_del_fct); PERM(vec_del_fct->tp); vec_del_fct->use(); vec_del_fct->dcl_print(0); one = new expr(IVAL,(Pexpr)1,0); one->tp = int_type; PERM(one);}Ptable scope; /* current scope for simpl() */Pname expand_fn; /* name of function being expanded or 0 */Ptable expand_tbl; /* scope for inline function variables */Pname classdef.has_oper(TOK op){ char* s = oper_name(op); Pname n; if (this == 0) error('i',"0->has_oper(%s)",s); n = memtbl->lookc(s,0); if (n == 0) return 0; switch (n->n_scope) { case 0: case PUBLIC: return n; default: return 0; }}int no_of_returns;void name.simpl(){ if (base == PUBLIC) return; if (tp == 0) error('i',"%n->name.simple(tp==0)",this); switch (tp->base) { case 0: error('i',"%n->name.simpl(tp->base==0)",this); case OVERLOAD: { Plist gl; for (gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl(); break; } case FCT: { Pfct f = (Pfct)tp; Pname n; Pname th = f->f_this;//error('d',"simpl%n tp=%t def=%d th=%d n_oper%k",this,tp,tp->defined,th,n_oper); if (th) { th->n_list = f->argtype; if (n_oper == CTOR) f->s_returns = th->tp; } if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return; // tp->defined |= SIMPLIFIED; for (n=(th)?th:f->argtype; n; n=n->n_list) n->simpl(); if (f->body) { Ptable oscope = scope; scope = f->body->memtbl; if (scope == 0) error('i',"%n memtbl missing",this); curr_fct = this; f->simpl(); if (f->f_inline && debug==0) { if (MIA<=f->nargs) { error('w',"too many arguments for inline%n (inline ignored)",this); f->f_inline = 0; scope = oscope; break; } int i = 0; for (n=(th)?th:f->argtype; n; n=n->n_list) { n->base = ANAME; n->n_val = i++; if (n->n_table != scope) error('i',"%s %d %d\n",n->string,n->n_table,scope); } expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0; expand_fn = this; if (expand_tbl) { // value returning: generate expression Pexpr ee = (Pexpr)f->body->expand(); /* the body still holds the memtbl */ f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee); /* print.c assumes expansion into comma expression */ } else { // not value return: can generate block f->f_expr = 0; f->body = (Pblock)f->body->expand(); } expand_fn = 0; expand_tbl = 0; } scope = oscope; } break; } case CLASS: Pclass(tp)->simpl(); break;/* case EOBJ: tp->base = INT; break;*/ default://error('d',"%n tp %t n_init %d",this,tp, n_initializer); break; } if (n_initializer) n_initializer->simpl(); tp->defined |= SIMPLIFIED;}void fct.simpl()/* call only for the function definition (body != 0) simplify argument initializers, and base class initializer, if any then simplify the body, if any for constructor:call allocator if this==0 and this not assigned to (auto and static objects call constructor with this!=0, the new operator generates calls with this==0) call base & member constructors for destructor: call deallocator (no effect if this==0) case base & member destructors for arguments and function return values look for class objects that must be passed by constructor "operator X(X&)". Allocate temporaries for class object expressions, and see if class object return values can be passed as pointers. call constructor and destructor for local class variables.*/{ Pexpr th = f_this; Ptable tbl = body->memtbl; Pstmt ss = 0; Pstmt tail; Pname cln; Pclass cl; Pstmt dtail = 0; not_inl = debug || f_inline==0; ret_var = tbl->look("_result",0); if (ret_var && not_inl==0) /* "_result" not used in inlines */ ret_var->n_used = ret_var->n_assigned_to = ret_var->n_addr_taken = 0; del_list = 0; block_del_list = 0; scope = tbl; if (scope == 0) error('i',"fct.simpl()"); if (th) { Pptr p = (Pptr)th->tp; cln = Pbase(p->typ)->b_name; cl = (Pclass)cln->tp; } if (curr_fct->n_oper == DTOR) { /* initialize del_list */ Pexpr ee; Pstmt es; class ifstmt * ifs; Pname bcln = cl->clbase; Pclass bcl; Pname d; Pname fa = new name("_free"); /* fake argument for dtor */ fa->tp = int_type; Pname free_arg = fa->dcl(body->memtbl,ARG); delete fa; f_this->n_list = free_arg; Ptable tbl = cl->memtbl; int i; Pname m; /* generate calls to destructors for all members of class cl */ for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) { Ptype t = m->tp; Pname cn; Pclass cl; Pname dtor; if (m->n_stclass == STATIC) continue; if (cn = t->is_cl_obj()) { cl = (Pclass)cn->tp; if (dtor = cl->has_dtor()) { /* dtor(this,0); */ Pexpr aa = new expr(ELIST,zero,0); ee = new ref(REF,th,m); ee = new ref(DOT,ee,dtor); ee = new call(ee,aa); ee->fct_name = dtor; ee->base = G_CALL; es = new estmt(SM,curloc,ee,0); if (dtail) dtail->s_list = es; else del_list = es; dtail = es; } } else if (cl_obj_vec) { cl = Pclass(cl_obj_vec->tp); if (dtor = cl->has_dtor()) { int esz = cl->tsizeof(); Pexpr noe = new expr(IVAL,Pexpr(t->tsizeof()/esz),0); Pexpr sz = new expr(IVAL,(Pexpr)esz,0); Pexpr mm = new ref(REF,th,m); Pexpr arg = new expr(ELIST,dtor,zero); dtor->lval(ADDROF); arg = new expr(ELIST,sz,arg); arg = new expr(ELIST,noe,arg); arg = new expr(ELIST,mm,arg); ee = new call(vec_del_fct,arg); ee->base = G_CALL; es = new estmt(SM,curloc,ee,0); if (dtail) dtail->s_list = es; else del_list = es; dtail = es; } } } // delete base if (bcln && (bcl=(Pclass)bcln->tp) && (d=bcl->has_dtor()) ) { // base.dtor(this,_free); Pexpr aa = new expr(ELIST,free_arg,0); ee = new ref(REF,th,d); ee = new call(ee,aa); /*ee->fct_name = d; NO would suppress virtual */ ee->base = G_CALL; es = new estmt(SM,curloc,ee,0); } else { // if (_free) _delete(this); Pexpr aa = new expr(ELIST,th,0); ee = new call(del_fct,aa); ee->fct_name = del_fct; ee->base = G_CALL; es = new estmt(SM,curloc,ee,0); es = new ifstmt(curloc,free_arg,es,0); } free_arg->use(); Pname(th)->use(); if (dtail) dtail->s_list = es; else del_list = es; ifs = new ifstmt(curloc,th,del_list,0);/* ifs = new ifstmt(curloc,cc,es,0); if (dtail) dtail->s_list = ifs; else del_list = ifs; dtail = ifs;*/ del_list = ifs; if (del_list) del_list->simpl(); }int ass_count; if (curr_fct->n_oper == CTOR) { Pexpr ee; Ptable tbl = cl->memtbl; Pname m; int i; /* generate: this=base::base(args) this->b_init == base::base(args) or 0 */ if (b_init) {//error('d',"b_init %k",b_init->base); switch (b_init->base) { case ASSIGN: case CM: break; default: { Pcall cc = (Pcall)b_init; Pname bn = cc->fct_name; Pname tt = Pfct(bn->tp)->f_this; ass_count = tt->n_assigned_to; cc->simpl(); init_list = new expr(ASSIGN,th,cc); } } } else { ass_count = 0; init_list = 0; } if (cl->virt_count) { /* generate: this->_vptr=virt_init; */ Pname vp = cl->memtbl->look("_vptr",0); Pexpr vtbl = new text_expr(cl->string,"_vtbl"); ee = new ref(REF,th,vp); ee = new expr(ASSIGN,ee,vtbl); init_list = (init_list) ? new expr(CM,init_list,ee) : ee; }for (Pname nn = f_init; nn; nn=nn->n_list) { if (nn->n_initializer == 0) continue; Pname m = tbl->look(nn->string, 0); if (m && m->n_table == tbl) m->n_initializer = nn->n_initializer;} /* generate cl.new(args) for all members of cl */ for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) { Ptype t = m->tp; Pname cn; Pclass cl; Pname ctor; switch (m->n_stclass) { case STATIC: case ENUM: continue; } switch (t->base) { case FCT: case OVERLOAD: case CLASS: case ENUM: continue; } if (m->base == PUBLIC) continue; if (cn=t->is_cl_obj()) { Pexpr ee = m->n_initializer; m->n_initializer = 0; // from fct must not persist until next fct if (ee == 0) { // try default cl = (Pclass)cn->tp; if (ctor = cl->has_ictor()) { ee = new ref(REF,th,m); ee = new ref(DOT,ee,ctor); ee = new call(ee,0); ee->fct_name = ctor; ee->base = G_CALL; ee = ee->typ(tbl); // look for default arguments } else if (cl->has_ctor()) { error("M%n needsIr (no default constructor forC %s)",m,cl->string); } } if (ee) { ee->simpl(); if (init_list) init_list = new expr(CM,init_list,ee); else init_list = ee; } } else if (cl_obj_vec) { cl = (Pclass)cl_obj_vec->tp; if (ctor = cl->has_ictor()) { /* _new_vec(vec,noe,sz,ctor); */ int esz = cl->tsizeof(); Pexpr noe = new expr(IVAL,(Pexpr)(t->tsizeof()/esz),0); Pexpr sz = new expr(IVAL,(Pexpr)esz,0); Pexpr mm = new ref(REF,th,m); Pexpr arg = new expr(ELIST,ctor,0); /*ctor->take_addr();*/ ctor->lval(ADDROF); arg = new expr(ELIST,sz,arg); arg = new expr(ELIST,noe,arg); arg = new expr(ELIST,mm,arg); ee = new call(vec_new_fct,arg); ee->fct_name = vec_new_fct; ee->base = G_CALL; /* ee = ee->typ(tbl); look for default arguments */ ee->simpl(); if (init_list) init_list = new expr(CM, init_list,ee); else init_list = ee; } else if (cl->has_ctor()) { error("M%n[] needsIr (no default constructor forC %s)",m,cl->string); } } else if (m->n_initializer) { // init of non-class mem // set in fct.mem_init() if (init_list) init_list = new expr(CM,init_list,m->n_initializer); else init_list = m->n_initializer; m->n_initializer = 0; // from fct must not persist until next fct } else if (t->is_ref()) { error("referenceM%n needsIr",m); } else if (t->tconst() && vec_const==0) { error("constM%n needsIr",m); } } // for m } no_of_returns = 0; tail = body->simpl(); if (body->s == 0) body->empty = 1; // null function if (returns->base != VOID) { /* return must have been seen */ if (no_of_returns) { switch (tail->base) { case SM: switch (tail->e->base) { case ICALL: case G_CALL: /* not good enough */ goto dontknow; }; default:/*fprintf(stderr,"t %d %d\n",tail->base,tail->e->base);*/ if (strcmp(curr_fct->string,"main")) error('w',"maybe no value returned from%n",curr_fct); if (del_list) goto zaq; break; case RETURN: case IF: case SWITCH: case DO: case FOR: case LABEL: case BLOCK: case PAIR:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -