/* $VER: vbcc (ic.c) V0.8 */ #include "vbc.h"#include "opt.h" static char FILE_[]=__FILE__; static struct IC *first_pushed;static unsigned int opushed;static int volatile_convert; int do_arith(np,struct IC *,np,struct obj *);np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2); static void handle_reglist(struct regargs_list *,struct obj *); #if HAVE_LIBCALLS/* avoid calling use_libcall with illegal operands */static char *use_libcall_wrap(int c,int t,int t2){ if(optflags&2) return 0; if(c==PMULT) c=MULT; if((c>=OR&&c<=XOR)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST) return use_libcall(c,t,t2); return 0;}#endif void gen_test(struct obj *o,int t,int branch,int label)/* Generiert ein test o, branch label und passt auf, dass *//* kein TEST const generiert wird. */{ struct IC *new; if(o->flags&KONST){ eval_const(&o->val,t); if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){ if(branch==BEQ) branch=BRA; else branch=0; }else{ if(branch==BNE) branch=BRA; else branch=0; } }else{#if HAVE_LIBCALLS static struct node n={TEST},nn={REINTERPRET}; static struct Typ nt,it={INT}; char *libname; n.left=&nn; n.ntyp=⁢ nn.ntyp=&nt; nt.flags=t; n.o=nn.o=*o; if(libname=use_libcall_wrap(TEST,t,0)){ new=new_IC(); new->code=TEST; new->q2.flags=new->z.flags=0; new->typf=INT; new->q1=gen_libcall(libname,&nn,&nt,0,0)->o; add_IC(new); }else{#endif new=new_IC(); new->code=TEST; new->q2.flags=new->z.flags=0; new->typf=t; new->q1=*o; add_IC(new);#if HAVE_LIBCALLS }#endif } if(branch){ new=new_IC(); new->code=branch; new->typf=label; add_IC(new); }} /* remove a freereg if a scratch register is needed more than once */static void keep_reg(int r){ struct IC *n; if(nocode) return; n=last_ic; while(n){ if(n->code==CALL&®scratch[r]){ struct IC *ret; regs[r]=1; savescratch(MOVEFROMREG,n->prev,0,&n->q1); ret=n->next; while(ret->code==ALLOCREG||ret->code==FREEREG) ret=ret->next; if(ret->code==GETRETURN){ if((ret->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ret->z.reg==r) ret->z.flags&=~REG; }else ret=ret->prev; savescratch(MOVETOREG,ret,0,&n->q1); } if(n->code==FREEREG&&n->q1.reg==r){ remove_IC(n); if(!nocode) regs[r]=1; break; } n=n->prev; }} /* Generate code to insert a bitfield */void insert_bitfield(struct obj *dest,struct obj *src,struct obj *val,int bfs,int bfo,int t,int isclear){ /*FIXME: shortcut beachten? */ struct IC *new; struct obj tmp1,tmp2,tmp3; int vmerk; bfo=bflayout(bfo,bfs,t); if((dest->flags®)&&!regs[dest->reg]) keep_reg(dest->reg); new=new_IC(); new->code=AND; new->typf=t; new->q1=*src; new->q1.flags&=~SCRATCH; new->q2.flags=KONST; gval.vmax=zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L)); eval_const(&gval,MAXINT); insert_const(&new->q2.val,t); get_scratch(&new->z,t,0,0); tmp1=new->z; if((new->q1.flags&(KONST|DREFOBJ))==KONST){ calc(AND,new->typf,&new->q1.val,&new->q2.val,&new->q1.val,0); new->code=ASSIGN; new->q2.flags=0; new->q2.val.vmax=sizetab[new->typf&NQ]; } *val=tmp1; vmerk=val->flags; tmp1.flags&=~SCRATCH; add_IC(new); if(bfo!=0){ new=new_IC(); new->code=LSHIFT; new->typf=t; new->typf2=INT; new->q1=tmp1; new->q2.flags=KONST; new->q2.val.vint=zm2zi(l2zm((long)bfo)); get_scratch(&new->z,t,0,0); tmp3=new->z; add_IC(new); }else{ tmp3=tmp1; } if(!isclear){ new=new_IC(); new->code=AND; new->typf=t; new->q1=*dest; new->q1.flags&=~SCRATCH; new->q2.flags=KONST; gval.vmax=zmkompl(zmlshift(zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L)),l2zm((long)bfo))); eval_const(&gval,MAXINT); insert_const(&new->q2.val,t); get_scratch(&new->z,t,0,0); tmp2=new->z; add_IC(new); } new=new_IC(); new->code=OR; new->typf=t; if(isclear) new->q1=*dest; else new->q1=tmp2; new->q2=tmp3; new->z=*dest; add_IC(new); if(dest->flags&(REG|SCRATCH)) free_reg(dest->reg); val->flags=vmerk;} void inline_memcpy(np z,np q,zmax size)/* fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht */{ struct IC *new=new_IC(); if(!ISPOINTER(z->ntyp->flags)) ierror(0); if(!ISPOINTER(q->ntyp->flags)) ierror(0); if(z->flags==ADDRESS||z->flags==ADDRESSA||z->flags==ADDRESSS){ gen_IC(z,0,0); new->z=z->left->o; if(z->flags!=ADDRESSS&&z->left->flags==IDENTIFIER&&is_vlength(z->left->ntyp)){ /* variable length array */ new->z.flags|=DREFOBJ; new->z.dtyp=POINTER_TYPE(z->ntyp->next); } }else{ gen_IC(z,0,0); if(z->o.flags&DREFOBJ){ struct IC *n2=new_IC(); n2->code=ASSIGN; n2->typf=q->ntyp->flags; n2->q1=z->o; get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags,z->ntyp); n2->q2.flags=0; n2->q2.val.vmax=sizetab[POINTER_TYPE(z->ntyp->next)]; new->z=n2->z; add_IC(n2); }else{ new->z=z->o; } if(new->z.flags&VARADR){ new->z.flags&=~VARADR; }else{ new->z.flags|=DREFOBJ; new->z.dtyp=POINTER_TYPE(z->ntyp->next); } } if(q->flags==ADDRESS||q->flags==ADDRESSA||q->flags==ADDRESSS){ gen_IC(q,0,0); new->q1=q->left->o; if(q->flags!=ADDRESSS&&q->left->flags==IDENTIFIER&&is_vlength(q->left->ntyp)){ /* variable length array */ new->q1.flags|=DREFOBJ; new->q1.dtyp=POINTER_TYPE(q->ntyp->next); } }else{ gen_IC(q,0,0); if(q->o.flags&DREFOBJ){ struct IC *n2=new_IC(); n2->code=ASSIGN; n2->typf=q->ntyp->flags; n2->q1=q->o; get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags,q->ntyp); n2->q2.flags=0; n2->q2.val.vmax=sizetab[POINTER_TYPE(q->ntyp->next)]; new->q1=n2->z; add_IC(n2); }else{ new->q1=q->o; } if(new->q1.flags&VARADR){ new->q1.flags&=~VARADR; }else{ new->q1.flags|=DREFOBJ; new->q1.dtyp=POINTER_TYPE(q->ntyp->next); } } new->code=ASSIGN; new->typf=UNSIGNED|CHAR; new->q2.flags=0; new->q2.val.vmax=size; add_IC(new);} void add_IC(struct IC *new)/* fuegt ein IC ein */{ int code; if(!new) return; if(nocode) {#ifdef HAVE_MISRA/* removed */#endif /*free(new);*/ /* building a list to free later would be nice... */ return; } new->next=0; new->q1.am=new->q2.am=new->z.am=0; new->line=line; new->file=filename; code=new->code; if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0; if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0; if(DEBUG&64){ pric(stdout,first_ic);printf("new\n");pric2(stdout,new);printf("-\n");} if(new->q1.flags&VAR){ if(!new->q1.v) ierror(0); new->q1.v->flags|=USEDASSOURCE; if(code==ADDRESS||(new->q1.flags&VARADR)) if(!is_vlength(new->q1.v->vtyp)) new->q1.v->flags|=USEDASADR; new->q1.v->priority+=currentpri; } if(new->q2.flags&VAR){ if(!new->q2.v) ierror(0); new->q2.v->flags|=USEDASSOURCE; if(code==ADDRESS||(new->q2.flags&VARADR)) if(!is_vlength(new->q2.v->vtyp)) new->q2.v->flags|=USEDASADR; new->q2.v->priority+=currentpri; } if(new->z.flags&VAR){ if(!new->z.v) ierror(0); if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST; new->z.v->priority+=currentpri; } if(block_vla[nesting]){ /* special handling for blocks with variable-length arrays */ struct llist *p; if(new->code==LABEL){ p=mymalloc(LSIZE); p->label=new->typf; p->next=vladeflabels[nesting]; vladeflabels[nesting]=p; }else if(0&&new->code==BRA&&!(new->flags&LOOP_COND_TRUE)){ p=mymalloc(LSIZE); p->label=new->typf; p->next=vlajmplabels[nesting]; vlajmplabels[nesting]=p; p=vladeflabels[nesting]; while(p){ if(p->label==new->typf) break; p=p->next; } if(!p){ /* label not declared in this block so far; re-adjust stack, but store the position - label may be declared later in the same block and adjustement must be removed */ struct vlaadjust_list *vl; struct IC *first; first=last_ic; freevl(); first=first->next; vl=mymalloc(sizeof(*vl)); vl->branch=new; vl->first=first; vl->next=vlaadjusts[nesting]; vlaadjusts[nesting]=vl; } } } if(/*(c_flags_val[0].l&2)&&*/code==LABEL){ /* entfernt Spruenge zu direkt folgenden Labels */ struct IC *p=last_ic; while(p){ if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){ struct IC *n; if(p->code!=BRA){ struct IC *cmp=p->prev; while(cmp&&cmp->code==FREEREG) cmp=cmp->prev; if(cmp->code==TEST){ if(is_volatile_obj(&cmp->q1)) break; else{ if(DEBUG&1) printf("preceding test removed\n"); remove_IC(cmp); } }else if(cmp->code==COMPARE){ if(is_volatile_obj(&cmp->q1)||is_volatile_obj(&cmp->q2)) break; else{ if(DEBUG&1) printf("preceding compare removed\n"); remove_IC(cmp); } }else break; } if(vlaadjusts[nesting]){ /* remove it from vlaadjusts-lists, if necessary */ struct vlaadjust_list *vl=vlaadjusts[nesting]; while(vl){ if(vl->branch==p){ struct IC *np=vl->branch->prev; while(np!=vl->first->prev){ if(!np) ierror(0); np->code=NOP; np->q1.flags=np->q2.flags=np->z.flags=0; np=np->prev; } vl->branch=0; } vl=vl->next; } } if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf); n=p->next; remove_IC(p); p=n; }else{ if(p->code!=LABEL) break; p=p->prev; } } } if(last_ic){ if(code==ASSIGN){ if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){ if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){ if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){ /* verbindet op a,b->reg,move reg->c zu op a,b->c */ /* hier fehlt aber noch Registerfreigabe */ last_ic->z=new->z; if(DEBUG&1) printf("move and op combined\n"); if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg); free(new); return; } } } if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){ if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){ if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){ /* verbindet op a,b->scratch,move scratch->c zu op a,b->c */ /* hier fehlt aber noch Registerfreigabe */ last_ic->z=new->z; if(DEBUG&1) printf("move and op combined(2)\n");/* if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg);*/ free(new); return; } } } } if(last_ic->code==BRA){ if(!dontdelete&&code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){ /* loescht alles nach bra bis ein Label kommt */ /* momentan noch nicht perfekt, da es bei alloc/freereg stoppt */ free(new);#ifdef HAVE_MISRA/* removed */#endif if(DEBUG&1) printf("Unreachable Statement deleted\n"); return; } if(last_ic->prev&&code==LABEL){ /* ersetzt bcc l1;bra l2;l1 durch b!cc l2 */ if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){ if(last_ic->next) pric2(stdout,last_ic->next); if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf); if(last_ic->prev->code&1) last_ic->prev->code--; else last_ic->prev->code++; last_ic->prev->typf=last_ic->typf; last_ic=last_ic->prev; free(last_ic->next); last_ic->next=new;new->prev=last_ic; last_ic=new; return; } } }/* }*/ new->prev=last_ic; last_ic->next=new; last_ic=new; }else{ last_ic=new;first_ic=new;new->prev=0; } ic_count++; /* Merken, on Fliesskomma benutzt wurde */ if(code!=LABEL&&(code<BEQ||code>BRA)){ if(ISFLOAT(new->typf)) float_used=1; if(code==CONVERT&&ISFLOAT(new->typf2)) float_used=1; } if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg); if((new->q2.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q2.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q2.reg);} np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2)/* generate call to a library function (emulate operation) */{ np new; struct argument_list *al=0,*t; new=new_node(); new->flags=CALL; new->right=0; new->left=new_node(); new->left->flags=IDENTIFIER; new->left->left=new->left->right=0; new->left->identifier=add_identifier(fname,strlen(fname)); new->left->ntyp=0; new->left->sidefx=0; new->left->val.vmax=l2zm(0L); new->alist=0; if(arg1){ al=mymalloc(sizeof(*al)); al->arg=arg1; al->next=0; if(t1){ np cnv=new_node(); cnv->flags=CAST; cnv->left=arg1; cnv->right=0; cnv->ntyp=t1; al->arg=cnv; }Lines 1–500 of 2571. Load more
/* $VER: vbcc (ic.c) V0.8 */ #include "vbc.h" #include "opt.h" static char FILE_[]=__FILE__; static struct IC *first_pushed; static unsigned int opushed; static int volatile_convert; int do_arith(np,struct IC *,np,struct obj *); np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2); static void handle_reglist(struct regargs_list *,struct obj *); #if HAVE_LIBCALLS /* avoid calling use_libcall with illegal operands */ static char *use_libcall_wrap(int c,int t,int t2) { if(optflags&2) return 0; if(c==PMULT) c=MULT; if((c>=OR&&c<=XOR)||(c>=LSHIFT&&c<=KOMPLEMENT)||c==COMPARE||c==CONVERT||c==MINUS||c==TEST) return use_libcall(c,t,t2); return 0; } #endif void gen_test(struct obj *o,int t,int branch,int label) /* Generiert ein test o, branch label und passt auf, dass */ /* kein TEST const generiert wird. */ { struct IC *new; if(o->flags&KONST){ eval_const(&o->val,t); if(zldeqto(vldouble,d2zld(0.0))&&zmeqto(vmax,l2zm(0L))&&zumeqto(vumax,ul2zum(0UL))){ if(branch==BEQ) branch=BRA; else branch=0; }else{ if(branch==BNE) branch=BRA; else branch=0; } }else{ #if HAVE_LIBCALLS static struct node n={TEST},nn={REINTERPRET}; static struct Typ nt,it={INT}; char *libname; n.left=&nn; n.ntyp=⁢ nn.ntyp=&nt; nt.flags=t; n.o=nn.o=*o; if(libname=use_libcall_wrap(TEST,t,0)){ new=new_IC(); new->code=TEST; new->q2.flags=new->z.flags=0; new->typf=INT; new->q1=gen_libcall(libname,&nn,&nt,0,0)->o; add_IC(new); }else{ #endif new=new_IC(); new->code=TEST; new->q2.flags=new->z.flags=0; new->typf=t; new->q1=*o; add_IC(new); #if HAVE_LIBCALLS } #endif } if(branch){ new=new_IC(); new->code=branch; new->typf=label; add_IC(new); } } /* remove a freereg if a scratch register is needed more than once */ static void keep_reg(int r) { struct IC *n; if(nocode) return; n=last_ic; while(n){ if(n->code==CALL&®scratch[r]){ struct IC *ret; regs[r]=1; savescratch(MOVEFROMREG,n->prev,0,&n->q1); ret=n->next; while(ret->code==ALLOCREG||ret->code==FREEREG) ret=ret->next; if(ret->code==GETRETURN){ if((ret->z.flags&(REG|DREFOBJ))==(REG|DREFOBJ)&&ret->z.reg==r) ret->z.flags&=~REG; }else ret=ret->prev; savescratch(MOVETOREG,ret,0,&n->q1); } if(n->code==FREEREG&&n->q1.reg==r){ remove_IC(n); if(!nocode) regs[r]=1; break; } n=n->prev; } } /* Generate code to insert a bitfield */ void insert_bitfield(struct obj *dest,struct obj *src,struct obj *val,int bfs,int bfo,int t,int isclear) { /*FIXME: shortcut beachten? */ struct IC *new; struct obj tmp1,tmp2,tmp3; int vmerk; bfo=bflayout(bfo,bfs,t); if((dest->flags®)&&!regs[dest->reg]) keep_reg(dest->reg); new=new_IC(); new->code=AND; new->typf=t; new->q1=*src; new->q1.flags&=~SCRATCH; new->q2.flags=KONST; gval.vmax=zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L)); eval_const(&gval,MAXINT); insert_const(&new->q2.val,t); get_scratch(&new->z,t,0,0); tmp1=new->z; if((new->q1.flags&(KONST|DREFOBJ))==KONST){ calc(AND,new->typf,&new->q1.val,&new->q2.val,&new->q1.val,0); new->code=ASSIGN; new->q2.flags=0; new->q2.val.vmax=sizetab[new->typf&NQ]; } *val=tmp1; vmerk=val->flags; tmp1.flags&=~SCRATCH; add_IC(new); if(bfo!=0){ new=new_IC(); new->code=LSHIFT; new->typf=t; new->typf2=INT; new->q1=tmp1; new->q2.flags=KONST; new->q2.val.vint=zm2zi(l2zm((long)bfo)); get_scratch(&new->z,t,0,0); tmp3=new->z; add_IC(new); }else{ tmp3=tmp1; } if(!isclear){ new=new_IC(); new->code=AND; new->typf=t; new->q1=*dest; new->q1.flags&=~SCRATCH; new->q2.flags=KONST; gval.vmax=zmkompl(zmlshift(zmsub(zmlshift(l2zm(1L),l2zm((int)bfs)),l2zm(1L)),l2zm((long)bfo))); eval_const(&gval,MAXINT); insert_const(&new->q2.val,t); get_scratch(&new->z,t,0,0); tmp2=new->z; add_IC(new); } new=new_IC(); new->code=OR; new->typf=t; if(isclear) new->q1=*dest; else new->q1=tmp2; new->q2=tmp3; new->z=*dest; add_IC(new); if(dest->flags&(REG|SCRATCH)) free_reg(dest->reg); val->flags=vmerk; } void inline_memcpy(np z,np q,zmax size) /* fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht */ { struct IC *new=new_IC(); if(!ISPOINTER(z->ntyp->flags)) ierror(0); if(!ISPOINTER(q->ntyp->flags)) ierror(0); if(z->flags==ADDRESS||z->flags==ADDRESSA||z->flags==ADDRESSS){ gen_IC(z,0,0); new->z=z->left->o; if(z->flags!=ADDRESSS&&z->left->flags==IDENTIFIER&&is_vlength(z->left->ntyp)){ /* variable length array */ new->z.flags|=DREFOBJ; new->z.dtyp=POINTER_TYPE(z->ntyp->next); } }else{ gen_IC(z,0,0); if(z->o.flags&DREFOBJ){ struct IC *n2=new_IC(); n2->code=ASSIGN; n2->typf=q->ntyp->flags; n2->q1=z->o; get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags,z->ntyp); n2->q2.flags=0; n2->q2.val.vmax=sizetab[POINTER_TYPE(z->ntyp->next)]; new->z=n2->z; add_IC(n2); }else{ new->z=z->o; } if(new->z.flags&VARADR){ new->z.flags&=~VARADR; }else{ new->z.flags|=DREFOBJ; new->z.dtyp=POINTER_TYPE(z->ntyp->next); } } if(q->flags==ADDRESS||q->flags==ADDRESSA||q->flags==ADDRESSS){ gen_IC(q,0,0); new->q1=q->left->o; if(q->flags!=ADDRESSS&&q->left->flags==IDENTIFIER&&is_vlength(q->left->ntyp)){ /* variable length array */ new->q1.flags|=DREFOBJ; new->q1.dtyp=POINTER_TYPE(q->ntyp->next); } }else{ gen_IC(q,0,0); if(q->o.flags&DREFOBJ){ struct IC *n2=new_IC(); n2->code=ASSIGN; n2->typf=q->ntyp->flags; n2->q1=q->o; get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags,q->ntyp); n2->q2.flags=0; n2->q2.val.vmax=sizetab[POINTER_TYPE(q->ntyp->next)]; new->q1=n2->z; add_IC(n2); }else{ new->q1=q->o; } if(new->q1.flags&VARADR){ new->q1.flags&=~VARADR; }else{ new->q1.flags|=DREFOBJ; new->q1.dtyp=POINTER_TYPE(q->ntyp->next); } } new->code=ASSIGN; new->typf=UNSIGNED|CHAR; new->q2.flags=0; new->q2.val.vmax=size; add_IC(new); } void add_IC(struct IC *new) /* fuegt ein IC ein */ { int code; if(!new) return; if(nocode) { #ifdef HAVE_MISRA /* removed */ #endif /*free(new);*/ /* building a list to free later would be nice... */ return; } new->next=0; new->q1.am=new->q2.am=new->z.am=0; new->line=line; new->file=filename; code=new->code; if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0; if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0; if(DEBUG&64){ pric(stdout,first_ic);printf("new\n");pric2(stdout,new);printf("-\n");} if(new->q1.flags&VAR){ if(!new->q1.v) ierror(0); new->q1.v->flags|=USEDASSOURCE; if(code==ADDRESS||(new->q1.flags&VARADR)) if(!is_vlength(new->q1.v->vtyp)) new->q1.v->flags|=USEDASADR; new->q1.v->priority+=currentpri; } if(new->q2.flags&VAR){ if(!new->q2.v) ierror(0); new->q2.v->flags|=USEDASSOURCE; if(code==ADDRESS||(new->q2.flags&VARADR)) if(!is_vlength(new->q2.v->vtyp)) new->q2.v->flags|=USEDASADR; new->q2.v->priority+=currentpri; } if(new->z.flags&VAR){ if(!new->z.v) ierror(0); if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST; new->z.v->priority+=currentpri; } if(block_vla[nesting]){ /* special handling for blocks with variable-length arrays */ struct llist *p; if(new->code==LABEL){ p=mymalloc(LSIZE); p->label=new->typf; p->next=vladeflabels[nesting]; vladeflabels[nesting]=p; }else if(0&&new->code==BRA&&!(new->flags&LOOP_COND_TRUE)){ p=mymalloc(LSIZE); p->label=new->typf; p->next=vlajmplabels[nesting]; vlajmplabels[nesting]=p; p=vladeflabels[nesting]; while(p){ if(p->label==new->typf) break; p=p->next; } if(!p){ /* label not declared in this block so far; re-adjust stack, but store the position - label may be declared later in the same block and adjustement must be removed */ struct vlaadjust_list *vl; struct IC *first; first=last_ic; freevl(); first=first->next; vl=mymalloc(sizeof(*vl)); vl->branch=new; vl->first=first; vl->next=vlaadjusts[nesting]; vlaadjusts[nesting]=vl; } } } if(/*(c_flags_val[0].l&2)&&*/code==LABEL){ /* entfernt Spruenge zu direkt folgenden Labels */ struct IC *p=last_ic; while(p){ if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){ struct IC *n; if(p->code!=BRA){ struct IC *cmp=p->prev; while(cmp&&cmp->code==FREEREG) cmp=cmp->prev; if(cmp->code==TEST){ if(is_volatile_obj(&cmp->q1)) break; else{ if(DEBUG&1) printf("preceding test removed\n"); remove_IC(cmp); } }else if(cmp->code==COMPARE){ if(is_volatile_obj(&cmp->q1)||is_volatile_obj(&cmp->q2)) break; else{ if(DEBUG&1) printf("preceding compare removed\n"); remove_IC(cmp); } }else break; } if(vlaadjusts[nesting]){ /* remove it from vlaadjusts-lists, if necessary */ struct vlaadjust_list *vl=vlaadjusts[nesting]; while(vl){ if(vl->branch==p){ struct IC *np=vl->branch->prev; while(np!=vl->first->prev){ if(!np) ierror(0); np->code=NOP; np->q1.flags=np->q2.flags=np->z.flags=0; np=np->prev; } vl->branch=0; } vl=vl->next; } } if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf); n=p->next; remove_IC(p); p=n; }else{ if(p->code!=LABEL) break; p=p->prev; } } } if(last_ic){ if(code==ASSIGN){ if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){ if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){ if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){ /* verbindet op a,b->reg,move reg->c zu op a,b->c */ /* hier fehlt aber noch Registerfreigabe */ last_ic->z=new->z; if(DEBUG&1) printf("move and op combined\n"); if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg); free(new); return; } } } if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){ if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){ if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){ /* verbindet op a,b->scratch,move scratch->c zu op a,b->c */ /* hier fehlt aber noch Registerfreigabe */ last_ic->z=new->z; if(DEBUG&1) printf("move and op combined(2)\n"); /* if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg);*/ free(new); return; } } } } if(last_ic->code==BRA){ if(!dontdelete&&code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){ /* loescht alles nach bra bis ein Label kommt */ /* momentan noch nicht perfekt, da es bei alloc/freereg stoppt */ free(new); #ifdef HAVE_MISRA /* removed */ #endif if(DEBUG&1) printf("Unreachable Statement deleted\n"); return; } if(last_ic->prev&&code==LABEL){ /* ersetzt bcc l1;bra l2;l1 durch b!cc l2 */ if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){ if(last_ic->next) pric2(stdout,last_ic->next); if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf); if(last_ic->prev->code&1) last_ic->prev->code--; else last_ic->prev->code++; last_ic->prev->typf=last_ic->typf; last_ic=last_ic->prev; free(last_ic->next); last_ic->next=new;new->prev=last_ic; last_ic=new; return; } } } /* }*/ new->prev=last_ic; last_ic->next=new; last_ic=new; }else{ last_ic=new;first_ic=new;new->prev=0; } ic_count++; /* Merken, on Fliesskomma benutzt wurde */ if(code!=LABEL&&(code<BEQ||code>BRA)){ if(ISFLOAT(new->typf)) float_used=1; if(code==CONVERT&&ISFLOAT(new->typf2)) float_used=1; } if((new->q1.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q1.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q1.reg); if((new->q2.flags&(SCRATCH|REG))==(SCRATCH|REG)&&(new->q2.reg!=new->z.reg||!(new->z.flags®))) free_reg(new->q2.reg); } np gen_libcall(char *fname,np arg1,struct Typ *t1,np arg2,struct Typ *t2) /* generate call to a library function (emulate operation) */ { np new; struct argument_list *al=0,*t; new=new_node(); new->flags=CALL; new->right=0; new->left=new_node(); new->left->flags=IDENTIFIER; new->left->left=new->left->right=0; new->left->identifier=add_identifier(fname,strlen(fname)); new->left->ntyp=0; new->left->sidefx=0; new->left->val.vmax=l2zm(0L); new->alist=0; if(arg1){ al=mymalloc(sizeof(*al)); al->arg=arg1; al->next=0; if(t1){ np cnv=new_node(); cnv->flags=CAST; cnv->left=arg1; cnv->right=0; cnv->ntyp=t1; al->arg=cnv; }