%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
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));
ast *rast = NULL;
initList *iloop;
int lcnt = 0, size = 0;
+ literalList *literalL;
/* take care of the special case */
/* array of characters can be init */
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));
}
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;
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 */
{IFX, "if", picIfx, NULL},
{INLINEASM, "", picInline, NULL},
{RECEIVE, "recv", picReceive, NULL},
- {SEND, "send", picGenericOne, NULL}
+ {SEND, "send", picGenericOne, NULL},
+ {ARRAYINIT, "arrayInit", picGenericOne, NULL},
};
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));
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 */
case INLINEASM:
geniCodeInline (tree);
return NULL;
+
+ case ARRAYINIT:
+ geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
+ return NULL;
}
return NULL;
#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
{
argLabel;
char *inlineAsm; /* pointer to inline assembler code */
+ literalList *arrayInitList; /* point to array initializer list. */
int lineno; /* file & lineno for debug information */
char *filename;
x->op == IPOP || \
x->op == JUMPTABLE || \
x->op == RECEIVE || \
+ x->op == ARRAYINIT || \
SKIP_IC1(x)|| \
x->op == SEND )
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))
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 */
/*------------------------------------------------------------------*/
}
value;
+typedef struct literalList
+{
+ double literalValue;
+ unsigned count;
+ struct literalList *next;
+} literalList;
+
+
enum
{
INIT_NODE,
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
0, /* leave ge */
0, /* leave != */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
}
+/*-----------------------------------------------------------------*/
+/* 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 */
/*-----------------------------------------------------------------*/
{
/* 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. */
addSet (&_G.sendSet, ic);
break;
+ case ARRAYINIT:
+ genArrayInit(ic);
+ break;
+
default:
ic = ic;
}
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ TRUE, /* we support array initializers. */
PORT_MAGIC
};
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
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;
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};
1, /* transform >= to ! < */
1, /* transform != to !(a == b) */
0, /* leave == */
+ FALSE, /* No array initializer support. */
PORT_MAGIC
};