I8 CmpType(ClassStruct *tempc) { if (tempc) { while (tempc->return_class) tempc=tempc->return_class; return tempc->sub_type; } return 0; } I8 CmpPType(ClassStruct *tempc) { if (tempc) { if (tempc->ptr_cnt) tempc-=sizeof(ClassStruct); while (tempc->return_class) tempc=tempc->return_class; return tempc->sub_type; } return 0; } void CmpOptPass2(LexStruct *lx,ClassStruct *fun_class,I8 *register_offsets) { ClassStruct *tempc,*tempc1,*tempc2,*tempc3; CbMiscStruct *lb; IntermediateCode *tempi,*tempi1,*tempi2,*tempi3,*tempii, *tempil1,*tempil2, *temp_lag[4],*last_with_class=NULL; I8 code,i,j,k,l,o[NUM_REGS],c[NUM_REGS],lea_s[NUM_REGS]; MemberListStruct *tempm,*m[NUM_REGS]; ParseStack *ps=OptStart(lx,temp_lag); for (i=0;imember_list; while (tempm) { if (!(tempm->flags & MLF_NO_REG_VARIABLE)) { k=tempm->use_cnt; if (tempm->flags & MLF_USE_REG_VARIABLE) k+=MAX_I8/2; //big but not too big if (k>c[NUM_REGS-1]) { for (i=0;ic[i]) { for (j=NUM_REGS-2;j>=i;j--) { c[j+1]=c[j]; o[j+1]=o[j]; m[j+1]=m[j]; } c[i]=k; o[i]=tempm->offset; m[i]=tempm; break; } } } tempm=tempm->next; } } tempi=lx->cb.cb_in_ptr; while (code=tempi->ic_opcode) { OptNext(tempi,temp_lag); if (code!=EC_NOP) { tempil1=temp_lag[1]; tempil2=temp_lag[2]; tempc=tempi->ic_class; switch (cmp_param_cnt[code]) { case 9: ps->ptr-=tempi->ic_data>>3; break; case 3: tempi3=PrsPop(ps); if (tempi3->ic_flags&ICF_R_TO_DOUBLE) tempc3=sys_internal_types[IT_DOUBLE]; else if (tempi3->ic_flags & ICF_R_TO_INT) tempc3=sys_internal_types[IT_I8]; else tempc3=tempi->p3c; tempi->p3.type=TY_STK+CmpType(tempc3); tempi->p3.ptype=CmpPType(tempc3); tempi->ic_flags|=ICF_P3_WAS_STK; case 2: tempi2=PrsPop(ps); if (tempi2->ic_flags&ICF_R_TO_DOUBLE) tempc2=sys_internal_types[IT_DOUBLE]; else if (tempi2->ic_flags & ICF_R_TO_INT) tempc2=sys_internal_types[IT_I8]; else tempc2=tempi->p2c; tempi->p2.type=TY_STK+CmpType(tempc2); tempi->p2.ptype=CmpPType(tempc2); tempi->ic_flags|=ICF_P2_WAS_STK; case 1: tempi1=PrsPop(ps); if (tempi1->ic_flags&ICF_R_TO_DOUBLE) tempc1=sys_internal_types[IT_DOUBLE]; else if (tempi1->ic_flags & ICF_R_TO_INT) tempc1=sys_internal_types[IT_I8]; else tempc1=tempi->p1c; tempi->p1.type=TY_STK+CmpType(tempc1); tempi->p1.ptype=CmpPType(tempc1); tempi->ic_flags|=ICF_P1_WAS_STK; break; } if (cmp_result_cnt[code]) { tempi->r.type=TY_STK+CmpType(tempc); tempi->r.ptype=CmpPType(tempc); tempi->ic_flags|=ICF_R_WAS_STK; PrsPush(ps,tempi); } switch (code) { case EC_IMM: case EC_DOUBLE: case EC_STR_CONST: case EC_FS: case EC_GS: case EC_PUSH_CMP: break; case EC_RBP: tempi->ic_opcode=EC_REG; tempi->p1.reg=CREG_RBP; break; case EC_REG: case EC_COM: case EC_NOT: case EC_UNARY_MINUS: break; case EC_DEREF: tempi->p1.ptype=tempi->r.type&IT_MASK; if (tempi1->ic_opcode==EC_LEA) { tempi->ic_flags|=tempi1->ic_flags; tempi1->ic_opcode=EC_NOP; tempi->p1.reg=tempi1->p1.reg; tempi->p1.disp=tempi1->p1.disp; tempi->p1.type=TY_DISP+tempi->r.type&IT_MASK; tempi->p1.ptype=tempi->r.ptype; tempi->ic_opcode=EC_MOV; if (tempi->p1.reg==CREG_RBP) for (i=0;ip1.disp) lea_s[i]--; } else if (tempil1->ic_opcode==EC_ADD_CONST) { if (tempil2->ic_opcode==EC_REG) { tempi->ic_flags|=tempil2->ic_flags|tempil1->ic_flags; tempil2->ic_opcode=EC_NOP; tempil1->ic_opcode=EC_NOP; tempi->p1.reg=tempil2->p1.reg; tempi->p1.disp=tempi->ic_data; tempi->p1.type=TY_DISP+tempi->r.type&IT_MASK; tempi->p1.ptype=tempi->r.ptype; tempi->ic_opcode=EC_MOV; } } break; case EC__PP: case EC__MM: case EC_PP_: case EC_MM_: if (tempi1->ic_opcode==EC_LEA && tempi1->p1.type&TY_MASK==TY_DISP && tempi1->p1.reg==CREG_RBP) for (i=0;ip1.disp) lea_s[i]--; tempi->p1.ptype=tempi->r.type&IT_MASK; tempi->r.ptype=CmpPType(tempi->p1c); break; case EC_POWER: case EC_SHL: case EC_SHR: case EC_MUL: case EC_DIV: case EC_MOD: case EC_AND: case EC_OR: case EC_XOR: break; case EC_ADD: if (tempi->ic_class->sub_type==IT_DOUBLE) break; if (FixupBinaryOp2(&tempi1,&tempi2)) { tempi->ic_flags|=tempi1->ic_flags; tempi1->ic_opcode=EC_NOP; if (tempi->p1t!=tempi2) tempi->p1c=tempi->p2c; tempi->ic_data=tempi1->ic_data; tempi->ic_opcode=EC_ADD_CONST; tempi->p1.ptype=tempi->r.type&IT_MASK; tempi->p2.type=TY_NULL; if (tempil2->ic_opcode==EC_REG && tempil2->p1.reg==CREG_RBP) { tempi->ic_flags|=tempil2->ic_flags; tempil2->ic_opcode=EC_NOP; tempi->ic_opcode=EC_LEA; tempi->p1.reg=CREG_RBP; tempi->p1.type=TY_DISP+tempi->p1.type&IT_MASK; tempi->p1.disp=tempi->ic_data; for (i=0;iic_data) lea_s[i]++; } } break; case EC_SUB: if (tempi->ic_class->sub_type==IT_DOUBLE) break; if (tempi2->ic_opcode==EC_IMM) { tempi->ic_flags|=tempi2->ic_flags; tempi2->ic_opcode=EC_NOP; tempi->ic_data=tempi2->ic_data; tempi->ic_opcode=EC_SUB_CONST; tempi->p2.type=TY_NULL; } break; case EC_EQUAL_EQUAL: case EC_NOT_EQUAL: case EC_LESS: case EC_GREATER: case EC_LESS_EQUAL: case EC_GREATER_EQUAL: case EC_AND_AND: case EC_OR_OR: case EC_XOR_XOR: case EC_COLON: break; case EC_ASSIGN: case EC_SHL_EQUAL: case EC_SHR_EQUAL: case EC_MUL_EQUAL: case EC_DIV_EQUAL: case EC_MOD_EQUAL: case EC_AND_EQUAL: case EC_OR_EQUAL: case EC_XOR_EQUAL: case EC_ADD_EQUAL: case EC_SUB_EQUAL: if (tempi1->ic_opcode==EC_LEA && tempi1->p1.type&TY_MASK==TY_DISP && tempi1->p1.reg==CREG_RBP) for (i=0;ip1.disp) lea_s[i]--; tempi->p1.ptype=tempi->r.type&IT_MASK; tempi->r.ptype=CmpPType(tempi->p1c); break; case EC_SHL_CONST: case EC_SHR_CONST: case EC_ENTER: case EC_ADD_RSP: case EC_CALL: case EC_CALL_INDIRECT: case EC_CALL_INDIRECT2: case EC_CALL_EXTERN: case EC_CLI: case EC_STI: case EC_WBINVD: case EC_INVD: case EC_ENABLE_CACHE: case EC_DISABLE_CACHE: case EC_GET_FLAGS: case EC_RDTSC: case EC_SET_FLAGS: case EC_GET_BASE_PTR: case EC_SET_BASE_PTR: case EC_GET_STACK_PTR: case EC_SET_STACK_PTR: case EC_SET_RAX: case EC_RETURN_START: case EC_RETURN_END: case EC_ABSOLUTE_ADDRESS: case EC_TYPE: case EC_BT: case EC_BTS: case EC_BTR: case EC_BTC: case EC_LBTS: case EC_LBTR: case EC_LBTC: case EC_BSF: case EC_BSR: case EC_PREEMPT: case EC_ABSI8: case EC_INSQUE: case EC_INSQUE_REV: case EC_REMQUE: case EC_MEMCPY: case EC_MEMSET: case EC_INPD: case EC_INPW: case EC_INP: case EC_STRLEN: case EC_OUTPD: case EC_OUTPW: case EC_OUTP: case EC_SWITCH: break; case EC_BR_ZERO: case EC_BR_NOT_ZERO: case EC_BR_NOT_EQUAL: case EC_BR_EQUAL_EQUAL: case EC_BR_GREATER_EQUAL: case EC_BR_LESS_EQUAL: case EC_BR_GREATER: case EC_BR_LESS: case EC_BR_AND_NOT_ZERO: case EC_BR_AND_ZERO: if (tempi->ic_flags&ICF_POP_CMP && !(tempi->ic_flags&ICF_USE_DOUBLE) && tempi2->ic_opcode==EC_IMM) { tempi->ic_flags=(tempi->ic_flags&~ICF_POP_CMP)|ICF_RCX_CMP2; temp_lag[3]->ic_flags=(temp_lag[3]->ic_flags&~ICF_PUSH_CMP)|ICF_RCX_CMP; } //fall through case EC_GET_LABEL: case EC_BR_BT: case EC_BR_BTS: case EC_BR_BTR: case EC_BR_BTC: case EC_BR_NOT_BT: case EC_BR_NOT_BTS: case EC_BR_NOT_BTR: case EC_BR_NOT_BTC: case EC_BR_LBTS: case EC_BR_LBTR: case EC_BR_LBTC: case EC_BR_NOT_LBTS: case EC_BR_NOT_LBTR: case EC_BR_NOT_LBTC: lb=tempi->ic_data; if (!(tempi->ic_flags&ICF_PUSH_CMP)) while (lb->forward) lb=lb->forward; lb->flags|=CBMF_USED; break; case EC_LEAVE: case EC_RET: if (fun_class && (tempii=last_with_class)) { if (fun_class->return_class->sub_type==IT_DOUBLE && tempii->ic_class->sub_type!=IT_DOUBLE) tempii->ic_flags|=ICF_R_TO_DOUBLE; if (fun_class->return_class->sub_type!=IT_DOUBLE && tempii->ic_class->sub_type==IT_DOUBLE) tempii->ic_flags|=ICF_R_TO_INT; } break; case EC_JMP: if (tempil1->ic_opcode==EC_LABEL) { lb=tempil1->ic_data; lb->forward=tempi->ic_data; if (tempil2->ic_opcode==EC_LABEL) { lb=tempil2->ic_data; lb->forward=tempi->ic_data; if (temp_lag[3]->ic_opcode==EC_LABEL) { lb=temp_lag[3]->ic_data; lb->forward=tempi->ic_data; } } } lb=tempi->ic_data; while (lb->forward) lb=lb->forward; lb->flags|=CBMF_USED; break; case EC_NOP: case EC_NULL: case EC_LABEL: case EC_ADDRESS: case EC_QUESTION: case EC_IRQ: case EC_END_EXP: case EC_CALL_END: case EC_CALL_END2: case EC_CALL_START: case EC_PUSH_REGS: case EC_POP_REGS: break; case EC_NOP1: ps->ptr+=tempi->ic_data; break; default: OptMissing(lx,2,tempi); } if (tempi->ic_class) { if (code!=EC_RETURN_END) last_with_class=tempi; } } tempi+=sizeof(IntermediateCode); } for (i=0;iused_reg_mask&=~(CREG_VARS_MASK|CREG_NON_PTR_MASK); if (fun_class && !Bt(&lx->flags,LFf_NO_REG_VAR) && !(lx->flags & LF_NO_REG_OPT)) { j=0; for (i=0;i0) { l=0; for (i=0;imember_class; while (tempc->return_class) tempc=tempc->return_class; if (!tempc->ptr_cnt && !tempm->cnt) { tempm->register=to_non_ptr_vars_map[l++]; register_offsets[tempm->register]=o[i]; if (Bt(&lx->flags,LFf_OPT_TRACE_PRESENT)) { PrintF("Function:%s\r\n",fun_class->str); PrintF("Reg %Z Var \"%s\" %08X[RBP]\r\n",tempm->register,"ST_U8_REGS", tempm->str,register_offsets[tempm->register]); } o[i]=MAX_I8; Bts(&fun_class->used_reg_mask,tempm->register); } } l=0; for (i=0;iregister=to_reg_vars_map[l++]; register_offsets[tempm->register]=o[i]; if (Bt(&lx->flags,LFf_OPT_TRACE_PRESENT)) PrintF("Reg %Z Var \"%s\" %08X[RBP]\r\n",tempm->register,"ST_U8_REGS", tempm->str,tempm->register); Bts(&fun_class->used_reg_mask,tempm->register); } } } } OptEnd(lx,2,ps); }