Mercurial > hg > CbC > old > device
view mc-inline.c @ 560:d6ff45d719a5 string-shared
string sharing
author | kono |
---|---|
date | Sat, 07 Jan 2006 18:11:53 +0900 |
parents | 528fed826f17 |
children | de0b0380c461 |
line wrap: on
line source
/* Micro-C Partial Evaluator Part */ /* $Id$ */ #include <stdio.h> #include "mc.h" #include "mc-parse.h" #include "mc-codegen.h" #include "mc-switch.h" #include "mc-code.h" #include "mc-inline.h" static int pvartable; static int pdisp; static int ret_register,ret_reg_mode; static int inline_lvars; /* Basic code generator from parse tree */ extern void st_decl(int e1){ // NMTBL *n = (NMTBL *)caddr(e1); // int stmode = cadddr(e1); } extern void st_if(int e1){ int l1,l2,slfree; int e2=caddr(e1),e3; // conv->if_(); slfree=lfree; checkret(); l1 = bexpr(car(e2),0,fwdlabel()); // conv->if_then_(); g_expr_u(cadr(e2)); checkret(); if ((e3=caddr(e2))) { // else // conv->if_else_(); if ((l2 = control)) gen_jmp(l2=fwdlabel()); fwddef(l1); g_expr_u(e3); checkret(); if (l2) fwddef(l2); } else { fwddef(l1); } // conv->if_endif_(); } extern void st_do(int e1){ int sbreak,scontinue,l; sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); clabel=fwdlabel(); control=1; checkret(); l=backdef(); // conv->dowhile_(); g_expr_u(cadddr(e1)); checkret(); // conv->dowhile_cond_(); bexpr(caddr(e1),1,l); // conv->dowhile_end_(); fwddef(blabel); clabel=scontinue; blabel=sbreak; } extern void st_while(int e1){ int sbreak,scontinue,e; sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); control=1; checkret(); clabel=backdef(); // conv->while_(); // conv->while_body_(); if(!(e=cadddr(e1))) { bexpr(caddr(e1),1,clabel); // conv->sm_(); } else { bexpr(caddr(e1),0,blabel); g_expr_u(e); checkret(); if(control) gen_jmp(clabel); } // conv->while_end_(); fwddef(blabel); clabel=scontinue; blabel=sbreak; } extern void st_for(int e1){ int p0,p1,p2,body; int l,e; int sbreak=blabel; int scontinue=clabel; e = caddr(e1); p0 = car(e); p1 = cadr(e); p2 = caddr(e); body = cadddr(e); blabel=fwdlabel(); // conv->for_(); if (p0) { checkret(); g_expr_u(p0); } // conv->for1_(); control=1; checkret(); l=backdef(); if (p1) { bexpr(p1,0,blabel); } // conv->for2_(); // conv->for_body_(); if (!p2) { clabel=l; g_expr_u(body); checkret(); } else { clabel=fwdlabel(); g_expr_u(body); checkret(); fwddef(clabel); g_expr_u(p2); } // conv->for_end_(); gen_jmp(l); fwddef(blabel); clabel=scontinue; blabel=sbreak; } extern void st_switch(int e1){ int sbreak,scase,sdefault,slfree,svalue,slist; int cst,e; checkret(); slist = cslist; cslist = 0; sbreak=blabel; /* save parents break label */ blabel=fwdlabel(); sdefault=dlabel; /* save parents default label */ dlabel=0; scase=cslabel; /* save parents next case label */ // conv->switch_(); slfree=lfree; svalue=csvalue1; /* save parents switch value */ e =caddr(e1); /* switch value */ if (car(e)==CONST) { cst = 1; csvalue1=glist2(CONST,cadr(e)); gen_jmp( cslabel=fwdlabel()); } else { cst = 0; gexpr(e,1); /* switch value */ csvalue1=csvalue() ; cslabel = control = 0; } // conv->switch_body_(); g_expr_u(cadddr(e1)); // conv->switch_end_(); checkret(); #if CASE_CODE if (!cst) { if (control) gen_jmp(blabel); genswitch(cslist,cslabel); } else if (!cslist) { if(dlabel) def_label(cslabel,dlabel); else fwddef(cslabel); } #else if (!(cst && cslist)) { if(dlabel) def_label(cslabel,dlabel); else fwddef(cslabel); } #endif free_glist2(csvalue1); if (cst && !cslist) { if(pending_jmp!=cslabel) fwddef(cslabel); else pending_jmp = 0; // cslabel is here } fwddef(blabel); csvalue1=svalue; cslabel=scase; dlabel=sdefault; blabel=sbreak; cslist = slist; } extern void st_comp(int e1){ g_expr_u(caddr(e1)); } extern void st_break(int e1){ checkret(); // conv->break_(); if (control) gen_jmp(blabel); } extern void st_continue(int e1){ checkret(); // conv->continue_(); if (control) gen_jmp(clabel); } extern void st_case(int e1){ #if CASE_CODE int l,clist=caddr(e1),c; int cst = (car(csvalue1)==CONST); if (cst) { c=cadr(csvalue1); for(;clist;clist=cadr(clist)) { if (car(clist)==c) break; } if (!clist) return; // no match } else l = fwdlabel(); if (retpending) { ret(); retpending=0; } if (cst) { if (cslist) { // may duplicat csvalue return; } cslist=1; fwddef(cslabel); return; } if (!cslabel) { if (!control) { cmpdimm(car(clist),csvalue1,cslabel=fwdlabel(),1); caddr(clist)=0; } else { error(-1); } } while(clist) { caddr(clist) = l; clist = cadr(c=clist); cadr(c) = 0; // insert destroy cadr of clist cslist=insert_ascend(cslist,c,docase_eq); } fwddef(l); control=1; #else int c,clist,l; int cst = (car(csvalue1)==CONST); clist = caddr(e1); if (cst) { c=cadr(csvalue1); for(;clist;clist=cadr(clist)) { if (car(clist)==c) break; // no match } if (!clist) return; } if (cst) { if (!cslist) { if (retpending) { ret(); retpending=0; } fwddef(cslabel); cslist = 1; } // else error(CSERR); return; } if (retpending) { ret(); retpending=0; } l=fwdlabel(); if (control) { control=0; gen_jmp(l); } if (cslabel) fwddef(cslabel); while(cadr(clist)) { cmpdimm(car(clist),csvalue1,l,0); clist=cadr(clist); } cmpdimm(car(clist),csvalue1,cslabel=fwdlabel(),1); if (l) fwddef(l); #endif } extern void st_default(int e1){ // int cst = (car(csvalue1)==CONST); control=1; checkret(); if (dlabel) error(STERR); // double default: dlabel = backdef(); // conv->case_(0,1); } extern void st_return(int e1){ int e,t; if (!cslabel) gen_jmp(cslabel = fwdlabel()); if(!(e=caddr(e1))) { // no return value retpending = 1; return; } t = type_value(cadr(fnptr->ty)); if (t>0 && (car(t)==STRUCT || car(t)==UNION)) { // copy is included in e, pass the pointer t = list2(POINTER,type_value(cadr(fnptr->ty))); } g_expr(e); if (ret_reg_mode==0) { // return value register is not fixed ret_reg_mode=1; ret_register = code_get_fixed_creg(USE_CREG,t); } else { code_set_fixed_creg(ret_register,1,t); } // conv->return_end_(); retpending = 1; } extern void st_goto(int e){ NMTBL *nptr0; int e1,e2,env; checkret(); e1 = caddr(e); if (car(e1)==RINDIRECT) { gen_indirect_goto(cadr(e1)); return ; } else if (car(e1)==RLVAR) { gen_indirect_goto(e1); return ; } else if (car(e1)==LVAR||car(e1)==FLABEL) { gen_jmp(cadr(e1)); control=0; return ; } else if (car(e1)==CODE) { /* CbC continuation */ // conv->jump_(env); // should be separate function e2 = cadr(e1); env = caddr(e1); if (car(e2) == FNAME) { nptr0=(NMTBL *)cadr(e2); if (nptr0->sc==EMPTY) nptr0->sc = EXTRN1; else if(nptr0->sc==FUNCTION) nptr0->sc = CODE; if (nptr0->ty>0&&car(nptr0->ty)==FUNCTION) car(nptr0->ty)=CODE; } gexpr(list3(CODE,e1,env),0); control=0; // conv->sm_(); return ; } else { error(-1); } } #if ASM_CODE extern void st_asm(int e1){ checkret(); g_expr_u(list3(ASM,caddr(e1),cadddr(e1))); } #endif extern void st_label(int e1){ int lb = caddr(e1); control=1; checkret(); if (car(lb)==LVAR) { // label variable case } else if (car(lb)!=FLABEL) error(-1); fwddef(cadr(lb)); } extern void st_comment(int e1){ gen_comment((char *)caddr(e1)); } /* partial evaluator */ static int p_vartable(int adisp,int ldisp) { int i; int pvartable = getfree(adisp-ldisp); // have to be local heap pdisp = pvartable-ldisp; for(i=ldisp;i<0;i++) { heap[pdisp+i] = 0; } return pvartable; } static int p_lvar(int e1) { int sz = is_memory(e1); int d = cadr(e1); int d1,e; if ((d1=(heap[pdisp+d]))) return d1; e = heap[pdisp+d]=list3(LVAR,new_lvar(sz),0); inline_lvars = glist2(e,inline_lvars); return e; } static int pfunction(int e) { // list4(INLINE,e1,arglist,ftype); // include code segement case int e1 = pexpr(cadr(e)); int arglist = caddr(e); int newargs = 0; int ftype = cadddr(e); int e3; for (e3 = arglist; e3; e3 = cadr(e3)) { newargs = list3( pexpr(car(e3)), newargs, caddr(e3)); } newargs = reverse0(newargs); return list4(car(e),e1,newargs,ftype); } static int prindirect(int e) { int lvar; int offset = caddr(e); if (car(lvar=cadr(e))==IVAR) { lvar=p_lvar(cadr(e)); // can be anything.... switch(car(lvar)) { case LVAR: if(offset) { return list3(car(e),lvar,offset); } return rvalue_t(lvar,cadddr(e)); case REGISTER: case DREGISTER: case FREGISTER: case LREGISTER: case CONST: case FCONST: case DCONST: case LCONST: // should do type check if (offset) error(-1); return lvar; } } return list3(car(e),pexpr(cadr(e)),offset); } static int pindirect(int e) { //int lvar; //if (car(lvar=cadr(e))==IVAR) // lvar=p_lvar(cadr(e)); // can be anything.... return list3(car(e),pexpr(cadr(e)),caddr(e)); } static int paddress(int e) { return list2(car(e),pexpr(cadr(e))); } static int p_conv(int e1,int e2) { int t; if (is_const(e2) && (t=type_of_conv(e1))) { return correct_type(e2,t); } return list3(CONV,pexpr(e2),e1); } static int pbinop(int op,int e1,int e2) { e1 = pexpr(e1); e2 = pexpr(e2); if (is_const(e1)&&is_const(e2)) { int t; if((t= type_of_bop(op))) return binop(op_of(op),e1,e2,t,t); } return list3(op,e1,e2); } static int plor(int op,int e1,int e2) { int e = pexpr(e1); return list3(op,e,pexpr(e2)); } static int pland(int op,int e1,int e2) { int e = pexpr(e1); return list3(op,e,pexpr(e2)); } static int psassign(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list4(car(e),e1,e2,cadddr(e)); } static int passign(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list3(car(e),e1,e2); } static int passop(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list4(car(e),e1,e2,cadddr(e)); } static int pdassign(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list3(car(e),e1,e2); } static int pdassop(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list4(car(e),e1,e2,cadddr(e)); } static int plassign(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list3(car(e),e1,e2); } static int plassop(int e) { int e1 = pexpr(cadr(e)); int e2 = pexpr(caddr(e)); return list4(car(e),e1,e2,cadddr(e)); } static int palloc(int e) { return list2(car(e),pexpr(cadr(e))); } static int pcomma(int e1,int e2) { int e = pexpr(e1); return list3(COMMA,e,pexpr(e2)); } static int prbit_field(int e) { return list3(car(e),pexpr(cadr(e)),caddr(e)); } static int pbassign(int e) { // list4(BASS,e1,e2,list2(BASS,t))); int e1=pexpr(caddr(e)); return list4(car(e),pexpr(cadr(e)),e1,cadddr(e)); } static int pbassop(int e) { int e1=pexpr(caddr(e)); return list4(car(e),pexpr(cadr(e)),e1,cadddr(e)); } static int p_decl(int e) { // list4(ST_DECL,parse,(int)n,list3(mode,stmode,ctmode)); int ctmode=cadddr(e); NMTBL *n=(NMTBL*)caddr(e); int dsp = n->dsp; int v; int sstmode = stmode; int smode = mode; // in real partial evaluation, we have to check whether this variable // is used or not. if (ctmode) { mode = car(ctmode); stmode = cadr(ctmode); ctmode = caddr(ctmode); } switch(stmode) { case EXTRN: case EXTRN1: case STATIC: // def(n,ctmode); we don't need this. already done. // stmode = sstmode; stmode = sstmode; mode = smode; return pexpr(cadr(e)); // case LLDECL: LLDECL is mode, not stmode (bad design) // v = list2(FLABEL,fwdlabel()); break; #if 1 case REGISTER: switch(n->ty) { case ULONGLONG: case LONGLONG: v = get_lregister_var(n); break; case FLOAT: v = get_dregister_var(n,0); break; case DOUBLE: v = get_dregister_var(n,1); break; default: if (scalar(n->ty)) v = get_register_var(n); else error(TYERR); } break; #endif default: if (n->sc==FLABEL) v = list3(LVAR,fwdlabel(),(int)n); else v = list3(LVAR,new_lvar(size(n->ty)),(int)n); } if (n->sc!=FLABEL) inline_lvars = glist2(v,inline_lvars); if (heap[pdisp+dsp]) error(-1); heap[pdisp+dsp]=v; stmode = sstmode; mode = smode; return pexpr(cadr(e)); } static int p_if(int e1) { int cond,l1,l2; int e2=caddr(e1),e3; cond = pexpr(car(e2)); // conv->if_then_(); l1 = pexpr(cadr(e2)); if ((e3=caddr(e2))) { // else l2 = pexpr(e3); } else { l2 = 0; } return list3(ST_IF,pexpr(cadr(e1)),list3(cond,l1,l2)); } static int p_do(int e) { int e2 = pexpr(caddr(e)); int e3 = pexpr(cadddr(e)); return list4(ST_DO,pexpr(cadr(e)),e2,e3); } static int p_while(int e) { int e2 = pexpr(caddr(e)); int e3 = pexpr(cadddr(e)); return list4(ST_WHILE,pexpr(cadr(e)),e2,e3); } static int p_for(int e) { int e1=caddr(e); int p0=pexpr(car(e1)); int p1=pexpr(cadr(e1)); int p2=pexpr(caddr(e1)); int p3=pexpr(cadddr(e1)); return list3(ST_FOR,pexpr(cadr(e)), list4(p0,p1,p2,p3)); } static int p_switch(int e) { int e2 = pexpr(caddr(e)); int e3 = pexpr(cadddr(e)); return list4(ST_SWITCH,pexpr(cadr(e)),e2,e3); } static int p_comp(int e) { int e1=pexpr(caddr(e)); return list3(ST_COMP,pexpr(cadr(e)),e1); } static int p_break(int e) { return list2(ST_BREAK,pexpr(cadr(e))); } static int p_continue(int e) { return list2(ST_CONTINUE,pexpr(cadr(e))); } static int p_case(int e) { int new=0,clist = caddr(e); // insert destory clist, we have to copy it now for(;clist;clist=cadr(clist)) new=glist3(car(clist),new,0); return list3(ST_CASE,pexpr(cadr(e)),reverse0(new)); } static int p_default(int e) { // should be removed if constant case value return list2(ST_DEFAULT,pexpr(cadr(e))); } static int p_return(int e) { int e1=pexpr(caddr(e)); return list3(ST_RETURN,pexpr(cadr(e)),e1); } static int p_goto(int e) { int e1,lb,e2; if ((e1=caddr(e))) { switch(car(e1)) { case RINDIRECT: e1=pexpr(e1); break; case CODE: e2=pexpr(cadr(e1)); e1=list3(CODE,e2,pexpr(caddr(e1))); break; case FLABEL: /* error(-1); */ break; case IVAR: lb = cadr(e1); if (!(e1=heap[pdisp+lb])) { e1 = heap[pdisp+lb]=list2(FLABEL,fwdlabel()); } } } return list3(ST_GOTO,pexpr(cadr(e)),e1); } static int p_list_expr(int e) { int e3,new = 0; for (e3 = e; e3; e3 = cadr(e3)) { new= list2( pexpr(car(e3)), new); } return reverse0(new); } static int p_asm(int e) { int param=caddr(e); int e1 = p_list_expr(cadddr(e)); return list4(ST_ASM,pexpr(cadr(e)),param,e1); } static int p_label(int e) { int e1,lb; if ((e1=caddr(e))) { switch(car(e1)) { case FLABEL: /* error(-1); */ break; case IVAR: lb = cadr(e1); if (!(e1=heap[pdisp+lb])) { e1 = heap[pdisp+lb]=list2(FLABEL,fwdlabel()); } } } return list3(ST_LABEL,pexpr(cadr(e)),e1); } static int p_label_var(int e) { int d,e1; switch(car(e1=e)) { case LVAR: /* error(-1) */ break; case IVAR: // should this done in p_decl? (in __label__?) d = cadr(e); if (!(e1=(heap[pdisp+d]))) { // error(-1); e1 = heap[pdisp+d]=list3(LVAR,fwdlabel(),caddr(e)); } } return list2(LABEL,e1); } static int p_bool(int e) { error(-1); return e; } static int p_comment(int e) { return list3(ST_COMMENT,pexpr(cadr(e)),caddr(e)); } static int p_inline(int e) { int e3; int narg; /* inline function arguments */ narg = 0; for (e3 = caddr(e); e3; e3 = cadr(e3)) { narg=list3(pexpr(car(e3)),narg,caddr(e3)); } return list4(INLINE,cadr(e),reverse0(narg),cadddr(e)); } extern int pexpr(int e1) { int e2,e3; // if (inmode) error(-1); if (e1==0) return 0; e2 = cadr(e1); switch (car(e1)){ case GVAR: case RGVAR: case CRGVAR: case CURGVAR: case SRGVAR: case SURGVAR: case REGISTER: case DREGISTER: case FREGISTER: case FRGVAR: case DRGVAR: case LREGISTER: case LRGVAR: case LURGVAR: case CONST: case DCONST: case FCONST: case LCONST: case STRING: case FNAME: case FLABEL: return e1; case RSTRUCT: // list3(RSTRUCT,e,size) return pexpr(e2); case LABEL: return p_label_var(e2); case LVAR: case RLVAR: case CRLVAR: case CURLVAR: case SRLVAR: case SURLVAR: case FRLVAR: case DRLVAR: case LRLVAR: case LURLVAR: return e1; case IVAR: return p_lvar(e1); case FUNCTION: return pfunction(e1); case CODE: return list2(car(e1),pexpr(e2)); case INLINE: return p_inline(e1); case INDIRECT: return pindirect(e1); case RINDIRECT: case URINDIRECT: case CRINDIRECT: case CURINDIRECT: case SRINDIRECT: case SURINDIRECT: case FRINDIRECT: case DRINDIRECT: case LRINDIRECT: case LURINDIRECT: return prindirect(e1); case ADDRESS: return paddress(e1); case MINUS: if ((e3 = pexpr(e2))==e2) return e1; if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return list2(CONST,-cadr(e3)); return list2(car(e1),e3); #if LONGLONG_CODE case LMINUS: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==LCONST) return llist2(LCONST,-lcadr(e3)); return list2(car(e1),e3); #endif #if FLOAT_CODE case DMINUS: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==DCONST) return dlist2(DCONST,-dcadr(e3)); if (car(e3)==FCONST) return dlist2(FCONST,-dcadr(e3)); return list2(car(e1),e3); case FMINUS: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==DCONST) return dlist2(DCONST,-dcadr(e3)); if (car(e3)==FCONST) return dlist2(FCONST,-dcadr(e3)); return list2(car(e1),e3); #endif case CONV: return p_conv(caddr(e1),e2); case BNOT: /* ~ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return list2(CONST,~cadr(e3)); return list2(BNOT,e3); case LNOT: /* ! */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return list2(CONST,!cadr(e3)); return list2(LNOT,e3); case PREINC: case UPREINC: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return list2(CONST,cadr(e3)+caddr(e1)); return list4(car(e1),e3,caddr(e1),cadddr(e1)); case POSTINC: case UPOSTINC: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return e3; return list4(car(e1),e3,caddr(e1),cadddr(e1)); #if FLOAT_CODE case DPREINC: /* ++d */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST) return dlist2(FCONST,dcadr(e3)+cadr(e2)); if (car(e3)==DCONST) return dlist2(DCONST,dcadr(e3)+cadr(e2)); return list4(car(e1),e3,caddr(e1),cadddr(e1)); case DPOSTINC: /* d++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST||car(e3)==DCONST) return e3; return list4(car(e1),e3,caddr(e1),cadddr(e1)); case FPREINC: /* ++f */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST) return dlist2(FCONST,dcadr(e3)+cadr(e2)); if (car(e3)==DCONST) return dlist2(DCONST,dcadr(e3)+cadr(e2)); return list4(car(e1),e3,caddr(e1),cadddr(e1)); case FPOSTINC: /* f++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST||car(e3)==DCONST) return e3; return list4(car(e1),e3,caddr(e1),cadddr(e1)); #endif #if LONGLONG_CODE case LPREINC: /* ++d */ case LUPREINC: /* ++d */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==LCONST) return llist2(LCONST,lcadr(e3)+cadr(e2)); return list4(car(e1),e3,caddr(e1),cadddr(e1)); case LPOSTINC: /* d++ */ case LUPOSTINC: /* d++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==LCONST) return e3; return list4(car(e1),e3,caddr(e1),cadddr(e1)); #endif case MUL: case UMUL: case DIV: case UDIV: case MOD: case UMOD: case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case CMPGE: case UCMP: case CMPEQ: case CMPNEQ: case UCMPGE: #if FLOAT_CODE case DMUL: case DDIV: case DADD: case DSUB: case DCMP: case DCMPGE: case DCMPEQ: case DCMPNEQ: case FMUL: case FDIV: case FADD: case FSUB: case FCMP: case FCMPGE: case FCMPEQ: case FCMPNEQ: #endif #if LONGLONG_CODE case LMUL: case LUMUL: case LDIV: case LUDIV: case LMOD: case LUMOD: case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: case LADD: case LSUB: case LBAND: case LEOR: case LBOR: case LCMP: #endif return pbinop(car(e1),e2,caddr(e1)); // relational operator case GT: case UGT: case GE: case UGE: case LT: case ULT: case LE: case ULE: case LOP+GT: case LOP+UGT: case LOP+GE: case LOP+UGE: case LOP+LT: case LOP+ULT: case LOP+LE: case LOP+ULE: case DOP+GT: case DOP+GE: case DOP+LT: case DOP+LE: case FOP+GT: case FOP+GE: case FOP+LT: case FOP+LE: case FOP+EQ: case FOP+NEQ: case EQ: case NEQ: case DOP+EQ: case DOP+NEQ: case LOP+EQ: case LOP+NEQ: return pbinop(car(e1),e2,caddr(e1)); case LAND: return pland(car(e1),cadr(e1),caddr(e1)); case LOR: return plor(car(e1),cadr(e1),caddr(e1)); case LCOND: case DCOND: case FCOND: case COND: case UCOND: case LUCOND: e2 = pexpr(e2); if (car(e2)==CONST) return caddr(e1)? pexpr(cadr(e2)?caddr(e1):cadddr(e1)) : pexpr(cadr(e2)?e2:cadddr(e1)); // GNU extension h?:g e3=pexpr(caddr(e1)); return list4(car(e1),e2,e3,pexpr(cadddr(e1))); case STASS: return psassign(e1); case ASS: case CASS: case SASS: return passign(e1); case SASSOP: case SUASSOP: case ASSOP: case CASSOP: case CUASSOP: return passop(e1); #if FLOAT_CODE case FASS: case DASS: return pdassign(e1); case DASSOP: case FASSOP: return pdassop(e1); #endif #if LONGLONG_CODE case LASS: return plassign(e1); case LASSOP: case LUASSOP: return plassop(e1); #endif case ALLOCA: return palloc(e2); case BUILTINP: return list2(CONST,is_const(pexpr(e2))); case COMMA: return pcomma(e2,caddr(e1)); case RETURN: case ENVIRONMENT: case LCALL: return e1; #if BIT_FIELD_CODE case RBIT_FIELD: return prbit_field(e1); case BIT_FIELD: return list3(BIT_FIELD,pexpr(e2),caddr(e1)); case BASS: return pbassign(e1); case BPREINC: case BPOSTINC: case BASSOP: return pbassop(e1); #endif #if ASM_CODE case ASM: return list3(ASM,list4( car(e2),cadr(e2),caddr(e2),cadddr(e2)), caddr(e1)); #endif case ST_DECL: return p_decl(e1); case ST_IF: return p_if(e1); case ST_DO: return p_do(e1); case ST_WHILE: return p_while(e1); case ST_FOR: return p_for(e1); case ST_SWITCH: return p_switch(e1); case ST_COMP: return p_comp(e1); case ST_BREAK: return p_break(e1); case ST_CONTINUE: return p_continue(e1); case ST_CASE: return p_case(e1); case ST_DEFAULT: return p_default(e1); case ST_RETURN: return p_return(e1); case ST_GOTO: return p_goto(e1); case ST_ASM: return p_asm(e1); case ST_LABEL: return p_label(e1); case ST_COMMENT: return p_comment(e1); default: error(-1); return p_bool(e1); } return VOID; } static int replace_inline_parameter(NMTBL *anptr,int t,int e4,int narg,int evals) { int arg; if (has_attr(anptr,KONST) && !has_attr(anptr,HAS_ADDRESS)) { if (is_memory(e4)) { heap[pdisp+narg]=reference(e4); return evals; } else if (is_const(e4)) { heap[pdisp+narg]=e4; return evals; } } arg = heap[pdisp+narg]=list3(LVAR,new_lvar(size(t)),0); inline_lvars = glist2(arg,inline_lvars); evals=list2(assign_expr0(arg,e4,anptr->ty,t),evals); return evals; } /* setup parameter replacement of inline call */ static void enter_inline(NMTBL *n, int e) { int e1 = attr_value(n,INLINE); int arg_disp = cadr(e1); // number of arguments int narg,e3,e4, e5, fargtype; int evals = 0; int t; NMTBL *anptr; fnptr = n; // st_return see this pvartable = p_vartable(arg_disp, /* number of arg */ caddr(e1) /* number of local parameter */); /* function arguments type */ fargtype = n->dsp; // we cannot do destruct reverse here /* inline function arguments */ narg = 0; if (!fargtype) { goto no_args; // wrong number of arguments } for (e3 = e5 = reverse0(caddr(e)); e3; e3 = cadr(e3)) { anptr = (NMTBL*)caddr(fargtype); if (!anptr) break; // should not happen? t=caddr(e3); // type e4 = car(e3); evals = replace_inline_parameter(anptr,t,e4,narg,evals); narg ++; fargtype = cadr(fargtype); } caddr(e) = reverse0(e5); // make it normal if (eval_order==NORMAL) evals = reverse0(evals); for(;evals;evals=cadr(evals)) { g_expr_u(car(evals)); } no_args: return; } /* pass local static variable list to our parents clean up and free used inline parameters */ static void leave_inline(int e1) { NMTBL *n; NMTBL *local_statics = (NMTBL*)cadddr(e1); // local static list if (retcont) error(STERR); // inline can't handle return/environment if (local_statics && local_statics != &null_nptr) { // append our local static variables to the parent list n = local_statics; while(n->next != &null_nptr) n=n->next; n->next = local_static_list; local_static_list = local_statics; cadddr(e1) = 0; // prevent duplicate initialize } while(inline_lvars) { int e; int l = car(inline_lvars); switch(car(l)) { case LVAR: free_lvar(cadr(l)); break; case REGISTER: case DREGISTER: case FREGISTER: case LREGISTER: free_register(cadr(l)); } e = cadr(inline_lvars); free_glist2(inline_lvars); inline_lvars = e; } } extern int gen_inline(int e) { // these saved value should be some struct int sretlabel; NMTBL *sfnptr; int svartable; int sretcont; int scslabel = cslabel; int sdisp = pdisp; int sret_register; int sret_reg_mode; int sinline_lvars; int slfree; // int slreg_count=lreg_count; NMTBL *n = (NMTBL*)cadr(cadr(e)); int e1 = attr_value(n,INLINE); int parse = car(e1); // inline parse tree int dots; int ret_type = function_type(cadddr(e),&dots); checkret(); checkjmp(-1); svartable = pvartable; sretcont = retcont; scslabel = cslabel; sdisp = pdisp; sret_register = ret_register; sret_reg_mode = ret_reg_mode; sinline_lvars = inline_lvars; slfree=lfree; // int slreg_count=lreg_count; sretlabel = retlabel; sfnptr = fnptr; retcont = 0; cslabel = -1; retpending = 0; ret_reg_mode = 0; ret_register = 5555; inline_lvars = 0; retlabel = fwdlabel(); enter_inline(n,e); // partial evaluation of parse tree // constant propergation, etc. parse = pexpr(parse); pdisp = sdisp; pvartable = svartable; // generate code if necessary if (ret_type!=VOID) g_expr0(parse); else g_expr_u(parse); checkret(); fwddef(retlabel); control=1; leave_inline(e1); fnptr = sfnptr; retlabel = sretlabel; retcont = sretcont; cslabel = scslabel; ret_register = sret_register; ret_reg_mode = sret_reg_mode; inline_lvars = sinline_lvars; lfree=slfree; return ret_type; } /* end */