/*-----------------------------------------------------------------*/ static S4O_RET termScanAtFunc (const lineNode *pl, int rIdx) { sym_link *ftype; bool banked_reg = (rIdx == R0_IDX) || (rIdx == R1_IDX) || (rIdx == R2_IDX); if (!isFunc (pl)) return S4O_CONTINUE; // let's assume calls to literally given locations use the default // most notably : (*(void (*)()) 0) (); see bug 1749275 if (IS_VALOP (IC_LEFT (pl->ic))) return (options.model == MODEL_HUGE) && banked_reg ? S4O_ABORT : options.all_callee_saves ? S4O_CONTINUE : S4O_TERM; ftype = OP_SYM_TYPE(IC_LEFT(pl->ic)); if (IS_FUNCPTR (ftype)) ftype = ftype->next; if (IFFUNC_ISBANKEDCALL(ftype) && banked_reg) return S4O_ABORT; if (FUNC_ARGS (ftype) && getSize (FUNC_ARGS (ftype)->type) > 4) return S4O_ABORT; if (FUNC_CALLEESAVES(ftype)) return S4O_CONTINUE; if (FUNC_ISNAKED(ftype)) return S4O_CONTINUE; return S4O_TERM; }
/*-----------------------------------------------------------------*/ static void convilong (iCode * ic, eBBlock * ebp, sym_link * type, int op) { symbol *func = NULL; iCode *ip = ic->next; iCode *newic; int lineno = ic->lineno; int bwd; int su; int bytesPushed=0; remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { if (op == '*') func = __muldiv[0][bwd][su]; else if (op == '/') func = __muldiv[1][bwd][su]; else if (op == '%') func = __muldiv[2][bwd][su]; else if (op == RRC) func = __rlrr[1][bwd][su]; else if (op == RLC) func = __rlrr[0][bwd][su]; else if (op == RIGHT_OP) func = __rlrr[1][bwd][su]; else if (op == LEFT_OP) func = __rlrr[0][bwd][su]; else assert (0); goto found; } } } assert (0); found: /* if int & long support routines NOT compiled as reentrant */ if (!options.intlong_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_LEFT (ic), NULL); else { newic = newiCode ('=', NULL, IC_LEFT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* compiled as reentrant then push */ /* push right */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, IC_RIGHT (ic), NULL); } else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_RIGHT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode (IPUSH, IC_LEFT (ic), NULL); newic->parmPush = 1; bytesPushed += getSize(operandType(IC_LEFT(ic))); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* for the result */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; // to clear the stack after the call addiCodeToeBBlock (ebp, newic, ip); }
/*-----------------------------------------------------------------*/ static void cnvToFcall (iCode * ic, eBBlock * ebp) { iCode *ip; iCode *newic; operand *left; operand *right; symbol *func = NULL; int lineno = ic->lineno; int bytesPushed=0; ip = ic->next; /* insertion point */ /* remove it from the iCode */ remiCodeFromeBBlock (ebp, ic); left = IC_LEFT (ic); right = IC_RIGHT (ic); switch (ic->op) { case '+': func = __fsadd; break; case '-': func = __fssub; break; case '/': func = __fsdiv; break; case '*': func = __fsmul; break; case EQ_OP: func = __fseq; break; case NE_OP: func = __fsneq; break; case '<': func = __fslt; break; case '>': func = __fsgt; break; case LE_OP: func = __fslteq; break; case GE_OP: func = __fsgteq; break; } /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode ('=', NULL, IC_LEFT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* second one */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, IC_LEFT (ic), NULL); } else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)->next); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* push right */ if (IS_REGPARM (FUNC_ARGS(func->type)->next->etype)) { newic = newiCode (SEND, right, NULL); } else { newic = newiCode (IPUSH, right, NULL); newic->parmPush = 1; bytesPushed+=4; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; /* insert push left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) { newic = newiCode (SEND, left, NULL); } else { newic = newiCode (IPUSH, left, NULL); newic->parmPush = 1; bytesPushed+=4; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* insert the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); newic->lineno = lineno; newic->parmBytes+=bytesPushed; addiCodeToeBBlock (ebp, newic, ip); }
/*-----------------------------------------------------------------*/ static void cnvFromFloatCast (iCode * ic, eBBlock * ebp) { iCode *ip, *newic; symbol *func; sym_link *type = operandType (IC_LEFT (ic)); int lineno = ic->lineno; int bwd, su; ip = ic->next; /* remove it from the iCode */ remiCodeFromeBBlock (ebp, ic); /* depending on the type */ for (bwd = 0; bwd < 3; bwd++) { for (su = 0; su < 2; su++) { if (compareType (type, __multypes[bwd][su]) == 1) { func = __conv[1][bwd][su]; goto found; } } } assert (0); found: /* if float support routines NOT compiled as reentrant */ if (!options.float_rent) { /* first one */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode ('=', NULL, IC_RIGHT (ic)); IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type)); } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } else { /* push the left */ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) newic = newiCode (SEND, IC_RIGHT (ic), NULL); else { newic = newiCode (IPUSH, IC_RIGHT (ic), NULL); newic->parmPush = 1; } addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; } /* make the call */ newic = newiCode (CALL, operandFromSymbol (func), NULL); IC_RESULT (newic) = IC_RESULT (ic); addiCodeToeBBlock (ebp, newic, ip); newic->lineno = lineno; }