📄 simpl.c
字号:
e1->simpl(); if (e1->base == CM) { /* &( , name). => ( ... , &name)-> */ Pexpr ex = e1; cfr: switch (ex->e2->base) { case NAME: base = REF; ex->e2 = ex->e2->address(); break; case CM: ex = ex->e2; goto cfr; } } break; case ASSIGN: { Pfct f = (Pfct)curr_fct->tp; Pexpr th = f->f_this; if (e1) e1->simpl(); if (e2) e2->simpl(); if (th && th==e1) { if (curr_fct->n_oper == CTOR) { if (init_list) { /* this=e2 => (this=e2,init_list) */ base = CM; e1 = new expr(ASSIGN,e1,e2); e2 = init_list; } } } break; } } if (tp && tp->base==INT) { Neval = 0; int i = eval(); if (Neval == 0) { base = IVAL; e1 = (Pexpr)i; } }}void call.simpl()/* fix member function calls: p->f(x) becomes f(p,x) o.f(x) becomes f(&o,x) or if f is virtual: p->f(x) becomes ( *p->_vptr[ type_of(p).index(f)-1 ] )(p,x) replace calls to inline functions by the expanded code*/{ Pname fn = fct_name; Pfct f = (fn) ? (Pfct)fn->tp : 0; if (fn == 0) e1->simpl(); if (f) { switch(f->base) { case ANY: return; case FCT: break; case OVERLOAD: { Pgen g = (Pgen)f; fct_name = fn = g->fct_list->f; f = (Pfct)fn->tp; } } } if (f && curr_expr==this) { /* check for class object returning fct */ Pname cln = f->returns->is_cl_obj(); if (cln && Pclass(cln->tp)->has_dtor()) error('s',"%n returned by%n is not used (%n has destructor)",cln,fn,cln); }//error('d',"simpl call%n e1: %d%k",fn,e1,e1->base); switch (e1->base) { case DOT: case REF: { Pref r = (Pref)e1; Pexpr a1 = r->e1;//error('d',"simpl fn %s f %d fv %d",fn?fn->string:"?",f,f?f->f_virtual:0); if (f && f->f_virtual) { Pexpr a11 = 0; switch(a1->base) { // see if temporary might be needed case NAME: a11 = a1; break; case ADDROF: case G_ADDROF: if (a1->e2->base == NAME) a11 = a1; break; } if (e1->base == DOT) { if (a11) a11 = a11->address(); a1 = a1->address(); } if (a11 == 0) { /* temporary (maybe) needed e->f() => (t=e,t->f(t)) */ char* s = make_name('K'); Pname n = new name(s); n->tp = a1->tp; n = n->dcl(scope,ARG); /* no init! */ n->n_scope = FCT; n->assign(); a11 = n; a1 = new expr(ASSIGN,n,a1); a1->tp = n->tp; a1->simpl(); Pcall cc = new call(0,0); *cc = *this; base = CM; e1 = a1; e2 = cc; this = cc; } e2 = new expr(ELIST,a11,e2); int index = f->f_virtual; Pexpr ie = (1<index) ? new expr(IVAL,(Pexpr)(index-1),0) : 0; Pname vp = fn->n_table->look("_vptr",0); Pexpr vptr = new ref(REF,a11,vp); /* p->vptr */ Pexpr ee = new expr(DEREF,vptr,ie); /* p->vptr[i] */ Ptype pft = new ptr(PTR,f); ee = new texpr(CAST,pft,ee); /* (T)p->vptr[i] */ ee->tp = (Ptype)f->f_this; /* encode argtype */ e1 = new expr(DEREF,ee,0); /* *(T)p->vptr[i] */ /* e1->tp must be 0, means "argtype encoded" */ fct_name = 0; fn = 0; e2->simpl(); return; /* (*(T)p->vptr[i])(e2) */ } else {//error('d',"a1 %k%k%n",a1->base,e1->base,r->mem); if (e1->base == DOT) a1 = a1->address(); e2 = new expr(ELIST,a1,e2); e1 = r->mem; } } }//error('d',"ex1 %d %d %d",fn,f->f_inline,debug); e2->simpl();//error('d',"ex2 %d %d %d",fn,f->f_inline,debug); if (e1->base==NAME && e1->tp->base==FCT) { /* reconstitute fn destroyed to suppress "virtual" */ fct_name = fn = (Pname)e1; f = (Pfct)fn->tp; }//error('d',"ex3 %d %d %d",fn,f->f_inline,debug); if (fn && f->f_inline && debug==0) {//error('d',"expand%n",fn); Pexpr ee = f->expand(fn,scope,e2);//error('d',"expanded %d %d",fn,ee); if (ee) *Pexpr(this) = *ee; }}Pexpr curr_expr; /* to protect against an inline being expanded twice in a simple expression keep track of expressions being simplified */Pstmt stmt.simpl()/* return a pointer to the last statement in the list, or 0*/{ if (this == 0) error('i',"0->stmt.simpl()");/*error('d',"stmt.simpl %d%k e %d%k s %d%k sl %d%k\n",this,base,e,e?e->base:0,s,s?s->base:0,s_list,s_list?s_list->base:0); fflush(stderr);*/ curr_expr = e; switch (base) { default: error('i',"stmt.simpl(%k)",base); case ASM: break; case BREAK: case CONTINUE: if (block_del_list) { /* break => { _dtor()s; break; } continue => { _dtor()s; continue; } */ Pstmt bs = new stmt(base,where,0); Pstmt dl = block_del_list->copy(); base = BLOCK; s = new pair(where,dl,bs); break; } break; case DEFAULT: s->simpl(); break; case SM: if (e) e->simpl(); break; case RETURN: { /* return x; => { _ret_var = x; _dtor()s; return _ret_var; } return ctor(x); => { ctor(&_result,x); _dtor()s; return _ret_var; } return; => { _dtor()s; return; } OR (in constructors) { _dtor()s; return _this; } */ no_of_returns++; if (not_inl) { Pstmt as; if (e && e!=dummy) { Pexpr ee; if (e->base==G_CALL && e->fct_name && e->fct_name->n_oper==CTOR && e->e1->base==DOT ) { Pref r = (Pref)e->e1; r->e1 = ret_var; ee = e; } else { ee = new expr(ASSIGN,ret_var,e); } ee->simpl(); as = new estmt(SM,where,ee,0); } else as = 0; base = BLOCK; s = 0; d = 0; own_tbl = (memtbl) ? 1 : 0; Pblock(this)->simpl(); Pstmt dl = (del_list) ? del_list->copy() : 0; if (s) dl = (dl) ? new pair(where,s,dl) : s; Pstmt rs = new estmt(RETURN,where,(ret_var)?(Pexpr)ret_var:0,0); if (as) { if (dl) as = new pair(where,as,dl); s = new pair(where,as,rs); } else { if (curr_fct->n_oper == CTOR) { rs->e = Pfct(curr_fct->tp)->f_this; } s = (dl) ? new pair(where,dl,rs) : rs; } } else { if (e->base == VALUE) error('s',"inlineF returns constructor"); e->simpl(); } break; } case WHILE: case DO: e->simpl(); s->simpl(); break; case SWITCH: e->simpl(); s->simpl(); switch (s->base) { case DEFAULT: case LABEL: case CASE: break; case BLOCK: if (s->s) switch (s->s->base) { case BREAK: /* to cope with the "break; case" macro */ case CASE: case LABEL: case DEFAULT: break; default: goto df; } break; default: df: error('w',&s->where,"statement not reached: case label missing"); } break; case CASE: e->simpl(); s->simpl(); break; case LABEL: if (del_list) error('s',"label in block with destructors"); s->simpl(); break; case GOTO: /* If the goto is going to a different (effective) scope, * then it is necessary to activate all relevant destructors * on the way out of nested scopes, and issue errors if there * are any constructors on the way into the target. */ /* Only bother if the goto and label have different effective * scopes. (If mem table of goto == mem table of label, then * they're in the same scope for all practical purposes. */ { Pname n = scope->look( d->string, LABEL ); if (n == 0) error('i',&where,"label%n missing",d); if( n->n_realscope != scope ) { /* Find the root of the smallest subtree containing * the path of the goto. This algorithm is quadratic * only if the goto is to an inner or unrelated scope. */ Ptable r = 0; for(Ptable q=n->n_realscope; q!=gtbl; q=q->next) { for( Ptable p = scope; p != gtbl; p = p->next ) { if( p==q ) { r = p; /* found root of subtree! */ goto xyzzy; } } }xyzzy: if( r==0 ) error( 'i',&where,"finding root of subtree" ); /* At this point, r = root of subtree, n->n_realscope * = mem table of label, and scope = mem table of goto. */ /* Climb the tree from the label mem table to the table * preceding the root of the subtree, looking for * initializers and ctors. If the mem table "belongs" * to an unsimplified block(s), the n_initializer field * indicates presence of initializer, otherwise initializer * information is recorded in the init_stat field of * mem table. */ for( Ptable p=n->n_realscope; p!=r; p=p->next ) if( p->init_stat == 2 ) { error(&where,"goto%n pastD withIr",d); goto plugh; /* avoid multiple error msgs */ } else if( p->init_stat == 0 ) { int i; for(Pname nn=p->get_mem(i=1);nn;nn=p->get_mem(++i)) if(nn->n_initializer||nn->n_evaluated){ error(&nn->where,"goto%n pastId%n",d,nn); goto plugh; } }plugh: /* Proceed in a similar manner from the point of the goto, * generating the code to activate dtors before the goto. */ /* There is a bug in this code. If there are class objects * of the same name and type in (of course) different mem * tables on the path to the root of the subtree from the * goto, then the innermost object's dtor will be activated * more than once. */ { Pstmt dd = 0, ddt; for( Ptable p=scope; p!=r; p=p->next ) { int i; for(Pname n=p->get_mem(i=1);n;n=p->get_mem(++i)) { Pname cln; if (n->tp == 0) continue; /* label */ if ( cln=n->tp->is_cl_obj() ) { Pclass cl = (Pclass)cln->tp; Pname d = cl->has_dtor(); if (d) { /* n->cl.delete(0); */ Pref r = new ref(DOT,n,d); Pexpr ee = new expr(ELIST,zero,0); Pcall dl = new call(r,ee); Pstmt dls = new estmt(SM,n->where,dl,0); dl->base = G_CALL; dl->fct_name = d; if (dd) ddt->s_list = dls; else dd = dls; ddt = dls; } } else if (cl_obj_vec) { /* never "new x" is a pointer */ Pclass cl = (Pclass)cl_obj_vec->tp; Pname c = cl->has_ictor(); Pname d = cl->has_dtor(); if (d) { /* _vec_delete(vec,noe,sz,dtor,0); */ Pstmt dls; int esz = cl->tsizeof(); Pexpr noe = new expr(IVAL, (Pexpr)(n->tp->tsizeof()/esz),0); Pexpr sz = new expr(IVAL,(Pexpr)esz,0); Pexpr arg = new expr(ELIST,d,zero); d->lval(ADDROF); arg = new expr(ELIST,sz,arg); arg = new expr(ELIST,noe,arg); arg = new expr(ELIST,n,arg); arg = new call(vec_del_fct,arg); arg->base = G_CALL; arg->fct_name = vec_del_fct; dls = new estmt(SM,n->where,arg,0); if (dd) ddt->s_list = dls; else dd = dls; ddt = dls; } } } /* end mem table scan */ } /* end dtor loop */ /* "activate" the list of dtors obtained. */ if( dd ) { dd->simpl(); Pstmt bs = new stmt( base, where, 0 ); *bs = *this; base = PAIR; s = dd; s2 = bs; } } } /* end special case for non-local goto */ } break; case IF: e->simpl(); s->simpl(); if (else_stmt) else_stmt->simpl(); break; case FOR: /* "for (s;e;e2) s2; => s; while(e) {s2;e3}" */ if (for_init) { for_init->simpl(); if (for_init->base==SM && for_init->e->tp==void_type) error('s',"call of inline voidF in for-expression"); } if (e) e->simpl(); if (e2) { curr_expr = e2; e2->simpl(); if (e2->base==ICALL && e2->tp==void_type) error('s',"call of inline voidF in for-expression"); } s->simpl(); break; case BLOCK: Pblock(this)->simpl(); break; case PAIR: break; } /*if (s) s->simpl();*/ if (base!=BLOCK && memtbl) { int i; Pstmt t1 = (s_list) ? s_list->simpl() : 0; Pstmt ss = 0; Pname cln; for (Pname tn = memtbl->get_mem(i=1); tn; tn=memtbl->get_mem(++i)) {/*fprintf(stderr,"tmp %s tbl %d\n",tn->string,memtbl);*/ if ( cln=tn->tp->is_cl_obj() ) { Pclass cl = (Pclass)cln->tp; Pname d = cl->has_dtor(); if (d) { /* n->cl.delete(0); */ Pref r = new ref(DOT,tn,d); Pexpr ee = new expr(ELIST,zero,0); Pcall dl = new call(r,ee); Pstmt dls = new estmt(SM,tn->where,dl,0); dl->base = G_CALL; dl->fct_name = d; dls->s_list = ss; ss = dls;/*error('d',"%d (tbl=%d): %n.%n %d->%d",this,memtbl,tn,d,ss,ss->s_list);*/ } } } if (ss) { Pstmt t2 = ss->simpl(); switch (base) { case IF: Pstmt es = ss->copy(); if (else_stmt) { for (Pstmt t=es; t->s_list; t=t->s_list); t->s_list = else_stmt; } else_stmt = es; t2->s_list = s; s = ss; break; case RETURN: case WHILE: case FOR: case DO: case SWITCH: error('s',"E in%kS needs temporary ofC%n with destructor",base,cln); break; default: if (t1) { t2->s_list = s_list; s_list = ss; return t1; } s_list = ss; return t2; } } return (t1) ? t1 : this; } return (s_list) ? s_list->simpl() : this;}Pstmt stmt.copy()// now handles dtors in the expression of an IF stmt// not general!{ Pstmt ns = new stmt(0,curloc,0); *ns = *this; if (s) ns->s = s->copy(); if (s_list) ns->s_list = s_list->copy(); switch (base) { case PAIR: ns->s2 = s2->copy(); break; } return ns;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -