* src/SDCCicode.c (geniCodeAddressOf): fixed part of bug #840381
[fw/sdcc] / src / SDCCicode.c
index 381e43fa46688418d6f0acea0ae8dc4db3cf94eb..2672a1ab6812af6dad99c95312aeaadb6c4652d5 100644 (file)
@@ -69,6 +69,8 @@ PRINTFUNC (picJumpTable);
 PRINTFUNC (picInline);
 PRINTFUNC (picReceive);
 PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
 
 iCodeTable codeTable[] =
 {
@@ -115,7 +117,9 @@ iCodeTable codeTable[] =
   {RECEIVE, "recv", picReceive, NULL},
   {SEND, "send", picGenericOne, NULL},
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
-  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+  {CRITICAL, "critical_start", picCritical, NULL},
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL}
 };
 
 /*-----------------------------------------------------------------*/
@@ -473,6 +477,28 @@ PRINTFUNC (picDummyRead)
   fprintf (of, "\n");
 }
 
+PRINTFUNC (picCritical)
+{
+  fprintf (of, "\t");
+  if (IC_RESULT (ic))
+    printOperand (IC_RESULT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, " = %s ", s);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picEndCritical)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s = ", s);
+  if (IC_RIGHT (ic))
+    printOperand (IC_RIGHT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, "\n");
+}
+
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
@@ -995,6 +1021,21 @@ isOperandOnStack (operand * op)
   return FALSE;
 }
 
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output     */
+/*                   storage class are expensive                   */
+/*-----------------------------------------------------------------*/
+bool 
+isOclsExpensive (struct memmap *oclass)
+{
+  if (port->oclsExpense)
+    return port->oclsExpense (oclass) > 0;
+
+  /* In the absence of port specific guidance, assume only */
+  /* farspace is expensive. */
+  return IN_FARSPACE (oclass);
+}
+
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
@@ -1094,8 +1135,7 @@ operandOperation (operand * left, operand * right,
                               (TYPE_UWORD) operandLitValue (right);
 
              retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
-             if (!options.lessPedantic &&
-                 ul != (TYPE_UWORD) ul)
+             if (ul != (TYPE_UWORD) ul)
                werror (W_INT_OVL);
            }
          else /* signed int */
@@ -1105,8 +1145,7 @@ operandOperation (operand * left, operand * right,
                             (TYPE_WORD) operandLitValue (right);
 
              retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
-             if (!options.lessPedantic &&
-                 l != (TYPE_WORD) l)
+             if (l != (TYPE_WORD) l)
                werror (W_INT_OVL);
            }
        }
@@ -1455,6 +1494,7 @@ operandFromSymbol (symbol * sym)
      register equivalent for a local symbol */
   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+      !TARGET_IS_HC08 &&
       (!(options.model == MODEL_FLAT24)) ) &&
       options.stackAuto == 0)
     ok = 0;
@@ -1734,7 +1774,7 @@ geniCodeRValue (operand * op, bool force)
   /* if this is not a temp symbol then */
   if (!IS_ITEMP (op) &&
       !force &&
-      !IN_FARSPACE (SPEC_OCLS (etype)))
+      !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
     {
       op = operandFromOperand (op);
       op->isaddr = 0;
@@ -1743,7 +1783,7 @@ geniCodeRValue (operand * op, bool force)
 
   if (IS_SPEC (type) &&
       IS_TRUE_SYMOP (op) &&
-      (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+      (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
       (options.model == MODEL_FLAT24) ))
     {
       op = operandFromOperand (op);
@@ -2068,7 +2108,7 @@ subtractExit:
   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
     return result;
   }
-
+  
   // should we really do this? is this ANSI?
   return geniCodeDivision (result,
                           operandFromLit (getSize (ltype->next)));
@@ -2228,13 +2268,14 @@ geniCodeArray (operand * left, operand * right,int lvl)
 {
   iCode *ic;
   sym_link *ltype = operandType (left);
-
+  
   if (IS_PTR (ltype))
     {
       if (IS_PTR (ltype->next) && left->isaddr)
        {
          left = geniCodeRValue (left, FALSE);
        }
+      
       return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
     }
 
@@ -2260,6 +2301,7 @@ geniCodeArray (operand * left, operand * right,int lvl)
 
   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
   ADDTOCHAIN (ic);
+
   return IC_RESULT (ic);
 }
 
@@ -2350,7 +2392,7 @@ geniCodePostInc (operand * op)
 /* geniCodePreInc - generate code for preIncrement                 */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodePreInc (operand * op)
+geniCodePreInc (operand * op, bool lvalue)
 {
   iCode *ic;
   sym_link *optype = operandType (op);
@@ -2376,8 +2418,11 @@ geniCodePreInc (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0);
+  if (lvalue || IS_TRUE_SYMOP (op))
+    return op;
+  else
+    return result;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2430,7 +2475,7 @@ geniCodePostDec (operand * op)
 /* geniCodePreDec - generate code for pre  decrement               */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodePreDec (operand * op)
+geniCodePreDec (operand * op, bool lvalue)
 {
   iCode *ic;
   sym_link *optype = operandType (op);
@@ -2456,8 +2501,11 @@ geniCodePreDec (operand * op)
   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
   ADDTOCHAIN (ic);
 
-
-  return geniCodeAssign (op, result, 0);
+  (void) geniCodeAssign (op, result, 0);
+  if (lvalue || IS_TRUE_SYMOP (op))
+    return op;
+  else
+    return result;
 }
 
 
@@ -2491,6 +2539,13 @@ geniCodeAddressOf (operand * op)
   sym_link *optype = operandType (op);
   sym_link *opetype = getSpec (optype);
 
+  if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
+    {
+      op = operandFromOperand (op);
+      op->isaddr = 0;
+      return op;
+    }
+  
   /* lvalue check already done in decorateType */
   /* this must be a lvalue */
 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
@@ -2830,11 +2885,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   else if (compareType (ltype, rtype) < 0)
     right = geniCodeCast (ltype, right, TRUE);
 
-  /* if left is a true symbol & ! volatile
+  /* If left is a true symbol & ! volatile
      create an assignment to temporary for
      the right & then assign this temporary
-     to the symbol this is SSA . isn't it simple
-     and folks have published mountains of paper on it */
+     to the symbol. This is SSA (static single
+     assignment). Isn't it simple and folks have
+     published mountains of paper on it */
   if (IS_TRUE_SYMOP (left) &&
       !isOperandVolatile (left, FALSE) &&
       isOperandGlobal (left))
@@ -2862,6 +2918,24 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   return left;
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeDummyRead - generate code for dummy read                */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeDummyRead (operand * op)
+{
+  iCode *ic;
+  sym_link *type = operandType (op);
+
+  if (!IS_VOLATILE(type))
+    return;
+    
+  ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
+  ADDTOCHAIN (ic);
+
+  ic->nosupdate = 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
@@ -3045,7 +3119,7 @@ geniCodeReceive (value * args)
          if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
            {
 
-             if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+             if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
                  options.stackAuto == 0 &&
                  (!(options.model == MODEL_FLAT24)) )
                {
@@ -3211,6 +3285,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   operand *boundary;
   symbol *falseLabel;
   set *labels = NULL;
+  int needRangeCheck = !optimize.noJTabBoundary
+                       || tree->values.switchVals.swDefault;
 
   if (!tree || !caseVals)
     return 0;
@@ -3246,7 +3322,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* 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 ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
+  if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
     return 0;
 
   if (tree->values.switchVals.swDefault)
@@ -3264,7 +3340,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* so we can create a jumptable */
   /* first we rule out the boundary conditions */
   /* if only optimization says so */
-  if (!optimize.noJTabBoundary)
+  if (needRangeCheck)
     {
       sym_link *cetype = getSpec (operandType (cond));
       /* no need to check the lower bound if
@@ -3286,7 +3362,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   if (min)
     {
       cond = geniCodeSubtract (cond, operandFromLit (min));
-      setOperandType (cond, UCHARTYPE);
+      if (!IS_LITERAL(getSpec(operandType(cond))))
+        setOperandType (cond, UCHARTYPE);
     }
 
   /* now create the jumptable */
@@ -3307,6 +3384,29 @@ geniCodeSwitch (ast * tree,int lvl)
   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
   value *caseVals = tree->values.switchVals.swVals;
   symbol *trueLabel, *falseLabel;
+      
+  /* If the condition is a literal, then just jump to the */
+  /* appropriate case label. */
+  if (IS_LITERAL(getSpec(operandType(cond))))
+    {
+      int switchVal, caseVal;
+      
+      switchVal = (int) floatFromVal (cond->operand.valOperand);
+      while (caseVals)
+        {
+          caseVal = (int) floatFromVal (caseVals);
+          if (caseVal == switchVal)
+            {
+              SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
+                       tree->values.switchVals.swNum, caseVal);
+              trueLabel = newiTempLabel (buffer);
+              geniCodeGoto (trueLabel);
+              goto jumpTable;
+            }
+          caseVals = caseVals->next;
+        }
+      goto defaultOrBreak;
+    }
 
   /* if we can make this a jump table */
   if (geniCodeJumpTable (cond, caseVals, tree))
@@ -3331,7 +3431,7 @@ geniCodeSwitch (ast * tree,int lvl)
     }
 
 
-
+defaultOrBreak:
   /* if default is present then goto break else break */
   if (tree->values.switchVals.swDefault)
     {
@@ -3382,6 +3482,34 @@ geniCodeArrayInit (ast * tree, operand *array)
   }
   ADDTOCHAIN (ic);
 }
+       
+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement   */
+/*-----------------------------------------------------------------*/
+static void 
+geniCodeCritical (ast *tree, int lvl)
+{
+  iCode *ic;
+  operand *op = NULL;
+
+  /* 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 */
+  ic = newiCode (CRITICAL, NULL, NULL);
+  IC_RESULT (ic) = op;
+  ADDTOCHAIN (ic);
+  
+  /* Generate the critical code sequence */
+  if (tree->left && tree->left->type == EX_VALUE)
+    geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+  else
+    ast2iCode (tree->left,lvl+1);
+  
+  /* Generate a restore of the original interrupt state */
+  ic = newiCode (ENDCRITICAL, NULL, op);
+  ADDTOCHAIN (ic);
+}
 
 /*-----------------------------------------------------------------*/
 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
@@ -3477,8 +3605,14 @@ ast2iCode (ast * tree,int lvl)
      (tree->opval.op == NULLOP ||
      tree->opval.op == BLOCK))
     {
-      ast2iCode (tree->left,lvl+1);
-      ast2iCode (tree->right,lvl+1);
+      if (tree->left && tree->left->type == EX_VALUE)
+        geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+      else
+        ast2iCode (tree->left,lvl+1);
+      if (tree->right && tree->right->type == EX_VALUE)
+        geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
+      else
+        ast2iCode (tree->right,lvl+1);
       return NULL;
     }
 
@@ -3491,7 +3625,8 @@ ast2iCode (ast * tree,int lvl)
       tree->opval.op != GOTO &&
       tree->opval.op != SWITCH &&
       tree->opval.op != FUNCTION &&
-      tree->opval.op != INLINEASM)
+      tree->opval.op != INLINEASM &&
+      tree->opval.op != CRITICAL)
     {
 
         if (IS_ASSIGN_OP (tree->opval.op) ||
@@ -3564,13 +3699,13 @@ ast2iCode (ast * tree,int lvl)
       if (left)
        return geniCodePostInc (left);
       else
-       return geniCodePreInc (right);
+       return geniCodePreInc (right, tree->lvalue);
 
     case DEC_OP:               /* decrement operator */
       if (left)
        return geniCodePostDec (left);
       else
-       return geniCodePreDec (right);
+       return geniCodePreDec (right, tree->lvalue);
 
     case '&':                  /* bitwise and or address of operator */
       if (right)
@@ -3604,7 +3739,7 @@ ast2iCode (ast * tree,int lvl)
        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
-      if (right)
+      if (right) 
        return geniCodeSubtract (geniCodeRValue (left, FALSE),
                                 geniCodeRValue (right, FALSE));
       else
@@ -3647,6 +3782,7 @@ ast2iCode (ast * tree,int lvl)
     case '~':
     case RRC:
     case RLC:
+    case SWAP:
       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
 
     case '!':
@@ -3825,6 +3961,9 @@ ast2iCode (ast * tree,int lvl)
     case ARRAYINIT:
        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
        return NULL;
+    
+    case CRITICAL:
+       geniCodeCritical (tree, lvl);    
     }
 
   return NULL;