(optionally) push static array initialization down to the ports code generator
authorkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 24 Aug 2001 19:04:40 +0000 (19:04 +0000)
committerkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 24 Aug 2001 19:04:40 +0000 (19:04 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1167 4a8a32a2-be11-0410-ad9d-d568d2c75423

17 files changed:
src/SDCC.y
src/SDCCast.c
src/SDCCast.h
src/SDCCicode.c
src/SDCCicode.h
src/SDCCmain.c
src/SDCCval.c
src/SDCCval.h
src/avr/main.c
src/ds390/gen.c
src/ds390/main.c
src/izt/i186.c
src/izt/tlcs900h.c
src/mcs51/main.c
src/pic/main.c
src/port.h
src/z80/main.c

index 8c09fb5840494c7a5c62a93c3ca7948171026973..53cd3b5a02f1d23de06fec5547685b12296ad6c6 100644 (file)
@@ -90,7 +90,7 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
 %token RRC RLC 
-%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND
+%token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
 
 %type <yyint>  Interrupt_storage
 %type <sym> identifier  declarator  declarator2 enumerator_list enumerator
index a28cf06f54f7dbc9f475e0352584c6aa74aac17a..4a5a25b3353f102eb22fdadd8e2cb8fa3a8c148f 100644 (file)
@@ -224,7 +224,12 @@ copyAstValues (ast * dest, ast * src)
     case INLINEASM:
       dest->values.inlineasm = Safe_calloc (1, strlen (src->values.inlineasm) + 1);
       strcpy (dest->values.inlineasm, src->values.inlineasm);
+      break;
 
+    case ARRAYINIT:
+       dest->values.constlist = copyLiteralList(src->values.constlist);
+       break;
+       
     case FOR:
       AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
       AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
@@ -832,6 +837,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   ast *rast = NULL;
   initList *iloop;
   int lcnt = 0, size = 0;
+  literalList *literalL;
 
   /* take care of the special   case  */
   /* array of characters can be init  */
@@ -843,51 +849,77 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
 
       return decorateType (resolveSymbols (rast));
 
-  /* not the special case             */
-  if (ilist->type != INIT_DEEP)
+    /* not the special case             */
+    if (ilist->type != INIT_DEEP)
     {
-      werror (E_INIT_STRUCT, "");
-      return NULL;
+       werror (E_INIT_STRUCT, "");
+       return NULL;
     }
 
-  iloop = ilist->init.deep;
-  lcnt = DCL_ELEM (type);
+    iloop = ilist->init.deep;
+    lcnt = DCL_ELEM (type);
 
-  for (;;)
+    if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
     {
-      ast *aSym;
-      size++;
-
-      aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size - 1))));
-      aSym = decorateType (resolveSymbols (aSym));
-      rast = createIval (aSym, type->next, iloop, rast);
-      iloop = (iloop ? iloop->next : NULL);
-      if (!iloop)
-       break;
-      /* if not array limits given & we */
-      /* are out of initialisers then   */
-      if (!DCL_ELEM (type) && !iloop)
-       break;
+       ast *aSym;
 
-      /* no of elements given and we    */
-      /* have generated for all of them */
-      if (!--lcnt) {
-       /* if initializers left */
-       if (iloop) {
-         // there has to be a better way
-         char *name=sym->opval.val->sym->name;
-         int lineno=sym->opval.val->sym->lineDef;
-         werror (W_EXESS_ARRAY_INITIALIZERS, name, lineno);
+       aSym = decorateType (resolveSymbols(sym));
+       
+       rast = newNode(ARRAYINIT, aSym, NULL);
+       rast->values.constlist = literalL;
+       
+       // Make sure size is set to length of initializer list.
+       while (iloop)
+       {
+           size++;
+           iloop = iloop->next;
+       }
+       
+       if (lcnt && size > lcnt)
+       {
+           // Array size was specified, and we have more initializers than needed.
+           char *name=sym->opval.val->sym->name;
+           int lineno=sym->opval.val->sym->lineDef;
+           
+           werror (W_EXESS_ARRAY_INITIALIZERS, name, lineno);
+       }
+    }
+    else
+    {
+       for (;;)
+       {
+           ast *aSym;
+           
+           aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (++size))));
+           aSym = decorateType (resolveSymbols (aSym));
+           rast = createIval (aSym, type->next, iloop, rast);
+           iloop = (iloop ? iloop->next : NULL);
+           if (!iloop)
+           {
+               break;
+           }
+           
+           /* no of elements given and we    */
+           /* have generated for all of them */
+           if (!--lcnt) 
+           {
+               // there has to be a better way
+               char *name=sym->opval.val->sym->name;
+               int lineno=sym->opval.val->sym->lineDef;
+               werror (W_EXESS_ARRAY_INITIALIZERS, name, lineno);
+               
+               break;
+           }
        }
-       break;
-      }
     }
 
-  /* if we have not been given a size  */
-  if (!DCL_ELEM (type))
-    DCL_ELEM (type) = size;
+    /* if we have not been given a size  */
+    if (!DCL_ELEM (type))
+    {
+       DCL_ELEM (type) = size;
+    }
 
-  return decorateType (resolveSymbols (rast));
+    return decorateType (resolveSymbols (rast));
 }
 
 
@@ -912,7 +944,6 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
        SPEC_SCLS (iexpr->etype) == S_CODE)
       && IS_ARRAY (iexpr->ftype))
     {
-
       /* for each character generate an assignment */
       /* to the array element */
       char *s = SPEC_CVAL (iexpr->etype).v_char;
index ff406517c288568853f466307400bf7df593176a..f0cbfaf69423251ae407bc4f7da32295aa589f7e 100644 (file)
@@ -66,6 +66,7 @@ typedef struct ast
     union
       {
        char *inlineasm;        /* pointer to inline assembler code */
+       literalList *constlist; /* init list for array initializer. */
        symbol *sym;            /* if block then -> symbols */
        value *args;            /* if function then args    */
        /* if switch then switch values */
index e784abc298adb4ea28981dc17e8e19bf0fde6803..b5885e01aff796a178133418581f622b462179e2 100644 (file)
@@ -109,7 +109,8 @@ iCodeTable codeTable[] =
   {IFX, "if", picIfx, NULL},
   {INLINEASM, "", picInline, NULL},
   {RECEIVE, "recv", picReceive, NULL},
-  {SEND, "send", picGenericOne, NULL}
+  {SEND, "send", picGenericOne, NULL},
+  {ARRAYINIT, "arrayInit", picGenericOne, NULL},
 };
 
 
@@ -610,6 +611,10 @@ copyiCode (iCode * ic)
       IC_INLINE (nic) = IC_INLINE (ic);
       break;
 
+    case ARRAYINIT:
+      IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
+      break;
+
     default:
       IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
       IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
@@ -3007,6 +3012,19 @@ geniCodeInline (ast * tree)
   ADDTOCHAIN (ic);
 }
 
+/*-----------------------------------------------------------------*/
+/* geniCodeArrayInit - intermediate code for array initializer     */
+/*-----------------------------------------------------------------*/
+static void 
+geniCodeArrayInit (ast * tree, operand *array)
+{
+  iCode *ic;
+
+  ic = newiCode (ARRAYINIT, array, NULL);
+  IC_ARRAYILIST (ic) = tree->values.constlist;
+  ADDTOCHAIN (ic);
+}
+
 /*-----------------------------------------------------------------*/
 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
 /* particular case. Ie : assigning or dereferencing array or ptr   */
@@ -3415,6 +3433,10 @@ ast2iCode (ast * tree,int lvl)
     case INLINEASM:
       geniCodeInline (tree);
       return NULL;
+       
+    case ARRAYINIT:
+       geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+       return NULL;
     }
 
   return NULL;
index ae5be9a1abf024c4c9f620bd3176dde5939e80ec..12d31f035b2877a2348e2433661208030dd451b0 100644 (file)
@@ -111,6 +111,7 @@ operand;
 #define IC_JTCOND(x) (x)->ulrrcnd.jmpTab.condition
 #define IC_JTLABELS(x) (x)->ulrrcnd.jmpTab.labels
 #define IC_INLINE(x) (x)->inlineAsm
+#define IC_ARRAYILIST(x) (x)->arrayInitList
 
 typedef struct iCode
   {
@@ -171,6 +172,7 @@ typedef struct iCode
     argLabel;
 
     char *inlineAsm;           /* pointer to inline assembler code */
+    literalList *arrayInitList; /* point to array initializer list. */
 
     int lineno;                        /* file & lineno for debug information */
     char *filename;
@@ -205,6 +207,7 @@ iCodeTable;
                       x->op == IPOP     ||     \
                       x->op == JUMPTABLE ||    \
                       x->op == RECEIVE  ||     \
+                     x->op == ARRAYINIT ||    \
                      SKIP_IC1(x)||  \
                      x->op == SEND         )
 
index 7f58094f4866837ee85e5cb22319028262443e49..a0cf598a73f70970bcfd332fbbaccab0053505c7 100644 (file)
@@ -1319,6 +1319,11 @@ main (int argc, char **argv, char **envp)
   setDefaultOptions ();
   parseCmdLine (argc, argv);
 
+  if (getenv("SDCPP"))
+  {
+    _preCmd[0] = getenv("SDCPP");
+  }
+    
   /* if no input then printUsage & exit */
   if ((!options.c1mode && !srcFileName && !nrelFiles) || 
       (options.c1mode && !srcFileName && !options.out_name))
index 357b503e07a6aa6858f4e15a30f60b3d5ecfe3bf..d4ba18f8f4c190b9ff4d709b7cb4eff2577cc53b 100644 (file)
@@ -97,6 +97,107 @@ revinit (initList * val)
   return prev;
 }
 
+bool
+convertIListToConstList(initList *src, literalList **lList)
+{
+    initList    *iLoop;
+    literalList *head, *last, *newL;
+    
+    head = last = NULL;
+    
+    if (!src || src->type != INIT_DEEP)
+    {
+       return FALSE;
+    }
+    
+    iLoop =  src->init.deep;
+    
+    while (iLoop)
+    {
+       if (iLoop->type != INIT_NODE)
+       {
+           return FALSE;
+       }
+       
+       if (!IS_AST_LIT_VALUE(iLoop->init.node))
+       {
+           return FALSE;
+       }
+       iLoop = iLoop->next;
+    }
+    
+    // We've now established that the initializer list contains only literal values.
+    
+    iLoop = src->init.deep;
+    while (iLoop)
+    {
+       double val = AST_LIT_VALUE(iLoop->init.node);
+       
+       if (last && last->literalValue == val)
+       {
+           last->count++;
+       }
+       else
+       {
+           newL = Safe_malloc(sizeof(literalList));
+           newL->literalValue = val;
+           newL->count = 1;
+           newL->next = NULL;
+           
+           if (last)
+           {
+               last->next = newL;
+           }
+           else
+           {
+               head = newL;
+           }
+           last = newL;
+       }
+       iLoop = iLoop->next;
+    }
+    
+    if (!head)    
+    {
+       return FALSE;
+    }
+    
+    *lList = head;
+    return TRUE;
+}
+
+literalList *
+copyLiteralList(literalList *src)
+{
+    literalList *head, *prev, *newL;
+    
+    head = prev = NULL;
+    
+    while (src)
+    {
+       newL = Safe_malloc(sizeof(literalList));
+       
+       newL->literalValue = src->literalValue;
+       newL->count = src->count;
+       newL->next = NULL;
+       
+       if (prev)
+       {
+           prev->next = newL;
+       }
+       else
+       {
+           head = newL;
+       }
+       prev = newL;
+       src = src->next;
+    }
+    
+    return head;
+}
+
+
+
 /*------------------------------------------------------------------*/
 /* copyIlist - copy initializer list            */
 /*------------------------------------------------------------------*/
index 17c4ba4a3df5597857a05dca0383bdc2d0ede3c1..b783970805403048de1ca9dffd49ff010fca5337 100644 (file)
@@ -37,6 +37,14 @@ typedef struct value
   }
 value;
 
+typedef struct literalList
+{
+    double    literalValue;
+    unsigned  count;
+    struct literalList *next;
+} literalList;
+
+
 enum
   {
     INIT_NODE,
@@ -104,4 +112,6 @@ value *valForArray (struct ast *);
 value *valForStructElem (struct ast *, struct ast *);
 value *valForCastAggr (struct ast *, sym_link *, struct ast *, int);
 value *valForCastArr (struct ast * , sym_link *);
+bool convertIListToConstList(initList *src, literalList **lList);
+literalList *copyLiteralList(literalList *src);
 #endif
index 84a1468139b62cfbf759f66d65d2c8b727f8544a..c14ba658c563932b5f918da05f14b6d680ad262b 100644 (file)
@@ -213,5 +213,6 @@ PORT avr_port = {
        0,                      /* leave ge */
        0,                      /* leave !=  */
        0,                      /* leave == */
+       FALSE,                        /* No array initializer support. */
        PORT_MAGIC
 };
index 21315fde238ff9c08ee0b880e299298d9c8b0e28..c47b03022a524be095168ec8b32a52e9b7a63fab 100644 (file)
@@ -9214,6 +9214,106 @@ release:
 
 }
 
+/*-----------------------------------------------------------------*/
+/* genArrayInit - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void
+genArrayInit (iCode * ic)
+{
+    literalList *iLoop;
+    int         ix, count;
+    int         elementSize = 0, eIndex;
+    unsigned    val, lastVal;
+    sym_link    *type;
+    
+    D (emitcode (";", "genArrayInit "););
+
+    aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
+    
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
+    {
+       // Load immediate value into DPTR.
+       emitcode("mov", "dptr, %s",
+            aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
+    }
+    else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
+    {
+       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+               "Unexpected operand to genArrayInit.\n");
+       exit(1);
+    }
+    
+    type = operandType(IC_LEFT(ic));
+    
+    if (type && type->next)
+    {
+       elementSize = getSize(type->next);
+    }
+    else
+    {
+       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                               "can't determine element size in genArrayInit.\n");
+       exit(1);
+    }
+    
+    iLoop = IC_ARRAYILIST(ic);
+    lastVal = 0xffff;
+    
+    while (iLoop)
+    {
+       bool firstpass = TRUE;
+       
+       emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
+                iLoop->count, (int)iLoop->literalValue, elementSize);
+       
+       ix = iLoop->count;
+       
+       while (ix)
+       {
+           symbol *tlbl = NULL;
+           
+           count = ix > 256 ? 256 : ix;
+           
+           if (count > 1)
+           {
+               tlbl = newiTempLabel (NULL);
+               if (firstpass || (count & 0xff))
+               {
+                   emitcode("mov", "b, #0x%x", count & 0xff);
+               }
+               
+               emitcode ("", "%05d$:", tlbl->key + 100);
+           }
+           
+           firstpass = FALSE;
+               
+           for (eIndex = 0; eIndex < elementSize; eIndex++)
+           {
+               val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+               if (val != lastVal)
+               {
+                   emitcode("mov", "a, #0x%x", val);
+                   lastVal = val;
+               }
+               
+               emitcode("movx", "@dptr, a");
+               emitcode("inc", "dptr");
+           }
+           
+           if (count > 1)
+           {
+               emitcode("djnz", "b, %05d$", tlbl->key + 100);
+           }
+           
+           ix -= count;
+       }
+       
+       iLoop = iLoop->next;
+    }
+    
+    freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
+}
+
 /*-----------------------------------------------------------------*/
 /* genFarFarAssign - assignment when both are in far space         */
 /*-----------------------------------------------------------------*/
@@ -9256,7 +9356,7 @@ genFarFarAssign (operand * result, operand * right, iCode * ic)
   {
       /* We can use the '390 auto-toggle feature to good effect here. */
       
-      D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
+      D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
       emitcode("mov", "dps, #0x21");   /* Select DPTR2 & auto-toggle. */
       emitcode ("mov", "dptr,#%s", rSym->rname); 
       /* DP2 = result, DP1 = right, DP1 is current. */
@@ -10047,6 +10147,10 @@ gen390Code (iCode * lic)
          addSet (&_G.sendSet, ic);
          break;
 
+       case ARRAYINIT:
+           genArrayInit(ic);
+           break;
+           
        default:
          ic = ic;
        }
index 3bafacb7ce2cff0a826d7a1fe8c2b3aa65988fe9..1cf35286d0c670a4ace5b4926c17c97d2022ad37 100644 (file)
@@ -271,5 +271,6 @@ PORT ds390_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  TRUE,                         /* we support array initializers. */
   PORT_MAGIC
 };
index 231a7aeb222e8908818809161b998ce70b246930..7a4e39ddd4299993217430c07e8c8aa65b56ef23 100644 (file)
@@ -205,5 +205,6 @@ PORT i186_port = {
     1,  /* transform >= to ! < */
     1,  /* transform != to !(a == b) */
     0,  /* leave == */
+    FALSE,                        /* No array initializer support. */
     PORT_MAGIC
 };
index bc9d8d50faec7225df11dcc81709cd0f9502bdff..e9f852084f0def9f5d412340cc6b349f23416fe2 100644 (file)
@@ -204,5 +204,6 @@ PORT tlcs900h_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */    
   PORT_MAGIC
 };
index 68e32ea3f8b77dfaaff991003e0107a1b4d35cc2..c06d08a9c6d0b0f6b44360da588127be7f522fe1 100644 (file)
@@ -211,5 +211,6 @@ PORT mcs51_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
   PORT_MAGIC
 };
index d411f5003944e553949b234f5041278d1863043e..f623d1ca432b69344fffe7d8127f54b7e2a59888 100644 (file)
@@ -295,5 +295,6 @@ PORT pic_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
   PORT_MAGIC
 };
index d53dd0ce0b68879288cdc2d074734b705d408083..897380323e740ce4d0dc0ee586f74868a3e0e14c 100644 (file)
@@ -214,6 +214,8 @@ typedef struct
     bool ne_neq;               /* transform a != b --> ! (a == b)  */
     bool eq_nne;               /* transform a == b --> ! (a != b)  */
 
+    bool arrayInitializerSuppported;  
+      
 #define PORT_MAGIC 0xAC32
 /** Used at runtime to detect if this structure has been completly filled in. */
     int magic;
index 0f6f498f1605a763faeceb450ccd6c86327798b8..7784f38fd9c174d49e6611c34dfeea00241f6d1d 100644 (file)
@@ -531,6 +531,7 @@ PORT z80_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */    
   PORT_MAGIC
 };
 
@@ -609,5 +610,6 @@ PORT gbz80_port =
   1,                           /* transform >= to ! < */
   1,                           /* transform != to !(a == b) */
   0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
   PORT_MAGIC
 };