From 5824097756886f8445cd0a4fe3aee106c98b11cd Mon Sep 17 00:00:00 2001 From: kvigor Date: Fri, 24 Aug 2001 19:04:40 +0000 Subject: [PATCH] (optionally) push static array initialization down to the ports code generator git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1167 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/SDCC.y | 2 +- src/SDCCast.c | 103 ++++++++++++++++++++++++++++--------------- src/SDCCast.h | 1 + src/SDCCicode.c | 24 +++++++++- src/SDCCicode.h | 3 ++ src/SDCCmain.c | 5 +++ src/SDCCval.c | 101 ++++++++++++++++++++++++++++++++++++++++++ src/SDCCval.h | 10 +++++ src/avr/main.c | 1 + src/ds390/gen.c | 106 ++++++++++++++++++++++++++++++++++++++++++++- src/ds390/main.c | 1 + src/izt/i186.c | 1 + src/izt/tlcs900h.c | 1 + src/mcs51/main.c | 1 + src/pic/main.c | 1 + src/port.h | 2 + src/z80/main.c | 2 + 17 files changed, 326 insertions(+), 39 deletions(-) diff --git a/src/SDCC.y b/src/SDCC.y index 8c09fb58..53cd3b5a 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -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 Interrupt_storage %type identifier declarator declarator2 enumerator_list enumerator diff --git a/src/SDCCast.c b/src/SDCCast.c index a28cf06f..4a5a25b3 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -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; diff --git a/src/SDCCast.h b/src/SDCCast.h index ff406517..f0cbfaf6 100644 --- a/src/SDCCast.h +++ b/src/SDCCast.h @@ -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 */ diff --git a/src/SDCCicode.c b/src/SDCCicode.c index e784abc2..b5885e01 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -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; diff --git a/src/SDCCicode.h b/src/SDCCicode.h index ae5be9a1..12d31f03 100644 --- a/src/SDCCicode.h +++ b/src/SDCCicode.h @@ -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 ) diff --git a/src/SDCCmain.c b/src/SDCCmain.c index 7f58094f..a0cf598a 100644 --- a/src/SDCCmain.c +++ b/src/SDCCmain.c @@ -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)) diff --git a/src/SDCCval.c b/src/SDCCval.c index 357b503e..d4ba18f8 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -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 */ /*------------------------------------------------------------------*/ diff --git a/src/SDCCval.h b/src/SDCCval.h index 17c4ba4a..b7839708 100644 --- a/src/SDCCval.h +++ b/src/SDCCval.h @@ -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 diff --git a/src/avr/main.c b/src/avr/main.c index 84a14681..c14ba658 100644 --- a/src/avr/main.c +++ b/src/avr/main.c @@ -213,5 +213,6 @@ PORT avr_port = { 0, /* leave ge */ 0, /* leave != */ 0, /* leave == */ + FALSE, /* No array initializer support. */ PORT_MAGIC }; diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 21315fde..c47b0302 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -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; } diff --git a/src/ds390/main.c b/src/ds390/main.c index 3bafacb7..1cf35286 100644 --- a/src/ds390/main.c +++ b/src/ds390/main.c @@ -271,5 +271,6 @@ PORT ds390_port = 1, /* transform >= to ! < */ 1, /* transform != to !(a == b) */ 0, /* leave == */ + TRUE, /* we support array initializers. */ PORT_MAGIC }; diff --git a/src/izt/i186.c b/src/izt/i186.c index 231a7aeb..7a4e39dd 100644 --- a/src/izt/i186.c +++ b/src/izt/i186.c @@ -205,5 +205,6 @@ PORT i186_port = { 1, /* transform >= to ! < */ 1, /* transform != to !(a == b) */ 0, /* leave == */ + FALSE, /* No array initializer support. */ PORT_MAGIC }; diff --git a/src/izt/tlcs900h.c b/src/izt/tlcs900h.c index bc9d8d50..e9f85208 100644 --- a/src/izt/tlcs900h.c +++ b/src/izt/tlcs900h.c @@ -204,5 +204,6 @@ PORT tlcs900h_port = 1, /* transform >= to ! < */ 1, /* transform != to !(a == b) */ 0, /* leave == */ + FALSE, /* No array initializer support. */ PORT_MAGIC }; diff --git a/src/mcs51/main.c b/src/mcs51/main.c index 68e32ea3..c06d08a9 100644 --- a/src/mcs51/main.c +++ b/src/mcs51/main.c @@ -211,5 +211,6 @@ PORT mcs51_port = 1, /* transform >= to ! < */ 1, /* transform != to !(a == b) */ 0, /* leave == */ + FALSE, /* No array initializer support. */ PORT_MAGIC }; diff --git a/src/pic/main.c b/src/pic/main.c index d411f500..f623d1ca 100644 --- a/src/pic/main.c +++ b/src/pic/main.c @@ -295,5 +295,6 @@ PORT pic_port = 1, /* transform >= to ! < */ 1, /* transform != to !(a == b) */ 0, /* leave == */ + FALSE, /* No array initializer support. */ PORT_MAGIC }; diff --git a/src/port.h b/src/port.h index d53dd0ce..89738032 100644 --- a/src/port.h +++ b/src/port.h @@ -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; diff --git a/src/z80/main.c b/src/z80/main.c index 0f6f498f..7784f38f 100644 --- a/src/z80/main.c +++ b/src/z80/main.c @@ -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 }; -- 2.47.2