* src/SDCCicode.c (geniCodeLogic): made it static,
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 10 Apr 2004 22:07:02 +0000 (22:07 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 10 Apr 2004 22:07:02 +0000 (22:07 +0000)
(geniCodeLogicAndOr): added in order to fix bug #905492,
(ast2iCode): fixed bug #905492
* support/regression/tests/bug-905492.c: added

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3283 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/SDCCicode.c
support/regression/tests/bug-905492.c [new file with mode: 0644]

index affaa1c07aa211a32dbfd9ed5ae09e9fd9770a0e..d5edd6b699391f339115e7aea22ecae74975e628 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-04-11 Bernhard Held <bernhard AT bernhardheld.de>
+
+       * src/SDCCicode.c (geniCodeLogic): made it static,
+       (geniCodeLogicAndOr): added in order to fix bug #905492,
+       (ast2iCode): fixed bug #905492
+       * support/regression/tests/bug-905492.c: added
+        
 2004-03-29 Bernhard Held <bernhard AT bernhardheld.de>
 
        * src/SDCCast.c (addCast): don't cast float to char
index aec706a18c4a049623e80b54676c2d3f5cbb4d91..ae54a48a2afbcdf0dd811513de1fd0c231f349ff 100644 (file)
@@ -2819,7 +2819,7 @@ geniCodeRightShift (operand * left, operand * right)
 /*-----------------------------------------------------------------*/
 /* geniCodeLogic- logic code                                       */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeLogic (operand * left, operand * right, int op)
 {
   iCode *ic;
@@ -2891,12 +2891,77 @@ geniCodeLogic (operand * left, operand * right, int op)
       op != NE_OP &&
       op != AND_OP &&
       op != OR_OP)
-    ic->supportRtn = 1;
+   ic->supportRtn = 1;
 
   ADDTOCHAIN (ic);
   return IC_RESULT (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeLogicAndOr - && || operations                           */
+/*-----------------------------------------------------------------*/
+static operand *
+geniCodeLogicAndOr (ast *tree, int lvl)
+{
+  iCode *ic;
+  symbol *falseLabel = newiTempLabel (NULL);
+  symbol *trueLabel  = newiTempLabel (NULL);
+  symbol *exitLabel  = newiTempLabel (NULL);
+  operand *op, *result, *condition;
+
+  /* AND_OP and OR_OP are no longer generated because of bug-905492.
+     They can be reenabled by executing the following block. If you find
+     a decent optimization you could start right here:
+  */
+#if 0
+  if (0)
+    {
+       operand *leftOp, *rightOp;
+
+       leftOp  = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
+       rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
+
+       return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+    }
+#endif
+
+  /* generate two IFX for the '&&' or '||' op */
+
+  /* evaluate left operand */
+  condition = ast2iCode (tree->left, lvl + 1);
+  op = geniCodeRValue (condition, FALSE);
+
+  /* test left operand */
+  if (tree->opval.op == AND_OP)
+    ic = newiCodeCondition (op, NULL, falseLabel);
+  else /* OR_OP */
+    ic = newiCodeCondition (op, trueLabel, NULL);
+  ADDTOCHAIN (ic);
+  
+  /* evaluate right operand */
+  condition = ast2iCode (tree->right, lvl + 1);
+  op = geniCodeRValue (condition, FALSE);
+  
+  /* test right operand */
+  ic = newiCodeCondition (op, trueLabel, NULL);
+  ADDTOCHAIN (ic);
+  
+  /* store 0 or 1 in result */
+  result = newiTempOperand (newCharLink(), 1);
+  
+  geniCodeLabel (falseLabel);
+  geniCodeAssign (result, operandFromLit (0), 0);
+  /* generate an unconditional goto */
+  geniCodeGoto (exitLabel);
+
+  geniCodeLabel (trueLabel);
+  geniCodeAssign (result, operandFromLit (1), 0);
+
+  geniCodeLabel (exitLabel);
+
+  return result;
+}
+
 /*-----------------------------------------------------------------*/
 /* geniCodeUnary - for a a generic unary operation                 */
 /*-----------------------------------------------------------------*/
@@ -3729,6 +3794,8 @@ ast2iCode (ast * tree,int lvl)
       tree->opval.op != '?' &&
       tree->opval.op != CALL &&
       tree->opval.op != IFX &&
+      tree->opval.op != AND_OP &&
+      tree->opval.op != OR_OP &&
       tree->opval.op != LABEL &&
       tree->opval.op != GOTO &&
       tree->opval.op != SWITCH &&
@@ -3907,28 +3974,29 @@ ast2iCode (ast * tree,int lvl)
        setOperandType (op, UCHARTYPE);
        return op;
       }
+    case AND_OP:
+    case OR_OP:
+      return geniCodeLogicAndOr (tree, lvl);
     case '>':
     case '<':
     case LE_OP:
     case GE_OP:
     case EQ_OP:
     case NE_OP:
-    case AND_OP:
-    case OR_OP:
       /* different compilers (even different gccs) evaluate
-        the two calls in a different order. to get the same
-        result on all machines we've to specify a clear sequence.
+         the two calls in a different order. to get the same
+         result on all machines we've to specify a clear sequence.
       return geniCodeLogic (geniCodeRValue (left, FALSE),
                             geniCodeRValue (right, FALSE),
                             tree->opval.op);
       */
       {
-       operand *leftOp, *rightOp;
+        operand *leftOp, *rightOp;
 
-       rightOp = geniCodeRValue (right, FALSE);
-       leftOp  = geniCodeRValue (left , FALSE);
+        leftOp  = geniCodeRValue (left , FALSE);
+        rightOp = geniCodeRValue (right, FALSE);
 
-       return geniCodeLogic (leftOp, rightOp, tree->opval.op);
+        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
       }
     case '?':
       return geniCodeConditional (tree,lvl);
diff --git a/support/regression/tests/bug-905492.c b/support/regression/tests/bug-905492.c
new file mode 100644 (file)
index 0000000..90b0131
--- /dev/null
@@ -0,0 +1,32 @@
+/* bug-905492.c
+
+   the standard guarantees left-to-right evaluation,
+   if the first operand is unequal 0 (resp. 0), the second isn't evaluated.
+*/
+
+#include <testfwk.h>
+
+char a;
+
+char
+inc_a(char c)
+{
+  a += 1;
+  return c;
+}
+
+void
+testLeftRightAndOr(void)
+{
+  volatile char c;
+
+  a = 0; c = inc_a(0) || inc_a(0); ASSERT(a == 2);
+  a = 0; c = inc_a(0) || inc_a(1); ASSERT(a == 2);
+  a = 0; c = inc_a(1) || inc_a(0); ASSERT(a == 1);
+  a = 0; c = inc_a(1) || inc_a(1); ASSERT(a == 1);
+
+  a = 0; c = inc_a(0) && inc_a(0); ASSERT(a == 1);
+  a = 0; c = inc_a(0) && inc_a(1); ASSERT(a == 1);
+  a = 0; c = inc_a(1) && inc_a(0); ASSERT(a == 2);
+  a = 0; c = inc_a(1) && inc_a(1); ASSERT(a == 2);
+}