* Added support for doing shifts by helper functions
[fw/sdcc] / src / SDCCicode.c
index 1ab038c57aa3aa5a39f796cc727dd243caeaf2da..4e93c888ce17805e5b38e4ade37243139f6c8165 100644 (file)
@@ -37,7 +37,6 @@ char *filename;
 int lineno;
 int block;
 int scopeLevel;
-int lvaluereq;
 
 symbol *returnLabel;           /* function return label */
 symbol *entryLabel;            /* function entry  label */
@@ -45,10 +44,11 @@ symbol *entryLabel;         /* function entry  label */
 /* forward definition of some functions */
 operand *geniCodeDivision (operand *, operand *);
 operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *);
+operand *geniCodeArray (operand *, operand *,int);
 operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
-operand *geniCodeDerefPtr (operand *);
+operand *geniCodeDerefPtr (operand *,int);
+int isLvaluereq(int lvl);
 
 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
 /* forward definition of ic print functions */
@@ -539,7 +539,7 @@ newiTempLabel (char *s)
   itmplbl->isitmp = 1;
   itmplbl->islbl = 1;
   itmplbl->key = labelKey++;
-  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
   return itmplbl;
 }
 
@@ -557,7 +557,7 @@ newiTempPreheaderLabel ()
   itmplbl->isitmp = 1;
   itmplbl->islbl = 1;
   itmplbl->key = labelKey++;
-  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
+  addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
   return itmplbl;
 }
 
@@ -839,11 +839,15 @@ operand *
 operandOperation (operand * left, operand * right,
                  int op, sym_link * type)
 {
+  sym_link *let , *ret=NULL;
   operand *retval = (operand *) 0;
-
+  
   assert (isOperandLiteral (left));
-  if (right)
+  let = getSpec(operandType(left));
+  if (right) {
     assert (isOperandLiteral (right));
+    ret = getSpec(operandType(left));
+  }
 
   switch (op)
     {
@@ -875,22 +879,34 @@ operandOperation (operand * left, operand * right,
                                                   operandLitValue (right)));
       break;
     case '%':
-      if ((unsigned long) operandLitValue (right) == 0)
-       {
+      if ((unsigned long) operandLitValue (right) == 0) {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
-       }
-      else
-       retval = operandFromLit ((unsigned long) operandLitValue (left) %
-                                (unsigned long) operandLitValue (right));
+      }
+      else 
+       retval = operandFromLit ((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) %
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right)));
+
       break;
     case LEFT_OP:
-      retval = operandFromLit ((unsigned long) operandLitValue (left) <<
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit (((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) <<
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right))));
       break;
     case RIGHT_OP:
-      retval = operandFromLit ((unsigned long) operandLitValue (left) >>
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit (((SPEC_USIGN(let) ? 
+                                 (unsigned long) operandLitValue (left) :
+                                 (long) operandLitValue (left)) >>
+                                (SPEC_USIGN(ret) ? 
+                                 (unsigned long) operandLitValue (right) :
+                                 (long) operandLitValue (right))));
       break;
     case EQ_OP:
       retval = operandFromLit (operandLitValue (left) ==
@@ -938,7 +954,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RRC:
       {
-       long i = operandLitValue (left);
+       long i = (long) operandLitValue (left);
 
        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
                                 (i << 1));
@@ -946,7 +962,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RLC:
       {
-       long i = operandLitValue (left);
+       long i = (long) operandLitValue (left);
 
        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
                                 (i >> 1));
@@ -1005,7 +1021,7 @@ isOperandEqual (operand * left, operand * right)
       return (floatFromVal (left->operand.valOperand) ==
              floatFromVal (right->operand.valOperand));
     case TYPE:
-      if (checkType (left->operand.typeOperand,
+      if (compareType (left->operand.typeOperand,
                     right->operand.typeOperand) == 1)
        return 1;
     }
@@ -1278,7 +1294,7 @@ operandFromLink (sym_link * type)
 /* operandFromLit - makes an operand from a literal value          */
 /*-----------------------------------------------------------------*/
 operand *
-operandFromLit (float i)
+operandFromLit (double i)
 {
   return operandFromValue (valueFromLit (i));
 }
@@ -1287,7 +1303,7 @@ operandFromLit (float i)
 /* operandFromAst - creates an operand from an ast                 */
 /*-----------------------------------------------------------------*/
 operand *
-operandFromAst (ast * tree)
+operandFromAst (ast * tree,int lvl)
 {
 
   if (!tree)
@@ -1297,7 +1313,7 @@ operandFromAst (ast * tree)
   switch (tree->type)
     {
     case EX_OP:
-      return ast2iCode (tree);
+      return ast2iCode (tree,lvl+1);
       break;
 
     case EX_VALUE:
@@ -1391,7 +1407,7 @@ usualUnaryConversions (operand * op)
 {
   if (IS_INTEGRAL (operandType (op)))
     {
-      if (getSize (operandType (op)) < INTSIZE)
+      if (getSize (operandType (op)) < (unsigned int) INTSIZE)
        {
          /* Widen to int. */
          return geniCodeCast (INTTYPE, op, TRUE);
@@ -1497,7 +1513,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
     }
 
   /* if the operand is already the desired type then do nothing */
-  if (checkType (type, optype) == 1)
+  if (compareType (type, optype) == 1)
     return op;
 
   /* if this is a literal then just change the type & return */
@@ -1513,7 +1529,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       !IS_GENPTR (type))
     {
       werror (E_INCOMPAT_CAST);
-      werror (E_CONTINUE, "from type '");
+      fprintf (stderr, "from type '");
       printTypeChain (optype, stderr);
       fprintf (stderr, "' to type '");
       printTypeChain (type, stderr);
@@ -1607,7 +1623,6 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
   if (resultIsInt)
     {
       SPEC_NOUN(getSpec(resType))=V_INT;
-      SPEC_SHORT(getSpec(resType))=0;
     }
 
   /* if the right is a literal & power of 2 */
@@ -1617,7 +1632,7 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
      if port has 1 byte muldiv */
   if (p2 && !IS_FLOAT (letype) &&
       !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
-       (port->muldiv.native_below == 1)))
+       (port->support.muldiv == 1)))
     {
       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
        {
@@ -1662,8 +1677,9 @@ geniCodeDivision (operand * left, operand * right)
   if (IS_LITERAL (retype) &&
       !IS_FLOAT (letype) &&
       (p2 = powof2 ((unsigned long)
-                   floatFromVal (right->operand.valOperand))))
-    ic = newiCode (RIGHT_OP, left, operandFromLit (p2));       /* right shift */
+                   floatFromVal (right->operand.valOperand)))) {
+    ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+  }
   else
     {
       ic = newiCode ('/', left, right);                /* normal division */
@@ -1785,7 +1801,7 @@ geniCodeSubtract (operand * left, operand * right)
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeAdd (operand * left, operand * right)
+geniCodeAdd (operand * left, operand * right,int lvl)
 {
   iCode *ic;
   sym_link *resType;
@@ -1795,7 +1811,7 @@ geniCodeAdd (operand * left, operand * right)
 
   /* if left is an array then array access */
   if (IS_ARRAY (ltype))
-    return geniCodeArray (left, right);
+    return geniCodeArray (left, right,lvl);
 
   /* if the right side is LITERAL zero */
   /* return the left side              */
@@ -1907,7 +1923,7 @@ geniCodeArray2Ptr (operand * op)
 /* geniCodeArray - array access                                    */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeArray (operand * left, operand * right)
+geniCodeArray (operand * left, operand * right,int lvl)
 {
   iCode *ic;
   sym_link *ltype = operandType (left);
@@ -1918,7 +1934,7 @@ geniCodeArray (operand * left, operand * right)
        {
          left = geniCodeRValue (left, FALSE);
        }
-      return geniCodeDerefPtr (geniCodeAdd (left, right));
+      return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
     }
 
   right = geniCodeMultiply (right,
@@ -2256,7 +2272,7 @@ setOClass (sym_link * ptr, sym_link * spec)
 /* geniCodeDerefPtr - dereference pointer with '*'                 */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeDerefPtr (operand * op)
+geniCodeDerefPtr (operand * op,int lvl)
 {
   sym_link *rtype, *retype;
   sym_link *optype = operandType (op);
@@ -2274,7 +2290,7 @@ geniCodeDerefPtr (operand * op)
     }
 
   /* now get rid of the pointer part */
-  if (lvaluereq && IS_ITEMP (op))
+  if (isLvaluereq(lvl) && IS_ITEMP (op))
     {
       retype = getSpec (rtype = copyLinkChain (optype));
     }
@@ -2300,7 +2316,7 @@ geniCodeDerefPtr (operand * op)
                IS_CHAR (rtype) ||
                IS_FLOAT (rtype));
 
-  if (!lvaluereq)
+  if (!isLvaluereq(lvl))
     op = geniCodeRValue (op, TRUE);
 
   setOperandType (op, rtype);
@@ -2376,9 +2392,9 @@ geniCodeLogic (operand * left, operand * right, int op)
   if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
     {
       int nbits = bitsForType (ltype);
-      long v = operandLitValue (right);
+      long v = (long) operandLitValue (right);
 
-      if (v > ((LONG_LONG) 1 << nbits) && v > 0)
+      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
        werror (W_CONST_RANGE, " compare operation ");
     }
 
@@ -2418,19 +2434,19 @@ geniCodeUnary (operand * op, int oper)
 /* geniCodeConditional - geniCode for '?' ':' operation            */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeConditional (ast * tree)
+geniCodeConditional (ast * tree,int lvl)
 {
   iCode *ic;
   symbol *falseLabel = newiTempLabel (NULL);
   symbol *exitLabel = newiTempLabel (NULL);
-  operand *cond = ast2iCode (tree->left);
+  operand *cond = ast2iCode (tree->left,lvl+1);
   operand *true, *false, *result;
 
   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
                          NULL, falseLabel);
   ADDTOCHAIN (ic);
 
-  true = ast2iCode (tree->right->left);
+  true = ast2iCode (tree->right->left,lvl+1);
 
   /* move the value to a new Operand */
   result = newiTempOperand (operandType (true), 0);
@@ -2442,7 +2458,7 @@ geniCodeConditional (ast * tree)
   /* now for the right side */
   geniCodeLabel (falseLabel);
 
-  false = ast2iCode (tree->right->right);
+  false = ast2iCode (tree->right->right,lvl+1);
   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
 
   /* create the exit label */
@@ -2472,9 +2488,9 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
     {
       int nbits = bitsForType (ltype);
-      long v = operandLitValue (right);
+      long v = (long) operandLitValue (right);
 
-      if (v > ((LONG_LONG) 1 << nbits) && v > 0)
+      if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
        werror (W_CONST_RANGE, " = operation");
     }
 
@@ -2485,12 +2501,12 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 
   /* first check the type for pointer assignement */
   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
-      checkType (ltype, rtype) < 0)
+      compareType (ltype, rtype) < 0)
     {
-      if (checkType (ltype->next, rtype) < 0)
+      if (compareType (ltype->next, rtype) < 0)
        right = geniCodeCast (ltype->next, right, TRUE);
     }
-  else if (checkType (ltype, rtype) < 0)
+  else if (compareType (ltype, rtype) < 0)
     right = geniCodeCast (ltype, right, TRUE);
 
   /* if left is a true symbol & ! volatile
@@ -2529,15 +2545,15 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 /* geniCodeSEParms - generate code for side effecting fcalls       */
 /*-----------------------------------------------------------------*/
 static void 
-geniCodeSEParms (ast * parms)
+geniCodeSEParms (ast * parms,int lvl)
 {
   if (!parms)
     return;
 
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      geniCodeSEParms (parms->left);
-      geniCodeSEParms (parms->right);
+      geniCodeSEParms (parms->left,lvl);
+      geniCodeSEParms (parms->right,lvl);
       return;
     }
 
@@ -2552,7 +2568,7 @@ geniCodeSEParms (ast * parms)
     parms->right->left->lvalue = 1;
 
   parms->opval.oprnd =
-    geniCodeRValue (ast2iCode (parms), FALSE);
+    geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
 
   parms->type = EX_OPERAND;
 }
@@ -2561,7 +2577,7 @@ geniCodeSEParms (ast * parms)
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
 static void 
-geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
+geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -2572,8 +2588,8 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
   /* if this is a param node then do the left & right */
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      geniCodeParms (parms->left, stack, fetype, func);
-      geniCodeParms (parms->right, stack, fetype, func);
+      geniCodeParms (parms->left, stack, fetype, func,lvl);
+      geniCodeParms (parms->right, stack, fetype, func,lvl);
       return;
     }
 
@@ -2593,7 +2609,7 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
          IS_ADDRESS_OF_OP (parms->right))
        parms->right->left->lvalue = 1;
 
-      pval = geniCodeRValue (ast2iCode (parms), FALSE);
+      pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
     }
 
   /* if register parm then make it a send */
@@ -2631,7 +2647,7 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
 /* geniCodeCall - generates temp code for calling                  */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeCall (operand * left, ast * parms)
+geniCodeCall (operand * left, ast * parms,int lvl)
 {
   iCode *ic;
   operand *result;
@@ -2641,10 +2657,10 @@ geniCodeCall (operand * left, ast * parms)
   /* take care of parameters with side-effecting
      function calls in them, this is required to take care
      of overlaying function parameters */
-  geniCodeSEParms (parms);
+  geniCodeSEParms (parms,lvl);
 
   /* first the parameters */
-  geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left));
+  geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
 
   /* now call : if symbol then pcall */
   if (IS_OP_POINTER (left) || IS_ITEMP(left))
@@ -2719,7 +2735,7 @@ geniCodeReceive (value * args)
 /* geniCodeFunctionBody - create the function body                 */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeFunctionBody (ast * tree)
+geniCodeFunctionBody (ast * tree,int lvl)
 {
   iCode *ic;
   operand *func;
@@ -2732,7 +2748,7 @@ geniCodeFunctionBody (ast * tree)
   iTempLblNum = 0;
   operandKey = 0;
   iCodeKey = 0;
-  func = ast2iCode (tree->left);
+  func = ast2iCode (tree->left,lvl+1);
   fetype = getSpec (operandType (func));
 
   savelineno = lineno;
@@ -2755,7 +2771,7 @@ geniCodeFunctionBody (ast * tree)
   geniCodeReceive (tree->values.args);
 
   /* generate code for the body */
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 
   /* create a label for return */
   geniCodeLabel (returnLabel);
@@ -2786,10 +2802,10 @@ geniCodeReturn (operand * op)
 /* geniCodeIfx - generates code for extended if statement          */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeIfx (ast * tree)
+geniCodeIfx (ast * tree,int lvl)
 {
   iCode *ic;
-  operand *condition = ast2iCode (tree->left);
+  operand *condition = ast2iCode (tree->left,lvl+1);
   sym_link *cetype;
 
   /* if condition is null then exit */
@@ -2838,7 +2854,7 @@ geniCodeIfx (ast * tree)
     }
 
 exit:
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2936,10 +2952,10 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
 void 
-geniCodeSwitch (ast * tree)
+geniCodeSwitch (ast * tree,int lvl)
 {
   iCode *ic;
-  operand *cond = geniCodeRValue (ast2iCode (tree->left), FALSE);
+  operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
   value *caseVals = tree->values.switchVals.swVals;
   symbol *trueLabel, *falseLabel;
 
@@ -2977,7 +2993,7 @@ geniCodeSwitch (ast * tree)
   geniCodeGoto (falseLabel);
 
 jumpTable:
-  ast2iCode (tree->right);
+  ast2iCode (tree->right,lvl+1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2993,18 +3009,78 @@ geniCodeInline (ast * tree)
   ADDTOCHAIN (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
+/* particular case. Ie : assigning or dereferencing array or ptr   */
+/*-----------------------------------------------------------------*/
+set * lvaluereqSet = NULL;
+typedef struct lvalItem
+  {
+    int req;
+    int lvl;
+  }
+lvalItem;
+
+/*-----------------------------------------------------------------*/
+/* addLvaluereq - add a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void addLvaluereq(int lvl)
+{
+  lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
+  lpItem->req=1;
+  lpItem->lvl=lvl;
+  addSetHead(&lvaluereqSet,lpItem);
+
+}
+/*-----------------------------------------------------------------*/
+/* delLvaluereq - del a flag for lvalreq for current ast level     */
+/*-----------------------------------------------------------------*/
+void delLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = getSet(&lvaluereqSet);
+  if(lpItem) free(lpItem);
+}
+/*-----------------------------------------------------------------*/
+/* clearLvaluereq - clear lvalreq flag                            */
+/*-----------------------------------------------------------------*/
+void clearLvaluereq()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) lpItem->req = 0;
+}
+/*-----------------------------------------------------------------*/
+/* getLvaluereq - get the last lvalreq level                      */
+/*-----------------------------------------------------------------*/
+int getLvaluereqLvl()
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return lpItem->lvl;
+  return 0;
+}
+/*-----------------------------------------------------------------*/
+/* isLvaluereq - is lvalreq valid for this level ?                */
+/*-----------------------------------------------------------------*/
+int isLvaluereq(int lvl)
+{
+  lvalItem * lpItem;
+  lpItem = peekSet(lvaluereqSet);
+  if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
+  return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* ast2iCode - creates an icodeList from an ast                    */
 /*-----------------------------------------------------------------*/
 operand *
-ast2iCode (ast * tree)
+ast2iCode (ast * tree,int lvl)
 {
   operand *left = NULL;
   operand *right = NULL;
-
   if (!tree)
     return NULL;
-
   /* set the global variables for filename & line number */
   if (tree->filename)
     filename = tree->filename;
@@ -3023,11 +3099,11 @@ ast2iCode (ast * tree)
 
   /* if we find a nullop */
   if (tree->type == EX_OP &&
-      (tree->opval.op == NULLOP ||
-       tree->opval.op == BLOCK))
+     (tree->opval.op == NULLOP ||
+     tree->opval.op == BLOCK))
     {
-      ast2iCode (tree->left);
-      ast2iCode (tree->right);
+      ast2iCode (tree->left,lvl+1);
+      ast2iCode (tree->right,lvl+1);
       return NULL;
     }
 
@@ -3043,44 +3119,37 @@ ast2iCode (ast * tree)
       tree->opval.op != INLINEASM)
     {
 
-      if (IS_ASSIGN_OP (tree->opval.op) ||
-         IS_DEREF_OP (tree) ||
-         (tree->opval.op == '&' && !tree->right) ||
-         tree->opval.op == PTR_OP)
-       {
-         lvaluereq++;
-         if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
-             (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
-           {
-             int olvr = lvaluereq;
-             lvaluereq = 0;
-             left = operandFromAst (tree->left);
-             lvaluereq = olvr - 1;
-           }
-         else
-           {
-             left = operandFromAst (tree->left);
-             lvaluereq--;
-           }
-         if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
-           left = geniCodeRValue (left, TRUE);
-       }
-      else
-       {
-         left = operandFromAst (tree->left);
-       }
-      if (tree->opval.op == INC_OP ||
-         tree->opval.op == DEC_OP)
-       {
-         lvaluereq++;
-         right = operandFromAst (tree->right);
-         lvaluereq--;
-       }
-      else
-       {
-         right = operandFromAst (tree->right);
-       }
-    }
+        if (IS_ASSIGN_OP (tree->opval.op) ||
+           IS_DEREF_OP (tree) ||
+           (tree->opval.op == '&' && !tree->right) ||
+           tree->opval.op == PTR_OP)
+          {
+            addLvaluereq(lvl);
+            if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
+               (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
+              clearLvaluereq();
+
+            left = operandFromAst (tree->left,lvl);
+            delLvaluereq();
+            if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
+             left = geniCodeRValue (left, TRUE);
+          }
+        else
+          {
+           left = operandFromAst (tree->left,lvl);
+          }
+        if (tree->opval.op == INC_OP ||
+           tree->opval.op == DEC_OP)
+          {
+           addLvaluereq(lvl);
+           right = operandFromAst (tree->right,lvl);
+           delLvaluereq();
+          }
+        else
+          {
+           right = operandFromAst (tree->right,lvl);
+          }
+      }
 
   /* now depending on the type of operand */
   /* this will be a biggy                 */
@@ -3094,7 +3163,7 @@ ast2iCode (ast * tree)
        right = geniCodeRValue (right, TRUE);
       }
 
-      return geniCodeArray (left, right);
+      return geniCodeArray (left, right,lvl);
 
     case '.':                  /* structure dereference */
       if (IS_PTR (operandType (left)))
@@ -3156,7 +3225,7 @@ ast2iCode (ast * tree)
        return geniCodeMultiply (geniCodeRValue (left, FALSE),
                                 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
       else
-       return geniCodeDerefPtr (geniCodeRValue (left, FALSE));
+       return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
       if (right)
@@ -3168,7 +3237,7 @@ ast2iCode (ast * tree)
     case '+':
       if (right)
        return geniCodeAdd (geniCodeRValue (left, FALSE),
-                           geniCodeRValue (right, FALSE));
+                           geniCodeRValue (right, FALSE),lvl);
       else
        return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
 
@@ -3207,7 +3276,7 @@ ast2iCode (ast * tree)
                            geniCodeRValue (right, FALSE),
                            tree->opval.op);
     case '?':
-      return geniCodeConditional (tree);
+      return geniCodeConditional (tree,lvl);
 
     case SIZEOF:
       return operandFromLit (getSize (tree->right->ftype));
@@ -3217,7 +3286,7 @@ ast2iCode (ast * tree)
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          right = geniCodeRValue (right, TRUE);
        else
          right = geniCodeRValue (right, FALSE);
@@ -3249,7 +3318,7 @@ ast2iCode (ast * tree)
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          right = geniCodeRValue (right, TRUE);
        else
          right = geniCodeRValue (right, FALSE);
@@ -3258,14 +3327,14 @@ ast2iCode (ast * tree)
        return geniCodeAssign (left,
                     geniCodeAdd (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 right), 0);
+                                 right,lvl), 0);
       }
     case SUB_ASSIGN:
       {
        sym_link *rtype = operandType (right);
        sym_link *ltype = operandType (left);
        if (IS_PTR (rtype) && IS_ITEMP (right)
-           && right->isaddr && checkType (rtype->next, ltype) == 1)
+           && right->isaddr && compareType (rtype->next, ltype) == 1)
          {
            right = geniCodeRValue (right, TRUE);
          }
@@ -3319,18 +3388,18 @@ ast2iCode (ast * tree)
       return geniCodeRValue (right, FALSE);
 
     case CALL:
-      return geniCodeCall (ast2iCode (tree->left),
-                          tree->right);
+      return geniCodeCall (ast2iCode (tree->left,lvl+1),
+                          tree->right,lvl);
     case LABEL:
-      geniCodeLabel (ast2iCode (tree->left)->operand.symOperand);
-      return ast2iCode (tree->right);
+      geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
 
     case GOTO:
-      geniCodeGoto (ast2iCode (tree->left)->operand.symOperand);
-      return ast2iCode (tree->right);
+      geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
+      return ast2iCode (tree->right,lvl+1);
 
     case FUNCTION:
-      geniCodeFunctionBody (tree);
+      geniCodeFunctionBody (tree,lvl);
       return NULL;
 
     case RETURN:
@@ -3338,11 +3407,11 @@ ast2iCode (ast * tree)
       return NULL;
 
     case IFX:
-      geniCodeIfx (tree);
+      geniCodeIfx (tree,lvl);
       return NULL;
 
     case SWITCH:
-      geniCodeSwitch (tree);
+      geniCodeSwitch (tree,lvl);
       return NULL;
 
     case INLINEASM:
@@ -3382,6 +3451,6 @@ iCodeFromAst (ast * tree)
 {
   returnLabel = newiTempLabel ("_return");
   entryLabel = newiTempLabel ("_entry");
-  ast2iCode (tree);
+  ast2iCode (tree,0);
   return reverseiCChain ();
 }