CLexCodeMisc *OptLabelFwd(CLexCodeMisc *lb) { CLexCodeMisc *lb1; while (lb1=lb->fwd) lb=lb1; return lb; } CHashClass *OptClassFwd(CHashClass *tempc) {//Class forwarding for unions and subclasses. CHashClass *tempc1; while (tempc1=tempc->fwd_class) tempc=tempc1; return tempc; } U0 OptSetNOP1(CIntermediateCode *tempi) { tempi->ic_code=IC_NOP1; tempi->ic_flags=0; tempi->a1.type=TY_NULL+tempi->a1.type&RT_MASK; tempi->r.type =TY_NULL+tempi->r.type &RT_MASK; } U0 OptSetNOP2(CIntermediateCode *tempi,I64 stk_delta=1) { tempi->ic_code=IC_NOP2; tempi->ic_data=stk_delta; tempi->a1.type=TY_NULL+tempi->a1.type&RT_MASK; tempi->r.type =TY_NULL+tempi->r.type &RT_MASK; } CIntermediateCode *OptFree(CIntermediateCode *tempi) {//We might access freed entries in CICTreeLinks QueRem(tempi); Free(tempi); return NULL; } CIntermediateCode *OptLag(CIntermediateCode *tempi) { do { if (!tempi->ic_code) return NULL; else tempi=tempi->last; } while (tempi->ic_code<=IC_END_EXP); return tempi; } CIntermediateCode *OptLag1(CIntermediateCode *tempi) { do { if (!tempi->ic_code) return NULL; else tempi=tempi->last; } while (tempi->ic_code==IC_NOP1||tempi->ic_code==IC_NOP2); return tempi; } CIntermediateCode *OptLag2(CIntermediateCode *tempi) { do { if (!tempi->ic_code) return NULL; else tempi=tempi->last; } while (tempi->ic_codenext; if (!tempi->ic_code) return NULL; } while (tempi->ic_code==IC_NOP1||tempi->ic_code==IC_NOP2); return tempi; } I64 CmpOffset2Reg(I64 offset,COptReg *reg_offsets) { I64 i; for (i=0;iic_class,*tempc1,*tempc2; if (tempi1->ic_flags&ICF_R_TO_INT) tempc1=cmp.internal_types[RT_I64]; else if (tempi1->ic_flags&ICF_R_TO_F64) tempc1=cmp.internal_types[RT_F64]; else { tempc1=OptClassFwd(tempi1->ic_class); } if (tempi2->ic_flags&ICF_R_TO_INT) tempc2=cmp.internal_types[RT_I64]; else if (tempi2->ic_flags&ICF_R_TO_F64) tempc2=cmp.internal_types[RT_F64]; else { tempc2=OptClassFwd(tempi2->ic_class); } if (tempc1->raw_type>tempc2->raw_type) tempc=tempi->ic_class=tempc1; else tempc=tempi->ic_class=tempc2; if (tempc->raw_type==RT_F64) { if (tempi1->ic_code==IC_IMM_I64) { tempi1->ic_data(F64)=tempi1->ic_data; tempi1->ic_class=cmp.internal_types[RT_F64]; tempi1->ic_code=IC_IMM_F64; tempi1->ic_flags&=~ICF_R_TO_F64; } else if (tempc1->raw_type!=RT_F64) tempi1->ic_flags|=ICF_R_TO_F64; if (tempi2->ic_code==IC_IMM_I64) { tempi2->ic_data(F64)=tempi2->ic_data; tempi2->ic_class=cmp.internal_types[RT_F64]; tempi2->ic_code=IC_IMM_F64; tempi2->ic_flags&=~ICF_R_TO_F64; } else if (tempc2->raw_type!=RT_F64) tempi2->ic_flags|=ICF_R_TO_F64; if (IC_LESS<=tempi->ic_code<=IC_GREATER_EQUAL && (tempii=OptLead1(tempi)) && tempii->ic_code!=IC_PUSH_CMP && tempii->ic_code!=IC_AND_AND) { //We are looking for float comparisons to zero to convert to int. if (tempi1->ic_code==IC_IMM_F64 && !tempi1->ic_data && tempi2->ic_code==IC_DEREF && tempc2==cmp.internal_types[RT_F64]) { tempi1->ic_code==IC_IMM_I64; goto fb_here1; } else if (tempi2->ic_code==IC_IMM_F64 && !tempi2->ic_data && tempi1->ic_code==IC_DEREF && tempc1==cmp.internal_types[RT_F64]) { tempi2->ic_code==IC_IMM_I64; fb_here1: tempi1->ic_flags&=~ICF_R_TO_F64; tempi->ic_class=tempi1->ic_class=tempi2->ic_class=cmp.internal_types[RT_I64]; *is_unsigned=FALSE; return FBO1_NOT_CONST; } goto fb_here2; } else { fb_here2: if (tempi1->ic_code==IC_IMM_F64 && tempi2->ic_code==IC_IMM_F64 && !(tempi->ic_flags&(ICF_PUSH_CMP|ICF_POP_CMP))) { tempi->ic_flags|=tempi1->ic_flags|tempi2->ic_flags; OptSetNOP1(tempi1); OptSetNOP1(tempi2); return FBO1_F64; } else return FBO1_NOT_CONST; } } *is_unsigned=tempc1->raw_type&1 || tempc2->raw_type&1; if (tempi1->ic_code==IC_IMM_I64 && tempi2->ic_code==IC_IMM_I64 && !(tempi->ic_flags&(ICF_PUSH_CMP|ICF_POP_CMP))) { tempi->ic_flags|=tempi1->ic_flags|tempi2->ic_flags; OptSetNOP1(tempi1); OptSetNOP1(tempi2); return FBO1_INT; } else return FBO1_NOT_CONST; } Bool OptFixupBinaryOp2(CIntermediateCode **tempi1,CIntermediateCode **tempi2) { CIntermediateCode *tempii1=*tempi1, *tempii2=*tempi2; if (tempii1->ic_code==IC_IMM_I64 && !(tempii1->ic_flags & ICF_R_TO_F64)) return TRUE; if (tempii2->ic_code==IC_IMM_I64 && !(tempii2->ic_flags & ICF_R_TO_F64)) { *tempi1=tempii2; *tempi2=tempii1; return TRUE; } return FALSE; } Bool OptFixupUnaryOp(CIntermediateCode *tempi, CIntermediateCode *tempi1, Bool *is_unsigned) { CHashClass *tempc,*tempc1; tempc1=OptClassFwd(tempi1->ic_class); tempi->ic_class=tempc1; tempc=tempi->ic_class; if (tempc->raw_type==RT_F64) { if (tempi1->ic_code==IC_IMM_I64) { tempi1->ic_data(F64)=tempi1->ic_data; tempi1->ic_class=cmp.internal_types[RT_F64]; tempi1->ic_code=IC_IMM_F64; tempi1->ic_flags&=~ICF_R_TO_F64; } else if (tempc1->raw_type!=RT_F64) tempi1->ic_flags|=ICF_R_TO_F64; if (tempi1->ic_code==IC_IMM_F64) { tempi->ic_flags|=tempi1->ic_flags; OptSetNOP1(tempi1); return FBO1_F64; } else return FBO1_NOT_CONST; } *is_unsigned=tempc1->raw_type&1; if (tempi1->ic_code==IC_IMM_I64) { tempi->ic_flags|=tempi1->ic_flags; OptSetNOP1(tempi1); return FBO1_INT; } else return FBO1_NOT_CONST; } extern U0 OptBrNotZero(CLex *lx,CIntermediateCode *tempi); CIntermediateCode *OptBrZero(CLex *lx,CIntermediateCode *tempi) { CLexCodeMisc *lb_true,*lb_false; CIntermediateCode *tempii=OptLag(tempi),*tempii2; switch (tempii->ic_code) { case IC_NOT: tempi->ic_code=IC_BR_NOT_ZERO; tempi->ic_class=tempii->ic_class; tempi->ic_flags|=tempii->ic_flags; tempi->t.a1c=tempii->t.a1c; tempi->t.a1t=tempii->t.a1t; OptFree(tempii); return OptBrNotZero(lx,tempi); case IC_EQUAL_EQUAL...IC_LESS_EQUAL: tempi->ic_code=(tempii->ic_code-IC_EQUAL_EQUAL)^1+IC_BR_EQUAL_EQUAL; break; case IC_OR_OR: tempi->ic_code=IC_BR_OR_OR_ZERO; break; case IC_AND_AND: tempi->ic_code=IC_BR_AND_AND_ZERO; break; case IC_AND: tempi->ic_code=IC_BR_AND_ZERO; break; case IC_MM_: if (lx->pass==2 && !(tempii->ic_flags&ICF_R_TO_F64) && tempii->ic_class->raw_type!=RT_F64) tempi->ic_code=IC_BR_MM_ZERO; break; case IC_CALL_END: tempii2=OptLag(tempii); switch (tempii2->ic_code) { sub_switch_start: case IC_CARRY: tempii2->ic_code=IC_BR_NOT_CARRY; break; case IC_BT: tempii2->ic_code=IC_BR_NOT_BT; break; case IC_LBTS: tempii2->ic_flags|=ICF_LOCK; case IC_BTS: tempii2->ic_code=IC_BR_NOT_BTS; break; case IC_LBTR: tempii2->ic_flags|=ICF_LOCK; case IC_BTR: tempii2->ic_code=IC_BR_NOT_BTR; break; case IC_LBTC: tempii2->ic_flags|=ICF_LOCK; case IC_BTC: tempii2->ic_code=IC_BR_NOT_BTC; break; sub_switch_end: tempii2->ic_data=tempi->ic_data; tempii->ic_code=IC_CALL_END2; OptSetNOP1(tempi); return tempii; } break; } if (tempi->ic_code!=IC_BR_ZERO) { tempi->ic_class=tempii->ic_class; tempi->ic_flags|=tempii->ic_flags; tempi->t.a1c=tempii->t.a1c; tempi->t.a2c=tempii->t.a2c; tempi->t.a1t=tempii->t.a1t; tempi->t.a2t=tempii->t.a2t; OptFree(tempii); if (tempi->ic_flags&ICF_PUSH_CMP && IC_BR_NOT_EQUAL<=tempi->ic_code<=IC_BR_LESS_EQUAL && !(tempi->ic_flags&ICF_USE_F64)) { tempi->ic_code+=IC_BR_EQUAL_EQUAL2-IC_BR_EQUAL_EQUAL; tempi->ic_flags&=~ICF_PUSH_CMP; tempii=tempi->next; //IC_PUSH_CMP instruction while (tempii->ic_code!=IC_PUSH_CMP) tempii=tempii->next; tempii->t.a1t=tempi; OptSetNOP1(tempii); } lb_true=tempi->ic_data; if (tempi->ic_code==IC_BR_AND_AND_ZERO) { tempii=tempi->t.a1t->next; tempii->ic_data=lb_true; tempii->t.a1t=tempi->t.a1t; tempii->t.a1c=tempi->t.a1c; tempii->ic_code=IC_BR_ZERO; OptBrZero(lx,tempii); tempii=tempi->t.a2t->next; tempii->t.a1t=tempi->t.a2t; tempii->t.a1c=tempi->t.a2c; tempii->ic_data=lb_true; tempii->ic_code=IC_BR_ZERO; tempii=OptBrZero(lx,tempii); OptSetNOP1(tempi); } else if (tempi->ic_code==IC_BR_OR_OR_ZERO) { lb_false=LCCMiscNew(lx,CMT_LABEL); tempi->ic_code=IC_LABEL; tempi->ic_flags=0; tempi->ic_data=lb_false; tempii=tempi->t.a1t->next; tempii->t.a1t=tempi->t.a1t; tempii->t.a1c=tempi->t.a1c; tempii->ic_data=lb_false; tempii->ic_code=IC_BR_NOT_ZERO; OptBrNotZero(lx,tempii); tempii=tempi->t.a2t->next; tempii->t.a1t=tempi->t.a2t; tempii->t.a1c=tempi->t.a2c; tempii->ic_data=lb_true; tempii->ic_code=IC_BR_ZERO; tempii=OptBrZero(lx,tempii); } else tempii=tempi; if (tempi->ic_flags&ICF_POP_CMP && tempi->t.a1t->ic_code==IC_NOP1) { tempi->t.a1t=tempi->t.a1t->t.a1t; tempi->ic_flags&=~ICF_POP_CMP; } return tempii; } return tempi; } CIntermediateCode *OptBrNotZero(CLex *lx,CIntermediateCode *tempi) { CLexCodeMisc *lb_true,*lb_false; CIntermediateCode *tempii=OptLag(tempi),*tempii2; switch (tempii->ic_code) { case IC_NOT: tempi->ic_code=IC_BR_ZERO; tempi->ic_class=tempii->ic_class; tempi->ic_flags|=tempii->ic_flags; tempi->t.a1c=tempii->t.a1c; tempi->t.a1t=tempii->t.a1t; OptFree(tempii); return OptBrZero(lx,tempi); case IC_EQUAL_EQUAL...IC_LESS_EQUAL: tempi->ic_code=tempii->ic_code+IC_BR_EQUAL_EQUAL-IC_EQUAL_EQUAL; break; case IC_OR_OR: tempi->ic_code=IC_BR_OR_OR_NOT_ZERO; break; case IC_AND_AND: tempi->ic_code=IC_BR_AND_AND_NOT_ZERO; break; case IC_AND: tempi->ic_code=IC_BR_AND_NOT_ZERO; break; case IC_MM_: if (lx->pass==2 && !(tempii->ic_flags&ICF_R_TO_F64) && tempii->ic_class->raw_type!=RT_F64) tempi->ic_code=IC_BR_MM_NOT_ZERO; break; case IC_CALL_END: tempii2=OptLag(tempii); switch (tempii2->ic_code) { sub_switch_start: case IC_CARRY: tempii2->ic_code=IC_BR_CARRY; break; case IC_BT: tempii2->ic_code=IC_BR_BT; break; case IC_LBTS: tempii2->ic_flags|=ICF_LOCK; case IC_BTS: tempii2->ic_code=IC_BR_BTS; break; case IC_LBTR: tempii2->ic_flags|=ICF_LOCK; case IC_BTR: tempii2->ic_code=IC_BR_BTR; break; case IC_LBTC: tempii2->ic_flags|=ICF_LOCK; case IC_BTC: tempii2->ic_code=IC_BR_BTC; break; sub_switch_end: tempii2->ic_data=tempi->ic_data; tempii->ic_code=IC_CALL_END2; OptSetNOP1(tempi); return tempii; } break; } if (tempi->ic_code!=IC_BR_NOT_ZERO) { tempi->ic_class=tempii->ic_class; tempi->ic_flags|=tempii->ic_flags; tempi->t.a1c=tempii->t.a1c; tempi->t.a2c=tempii->t.a2c; tempi->t.a1t=tempii->t.a1t; tempi->t.a2t=tempii->t.a2t; OptFree(tempii); if (tempi->ic_flags&ICF_PUSH_CMP && IC_BR_NOT_EQUAL<=tempi->ic_code<=IC_BR_LESS_EQUAL && !(tempi->ic_flags&ICF_USE_F64)) { tempi->ic_code+=IC_BR_EQUAL_EQUAL2-IC_BR_EQUAL_EQUAL; tempi->ic_flags&=~ICF_PUSH_CMP; tempii=tempi->next; //IC_PUSH_CMP instruction while (tempii->ic_code!=IC_PUSH_CMP) tempii=tempii->next; tempii->t.a1t=tempi; OptSetNOP1(tempii); } lb_true=tempi->ic_data; if (tempi->ic_code==IC_BR_OR_OR_NOT_ZERO) { tempii=tempi->t.a1t->next; tempii->t.a1t=tempi->t.a1t; tempii->t.a1c=tempi->t.a1c; tempii->ic_data=lb_true; tempii->ic_code=IC_BR_NOT_ZERO; OptBrNotZero(lx,tempii); tempii=tempi->t.a2t->next; tempii->t.a1t=tempi->t.a2t; tempii->t.a1c=tempi->t.a2c; tempii->ic_data=lb_true; tempii->ic_code=IC_BR_NOT_ZERO; tempii=OptBrNotZero(lx,tempii); OptSetNOP1(tempi); } else if (tempi->ic_code==IC_BR_AND_AND_NOT_ZERO) { lb_false=LCCMiscNew(lx,CMT_LABEL); tempi->ic_code=IC_LABEL; tempi->ic_flags=0; tempi->ic_data=lb_false; tempii=tempi->t.a1t->next; tempii->t.a1t=tempi->t.a1t; tempii->t.a1c=tempi->t.a1c; tempii->ic_data=lb_false; tempii->ic_code=IC_BR_ZERO; OptBrZero(lx,tempii); tempii=tempi->t.a2t->next; tempii->t.a1t=tempi->t.a2t; tempii->t.a1c=tempi->t.a2c; tempii->ic_data=lb_true; tempii->ic_code=IC_BR_NOT_ZERO; tempii=OptBrNotZero(lx,tempii); } else tempii=tempi; if (tempi->ic_flags&ICF_POP_CMP && tempi->t.a1t->ic_code==IC_NOP1) { tempi->t.a1t=tempi->t.a1t->t.a1t; tempi->ic_flags&=~ICF_POP_CMP; } return tempii; } return tempi; } U0 OptFixSizeOf(CIntermediateCode *tempi1,CIntermediateCode *tempi_push,CHashClass *tempcc) { if (tempi1->ic_code==IC_MUL && tempi1->t.a2t->ic_code==IC_SIZEOF) { tempi1->t.a2t->ic_code=IC_IMM_I64; tempi1->t.a2t->ic_class=tempcc; tempi_push->ic_class=tempcc; if (tempcc->ptr_stars_cnt) { tempcc--; if (tempcc->size==1) goto here; tempi1->t.a2t->ic_data=tempcc->size; } else { here: if (tempi_push==tempi1) tempi1->t.a2t->ic_data=1; else { OptSetNOP1(tempi1->t.a2t); OptSetNOP1(tempi1); } } } } I64 CmpRawType(CHashClass *tempc) { if (tempc) { tempc=OptClassFwd(tempc); return tempc->raw_type; } return 0; } I64 CmpRawTypePointed(CHashClass *tempc) { if (tempc) { if (tempc->ptr_stars_cnt) tempc--; tempc=OptClassFwd(tempc); return tempc->raw_type; } return 0; } U0 CmpF1PushPop(CIntermediateCode *tempi,CIntermediateCode *tempi2) { if (intermediate_code_table[tempi2->ic_code].fpop|| tempi2->ic_flags&ICF_R_TO_F64) Bts(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0); } U0 CmpF2PushPop(CIntermediateCode *tempi,CIntermediateCode *tempi1,CIntermediateCode *tempi2) { if ((tempi2->ic_code==IC_MOV || tempi2->ic_code==IC_IMM_F64) && !(tempi2->ic_flags&ICF_R_TO_F64) && (intermediate_code_table[tempi1->ic_code].fpop || tempi1->ic_flags&ICF_R_TO_F64)) Bts(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0); else if ((intermediate_code_table[tempi2->ic_code].fpop || tempi2->ic_flags&ICF_R_TO_F64)&& !(tempi1->ic_flags&ICF_R_TO_F64)) Bts(&tempi->ic_flags,ICf_DONT_PUSH_FLOAT0); } class COptMemberVar { I64 score,offset_start,offset_end,lea_balance; CMemberLst *m; }; I64 OptMVCompare(COptMemberVar *mv1,COptMemberVar *mv2) { return mv2->score-mv1->score; }