Mercurial > hg > CbC > old > device
view mc-inline.c @ 491:a379da780856
cond signed/unsigned
author | kono |
---|---|
date | Wed, 21 Dec 2005 11:33:53 +0900 |
parents | d88f08d81bba |
children | 0a4ca939f403 |
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; /* 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; 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 */ gexpr(caddr(e1),1); csvalue1=csvalue() ; // conv->switch_body_(); cslabel = control = 0; g_expr_u(cadddr(e1)); // conv->switch_end_(); checkret(); #if CASE_CODE if (control) gen_jmp(blabel); genswitch(cslist,cslabel); #else if(dlabel) def_label(cslabel,dlabel); else fwddef(cslabel); #endif csvalue1=svalue; cslabel=scase; dlabel=sdefault; fwddef(blabel); 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; l = fwdlabel(); // conv->case_begin_(0,0); // conv->case_(0,0); if (retpending) { ret(); retpending=0; } 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 /* casading branch implementation */ int c,l; c = caddr(e1); if (retpending) { ret(); retpending=0; } // conv->case_begin_(0,0); // conv->case_(0,0); l=fwdlabel(); if (control) { control=0; gen_jmp(l); } if (cslabel) fwddef(cslabel); while(cadr(c)) { cmpdimm(car(c),csvalue1,l,0); c=cadr(c); } cmpdimm(car(c),csvalue1,cslabel=fwdlabel(),1); if (l) fwddef(l); #endif } extern void st_default(int e1){ control=1; checkret(); if (dlabel) error(STERR); // double default: dlabel = backdef(); // conv->case_(0,1); } extern void st_return(int e1){ int e; if (!cslabel) gen_jmp(cslabel = fwdlabel()); if(!(e=caddr(e1))) { // conv->return_(); // conv->return_end_(); retpending = 1; return; } // conv->return_(); if (struct_return) { if ((car(type)==STRUCT || car(type)==UNION)&& size(type)==cadr(struct_return)) { if(car(e)==RSTRUCT && car(cadr(e))==FUNCTION) { /* pass the return pointer to the called function */ replace_return_struct(cadr(e), rvalue_t(car(struct_return),caddr(struct_return))); replace_return_struct(cadr(e), rvalue_t(car(struct_return),caddr(struct_return))); gexpr(cadr(e),0); } else { type = caddr(struct_return); // e1 = rvalue_t(cadr(struct_return),INT); /* size */ e1 = cadr(struct_return); /* size */ gexpr(list4(STASS,rvalue(car(struct_return)),e,e1),0); } } else { error(TYERR); /* should check compatible */ } } else { gexpr(correct_type(e,cadr(fnptr->ty)),1); } // conv->return_end_(); retpending = 1; } extern void st_goto(int e){ NMTBL *nlist,*nptr0; int t,e1,e2,env; checkret(); // conv->goto_(); e1 = caddr(e); if (car(e1)==RINDIRECT) { gen_indirect_goto(cadr(e1)); return; } else if (car(e1)==FLABEL) { nlist = (NMTBL *)cadr(e1); nptr0 = name_space_search(nlist,0); t = nptr0->sc; if (t==EMPTY||t==EXTRN1||t==EXTRN) { nptr0 = make_local_scope(nlist,nptr0,0); nptr0->sc = FLABEL; nptr0->dsp = fwdlabel(); } else if (!(t==FLABEL||t==BLABEL)) { error(STERR); } gen_jmp(nptr0->dsp); control=0; // conv->sm_(); // conv->goto_label_(nptr0); return; } else { /* CbC continuation */ // conv->jump_(env); 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; } } #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){ NMTBL *nptr,*nlist; nlist = (NMTBL *)caddr(e1); nptr = name_space_search(nlist,0); control=1; checkret(); if(nptr->sc == FLABEL) { fwddef(nptr->dsp); } else if(nptr->sc != EMPTY && nptr->sc != EXTRN1 && nptr->sc !=BLABEL) { error(TYERR); } else { nptr->sc=EMPTY; nptr = make_local_scope(nlist,nptr,0); nptr->sc = BLABEL; nptr->dsp = backdef(); } // conv->label_(); } extern void st_comment(int e1){ gen_comment((char *)caddr(e1)); } /* partial evaluator */ static int p_vartable(int e,int adisp,int ldisp) { int i; pvartable = getfree(adisp+ldisp); pdisp = pvartable+adisp; for(i=adisp+ldisp;i>=0;i--) { pvartable = 0; } return 0; } static int p_lvar(int e1) { int sz = is_memory(e1); int d = cadr(e1); int d1; if ((d1=(heap[pdisp+e1]))) return d1; return (heap[pdisp+d]=new_lvar(sz)); } static int pfunction(int e) { return e; } static int prindirect(int e) { return e; } static int paddress(int e) { return e; } static int p_conv(int e1,int e2) { return e1; } static int pbinop(int op,int e1,int e2) { return e1; } static int psassign(int e) { return e; } static int passign(int e) { return e; } static int passop(int e) { return e; } static int pdassign(int e) { return e; } static int pdassop(int e) { return e; } static int plassign(int e) { return e; } static int plassop(int e) { return e; } static int palloc(int e) { return e; } static int pcomma(int e1,int e2) { return e1; } static int prbit_field(int e) { return e; } static int pbassign(int e) { return e; } static int pbassop(int e) { return e; } static int p_decl(int e) { // list4(ST_DECL,parse,(int)n,stmode); int stmode=cadddr(e); NMTBL *n=(NMTBL*)caddr(e); int dsp = n->dsp; int v; switch(stmode) { 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_dregister_var(n,1); else error(TYERR); } case EXTRN: case EXTRN1: case STATIC: return pexpr(cadr(e)); default: v = new_lvar(size(n->dsp)); } if (heap[pdisp+dsp]) error(-1); heap[pdisp+dsp]=v; return pexpr(cadr(e)); } static int p_if(int e) { return e; } static int p_do(int e) { return e; } static int p_while(int e) { return e; } static int p_for(int e) { return e; } static int p_switch(int e) { return e; } static int p_comp(int e) { return e; } static int p_break(int e) { return e; } static int p_continue(int e) { return e; } static int p_case(int e) { return e; } static int p_default(int e) { return e; } static int p_return(int e) { return e; } static int p_goto(int e) { return e; } static int p_asm(int e) { return e; } static int p_label(int e) { return e; } static int p_bool(int e) { return e; } static int p_comment(int e) { return e; } extern int pexpr(int e1) { int e2,e3; // if (inmode) error(-1); e2 = cadr(e1); switch (car(e1)){ case GVAR: case RGVAR: case CRGVAR: case CURGVAR: case SRGVAR: case SURGVAR: case REGISTER: #if FLOAT_CODE case DREGISTER: case FREGISTER: #endif #if LONGLONG_CODE case LREGISTER: #endif case LABEL: case CONST: #if FLOAT_CODE case DCONST: case FCONST: #endif #if LONGLONG_CODE case LCONST: #endif case STRING: case FNAME: case RSTRUCT: return e1; case LVAR: case RLVAR: case CRLVAR: case CURLVAR: case SRLVAR: case SURLVAR: #if FLOAT_CODE case FRLVAR: case FRGVAR: case DRLVAR: case DRGVAR: #endif #if LONGLONG_CODE case LRLVAR: case LRGVAR: case LURLVAR: case LURGVAR: return p_lvar(e1); #endif case FUNCTION: return pfunction(e1); case CODE: return list2(car(e1),pexpr(e2)); case INLINE: return gen_inline(e1); case INDIRECT: return prindirect(e1); case RINDIRECT: case URINDIRECT: case CRINDIRECT: case CURINDIRECT: case SRINDIRECT: case SURINDIRECT: #if FLOAT_CODE case FRINDIRECT: case DRINDIRECT: #endif #if LONGLONG_CODE case LRINDIRECT: case LURINDIRECT: #endif return prindirect(e1); case ADDRESS: return paddress(pexpr(e2)); case MINUS: 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),pexpr(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)+1); return list2(car(e1),e3); case POSTINC: case UPOSTINC: if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==CONST) return e3; return list2(car(e1),e3); #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 list2(car(e1),e3); case DPOSTINC: /* d++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST||car(e3)==DCONST) return e3; return list2(car(e1),e3); 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 list2(car(e1),e3); case FPOSTINC: /* f++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==FCONST||car(e3)==DCONST) return e3; return list2(car(e1),e3); #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 list2(car(e1),e3); case LPOSTINC: /* d++ */ case LUPOSTINC: /* d++ */ if ((e3 = pexpr(e2))==e2) return e1; if (car(e3)==LCONST) return e3; return list2(car(e1),e3); #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 e3 = pexpr(e2); e2 = pexpr(caddr(e1)); if (e3==cadr(e1)&&e2==caddr(e1)) return e1; return pbinop(car(e1),e3,e2); case LCOND: case DCOND: case FCOND: case COND: e3 = pexpr(e2); if (car(e3)==CONST) return pexpr(cadr(e3)?caddr(e1):cadddr(e1)); return list4(car(e1),e3,pexpr(cadr(e1)),pexpr(cadr(e2))); 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(pexpr(e2)); case BUILTINP: return list2(CONST,is_const(pexpr(e2))); case COMMA: return pcomma(pexpr(e2),pexpr(caddr(e1))); case RETURN: case ENVIRONMENT: case LCALL: return e1; #if BIT_FIELD_CODE case RBIT_FIELD: return prbit_field(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( pexpr(car(e2)),pexpr(cadr(e2)),pexpr(caddr(e2)),pexpr(cadddr(e2))), pexpr(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: return p_bool(e1); } return VOID; } #define round4(i) ((i+(SIZE_OF_INT-1))&~(SIZE_OF_INT-1)) extern int gen_inline(int e) { int svartable = pvartable; int sdisp = pdisp; int narg,arg; NMTBL *n = (NMTBL*)cadr(cadr(e)); int e1 = attr_value(n,INLINE); int parse = car(e1); int arg_disp = cadr(e1); int e3,t; pvartable = p_vartable(e,pdisp=arg_disp,caddr(e1)); /* inline function arguments */ narg = 0; for (e3 = e1 = reverse0(caddr(e)); e3; e3 = cadr(e3)) { t=caddr(e3); if (is_const(e3) /* ||(is_memory(e3)&&is_readonly(e3)) */ ) { heap[pdisp+narg]=e3; } else { arg = heap[pdisp+narg]=new_lvar(size(t)); g_expr_u(assign_expr0(arg,e3,t,t)); } narg += (size(t)+3)/4; } e = pexpr(parse); pdisp = sdisp; pvartable = svartable; return e; } /* end */