1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
30 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
34 symbol *interrupts[256];
36 void printIval (symbol *, sym_link *, initList *, FILE *);
37 set *publics = NULL; /* public variables */
38 set *externs = NULL; /* Varibles that are declared as extern */
40 /* TODO: this should be configurable (DS803C90 uses more than 6) */
41 unsigned maxInterrupts = 6;
44 extern char *VersionString;
45 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
46 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
48 /*-----------------------------------------------------------------*/
49 /* closeTmpFiles - closes all tmp files created by the compiler */
50 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
51 /*-----------------------------------------------------------------*/
52 DEFSETFUNC (closeTmpFiles)
62 /*-----------------------------------------------------------------*/
63 /* rmTmpFiles - closes all tmp files created by the compiler */
64 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
65 /*-----------------------------------------------------------------*/
66 DEFSETFUNC (rmTmpFiles)
78 /*-----------------------------------------------------------------*/
79 /* copyFile - copies source file to destination file */
80 /*-----------------------------------------------------------------*/
82 copyFile (FILE * dest, FILE * src)
88 if ((ch = fgetc (src)) != EOF)
93 aopLiteralLong (value * val, int offset, int size)
103 // assuming we have been warned before
107 /* if it is a float then it gets tricky */
108 /* otherwise it is fairly simple */
109 if (!IS_FLOAT (val->type)) {
110 unsigned long v = (unsigned long) floatFromVal (val);
115 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
118 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
121 /* Hmm. Too big for now. */
124 rs = Safe_calloc (1, strlen (buffer) + 1);
125 return strcpy (rs, buffer);
128 /* PENDING: For now size must be 1 */
131 /* it is type float */
132 fl.f = (float) floatFromVal (val);
134 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
136 tsprintf (buffer, "!immedbyte", fl.c[offset]);
138 rs = Safe_calloc (1, strlen (buffer) + 1);
139 return strcpy (rs, buffer);
142 /*-----------------------------------------------------------------*/
143 /* aopLiteral - string from a literal value */
144 /*-----------------------------------------------------------------*/
146 aopLiteral (value * val, int offset)
148 return aopLiteralLong (val, offset, 1);
151 /*-----------------------------------------------------------------*/
152 /* emitRegularMap - emit code for maps with no special cases */
153 /*-----------------------------------------------------------------*/
155 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
165 /* PENDING: special case here - should remove */
166 if (!strcmp (map->sname, CODE_NAME))
167 tfprintf (map->oFile, "\t!areacode\n", map->sname);
168 else if (!strcmp (map->sname, DATA_NAME))
169 tfprintf (map->oFile, "\t!areadata\n", map->sname);
170 else if (!strcmp (map->sname, HOME_NAME))
171 tfprintf (map->oFile, "\t!areahome\n", map->sname);
173 tfprintf (map->oFile, "\t!area\n", map->sname);
176 for (sym = setFirstItem (map->syms); sym;
177 sym = setNextItem (map->syms))
181 /* if extern then add it into the extern list */
182 if (IS_EXTERN (sym->etype))
184 addSetHead (&externs, sym);
188 /* if allocation required check is needed
189 then check if the symbol really requires
190 allocation only for local variables */
192 if (arFlag && !IS_AGGREGATE (sym->type) &&
193 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
194 !sym->allocreq && sym->level)
197 /* for bitvar locals and parameters */
198 if (!arFlag && !sym->allocreq && sym->level
199 && !SPEC_ABSA (sym->etype)) {
203 /* if global variable & not static or extern
204 and addPublics allowed then add it to the public set */
205 if ((sym->level == 0 ||
206 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
208 !IS_STATIC (sym->etype) &&
209 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
211 addSetHead (&publics, sym);
214 /* if extern then do nothing or is a function
216 if (IS_FUNC (sym->type))
219 /* print extra debug info if required */
221 cdbSymbol (sym, cdbFile, FALSE, FALSE);
222 if (!sym->level) /* global */
223 if (IS_STATIC (sym->etype))
224 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
226 fprintf (map->oFile, "G$"); /* scope is global */
228 /* symbol is local */
229 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
230 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
233 /* if it has an initial value then do it only if
234 it is a global variable */
235 if (sym->ival && sym->level == 0) {
236 if (SPEC_OCLS(sym->etype)==xidata) {
237 // create a new "XINIT (CODE)" symbol, that will be emitted later
238 newSym=copySymbol (sym);
239 SPEC_OCLS(newSym->etype)=xinit;
240 sprintf (newSym->name, "__xinit_%s", sym->name);
241 sprintf (newSym->rname,"__xinit_%s", sym->rname);
242 SPEC_CONST(newSym->etype)=1;
243 SPEC_STAT(newSym->etype)=1;
244 resolveIvalSym(newSym->ival);
246 // add it to the "XINIT (CODE)" segment
247 addSet(&xinit->syms, newSym);
250 if (IS_AGGREGATE (sym->type)) {
251 ival = initAggregates (sym, sym->ival, NULL);
253 if (getNelements(sym->type, sym->ival)>1) {
254 werror (W_EXCESS_INITIALIZERS, "scalar",
255 sym->name, sym->lineDef);
257 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
258 decorateType (resolveSymbols (list2expr (sym->ival))));
260 codeOutFile = statsg->oFile;
263 // set ival's lineno to where the symbol was defined
264 setAstLineno (ival, lineno=sym->lineDef);
265 // check if this is not a constant expression
266 if (!constExprTree(ival)) {
267 werror (E_CONST_EXPECTED, "found expression");
268 // but try to do it anyway
271 eBBlockFromiCode (iCodeFromAst (ival));
278 /* if is has an absolute address then generate
279 an equate for this no need to allocate space */
280 if (SPEC_ABSA (sym->etype))
284 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
286 if (TARGET_IS_XA51) {
289 } else if (map==bit || map==sfrbit) {
293 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
295 SPEC_ADDR (sym->etype));
298 int size = getSize (sym->type);
300 werror(E_UNKNOWN_SIZE,sym->name);
304 fprintf (map->oFile, "==.\n");
306 if (IS_STATIC (sym->etype))
307 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
309 tfprintf (map->oFile, "!labeldef\n", sym->rname);
310 tfprintf (map->oFile, "\t!ds\n",
311 (unsigned int) size & 0xffff);
316 /*-----------------------------------------------------------------*/
317 /* initPointer - pointer initialization code massaging */
318 /*-----------------------------------------------------------------*/
320 initPointer (initList * ilist, sym_link *toType)
323 ast *expr = list2expr (ilist);
328 /* try it the oldway first */
329 if ((val = constExprValue (expr, FALSE)))
332 /* ( ptr + constant ) */
333 if (IS_AST_OP (expr) &&
334 (expr->opval.op == '+' || expr->opval.op == '-') &&
335 IS_AST_SYM_VALUE (expr->left) &&
336 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
337 compareType(toType, expr->left->ftype) &&
338 IS_AST_LIT_VALUE (expr->right)) {
339 return valForCastAggr (expr->left, expr->left->ftype,
345 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
346 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
347 if (compareType(toType, expr->left->ftype)!=1) {
348 werror (W_INIT_WRONG);
349 printFromToType(expr->left->ftype, toType);
355 /* no then we have to do these cludgy checks */
356 /* pointers can be initialized with address of
357 a variable or address of an array element */
358 if (IS_AST_OP (expr) && expr->opval.op == '&') {
359 /* address of symbol */
360 if (IS_AST_SYM_VALUE (expr->left)) {
361 val = copyValue (AST_VALUE (expr->left));
362 val->type = newLink ();
363 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
364 DCL_TYPE (val->type) = CPOINTER;
365 DCL_PTR_CONST (val->type) = port->mem.code_ro;
367 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
368 DCL_TYPE (val->type) = FPOINTER;
369 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
370 DCL_TYPE (val->type) = PPOINTER;
371 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
372 DCL_TYPE (val->type) = IPOINTER;
373 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
374 DCL_TYPE (val->type) = EEPPOINTER;
376 DCL_TYPE (val->type) = POINTER;
377 val->type->next = expr->left->ftype;
378 val->etype = getSpec (val->type);
382 /* if address of indexed array */
383 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
384 return valForArray (expr->left);
386 /* if address of structure element then
388 if (IS_AST_OP (expr->left) &&
389 expr->left->opval.op == '.') {
390 return valForStructElem (expr->left->left,
395 (&some_struct)->element */
396 if (IS_AST_OP (expr->left) &&
397 expr->left->opval.op == PTR_OP &&
398 IS_ADDRESS_OF_OP (expr->left->left)) {
399 return valForStructElem (expr->left->left->left,
403 /* case 3. (((char *) &a) +/- constant) */
404 if (IS_AST_OP (expr) &&
405 (expr->opval.op == '+' || expr->opval.op == '-') &&
406 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
407 IS_AST_OP (expr->left->right) &&
408 expr->left->right->opval.op == '&' &&
409 IS_AST_LIT_VALUE (expr->right)) {
411 return valForCastAggr (expr->left->right->left,
412 expr->left->left->opval.lnk,
413 expr->right, expr->opval.op);
416 /* case 4. (char *)(array type) */
417 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
418 IS_ARRAY(expr->right->ftype)) {
420 val = copyValue (AST_VALUE (expr->right));
421 val->type = newLink ();
422 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
423 DCL_TYPE (val->type) = CPOINTER;
424 DCL_PTR_CONST (val->type) = port->mem.code_ro;
426 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
427 DCL_TYPE (val->type) = FPOINTER;
428 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
429 DCL_TYPE (val->type) = PPOINTER;
430 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
431 DCL_TYPE (val->type) = IPOINTER;
432 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
433 DCL_TYPE (val->type) = EEPPOINTER;
435 DCL_TYPE (val->type) = POINTER;
436 val->type->next = expr->right->ftype->next;
437 val->etype = getSpec (val->type);
441 werror (E_INCOMPAT_PTYPES);
446 /*-----------------------------------------------------------------*/
447 /* printChar - formats and prints a characater string with DB */
448 /*-----------------------------------------------------------------*/
450 printChar (FILE * ofile, char *s, int plen)
453 int len = strlen (s);
458 while (len && pplen < plen)
461 while (i && *s && pplen < plen)
463 if (*s < ' ' || *s == '\"' || *s=='\\')
467 tfprintf (ofile, "\t!ascii\n", buf);
468 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
483 tfprintf (ofile, "\t!ascii\n", buf);
492 tfprintf (ofile, "\t!db !constbyte\n", 0);
495 /*-----------------------------------------------------------------*/
496 /* return the generic pointer high byte for a given pointer type. */
497 /*-----------------------------------------------------------------*/
499 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
507 werror (E_CANNOT_USE_GENERIC_POINTER,
508 iname ? iname : "<null>",
509 oname ? oname : "<null>");
516 return GPTYPE_XSTACK;
518 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
526 /*-----------------------------------------------------------------*/
527 /* printPointerType - generates ival for pointer type */
528 /*-----------------------------------------------------------------*/
530 _printPointerType (FILE * oFile, const char *name)
532 /* if (TARGET_IS_DS390) */
533 if (options.model == MODEL_FLAT24)
535 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
539 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
543 /*-----------------------------------------------------------------*/
544 /* printPointerType - generates ival for pointer type */
545 /*-----------------------------------------------------------------*/
547 printPointerType (FILE * oFile, const char *name)
549 _printPointerType (oFile, name);
550 fprintf (oFile, "\n");
553 /*-----------------------------------------------------------------*/
554 /* printGPointerType - generates ival for generic pointer type */
555 /*-----------------------------------------------------------------*/
557 printGPointerType (FILE * oFile, const char *iname, const char *oname,
558 const unsigned int type)
560 _printPointerType (oFile, iname);
561 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
564 /*-----------------------------------------------------------------*/
565 /* printIvalType - generates ival for int/char */
566 /*-----------------------------------------------------------------*/
568 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
572 /* if initList is deep */
573 if (ilist->type == INIT_DEEP)
574 ilist = ilist->init.deep;
576 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
577 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
580 if (!(val = list2val (ilist))) {
581 // assuming a warning has been thrown
585 if (val->type != type) {
586 val = valCastLiteral(type, floatFromVal(val));
589 switch (getSize (type)) {
592 tfprintf (oFile, "\t!db !constbyte\n", 0);
594 tfprintf (oFile, "\t!dbs\n",
595 aopLiteral (val, 0));
599 if (port->use_dw_for_init)
600 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
602 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
606 tfprintf (oFile, "\t!dw !constword\n", 0);
607 tfprintf (oFile, "\t!dw !constword\n", 0);
610 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
611 aopLiteral (val, 0), aopLiteral (val, 1),
612 aopLiteral (val, 2), aopLiteral (val, 3));
618 /*-----------------------------------------------------------------*/
619 /* printIvalBitFields - generate initializer for bitfields */
620 /*-----------------------------------------------------------------*/
621 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
625 initList *lilist = *ilist ;
626 unsigned long ival = 0;
632 val = list2val(lilist);
634 if (SPEC_BLEN(lsym->etype) > 8) {
635 size += ((SPEC_BLEN (lsym->etype) / 8) +
636 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
639 size = ((SPEC_BLEN (lsym->etype) / 8) +
640 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
642 i = (unsigned long)floatFromVal(val);
643 i <<= SPEC_BSTR (lsym->etype);
645 if (! ( lsym->next &&
646 (IS_BITFIELD(lsym->next->type)) &&
647 (SPEC_BSTR(lsym->next->etype)))) break;
649 lilist = lilist->next;
653 tfprintf (oFile, "\t!db !constbyte\n",ival);
657 tfprintf (oFile, "\t!dw !constword\n",ival);
660 tfprintf (oFile, "\t!db !constword,!constword\n",
661 (ival >> 8) & 0xffff, (ival & 0xffff));
668 /*-----------------------------------------------------------------*/
669 /* printIvalStruct - generates initial value for structures */
670 /*-----------------------------------------------------------------*/
672 printIvalStruct (symbol * sym, sym_link * type,
673 initList * ilist, FILE * oFile)
678 sflds = SPEC_STRUCT (type)->fields;
679 if (ilist->type != INIT_DEEP) {
680 werror (E_INIT_STRUCT, sym->name);
684 iloop = ilist->init.deep;
686 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
687 if (IS_BITFIELD(sflds->type)) {
688 printIvalBitFields(&sflds,&iloop,oFile);
690 printIval (sym, sflds->type, iloop, oFile);
694 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
699 /*-----------------------------------------------------------------*/
700 /* printIvalChar - generates initital value for character array */
701 /*-----------------------------------------------------------------*/
703 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
711 val = list2val (ilist);
712 /* if the value is a character string */
713 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
715 if (!DCL_ELEM (type))
716 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
718 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
720 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
722 tfprintf (oFile, "\t!db !constbyte\n", 0);
730 printChar (oFile, s, strlen (s) + 1);
734 /*-----------------------------------------------------------------*/
735 /* printIvalArray - generates code for array initialization */
736 /*-----------------------------------------------------------------*/
738 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
742 int lcnt = 0, size = 0;
745 /* take care of the special case */
746 /* array of characters can be init */
748 if (IS_CHAR (type->next)) {
749 if (!IS_LITERAL(list2val(ilist)->etype)) {
750 werror (E_CONST_EXPECTED);
753 if (printIvalChar (type,
754 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
755 oFile, SPEC_CVAL (sym->etype).v_char))
758 /* not the special case */
759 if (ilist->type != INIT_DEEP)
761 werror (E_INIT_STRUCT, sym->name);
765 iloop = ilist->init.deep;
766 lcnt = DCL_ELEM (type);
767 for (last_type = type->next; last_type && DCL_ELEM (last_type); last_type = last_type->next)
768 lcnt *= DCL_ELEM (last_type);
773 printIval (sym, type->next, iloop, oFile);
774 iloop = (iloop ? iloop->next : NULL);
777 /* if not array limits given & we */
778 /* are out of initialisers then */
779 if (!DCL_ELEM (type) && !iloop)
782 /* no of elements given and we */
783 /* have generated for all of them */
785 /* if initializers left */
787 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
793 /* if we have not been given a size */
794 if (!DCL_ELEM (type))
795 DCL_ELEM (type) = size;
800 /*-----------------------------------------------------------------*/
801 /* printIvalFuncPtr - generate initial value for function pointers */
802 /*-----------------------------------------------------------------*/
804 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
809 val = list2val (ilist);
812 // an error has been thrown allready
816 if (IS_LITERAL(val->etype)) {
817 if (compareType(type,val->etype)==0) {
818 werror (E_INCOMPAT_TYPES);
819 printFromToType (val->type, type);
821 printIvalCharPtr (NULL, type, val, oFile);
825 /* check the types */
826 if ((dLvl = compareType (val->type, type->next)) <= 0)
828 tfprintf (oFile, "\t!dw !constword\n", 0);
832 /* now generate the name */
835 if (port->use_dw_for_init)
837 tfprintf (oFile, "\t!dws\n", val->name);
841 printPointerType (oFile, val->name);
844 else if (port->use_dw_for_init)
846 tfprintf (oFile, "\t!dws\n", val->sym->rname);
850 printPointerType (oFile, val->sym->rname);
856 /*-----------------------------------------------------------------*/
857 /* printIvalCharPtr - generates initial values for character pointers */
858 /*-----------------------------------------------------------------*/
860 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
864 /* PENDING: this is _very_ mcs51 specific, including a magic
866 It's also endin specific.
868 size = getSize (type);
870 if (val->name && strlen (val->name))
872 if (size == 1) /* This appears to be Z80 specific?? */
875 "\t!dbs\n", val->name);
877 else if (size == FPTRSIZE)
879 if (port->use_dw_for_init)
881 tfprintf (oFile, "\t!dws\n", val->name);
885 printPointerType (oFile, val->name);
888 else if (size == GPTRSIZE)
891 if (IS_PTR (val->type)) {
892 type = DCL_TYPE (val->type);
894 type = PTR_TYPE (SPEC_OCLS (val->etype));
896 if (val->sym && val->sym->isstrlit) {
897 // this is a literal string
900 printGPointerType (oFile, val->name, sym->name, type);
904 fprintf (stderr, "*** internal error: unknown size in "
905 "printIvalCharPtr.\n");
910 // these are literals assigned to pointers
914 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
917 if (port->use_dw_for_init)
918 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
920 tfprintf (oFile, "\t.byte %s,%s\n",
921 aopLiteral (val, 0), aopLiteral (val, 1));
924 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
925 // non-zero mcs51 generic pointer
926 werror (E_LITERAL_GENERIC);
928 fprintf (oFile, "\t.byte %s,%s,%s\n",
931 aopLiteral (val, 2));
934 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
935 // non-zero ds390 generic pointer
936 werror (E_LITERAL_GENERIC);
938 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
942 aopLiteral (val, 3));
949 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
950 addSet (&statsg->syms, val->sym);
956 /*-----------------------------------------------------------------*/
957 /* printIvalPtr - generates initial value for pointers */
958 /*-----------------------------------------------------------------*/
960 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
966 if (ilist->type == INIT_DEEP)
967 ilist = ilist->init.deep;
969 /* function pointer */
970 if (IS_FUNC (type->next))
972 printIvalFuncPtr (type, ilist, oFile);
976 if (!(val = initPointer (ilist, type)))
979 /* if character pointer */
980 if (IS_CHAR (type->next))
981 if (printIvalCharPtr (sym, type, val, oFile))
985 if (compareType (type, val->type) == 0) {
986 werror (W_INIT_WRONG);
987 printFromToType (val->type, type);
990 /* if val is literal */
991 if (IS_LITERAL (val->etype))
993 switch (getSize (type))
996 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
999 if (port->use_dw_for_init)
1000 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1002 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1004 case 3: // how about '390??
1005 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1006 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1012 size = getSize (type);
1014 if (size == 1) /* Z80 specific?? */
1016 tfprintf (oFile, "\t!dbs\n", val->name);
1018 else if (size == FPTRSIZE)
1020 if (port->use_dw_for_init) {
1021 tfprintf (oFile, "\t!dws\n", val->name);
1023 printPointerType (oFile, val->name);
1026 else if (size == GPTRSIZE)
1028 printGPointerType (oFile, val->name, sym->name,
1029 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1030 PTR_TYPE (SPEC_OCLS (val->etype))));
1035 /*-----------------------------------------------------------------*/
1036 /* printIval - generates code for initial value */
1037 /*-----------------------------------------------------------------*/
1039 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1044 /* update line number for error msgs */
1045 lineno=sym->lineDef;
1047 /* if structure then */
1048 if (IS_STRUCT (type))
1050 printIvalStruct (sym, type, ilist, oFile);
1054 /* if this is a pointer */
1057 printIvalPtr (sym, type, ilist, oFile);
1061 /* if this is an array */
1062 if (IS_ARRAY (type))
1064 printIvalArray (sym, type, ilist, oFile);
1068 /* if type is SPECIFIER */
1071 printIvalType (sym, type, ilist, oFile);
1076 /*-----------------------------------------------------------------*/
1077 /* emitStaticSeg - emitcode for the static segment */
1078 /*-----------------------------------------------------------------*/
1080 emitStaticSeg (memmap * map, FILE * out)
1084 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1086 /* for all variables in this segment do */
1087 for (sym = setFirstItem (map->syms); sym;
1088 sym = setNextItem (map->syms))
1091 /* if it is "extern" then do nothing */
1092 if (IS_EXTERN (sym->etype))
1095 /* if it is not static add it to the public
1097 if (!IS_STATIC (sym->etype))
1099 addSetHead (&publics, sym);
1102 /* print extra debug info if required */
1103 if (options.debug) {
1104 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1107 if (IS_STATIC (sym->etype))
1108 fprintf (out, "F%s$", moduleName); /* scope is file */
1110 fprintf (out, "G$"); /* scope is global */
1113 /* symbol is local */
1114 fprintf (out, "L%s$",
1115 (sym->localof ? sym->localof->name : "-null-"));
1116 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1119 /* if it has an absolute address */
1120 if (SPEC_ABSA (sym->etype))
1123 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1125 fprintf (out, "%s\t=\t0x%04x\n",
1127 SPEC_ADDR (sym->etype));
1132 fprintf (out, " == .\n");
1134 /* if it has an initial value */
1137 fprintf (out, "%s:\n", sym->rname);
1139 resolveIvalSym (sym->ival);
1140 printIval (sym, sym->type, sym->ival, out);
1144 /* allocate space */
1145 int size = getSize (sym->type);
1148 werror(E_UNKNOWN_SIZE,sym->name);
1150 fprintf (out, "%s:\n", sym->rname);
1151 /* special case for character strings */
1152 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1153 SPEC_CVAL (sym->etype).v_char)
1155 SPEC_CVAL (sym->etype).v_char,
1156 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1158 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1164 /*-----------------------------------------------------------------*/
1165 /* emitMaps - emits the code for the data portion the code */
1166 /*-----------------------------------------------------------------*/
1171 /* no special considerations for the following
1172 data, idata & bit & xdata */
1173 emitRegularMap (data, TRUE, TRUE);
1174 emitRegularMap (idata, TRUE, TRUE);
1175 emitRegularMap (bit, TRUE, FALSE);
1176 emitRegularMap (xdata, TRUE, TRUE);
1177 if (port->genXINIT) {
1178 emitRegularMap (xidata, TRUE, TRUE);
1180 emitRegularMap (sfr, FALSE, FALSE);
1181 emitRegularMap (sfrbit, FALSE, FALSE);
1182 emitRegularMap (home, TRUE, FALSE);
1183 emitRegularMap (code, TRUE, FALSE);
1185 emitStaticSeg (statsg, code->oFile);
1186 if (port->genXINIT) {
1187 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1188 emitStaticSeg (xinit, code->oFile);
1193 /*-----------------------------------------------------------------*/
1194 /* flushStatics - flush all currently defined statics out to file */
1195 /* and delete. Temporary function */
1196 /*-----------------------------------------------------------------*/
1200 emitStaticSeg (statsg, codeOutFile);
1201 statsg->syms = NULL;
1204 /*-----------------------------------------------------------------*/
1205 /* createInterruptVect - creates the interrupt vector */
1206 /*-----------------------------------------------------------------*/
1208 createInterruptVect (FILE * vFile)
1211 mainf = newSymbol ("main", 0);
1214 /* only if the main function exists */
1215 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1217 if (!options.cc_only && !noAssemble)
1222 /* if the main is only a prototype ie. no body then do nothing */
1223 if (!IFFUNC_HASBODY(mainf->type))
1225 /* if ! compile only then main function should be present */
1226 if (!options.cc_only && !noAssemble)
1231 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1232 fprintf (vFile, "__interrupt_vect:\n");
1235 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1237 /* "generic" interrupt table header (if port doesn't specify one).
1238 * Look suspiciously like 8051 code to me...
1241 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1244 /* now for the other interrupts */
1245 for (; i < maxInterrupts; i++)
1248 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1250 fprintf (vFile, "\treti\n\t.ds\t7\n");
1257 ";--------------------------------------------------------\n"
1258 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1262 ";--------------------------------------------------------\n"};
1265 /*-----------------------------------------------------------------*/
1266 /* initialComments - puts in some initial comments */
1267 /*-----------------------------------------------------------------*/
1269 initialComments (FILE * afile)
1273 fprintf (afile, "%s", iComments1);
1274 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1275 fprintf (afile, "%s", iComments2);
1278 /*-----------------------------------------------------------------*/
1279 /* printPublics - generates .global for publics */
1280 /*-----------------------------------------------------------------*/
1282 printPublics (FILE * afile)
1286 fprintf (afile, "%s", iComments2);
1287 fprintf (afile, "; Public variables in this module\n");
1288 fprintf (afile, "%s", iComments2);
1290 for (sym = setFirstItem (publics); sym;
1291 sym = setNextItem (publics))
1292 tfprintf (afile, "\t!global\n", sym->rname);
1295 /*-----------------------------------------------------------------*/
1296 /* printExterns - generates .global for externs */
1297 /*-----------------------------------------------------------------*/
1299 printExterns (FILE * afile)
1303 fprintf (afile, "%s", iComments2);
1304 fprintf (afile, "; Externals used\n");
1305 fprintf (afile, "%s", iComments2);
1307 for (sym = setFirstItem (externs); sym;
1308 sym = setNextItem (externs))
1309 tfprintf (afile, "\t!extern\n", sym->rname);
1312 /*-----------------------------------------------------------------*/
1313 /* emitOverlay - will emit code for the overlay stuff */
1314 /*-----------------------------------------------------------------*/
1316 emitOverlay (FILE * afile)
1320 if (!elementsInSet (ovrSetSets))
1321 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1323 /* for each of the sets in the overlay segment do */
1324 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1325 ovrset = setNextItem (ovrSetSets))
1330 if (elementsInSet (ovrset))
1332 /* output the area informtion */
1333 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1336 for (sym = setFirstItem (ovrset); sym;
1337 sym = setNextItem (ovrset))
1339 /* if extern then it is in the publics table: do nothing */
1340 if (IS_EXTERN (sym->etype))
1343 /* if allocation required check is needed
1344 then check if the symbol really requires
1345 allocation only for local variables */
1346 if (!IS_AGGREGATE (sym->type) &&
1347 !(sym->_isparm && !IS_REGPARM (sym->etype))
1348 && !sym->allocreq && sym->level)
1351 /* if global variable & not static or extern
1352 and addPublics allowed then add it to the public set */
1353 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1354 && !IS_STATIC (sym->etype))
1356 addSetHead (&publics, sym);
1359 /* if extern then do nothing or is a function
1361 if (IS_FUNC (sym->type))
1364 /* print extra debug info if required */
1367 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1371 if (IS_STATIC (sym->etype))
1372 fprintf (afile, "F%s$", moduleName); /* scope is file */
1374 fprintf (afile, "G$"); /* scope is global */
1377 /* symbol is local */
1378 fprintf (afile, "L%s$",
1379 (sym->localof ? sym->localof->name : "-null-"));
1380 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1383 /* if is has an absolute address then generate
1384 an equate for this no need to allocate space */
1385 if (SPEC_ABSA (sym->etype))
1389 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1391 fprintf (afile, "%s\t=\t0x%04x\n",
1393 SPEC_ADDR (sym->etype));
1396 int size = getSize(sym->type);
1399 werror(E_UNKNOWN_SIZE,sym->name);
1402 fprintf (afile, "==.\n");
1404 /* allocate space */
1405 tfprintf (afile, "!labeldef\n", sym->rname);
1406 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1413 /*-----------------------------------------------------------------*/
1414 /* glue - the final glue that hold the whole thing together */
1415 /*-----------------------------------------------------------------*/
1421 FILE *ovrFile = tempfile ();
1423 addSetHead (&tmpfileSet, ovrFile);
1424 /* print the global struct definitions */
1426 cdbStructBlock (0, cdbFile);
1428 vFile = tempfile ();
1429 /* PENDING: this isnt the best place but it will do */
1430 if (port->general.glue_up_main)
1432 /* create the interrupt vector table */
1433 createInterruptVect (vFile);
1436 addSetHead (&tmpfileSet, vFile);
1438 /* emit code for the all the variables declared */
1440 /* do the overlay segments */
1441 emitOverlay (ovrFile);
1443 /* now put it all together into the assembler file */
1444 /* create the assembler file name */
1446 if (!options.c1mode)
1448 sprintf (scratchFileName, srcFileName);
1449 strcat (scratchFileName, port->assembler.file_ext);
1453 strcpy (scratchFileName, options.out_name);
1456 if (!(asmFile = fopen (scratchFileName, "w")))
1458 werror (E_FILE_OPEN_ERR, scratchFileName);
1462 /* initial comments */
1463 initialComments (asmFile);
1465 /* print module name */
1466 tfprintf (asmFile, "\t!module\n", moduleName);
1467 tfprintf (asmFile, "\t!fileprelude\n");
1469 /* Let the port generate any global directives, etc. */
1470 if (port->genAssemblerPreamble)
1472 port->genAssemblerPreamble (asmFile);
1475 /* print the global variables in this module */
1476 printPublics (asmFile);
1477 if (port->assembler.externGlobal)
1478 printExterns (asmFile);
1480 /* copy the sfr segment */
1481 fprintf (asmFile, "%s", iComments2);
1482 fprintf (asmFile, "; special function registers\n");
1483 fprintf (asmFile, "%s", iComments2);
1484 copyFile (asmFile, sfr->oFile);
1486 /* copy the sbit segment */
1487 fprintf (asmFile, "%s", iComments2);
1488 fprintf (asmFile, "; special function bits \n");
1489 fprintf (asmFile, "%s", iComments2);
1490 copyFile (asmFile, sfrbit->oFile);
1492 /* copy the data segment */
1493 fprintf (asmFile, "%s", iComments2);
1494 fprintf (asmFile, "; internal ram data\n");
1495 fprintf (asmFile, "%s", iComments2);
1496 copyFile (asmFile, data->oFile);
1499 /* create the overlay segments */
1501 fprintf (asmFile, "%s", iComments2);
1502 fprintf (asmFile, "; overlayable items in internal ram \n");
1503 fprintf (asmFile, "%s", iComments2);
1504 copyFile (asmFile, ovrFile);
1507 /* create the stack segment MOF */
1508 if (mainf && IFFUNC_HASBODY(mainf->type))
1510 fprintf (asmFile, "%s", iComments2);
1511 fprintf (asmFile, "; Stack segment in internal ram \n");
1512 fprintf (asmFile, "%s", iComments2);
1513 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1514 "__start__stack:\n\t.ds\t1\n\n");
1517 /* create the idata segment */
1519 fprintf (asmFile, "%s", iComments2);
1520 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1521 fprintf (asmFile, "%s", iComments2);
1522 copyFile (asmFile, idata->oFile);
1525 /* copy the bit segment */
1526 fprintf (asmFile, "%s", iComments2);
1527 fprintf (asmFile, "; bit data\n");
1528 fprintf (asmFile, "%s", iComments2);
1529 copyFile (asmFile, bit->oFile);
1531 /* if external stack then reserve space of it */
1532 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1534 fprintf (asmFile, "%s", iComments2);
1535 fprintf (asmFile, "; external stack \n");
1536 fprintf (asmFile, "%s", iComments2);
1537 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1538 fprintf (asmFile, "\t.ds 256\n");
1542 /* copy xtern ram data */
1543 fprintf (asmFile, "%s", iComments2);
1544 fprintf (asmFile, "; external ram data\n");
1545 fprintf (asmFile, "%s", iComments2);
1546 copyFile (asmFile, xdata->oFile);
1548 /* copy xternal initialized ram data */
1549 fprintf (asmFile, "%s", iComments2);
1550 fprintf (asmFile, "; external initialized ram data\n");
1551 fprintf (asmFile, "%s", iComments2);
1552 copyFile (asmFile, xidata->oFile);
1554 /* copy the interrupt vector table */
1555 if (mainf && IFFUNC_HASBODY(mainf->type))
1557 fprintf (asmFile, "%s", iComments2);
1558 fprintf (asmFile, "; interrupt vector \n");
1559 fprintf (asmFile, "%s", iComments2);
1560 copyFile (asmFile, vFile);
1563 /* copy global & static initialisations */
1564 fprintf (asmFile, "%s", iComments2);
1565 fprintf (asmFile, "; global & static initialisations\n");
1566 fprintf (asmFile, "%s", iComments2);
1568 /* Everywhere we generate a reference to the static_name area,
1569 * (which is currently only here), we immediately follow it with a
1570 * definition of the post_static_name area. This guarantees that
1571 * the post_static_name area will immediately follow the static_name
1574 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1575 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1576 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1578 if (mainf && IFFUNC_HASBODY(mainf->type))
1580 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1581 /* if external stack is specified then the
1582 higher order byte of the xdatalocation is
1583 going into P2 and the lower order going into
1585 if (options.useXstack)
1587 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1588 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1589 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1590 (unsigned int) options.xdata_loc & 0xff);
1593 /* initialise the stack pointer */
1594 /* if the user specified a value then use it */
1595 if (options.stack_loc)
1596 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff);
1598 /* no: we have to compute it */
1599 if (!options.stackOnData && maxRegBank <= 3)
1600 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1602 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1604 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1605 fprintf (asmFile, "\tmov\ta,dpl\n");
1606 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1607 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1608 fprintf (asmFile, "__sdcc_init_data:\n");
1610 // if the port can copy the XINIT segment to XISEG
1611 if (port->genXINIT) {
1612 port->genXINIT(asmFile);
1616 copyFile (asmFile, statsg->oFile);
1618 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1620 /* This code is generated in the post-static area.
1621 * This area is guaranteed to follow the static area
1622 * by the ugly shucking and jiving about 20 lines ago.
1624 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1625 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1631 "%s", iComments2, iComments2);
1632 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1633 copyFile (asmFile, home->oFile);
1635 /* copy over code */
1636 fprintf (asmFile, "%s", iComments2);
1637 fprintf (asmFile, "; code\n");
1638 fprintf (asmFile, "%s", iComments2);
1639 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1640 if (mainf && IFFUNC_HASBODY(mainf->type))
1643 /* entry point @ start of CSEG */
1644 fprintf (asmFile, "__sdcc_program_startup:\n");
1646 /* put in the call to main */
1647 fprintf (asmFile, "\tlcall\t_main\n");
1648 if (options.mainreturn)
1651 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1652 fprintf (asmFile, "\tret\n");
1658 fprintf (asmFile, ";\treturn from main will lock up\n");
1659 fprintf (asmFile, "\tsjmp .\n");
1662 copyFile (asmFile, code->oFile);
1664 if (port->genAssemblerEnd) {
1665 port->genAssemblerEnd(asmFile);
1668 applyToSet (tmpfileSet, closeTmpFiles);
1669 applyToSet (tmpfileNameSet, rmTmpFiles);
1672 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1676 applyToSet (tmpfileSet, closeTmpFiles);
1677 applyToSet (tmpfileNameSet, rmTmpFiles);
1681 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1682 in cygwin wrt c:\tmp.
1683 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1688 const char *tmpdir = NULL;
1690 tmpdir = getenv ("TMP");
1691 else if (getenv ("TEMP"))
1692 tmpdir = getenv ("TEMP");
1693 else if (getenv ("TMPDIR"))
1694 tmpdir = getenv ("TMPDIR");
1697 char *name = tempnam (tmpdir, "sdcc");
1703 return tmpnam (NULL);
1706 /** Creates a temporary file a'la tmpfile which avoids the bugs
1707 in cygwin wrt c:\tmp.
1708 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1713 const char *tmpdir = NULL;
1715 tmpdir = getenv ("TMP");
1716 else if (getenv ("TEMP"))
1717 tmpdir = getenv ("TEMP");
1718 else if (getenv ("TMPDIR"))
1719 tmpdir = getenv ("TMPDIR");
1722 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1725 FILE *fp = fopen (name, "w+b");
1728 addSetHead (&tmpfileNameSet, name);