X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=src%2FSDCCicode.c;h=6e7dcb262fc52ef06ae40921282ef80f0e7cb759;hb=004fae966ab15b26fe0b28fdf671ba0954d63ab7;hp=9b841e5219bc278fc546397106634b626160a5ad;hpb=0ec1c5ce1015c8068d60bd2f21eee32875042a18;p=fw%2Fsdcc diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 9b841e52..6e7dcb26 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -120,7 +120,8 @@ iCodeTable codeTable[] = {ARRAYINIT, "arrayInit", picGenericOne, NULL}, {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}, {CRITICAL, "critical_start", picCritical, NULL}, - {ENDCRITICAL, "critical_end", picEndCritical, NULL} + {ENDCRITICAL, "critical_end", picEndCritical, NULL}, + {SWAP, "swap", picGenericOne, NULL} }; /*-----------------------------------------------------------------*/ @@ -233,12 +234,12 @@ printOperand (operand * op, FILE * file) case SYMBOL: #define REGA 1 #ifdef REGA - fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */ + fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d a2p%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */ (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name), op->key, OP_LIVEFROM (op), OP_LIVETO (op), OP_SYMBOL (op)->stack, - op->isaddr, OP_SYMBOL (op)->isreqv, + op->isaddr, op->aggr2ptr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc, OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr ); @@ -398,6 +399,9 @@ PRINTFUNC (picGenericOne) if (ic->op == SEND || ic->op == RECEIVE) { fprintf(of,"{argreg = %d}",ic->argreg); } + if (ic->op == IPUSH) { + fprintf(of,"{parmPush = %d}",ic->parmPush); + } fprintf (of, "\n"); } @@ -513,7 +517,7 @@ piCode (void *item, FILE * of) of = stdout; icTab = getTableEntry (ic->op); - fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t", + fprintf (of, "%s(%d:%d:%d:%d:%d)\t", ic->filename, ic->lineno, ic->seq, ic->key, ic->depth, ic->supportRtn); icTab->iCodePrint (of, ic, icTab->printName); @@ -656,7 +660,7 @@ newiTempLabel (char *s) { symbol *itmplbl; - /* check if this alredy exists */ + /* check if this already exists */ if (s && (itmplbl = findSym (LabelTab, NULL, s))) return itmplbl; @@ -1038,6 +1042,40 @@ isOclsExpensive (struct memmap *oclass) return IN_FARSPACE (oclass); } +/*-----------------------------------------------------------------*/ +/* isiCodeInFunctionCall - return TRUE if an iCode is between a */ +/* CALL/PCALL and the first IPUSH/SEND associated with the call */ +/*-----------------------------------------------------------------*/ +int +isiCodeInFunctionCall (iCode * ic) +{ + iCode * lic = ic; + + /* Find the next CALL/PCALL */ + while (lic) + { + if (lic->op == CALL || lic->op == PCALL) + break; + lic = lic->next; + } + + if (!lic) + return FALSE; + + /* A function call was found. Scan backwards and see if an */ + /* IPUSH or SEND is encountered */ + while (ic) + { + if (lic != ic && (ic->op == CALL || ic->op == PCALL)) + return FALSE; + if (ic->op == SEND || (ic->op == IPUSH && ic->parmPush)) + return TRUE; + ic = ic->prev; + } + + return FALSE; +} + /*-----------------------------------------------------------------*/ /* operandLitValue - literal value of an operand */ /*-----------------------------------------------------------------*/ @@ -1919,7 +1957,13 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) } } } else { // from a pointer to a pointer - if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) { + if (IS_GENPTR(type) && IS_VOID(type->next)) + { // cast to void* is always allowed + } + else if (IS_GENPTR(optype) && IS_VOID(optype->next)) + { // cast from void* is always allowed + } + else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) { // if not a pointer to a function if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) { if (implicit) { // if not to generic, they have to match @@ -1983,9 +2027,10 @@ geniCodeCast (sym_link * type, operand * op, bool implicit) restype = getSpec (operandType (IC_RESULT (ic))); if (!IS_LITERAL(opetype) && !IS_BIT(opetype)) + { SPEC_SCLS (restype) = SPEC_SCLS (opetype); - SPEC_OCLS (restype) = SPEC_OCLS (opetype); - + SPEC_OCLS (restype) = SPEC_OCLS (opetype); + } ADDTOCHAIN (ic); return IC_RESULT (ic); } @@ -2300,7 +2345,7 @@ geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl) } /*-----------------------------------------------------------------*/ -/* aggrToPtr - changes an aggregate to pointer to an aggregate */ +/* aggrToPtr - changes an "aggregate" to a "pointer to aggregate" */ /*-----------------------------------------------------------------*/ sym_link * aggrToPtr (sym_link * type, bool force) @@ -2409,7 +2454,11 @@ geniCodeArray (operand * left, operand * right, int lvl) !IS_PTR (ltype->next)) ? ltype : ltype->next), 0); - IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next)); + if (!IS_AGGREGATE (ltype->next)) + { + IC_RESULT (ic)->isaddr = 1; + IC_RESULT (ic)->aggr2ptr = 1; + } ADDTOCHAIN (ic); return IC_RESULT (ic); @@ -2429,7 +2478,7 @@ geniCodeStruct (operand * left, operand * right, bool islval) right->operand.symOperand); wassert(IS_SYMOP(right)); - + /* add the offset */ ic = newiCode ('+', left, operandFromLit (element->offset)); @@ -2442,10 +2491,10 @@ geniCodeStruct (operand * left, operand * right, bool islval) SPEC_OCLS (retype) = SPEC_OCLS (etype); SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype); SPEC_CONST (retype) |= SPEC_CONST (etype); - + if (IS_PTR (element->type)) setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE)); - + IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type)); ADDTOCHAIN (ic); @@ -2484,6 +2533,8 @@ geniCodePostInc (operand * op) geniCodeAssign (rOp, rv, 0, 0); size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1); + if (size == 0) + werror(W_SIZEOF_VOID); if (IS_FLOAT (rvtype)) ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0"))); else @@ -2519,8 +2570,9 @@ geniCodePreInc (operand * op, bool lvalue) return op; } - size = (IS_PTR (roptype) ? getSize (roptype->next) : 1); + if (size == 0) + werror(W_SIZEOF_VOID); if (IS_FLOAT (roptype)) ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0"))); else @@ -2567,6 +2619,8 @@ geniCodePostDec (operand * op) geniCodeAssign (rOp, rv, 0, 0); size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1); + if (size == 0) + werror(W_SIZEOF_VOID); if (IS_FLOAT (rvtype)) ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0"))); else @@ -2602,8 +2656,9 @@ geniCodePreDec (operand * op, bool lvalue) return op; } - size = (IS_PTR (roptype) ? getSize (roptype->next) : 1); + if (size == 0) + werror(W_SIZEOF_VOID); if (IS_FLOAT (roptype)) ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0"))); else @@ -3183,12 +3238,12 @@ geniCodeParms (ast * parms, value *argVals, int *stack, /* hack don't like this but too lazy to think of something better */ if (IS_ADDRESS_OF_OP (parms)) - parms->left->lvalue = 1; + parms->left->lvalue = 1; if (IS_CAST_OP (parms) && - IS_PTR (parms->ftype) && - IS_ADDRESS_OF_OP (parms->right)) - parms->right->left->lvalue = 1; + IS_PTR (parms->ftype) && + IS_ADDRESS_OF_OP (parms->right)) + parms->right->left->lvalue = 1; pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE); } @@ -3206,24 +3261,24 @@ geniCodeParms (ast * parms, value *argVals, int *stack, { /* now decide whether to push or assign */ if (!(options.stackAuto || IFFUNC_ISREENT (ftype))) - { + { - /* assign */ - operand *top = operandFromSymbol (argVals->sym); - /* clear useDef and other bitVectors */ - OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL; - geniCodeAssign (top, pval, 1, 0); - } + /* assign */ + operand *top = operandFromSymbol (argVals->sym); + /* clear useDef and other bitVectors */ + OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL; + geniCodeAssign (top, pval, 1, 0); + } else - { - sym_link *p = operandType (pval); - /* push */ - ic = newiCode (IPUSH, pval, NULL); - ic->parmPush = 1; - /* update the stack adjustment */ - *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p); - ADDTOCHAIN (ic); - } + { + sym_link *p = operandType (pval); + /* push */ + ic = newiCode (IPUSH, pval, NULL); + ic->parmPush = 1; + /* update the stack adjustment */ + *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p); + ADDTOCHAIN (ic); + } } argVals=argVals->next; @@ -3464,7 +3519,8 @@ exit: int geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) { - int min = 0, max = 0, t, cnt = 0; + int min, max, cnt = 1; + int i, t; value *vch; iCode *ic; operand *boundary; @@ -3472,6 +3528,10 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) set *labels = NULL; int needRangeCheck = !optimize.noJTabBoundary || tree->values.switchVals.swDefault; + sym_link *cetype = getSpec (operandType (cond)); + int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost; + int sizeofMatchJump, sizeofJumpTable; + int sizeIndex; if (!tree || !caseVals) return 0; @@ -3479,50 +3539,132 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /* the criteria for creating a jump table is */ /* all integer numbers between the maximum & minimum must */ /* be present , the maximum value should not exceed 255 */ - min = max = (int) floatFromVal (vch = caseVals); - SNPRINTF (buffer, sizeof(buffer), - "_case_%d_%d", - tree->values.switchVals.swNum, - min); - addSet (&labels, newiTempLabel (buffer)); - - /* if there is only one case value then no need */ - if (!(vch = vch->next)) - return 0; + /* If not all integer numbers are present the algorithm */ + /* inserts jumps to the default label for the missing numbers */ + /* and decides later whether it is worth it */ + min = (int) floatFromVal (vch = caseVals); - while (vch) + while (vch->next) { - if (((t = (int) floatFromVal (vch)) - max) != 1) - return 0; - SNPRINTF (buffer, sizeof(buffer), - "_case_%d_%d", - tree->values.switchVals.swNum, - t); - addSet (&labels, newiTempLabel (buffer)); - max = t; cnt++; vch = vch->next; } + max = (int) floatFromVal (vch); - /* if the number of case statements <= 2 then */ - /* it is not economical to create the jump table */ - /* since two compares are needed for boundary conditions */ - if ((needRangeCheck && cnt <= 2) || max > (255 / 3)) + /* Exit if the range is too large to handle with a jump table. */ + if (1 + max - min > port->jumptableCost.maxCount) return 0; - if (tree->values.switchVals.swDefault) + switch (getSize (operandType (cond))) { - SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum); + case 1: sizeIndex = 0; break; + case 2: sizeIndex = 1; break; + case 4: sizeIndex = 2; break; + default: return 0; } - else + + /* Compute the size cost of the range check and subtraction. */ + sizeofMinCost = 0; + sizeofZeroMinCost = 0; + sizeofMaxCost = 0; + if (needRangeCheck) { - SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum); + if (!(min==0 && IS_UNSIGNED (cetype))) + sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex]; + if (!IS_UNSIGNED (cetype)) + sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex]; + sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex]; + } + if (min) + sizeofMinCost += port->jumptableCost.sizeofSubtract; + + /* If the size cost of handling a non-zero minimum exceeds the */ + /* cost of extending the range down to zero, then it might be */ + /* better to extend the range to zero. */ + if (min > 0 && (sizeofMinCost-sizeofZeroMinCost) + >= (min * port->jumptableCost.sizeofElement)) + { + /* Only extend the jump table if it would still be manageable. */ + if (1 + max <= port->jumptableCost.maxCount) + { + min = 0; + if (IS_UNSIGNED (cetype)) + sizeofMinCost = 0; + else + sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex]; + } } + /* Compute the total size cost of a jump table. */ + sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement + + port->jumptableCost.sizeofDispatch + + sizeofMinCost + sizeofMaxCost; + + /* Compute the total size cost of a match & jump sequence */ + sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex]; + /* If the size cost of the jump table is uneconomical then exit */ + if (sizeofMatchJump < sizeofJumpTable) + return 0; + + /* The jump table is preferable. */ + + /* First, a label for the default or missing cases. */ + if (tree->values.switchVals.swDefault) + { + SNPRINTF (buffer, sizeof(buffer), + "_default_%d", + tree->values.switchVals.swNum); + } + else + { + SNPRINTF (buffer, sizeof(buffer), + "_swBrk_%d", + tree->values.switchVals.swNum); + } falseLabel = newiTempLabel (buffer); - /* so we can create a jumptable */ + /* Build the list of labels for the jump table. */ + vch = caseVals; + t = (int) floatFromVal (vch); + for (i=min; i<=max; i++) + { + if (vch && t==i) + { + /* Explicit case: make a new label for it. */ + SNPRINTF (buffer, sizeof(buffer), + "_case_%d_%d", + tree->values.switchVals.swNum, + i); + addSet (&labels, newiTempLabel (buffer)); + vch = vch->next; + if (vch) + t = (int) floatFromVal (vch); + } + else + { + /* Implicit case: use the default label. */ + addSet (&labels, falseLabel); + } + } + + /* If cond is volatile, it might change after the boundary */ + /* conditions are tested to an out of bounds value, causing */ + /* a jump to a location outside of the jump table. To avoid */ + /* this possibility, use a non-volatile copy of it instead. */ + if (IS_OP_VOLATILE (cond)) + { + operand * newcond; + iCode * ic; + + newcond = newiTempOperand (operandType (cond), TRUE); + newcond->isvolatile = 0; + ic = newiCode ('=', NULL, cond); + IC_RESULT (ic) = newcond; + ADDTOCHAIN (ic); + cond = newcond; + } + /* first we rule out the boundary conditions */ /* if only optimization says so */ if (needRangeCheck) @@ -3676,11 +3818,23 @@ geniCodeCritical (ast *tree, int lvl) { iCode *ic; operand *op = NULL; + sym_link *type; + + if (!options.stackAuto) + { + type = newLink(SPECIFIER); + SPEC_VOLATILE(type) = 1; + SPEC_NOUN(type) = V_BIT; + SPEC_SCLS(type) = S_BIT; + SPEC_BLEN(type) = 1; + SPEC_BSTR(type) = 0; + op = newiTempOperand(type, 1); + } /* If op is NULL, the original interrupt state will saved on */ /* the stack. Otherwise, it will be saved in op. */ - /* Generate a save of the current interrupt state & disabled */ + /* Generate a save of the current interrupt state & disable */ ic = newiCode (CRITICAL, NULL, NULL); IC_RESULT (ic) = op; ADDTOCHAIN (ic);