From d65f0b910fb11f23dfff2724e666b7e742af007e Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Sat, 10 Apr 2004 22:07:02 +0000 Subject: [PATCH] * 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 git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3283 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 7 +++ src/SDCCicode.c | 88 ++++++++++++++++++++++++--- support/regression/tests/bug-905492.c | 32 ++++++++++ 3 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 support/regression/tests/bug-905492.c diff --git a/ChangeLog b/ChangeLog index affaa1c0..d5edd6b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-04-11 Bernhard Held + + * 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 * src/SDCCast.c (addCast): don't cast float to char diff --git a/src/SDCCicode.c b/src/SDCCicode.c index aec706a1..ae54a48a 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -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 index 00000000..90b01310 --- /dev/null +++ b/support/regression/tests/bug-905492.c @@ -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 + +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); +} -- 2.47.2