This makes the dump files more readable
[fw/sdcc] / src / SDCCicode.c
index 3968b3ea3302b07300dd5abbe717a535137d3928..9c37fe0a2d5f22cdc4197ffc06ea11eb134f0c4f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "common.h"
 #include "newalloc.h"
+#include "math.h"
 
 /*-----------------------------------------------------------------*/
 /* global variables       */
@@ -41,12 +42,6 @@ int scopeLevel;
 symbol *returnLabel;           /* function return label */
 symbol *entryLabel;            /* function entry  label */
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define LONG_LONG __int64
-#else
-#define LONG_LONG long long
-#endif
-
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
 operand *geniCodeDivision (operand *, operand *);
@@ -131,12 +126,29 @@ iCodeTable codeTable[] =
      pedantic>1: "char c=200" is not allowed (evaluates to -56)
 */
 
-void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
-  LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
-  char message[132]="";
+void checkConstantRange(sym_link *ltype, value *val, char *msg, 
+                       int pedantic) {
+  double max;
   int warnings=0;
   int negative=0;
-  long v=SPEC_CVAL(val->type).v_long;
+  long v;
+
+  max = pow ((double)2.0, (double)bitsForType(ltype));
+
+  if (SPEC_LONG(val->type)) {
+    if (SPEC_USIGN(val->type)) {
+      v=SPEC_CVAL(val->type).v_ulong;
+    } else {
+      v=SPEC_CVAL(val->type).v_long;
+    }
+  } else {
+    if (SPEC_USIGN(val->type)) {
+      v=SPEC_CVAL(val->type).v_uint;
+    } else {
+      v=SPEC_CVAL(val->type).v_int;
+    }
+  }
+
 
 #if 0
   // this could be a good idea
@@ -166,8 +178,9 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
     warnings++;
   }
 
+#if 0 // temporary disabled, leaving the warning as a reminder
   if (warnings) {
-    sprintf (message, "for %s %s in %s", 
+    SNPRINTF (message, sizeof(message), "for %s %s in %s", 
             SPEC_USIGN(ltype) ? "unsigned" : "signed",
             nounName(ltype), msg);
     werror (W_CONST_RANGE, message);
@@ -175,6 +188,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
     if (pedantic>1)
       fatalError++;
   }
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -210,12 +224,14 @@ 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}",          /*{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 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_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
+              op->isaddr, OP_SYMBOL (op)->isreqv, 
+              OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
+              OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
        );
       {
        fprintf (file, "{");
@@ -370,6 +386,9 @@ PRINTFUNC (picGenericOne)
   if (!IC_RESULT (ic) && !IC_LEFT (ic))
     fprintf (of, s);
 
+  if (ic->op == SEND || ic->op == RECEIVE) {
+      fprintf(of,"{argreg = %d}",ic->argreg);
+  }
   fprintf (of, "\n");
 }
 
@@ -481,7 +500,7 @@ printiCChain (iCode * icChain, FILE * of)
     {
       if ((icTab = getTableEntry (loop->op)))
        {
-         fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+         fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
                   loop->filename, loop->lineno,
                   loop->seq, loop->key, loop->depth, loop->supportRtn);
 
@@ -499,7 +518,7 @@ newOperand ()
 {
   operand *op;
 
-  op = Safe_calloc (1, sizeof (operand));
+  op = Safe_alloc ( sizeof (operand));
 
   op->key = 0;
   return op;
@@ -513,7 +532,7 @@ newiCode (int op, operand * left, operand * right)
 {
   iCode *ic;
 
-  ic = Safe_calloc (1, sizeof (iCode));
+  ic = Safe_alloc ( sizeof (iCode));
 
   ic->lineno = lineno;
   ic->filename = filename;
@@ -537,7 +556,7 @@ newiCodeCondition (operand * condition,
 {
   iCode *ic;
 
-  if (IS_VOID(OP_SYMBOL(condition)->type)) {
+  if (IS_VOID(operandType(condition))) {
     werror(E_VOID_VALUE_USED);
   }
 
@@ -558,7 +577,7 @@ newiCodeLabelGoto (int op, symbol * label)
 
   ic = newiCode (op, NULL, NULL);
   ic->op = op;
-  ic->argLabel.label = label;
+  ic->label = label;
   IC_LEFT (ic) = NULL;
   IC_RIGHT (ic) = NULL;
   IC_RESULT (ic) = NULL;
@@ -574,11 +593,16 @@ newiTemp (char *s)
   symbol *itmp;
 
   if (s)
-    sprintf (buffer, "%s", s);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "%s", s);
+  }
   else
-    sprintf (buffer, "iTemp%d", iTempNum++);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
+  }
+    
   itmp = newSymbol (buffer, 1);
-  strcpy (itmp->rname, itmp->name);
+  strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
   itmp->isitmp = 1;
 
   return itmp;
@@ -597,10 +621,12 @@ newiTempLabel (char *s)
     return itmplbl;
 
   if (s)
-    itmplbl = newSymbol (s, 1);
+    {
+       itmplbl = newSymbol (s, 1);
+    }
   else
     {
-      sprintf (buffer, "iTempLbl%d", iTempLblNum++);
+      SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
       itmplbl = newSymbol (buffer, 1);
     }
 
@@ -619,7 +645,7 @@ newiTempPreheaderLabel ()
 {
   symbol *itmplbl;
 
-  sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
+  SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
   itmplbl = newSymbol (buffer, 1);
 
   itmplbl->isitmp = 1;
@@ -671,7 +697,6 @@ copyiCode (iCode * ic)
     case PCALL:
       IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
       IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
-      IC_ARGS (nic) = IC_ARGS (ic);
       break;
 
     case INLINEASM:
@@ -774,6 +799,8 @@ isParameterToCall (value * args, operand * op)
 {
   value *tval = args;
 
+  wassert (IS_SYMOP(op));
+    
   while (tval)
     {
       if (tval->sym &&
@@ -796,7 +823,7 @@ isOperandGlobal (operand * op)
   if (IS_ITEMP (op))
     return 0;
 
-  if (op->type == SYMBOL &&
+  if (IS_SYMOP(op) &&
       (op->operand.symOperand->level == 0 ||
        IS_STATIC (op->operand.symOperand->etype) ||
        IS_EXTERN (op->operand.symOperand->etype))
@@ -846,6 +873,7 @@ isOperandLiteral (operand * op)
 
   return 0;
 }
+
 /*-----------------------------------------------------------------*/
 /* isOperandInFarSpace - will return true if operand is in farSpace */
 /*-----------------------------------------------------------------*/
@@ -874,6 +902,64 @@ isOperandInFarSpace (operand * op)
   return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
 }
 
+/*------------------------------------------------------------------*/
+/* isOperandInDirSpace - will return true if operand is in dirSpace */
+/*------------------------------------------------------------------*/
+bool 
+isOperandInDirSpace (operand * op)
+{
+  sym_link *etype;
+
+  if (!op)
+    return FALSE;
+
+  if (!IS_SYMOP (op))
+    return FALSE;
+
+  if (!IS_TRUE_SYMOP (op))
+    {
+      if (SPIL_LOC (op))
+       etype = SPIL_LOC (op)->etype;
+      else
+       return FALSE;
+    }
+  else
+    {
+      etype = getSpec (operandType (op));
+    }
+  return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
+/*--------------------------------------------------------------------*/
+/* isOperandInCodeSpace - will return true if operand is in codeSpace */
+/*--------------------------------------------------------------------*/
+bool 
+isOperandInCodeSpace (operand * op)
+{
+  sym_link *etype;
+
+  if (!op)
+    return FALSE;
+
+  if (!IS_SYMOP (op))
+    return FALSE;
+
+  etype = getSpec (operandType (op));
+
+  if (!IS_TRUE_SYMOP (op))
+    {
+      if (SPIL_LOC (op))
+       etype = SPIL_LOC (op)->etype;
+      else
+       return FALSE;
+    }
+  else
+    {
+      etype = getSpec (operandType (op));
+    }
+  return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
+}
+
 /*-----------------------------------------------------------------*/
 /* isOperandOnStack - will return true if operand is on stack      */
 /*-----------------------------------------------------------------*/
@@ -889,8 +975,12 @@ isOperandOnStack (operand * op)
     return FALSE;
 
   etype = getSpec (operandType (op));
+  if (IN_STACK (etype) ||
+      OP_SYMBOL(op)->onStack ||
+      (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
+    return TRUE;
 
-  return ((IN_STACK (etype)) ? TRUE : FALSE);
+  return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
@@ -904,6 +994,31 @@ operandLitValue (operand * op)
   return floatFromVal (op->operand.valOperand);
 }
 
+/*-----------------------------------------------------------------*/
+/* getBuiltInParms - returns parameters to a builtin functions     */
+/*-----------------------------------------------------------------*/
+iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
+{
+    sym_link *ftype;
+
+    *pcount = 0;
+    /* builtin functions uses only SEND for parameters */
+    while (ic->op != CALL) {
+       assert(ic->op == SEND && ic->builtinSEND);
+       ic->generated = 1;    /* mark the icode as generated */
+       parms[*pcount] = IC_LEFT(ic);
+       ic = ic->next;
+       (*pcount)++;
+    }
+    
+    ic->generated = 1;
+    /* make sure this is a builtin function call */
+    assert(IS_SYMOP(IC_LEFT(ic)));
+    ftype = operandType(IC_LEFT(ic));
+    assert(IFFUNC_ISBUILTIN(ftype));
+    return ic;
+}
+
 /*-----------------------------------------------------------------*/
 /* operandOperation - perforoms operations on operands             */
 /*-----------------------------------------------------------------*/
@@ -965,21 +1080,34 @@ operandOperation (operand * left, operand * right,
 
       break;
     case LEFT_OP:
-      retval = operandFromLit (((SPEC_USIGN(let) ? 
+      retval = operandFromLit ((SPEC_USIGN(let) ? 
                                  (unsigned long) operandLitValue (left) :
                                  (long) operandLitValue (left)) <<
                                 (SPEC_USIGN(ret) ? 
                                  (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right))));
+                                 (long) operandLitValue (right)));
       break;
-    case RIGHT_OP:
-      retval = operandFromLit (((SPEC_USIGN(let) ? 
-                                 (unsigned long) operandLitValue (left) :
-                                 (long) operandLitValue (left)) >>
-                                (SPEC_USIGN(ret) ? 
-                                 (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right))));
+    case RIGHT_OP: {
+      double lval = operandLitValue(left), rval = operandLitValue(right);
+      double res=0;
+      switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0)) 
+       {
+       case 0: // left=unsigned right=unsigned
+         res=(unsigned long)lval >> (unsigned long)rval;
+         break;
+       case 1: // left=unsigned right=signed
+         res=(unsigned long)lval >> (signed long)rval;
+         break;
+       case 2: // left=signed right=unsigned
+         res=(signed long)lval >> (unsigned long)rval;
+         break;
+       case 3: // left=signed right=signed
+         res=(signed long)lval >> (signed long)rval;
+         break;
+       }
+      retval = operandFromLit (res);
       break;
+    }
     case EQ_OP:
       retval = operandFromLit (operandLitValue (left) ==
                               operandLitValue (right));
@@ -1005,16 +1133,16 @@ operandOperation (operand * left, operand * right,
                               operandLitValue (right));
       break;
     case BITWISEAND:
-      retval = operandFromLit ((unsigned long) operandLitValue (left) &
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit ((long)operandLitValue(left) & 
+                              (long)operandLitValue(right));
       break;
     case '|':
-      retval = operandFromLit ((unsigned long) operandLitValue (left) |
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit ((long)operandLitValue (left) |
+                              (long)operandLitValue (right));
       break;
     case '^':
-      retval = operandFromLit ((unsigned long) operandLitValue (left) ^
-                              (unsigned long) operandLitValue (right));
+      retval = operandFromLit ((long)operandLitValue (left) ^
+                              (long)operandLitValue (right));
       break;
     case AND_OP:
       retval = operandFromLit (operandLitValue (left) &&
@@ -1254,7 +1382,6 @@ 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_DS390)) && */
       (!(options.model == MODEL_FLAT24)) ) &&
       options.stackAuto == 0)
     ok = 0;
@@ -1264,7 +1391,7 @@ operandFromSymbol (symbol * sym)
       !sym->_isparm &&         /* not a parameter  */
       sym->level &&            /* is a local variable */
       !sym->addrtaken &&       /* whose address has not been taken */
-      !sym->reqv &&            /* does not already have a register euivalence */
+      !sym->reqv &&            /* does not already have a reg equivalence */
       !IS_VOLATILE (sym->etype) &&     /* not declared as volatile */
       !IS_STATIC (sym->etype) &&       /* and not declared static  */
       !sym->islbl &&           /* not a label */
@@ -1280,6 +1407,7 @@ operandFromSymbol (symbol * sym)
       OP_SYMBOL (sym->reqv)->key = sym->key;
       OP_SYMBOL (sym->reqv)->isreqv = 1;
       OP_SYMBOL (sym->reqv)->islocal = 1;
+      OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
       SPIL_LOC (sym->reqv) = sym;
     }
 
@@ -1318,8 +1446,6 @@ operandFromSymbol (symbol * sym)
   else
     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
 
-  IC_RESULT (ic)->operand.symOperand->args = sym->args;
-
   ADDTOCHAIN (ic);
 
   return IC_RESULT (ic);
@@ -1500,6 +1626,7 @@ usualBinaryConversions (operand ** op1, operand ** op2)
   sym_link *ltype = operandType (*op1);
   
   ctype = computeType (ltype, rtype);
+
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
   
@@ -1541,7 +1668,6 @@ geniCodeRValue (operand * op, bool force)
   if (IS_SPEC (type) &&
       IS_TRUE_SYMOP (op) &&
       (!IN_FARSPACE (SPEC_OCLS (etype)) ||
-      /* TARGET_IS_DS390)) */
       (options.model == MODEL_FLAT24) ))
     {
       op = operandFromOperand (op);
@@ -1560,10 +1686,6 @@ geniCodeRValue (operand * op, bool force)
 
 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
 
-  /* if the right is a symbol */
-  if (op->type == SYMBOL)
-    IC_RESULT (ic)->operand.symOperand->args =
-      op->operand.symOperand->args;
   ADDTOCHAIN (ic);
 
   return IC_RESULT (ic);
@@ -1599,9 +1721,9 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
 
   /* if casting to/from pointers, do some checking */
   if (IS_PTR(type)) { // to a pointer
-    if (!IS_PTR(optype) && !IS_FUNC(optype)) { // from a non pointer
+    if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
       if (IS_INTEGRAL(optype)) { 
-       // maybe this is NULL, than it's ok.
+       // maybe this is NULL, than it's ok. 
        if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
          if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
            // no way to set the storage
@@ -1652,13 +1774,7 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
     }
   }
   if (errors) {
-    /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
-       implicit?"(implicit)":"", errors); */
-    fprintf (stderr, "from type '");
-    printTypeChain (optype, stderr);
-    fprintf (stderr, "' to type '");
-    printTypeChain (type, stderr);
-    fprintf (stderr, "'\n");
+    printFromToType (optype, type);
   }
 
   /* if they are the same size create an assignment */
@@ -1687,7 +1803,8 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   /* preserve the storage class & output class */
   /* of the original variable                  */
   restype = getSpec (operandType (IC_RESULT (ic)));
-  SPEC_SCLS (restype) = SPEC_SCLS (opetype);
+  if (!IS_LITERAL(opetype))
+      SPEC_SCLS (restype) = SPEC_SCLS (opetype);
   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
 
   ADDTOCHAIN (ic);
@@ -1797,10 +1914,12 @@ geniCodeDivision (operand * left, operand * right)
 
   resType = usualBinaryConversions (&left, &right);
 
-  /* if the right is a literal & power of 2 */
-  /* then make it a right shift             */
+  /* if the right is a literal & power of 2 
+     and left is unsigned then make it a    
+     right shift */
   if (IS_LITERAL (retype) &&
       !IS_FLOAT (letype) &&
+      SPEC_USIGN(letype) &&
       (p2 = powof2 ((unsigned long)
                    floatFromVal (right->operand.valOperand)))) {
     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
@@ -1870,6 +1989,11 @@ geniCodePtrPtrSubtract (operand * left, operand * right)
   ADDTOCHAIN (ic);
 
 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)));
 }
@@ -1926,7 +2050,7 @@ geniCodeSubtract (operand * left, operand * right)
 /* geniCodeAdd - generates iCode for addition                      */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeAdd (operand * left, operand * right,int lvl)
+geniCodeAdd (operand * left, operand * right, int lvl)
 {
   iCode *ic;
   sym_link *resType;
@@ -1934,9 +2058,11 @@ geniCodeAdd (operand * left, operand * right,int lvl)
   int isarray = 0;
   LRTYPE;
 
+#if 0
   /* if left is an array then array access */
   if (IS_ARRAY (ltype))
     return geniCodeArray (left, right,lvl);
+#endif
 
   /* if the right side is LITERAL zero */
   /* return the left side              */
@@ -1947,8 +2073,8 @@ geniCodeAdd (operand * left, operand * right,int lvl)
   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
     return right;
 
-  /* if left is an array or pointer then size */
-  if (IS_PTR (ltype))
+  /* if left is a pointer then size */
+  if (IS_PTR (ltype) || IS_ARRAY(ltype))
     {
       isarray = left->isaddr;
       // there is no need to multiply with 1
@@ -1959,7 +2085,7 @@ geniCodeAdd (operand * left, operand * right,int lvl)
       resType = copyLinkChain (ltype);
     }
   else
-    {                          /* make them the same size */
+    { // make them the same size
       resType = usualBinaryConversions (&left, &right);
     }
 
@@ -2059,7 +2185,7 @@ geniCodeArray (operand * left, operand * right,int lvl)
        {
          left = geniCodeRValue (left, FALSE);
        }
-      return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
+      return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
     }
 
   right = geniCodeMultiply (right,
@@ -2100,6 +2226,8 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   symbol *element = getStructElement (SPEC_STRUCT (etype),
                                      right->operand.symOperand);
 
+  wassert(IS_SYMOP(right));
+    
   /* add the offset */
   ic = newiCode ('+', left, operandFromLit (element->offset));
 
@@ -2565,7 +2693,7 @@ geniCodeConditional (ast * tree,int lvl)
   true = ast2iCode (tree->right->left,lvl+1);
 
   /* move the value to a new Operand */
-  result = newiTempOperand (operandType (true), 0);
+  result = newiTempOperand (tree->right->ftype, 0);
   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
 
   /* generate an unconditional goto */
@@ -2614,7 +2742,7 @@ geniCodeAssign (operand * left, operand * right, int nosupdate)
 
   /* first check the type for pointer assignement */
   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
-      compareType (ltype, rtype) < 0)
+      compareType (ltype, rtype) <= 0)
     {
       if (compareType (ltype->next, rtype) < 0)
        right = geniCodeCast (ltype->next, right, TRUE);
@@ -2680,30 +2808,38 @@ geniCodeSEParms (ast * parms,int lvl)
       IS_ADDRESS_OF_OP (parms->right))
     parms->right->left->lvalue = 1;
 
-  parms->opval.oprnd =
+  parms->opval.oprnd = 
     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
-
+               
   parms->type = EX_OPERAND;
+  AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
+               SPEC_ARGREG(parms->ftype);
 }
 
 /*-----------------------------------------------------------------*/
 /* geniCodeParms - generates parameters                            */
 /*-----------------------------------------------------------------*/
-static void 
-geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
+value *
+geniCodeParms (ast * parms, value *argVals, int *stack, 
+              sym_link * fetype, symbol * func,int lvl)
 {
   iCode *ic;
   operand *pval;
 
   if (!parms)
-    return;
+    return argVals;
+
+  if (argVals==NULL) {
+    // first argument
+    argVals=FUNC_ARGS(func->type);
+  }
 
   /* 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,lvl);
-      geniCodeParms (parms->right, stack, fetype, func,lvl);
-      return;
+      argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
+      argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+      return argVals;
     }
 
   /* get the parameter value */
@@ -2726,20 +2862,24 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl
     }
 
   /* if register parm then make it a send */
-  if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
-       IS_REGPARM (parms->etype)) && !func->hasVargs)
+  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
+      IFFUNC_ISBUILTIN(func->type))
     {
       ic = newiCode (SEND, pval, NULL);
+      ic->argreg = SPEC_ARGREG(parms->etype);
+      ic->builtinSEND = FUNC_ISBUILTIN(func->type);
       ADDTOCHAIN (ic);
     }
   else
     {
       /* now decide whether to push or assign */
-      if (!(options.stackAuto || IS_RENT (fetype)))
+      if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
        {
 
          /* assign */
-         operand *top = operandFromSymbol (parms->argSym);
+         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);
        }
       else
@@ -2754,6 +2894,8 @@ geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl
        }
     }
 
+  argVals=argVals->next;
+  return argVals;
 }
 
 /*-----------------------------------------------------------------*/
@@ -2779,15 +2921,15 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   geniCodeSEParms (parms,lvl);
 
   /* first the parameters */
-  geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+  geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
 
   /* now call : if symbol then pcall */
-  if (IS_OP_POINTER (left) || IS_ITEMP(left))
+  if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
     ic = newiCode (PCALL, left, NULL);
-  else
+  } else {
     ic = newiCode (CALL, left, NULL);
+  }
 
-  IC_ARGS (ic) = left->operand.symOperand->args;
   type = copyLinkChain (operandType (left)->next);
   etype = getSpec (type);
   SPEC_EXTR (etype) = 0;
@@ -2810,7 +2952,7 @@ geniCodeReceive (value * args)
   /* for all arguments that are passed in registers */
   while (args)
     {
-
+      int first = 1;
       if (IS_REGPARM (args->etype))
        {
          operand *opr = operandFromValue (args);
@@ -2825,7 +2967,6 @@ geniCodeReceive (value * args)
 
              if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
                  options.stackAuto == 0 &&
-                 /* !TARGET_IS_DS390) */
                  (!(options.model == MODEL_FLAT24)) )
                {
                }
@@ -2841,8 +2982,12 @@ geniCodeReceive (value * args)
                }
            }
 
-         ic = newiCode (RECEIVE, NULL, NULL);
-         currFunc->recvSize = getSize (sym->etype);
+         ic = newiCode (RECEIVE, NULL, NULL);    
+         ic->argreg = SPEC_ARGREG(args->etype);
+         if (first) {
+             currFunc->recvSize = getSize (sym->type);
+             first = 0;
+         }
          IC_RESULT (ic) = opr;
          ADDTOCHAIN (ic);
        }
@@ -2879,10 +3024,7 @@ geniCodeFunctionBody (ast * tree,int lvl)
 
   /* create a proc icode */
   ic = newiCode (FUNCTION, func, NULL);
-  /* if the function has parmas   then */
-  /* save the parameters information    */
-  ic->argLabel.args = tree->values.args;
-  ic->lineno = OP_SYMBOL (func)->lineDef;
+  lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
 
   ADDTOCHAIN (ic);
 
@@ -2943,14 +3085,14 @@ geniCodeIfx (ast * tree,int lvl)
          if (tree->trueLabel)
            geniCodeGoto (tree->trueLabel);
          else
-           assert (1);
+           assert (0);
        }
       else
        {
          if (tree->falseLabel)
            geniCodeGoto (tree->falseLabel);
          else
-           assert (1);
+           assert (0);
        }
       goto exit;
     }
@@ -2997,7 +3139,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* all integer numbers between the maximum & minimum must */
   /* be present , the maximum value should not exceed 255 */
   min = max = (int) floatFromVal (vch = caseVals);
-  sprintf (buffer, "_case_%d_%d",
+  SNPRINTF (buffer, sizeof(buffer), 
+           "_case_%d_%d",
           tree->values.switchVals.swNum,
           min);
   addSet (&labels, newiTempLabel (buffer));
@@ -3010,7 +3153,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
     {
       if (((t = (int) floatFromVal (vch)) - max) != 1)
        return 0;
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), 
+               "_case_%d_%d",
               tree->values.switchVals.swNum,
               t);
       addSet (&labels, newiTempLabel (buffer));
@@ -3026,9 +3170,14 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
     return 0;
 
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
+    
 
   falseLabel = newiTempLabel (buffer);
 
@@ -3091,7 +3240,7 @@ geniCodeSwitch (ast * tree,int lvl)
                                        operandFromValue (caseVals),
                                        EQ_OP);
 
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
               tree->values.switchVals.swNum,
               (int) floatFromVal (caseVals));
       trueLabel = newiTempLabel (buffer);
@@ -3105,9 +3254,13 @@ geniCodeSwitch (ast * tree,int lvl)
 
   /* if default is present then goto break else break */
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
 
   falseLabel = newiTempLabel (buffer);
   geniCodeGoto (falseLabel);
@@ -3167,7 +3320,7 @@ lvalItem;
 /*-----------------------------------------------------------------*/
 void addLvaluereq(int lvl)
 {
-  lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
+  lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
   lpItem->req=1;
   lpItem->lvl=lvl;
   addSetHead(&lvaluereqSet,lpItem);
@@ -3180,7 +3333,7 @@ void delLvaluereq()
 {
   lvalItem * lpItem;
   lpItem = getSet(&lvaluereqSet);
-  if(lpItem) free(lpItem);
+  if(lpItem) Safe_free(lpItem);
 }
 /*-----------------------------------------------------------------*/
 /* clearLvaluereq - clear lvalreq flag                            */
@@ -3222,6 +3375,7 @@ ast2iCode (ast * tree,int lvl)
   operand *right = NULL;
   if (!tree)
     return NULL;
+
   /* set the global variables for filename & line number */
   if (tree->filename)
     filename = tree->filename;
@@ -3600,3 +3754,35 @@ iCodeFromAst (ast * tree)
   ast2iCode (tree,0);
   return reverseiCChain ();
 }
+
+static const char *opTypeToStr(OPTYPE op)
+{
+    switch(op)
+    {
+      case SYMBOL: return "symbol";
+      case VALUE: return "value";
+      case TYPE: return "type";
+    }
+    return "undefined type";    
+}
+
+
+operand *validateOpType(operand        *op, 
+                       const char      *macro,
+                       const char      *args,
+                       OPTYPE          type,
+                       const char      *file, 
+                       unsigned        line)
+{    
+    if (op && op->type == type)
+    {
+       return op;
+    }
+    fprintf(stderr, 
+           "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+           " expected %s, got %s\n",
+           macro, args, file, line, 
+           opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+    exit(-1);
+    return op; // never reached, makes compiler happy.
+}