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)))
333 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
334 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
335 if (compareType(toType, expr->left->ftype)!=1) {
336 werror (W_INIT_WRONG);
337 printFromToType(expr->left->ftype, toType);
343 /* no then we have to do these cludgy checks */
344 /* pointers can be initialized with address of
345 a variable or address of an array element */
346 if (IS_AST_OP (expr) && expr->opval.op == '&') {
347 /* address of symbol */
348 if (IS_AST_SYM_VALUE (expr->left)) {
349 val = copyValue (AST_VALUE (expr->left));
350 val->type = newLink ();
351 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
352 DCL_TYPE (val->type) = CPOINTER;
353 DCL_PTR_CONST (val->type) = port->mem.code_ro;
355 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
356 DCL_TYPE (val->type) = FPOINTER;
357 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
358 DCL_TYPE (val->type) = PPOINTER;
359 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
360 DCL_TYPE (val->type) = IPOINTER;
361 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
362 DCL_TYPE (val->type) = EEPPOINTER;
364 DCL_TYPE (val->type) = POINTER;
365 val->type->next = expr->left->ftype;
366 val->etype = getSpec (val->type);
370 /* if address of indexed array */
371 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
372 return valForArray (expr->left);
374 /* if address of structure element then
376 if (IS_AST_OP (expr->left) &&
377 expr->left->opval.op == '.') {
378 return valForStructElem (expr->left->left,
383 (&some_struct)->element */
384 if (IS_AST_OP (expr->left) &&
385 expr->left->opval.op == PTR_OP &&
386 IS_ADDRESS_OF_OP (expr->left->left)) {
387 return valForStructElem (expr->left->left->left,
391 /* case 3. (((char *) &a) +/- constant) */
392 if (IS_AST_OP (expr) &&
393 (expr->opval.op == '+' || expr->opval.op == '-') &&
394 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
395 IS_AST_OP (expr->left->right) &&
396 expr->left->right->opval.op == '&' &&
397 IS_AST_LIT_VALUE (expr->right)) {
399 return valForCastAggr (expr->left->right->left,
400 expr->left->left->opval.lnk,
401 expr->right, expr->opval.op);
405 /* case 4. (char *)(array type) */
406 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
407 IS_ARRAY(expr->right->ftype)) {
409 val = copyValue (AST_VALUE (expr->right));
410 val->type = newLink ();
411 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
412 DCL_TYPE (val->type) = CPOINTER;
413 DCL_PTR_CONST (val->type) = port->mem.code_ro;
415 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
416 DCL_TYPE (val->type) = FPOINTER;
417 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
418 DCL_TYPE (val->type) = PPOINTER;
419 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
420 DCL_TYPE (val->type) = IPOINTER;
421 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
422 DCL_TYPE (val->type) = EEPPOINTER;
424 DCL_TYPE (val->type) = POINTER;
425 val->type->next = expr->right->ftype->next;
426 val->etype = getSpec (val->type);
430 werror (W_INIT_WRONG);
435 /*-----------------------------------------------------------------*/
436 /* printChar - formats and prints a characater string with DB */
437 /*-----------------------------------------------------------------*/
439 printChar (FILE * ofile, char *s, int plen)
442 int len = strlen (s);
447 while (len && pplen < plen)
450 while (i && *s && pplen < plen)
452 if (*s < ' ' || *s == '\"' || *s=='\\')
456 tfprintf (ofile, "\t!ascii\n", buf);
457 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
472 tfprintf (ofile, "\t!ascii\n", buf);
481 tfprintf (ofile, "\t!db !constbyte\n", 0);
484 /*-----------------------------------------------------------------*/
485 /* return the generic pointer high byte for a given pointer type. */
486 /*-----------------------------------------------------------------*/
488 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
496 /* hack - if we get a generic pointer, we just assume
497 * it's an FPOINTER (i.e. in XDATA space).
499 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
509 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
517 /*-----------------------------------------------------------------*/
518 /* printPointerType - generates ival for pointer type */
519 /*-----------------------------------------------------------------*/
521 _printPointerType (FILE * oFile, const char *name)
523 /* if (TARGET_IS_DS390) */
524 if (options.model == MODEL_FLAT24)
526 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
530 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
534 /*-----------------------------------------------------------------*/
535 /* printPointerType - generates ival for pointer type */
536 /*-----------------------------------------------------------------*/
538 printPointerType (FILE * oFile, const char *name)
540 _printPointerType (oFile, name);
541 fprintf (oFile, "\n");
544 /*-----------------------------------------------------------------*/
545 /* printGPointerType - generates ival for generic pointer type */
546 /*-----------------------------------------------------------------*/
548 printGPointerType (FILE * oFile, const char *iname, const char *oname,
549 const unsigned int type)
551 _printPointerType (oFile, iname);
552 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
555 /*-----------------------------------------------------------------*/
556 /* printIvalType - generates ival for int/char */
557 /*-----------------------------------------------------------------*/
559 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
563 /* if initList is deep */
564 if (ilist->type == INIT_DEEP)
565 ilist = ilist->init.deep;
567 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
568 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
571 if (!(val = list2val (ilist))) {
572 // assuming a warning has been thrown
576 if (val->type != type) {
577 val = valCastLiteral(type, floatFromVal(val));
580 switch (getSize (type)) {
583 tfprintf (oFile, "\t!db !constbyte\n", 0);
585 tfprintf (oFile, "\t!dbs\n",
586 aopLiteral (val, 0));
590 if (port->use_dw_for_init)
591 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
593 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
597 tfprintf (oFile, "\t!dw !constword\n", 0);
598 tfprintf (oFile, "\t!dw !constword\n", 0);
601 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
602 aopLiteral (val, 0), aopLiteral (val, 1),
603 aopLiteral (val, 2), aopLiteral (val, 3));
609 /*-----------------------------------------------------------------*/
610 /* printIvalBitFields - generate initializer for bitfields */
611 /*-----------------------------------------------------------------*/
612 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
616 initList *lilist = *ilist ;
617 unsigned long ival = 0;
623 val = list2val(lilist);
625 if (SPEC_BLEN(lsym->etype) > 8) {
626 size += ((SPEC_BLEN (lsym->etype) / 8) +
627 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
630 size = ((SPEC_BLEN (lsym->etype) / 8) +
631 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
633 i = (unsigned long)floatFromVal(val);
634 i <<= SPEC_BSTR (lsym->etype);
636 if (! ( lsym->next &&
637 (IS_BITFIELD(lsym->next->type)) &&
638 (SPEC_BSTR(lsym->next->etype)))) break;
640 lilist = lilist->next;
644 tfprintf (oFile, "\t!db !constbyte\n",ival);
648 tfprintf (oFile, "\t!dw !constword\n",ival);
651 tfprintf (oFile, "\t!db !constword,!constword\n",
652 (ival >> 8) & 0xffff, (ival & 0xffff));
659 /*-----------------------------------------------------------------*/
660 /* printIvalStruct - generates initial value for structures */
661 /*-----------------------------------------------------------------*/
663 printIvalStruct (symbol * sym, sym_link * type,
664 initList * ilist, FILE * oFile)
669 sflds = SPEC_STRUCT (type)->fields;
670 if (ilist->type != INIT_DEEP) {
671 werror (E_INIT_STRUCT, sym->name);
675 iloop = ilist->init.deep;
677 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
678 if (IS_BITFIELD(sflds->type)) {
679 printIvalBitFields(&sflds,&iloop,oFile);
681 printIval (sym, sflds->type, iloop, oFile);
685 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
690 /*-----------------------------------------------------------------*/
691 /* printIvalChar - generates initital value for character array */
692 /*-----------------------------------------------------------------*/
694 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
702 val = list2val (ilist);
703 /* if the value is a character string */
704 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
706 if (!DCL_ELEM (type))
707 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
709 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
711 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
713 tfprintf (oFile, "\t!db !constbyte\n", 0);
721 printChar (oFile, s, strlen (s) + 1);
725 /*-----------------------------------------------------------------*/
726 /* printIvalArray - generates code for array initialization */
727 /*-----------------------------------------------------------------*/
729 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
733 int lcnt = 0, size = 0;
735 /* take care of the special case */
736 /* array of characters can be init */
738 if (IS_CHAR (type->next)) {
739 if (!IS_LITERAL(list2val(ilist)->etype)) {
740 werror (W_INIT_WRONG);
743 if (printIvalChar (type,
744 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
745 oFile, SPEC_CVAL (sym->etype).v_char))
748 /* not the special case */
749 if (ilist->type != INIT_DEEP)
751 werror (E_INIT_STRUCT, sym->name);
755 iloop = ilist->init.deep;
756 lcnt = DCL_ELEM (type);
761 printIval (sym, type->next, iloop, oFile);
762 iloop = (iloop ? iloop->next : NULL);
765 /* if not array limits given & we */
766 /* are out of initialisers then */
767 if (!DCL_ELEM (type) && !iloop)
770 /* no of elements given and we */
771 /* have generated for all of them */
773 /* if initializers left */
775 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
781 /* if we have not been given a size */
782 if (!DCL_ELEM (type))
783 DCL_ELEM (type) = size;
788 /*-----------------------------------------------------------------*/
789 /* printIvalFuncPtr - generate initial value for function pointers */
790 /*-----------------------------------------------------------------*/
792 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
797 val = list2val (ilist);
800 // an error has been thrown allready
804 if (IS_LITERAL(val->etype)) {
805 if (compareType(type,val->etype)==0) {
806 werror (E_INCOMPAT_TYPES);
807 printFromToType (val->type, type);
809 printIvalCharPtr (NULL, type, val, oFile);
813 /* check the types */
814 if ((dLvl = compareType (val->type, type->next)) <= 0)
816 tfprintf (oFile, "\t!dw !constword\n", 0);
820 /* now generate the name */
823 if (port->use_dw_for_init)
825 tfprintf (oFile, "\t!dws\n", val->name);
829 printPointerType (oFile, val->name);
832 else if (port->use_dw_for_init)
834 tfprintf (oFile, "\t!dws\n", val->sym->rname);
838 printPointerType (oFile, val->sym->rname);
844 /*-----------------------------------------------------------------*/
845 /* printIvalCharPtr - generates initial values for character pointers */
846 /*-----------------------------------------------------------------*/
848 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
852 /* PENDING: this is _very_ mcs51 specific, including a magic
854 It's also endin specific.
856 size = getSize (type);
858 if (val->name && strlen (val->name))
860 if (size == 1) /* This appears to be Z80 specific?? */
863 "\t!dbs\n", val->name);
865 else if (size == FPTRSIZE)
867 if (port->use_dw_for_init)
869 tfprintf (oFile, "\t!dws\n", val->name);
873 printPointerType (oFile, val->name);
876 else if (size == GPTRSIZE)
879 if (IS_PTR (val->type)) {
880 type = DCL_TYPE (val->type);
882 type = PTR_TYPE (SPEC_OCLS (val->etype));
884 if (val->sym && val->sym->isstrlit) {
885 // this is a literal string
888 printGPointerType (oFile, val->name, sym->name, type);
892 fprintf (stderr, "*** internal error: unknown size in "
893 "printIvalCharPtr.\n");
898 // these are literals assigned to pointers
902 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
905 if (port->use_dw_for_init)
906 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
908 tfprintf (oFile, "\t.byte %s,%s\n",
909 aopLiteral (val, 0), aopLiteral (val, 1));
912 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
913 // non-zero mcs51 generic pointer
914 werror (E_LITERAL_GENERIC);
916 fprintf (oFile, "\t.byte %s,%s,%s\n",
919 aopLiteral (val, 2));
922 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
923 // non-zero ds390 generic pointer
924 werror (E_LITERAL_GENERIC);
926 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
930 aopLiteral (val, 3));
937 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
938 addSet (&statsg->syms, val->sym);
944 /*-----------------------------------------------------------------*/
945 /* printIvalPtr - generates initial value for pointers */
946 /*-----------------------------------------------------------------*/
948 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
954 if (ilist->type == INIT_DEEP)
955 ilist = ilist->init.deep;
957 /* function pointer */
958 if (IS_FUNC (type->next))
960 printIvalFuncPtr (type, ilist, oFile);
964 if (!(val = initPointer (ilist, type)))
967 /* if character pointer */
968 if (IS_CHAR (type->next))
969 if (printIvalCharPtr (sym, type, val, oFile))
973 if (compareType (type, val->type) == 0)
974 werror (W_INIT_WRONG);
976 /* if val is literal */
977 if (IS_LITERAL (val->etype))
979 switch (getSize (type))
982 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
985 if (port->use_dw_for_init)
986 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
988 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
991 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
992 aopLiteral (val, 0), aopLiteral (val, 1));
998 size = getSize (type);
1000 if (size == 1) /* Z80 specific?? */
1002 tfprintf (oFile, "\t!dbs\n", val->name);
1004 else if (size == FPTRSIZE)
1006 if (port->use_dw_for_init) {
1007 tfprintf (oFile, "\t!dws\n", val->name);
1009 printPointerType (oFile, val->name);
1012 else if (size == GPTRSIZE)
1014 printGPointerType (oFile, val->name, sym->name,
1015 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1016 PTR_TYPE (SPEC_OCLS (val->etype))));
1021 /*-----------------------------------------------------------------*/
1022 /* printIval - generates code for initial value */
1023 /*-----------------------------------------------------------------*/
1025 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1030 /* if structure then */
1031 if (IS_STRUCT (type))
1033 printIvalStruct (sym, type, ilist, oFile);
1037 /* if this is a pointer */
1040 printIvalPtr (sym, type, ilist, oFile);
1044 /* if this is an array */
1045 if (IS_ARRAY (type))
1047 printIvalArray (sym, type, ilist, oFile);
1051 /* if type is SPECIFIER */
1054 printIvalType (sym, type, ilist, oFile);
1059 /*-----------------------------------------------------------------*/
1060 /* emitStaticSeg - emitcode for the static segment */
1061 /*-----------------------------------------------------------------*/
1063 emitStaticSeg (memmap * map, FILE * out)
1067 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1069 /* for all variables in this segment do */
1070 for (sym = setFirstItem (map->syms); sym;
1071 sym = setNextItem (map->syms))
1074 /* if it is "extern" then do nothing */
1075 if (IS_EXTERN (sym->etype))
1078 /* if it is not static add it to the public
1080 if (!IS_STATIC (sym->etype))
1082 addSetHead (&publics, sym);
1085 /* print extra debug info if required */
1086 if (options.debug) {
1087 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1090 if (IS_STATIC (sym->etype))
1091 fprintf (out, "F%s$", moduleName); /* scope is file */
1093 fprintf (out, "G$"); /* scope is global */
1096 /* symbol is local */
1097 fprintf (out, "L%s$",
1098 (sym->localof ? sym->localof->name : "-null-"));
1099 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1102 /* if it has an absolute address */
1103 if (SPEC_ABSA (sym->etype))
1106 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1108 fprintf (out, "%s\t=\t0x%04x\n",
1110 SPEC_ADDR (sym->etype));
1115 fprintf (out, " == .\n");
1117 /* if it has an initial value */
1120 fprintf (out, "%s:\n", sym->rname);
1122 resolveIvalSym (sym->ival);
1123 printIval (sym, sym->type, sym->ival, out);
1127 /* allocate space */
1128 int size = getSize (sym->type);
1131 werror(E_UNKNOWN_SIZE,sym->name);
1133 fprintf (out, "%s:\n", sym->rname);
1134 /* special case for character strings */
1135 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1136 SPEC_CVAL (sym->etype).v_char)
1138 SPEC_CVAL (sym->etype).v_char,
1139 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1141 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1147 /*-----------------------------------------------------------------*/
1148 /* emitMaps - emits the code for the data portion the code */
1149 /*-----------------------------------------------------------------*/
1154 /* no special considerations for the following
1155 data, idata & bit & xdata */
1156 emitRegularMap (data, TRUE, TRUE);
1157 emitRegularMap (idata, TRUE, TRUE);
1158 emitRegularMap (bit, TRUE, FALSE);
1159 emitRegularMap (xdata, TRUE, TRUE);
1160 if (port->genXINIT) {
1161 emitRegularMap (xidata, TRUE, TRUE);
1163 emitRegularMap (sfr, FALSE, FALSE);
1164 emitRegularMap (sfrbit, FALSE, FALSE);
1165 emitRegularMap (home, TRUE, FALSE);
1166 emitRegularMap (code, TRUE, FALSE);
1168 emitStaticSeg (statsg, code->oFile);
1169 if (port->genXINIT) {
1170 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1171 emitStaticSeg (xinit, code->oFile);
1176 /*-----------------------------------------------------------------*/
1177 /* flushStatics - flush all currently defined statics out to file */
1178 /* and delete. Temporary function */
1179 /*-----------------------------------------------------------------*/
1183 emitStaticSeg (statsg, codeOutFile);
1184 statsg->syms = NULL;
1187 /*-----------------------------------------------------------------*/
1188 /* createInterruptVect - creates the interrupt vector */
1189 /*-----------------------------------------------------------------*/
1191 createInterruptVect (FILE * vFile)
1194 mainf = newSymbol ("main", 0);
1197 /* only if the main function exists */
1198 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1200 if (!options.cc_only && !noAssemble)
1205 /* if the main is only a prototype ie. no body then do nothing */
1206 if (!IFFUNC_HASBODY(mainf->type))
1208 /* if ! compile only then main function should be present */
1209 if (!options.cc_only && !noAssemble)
1214 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1215 fprintf (vFile, "__interrupt_vect:\n");
1218 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1220 /* "generic" interrupt table header (if port doesn't specify one).
1221 * Look suspiciously like 8051 code to me...
1224 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1227 /* now for the other interrupts */
1228 for (; i < maxInterrupts; i++)
1231 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1233 fprintf (vFile, "\treti\n\t.ds\t7\n");
1240 ";--------------------------------------------------------\n"
1241 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1245 ";--------------------------------------------------------\n"};
1248 /*-----------------------------------------------------------------*/
1249 /* initialComments - puts in some initial comments */
1250 /*-----------------------------------------------------------------*/
1252 initialComments (FILE * afile)
1256 fprintf (afile, "%s", iComments1);
1257 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1258 fprintf (afile, "%s", iComments2);
1261 /*-----------------------------------------------------------------*/
1262 /* printPublics - generates .global for publics */
1263 /*-----------------------------------------------------------------*/
1265 printPublics (FILE * afile)
1269 fprintf (afile, "%s", iComments2);
1270 fprintf (afile, "; Public variables in this module\n");
1271 fprintf (afile, "%s", iComments2);
1273 for (sym = setFirstItem (publics); sym;
1274 sym = setNextItem (publics))
1275 tfprintf (afile, "\t!global\n", sym->rname);
1278 /*-----------------------------------------------------------------*/
1279 /* printExterns - generates .global for externs */
1280 /*-----------------------------------------------------------------*/
1282 printExterns (FILE * afile)
1286 fprintf (afile, "%s", iComments2);
1287 fprintf (afile, "; Externals used\n");
1288 fprintf (afile, "%s", iComments2);
1290 for (sym = setFirstItem (externs); sym;
1291 sym = setNextItem (externs))
1292 tfprintf (afile, "\t!extern\n", sym->rname);
1295 /*-----------------------------------------------------------------*/
1296 /* emitOverlay - will emit code for the overlay stuff */
1297 /*-----------------------------------------------------------------*/
1299 emitOverlay (FILE * afile)
1303 if (!elementsInSet (ovrSetSets))
1304 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1306 /* for each of the sets in the overlay segment do */
1307 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1308 ovrset = setNextItem (ovrSetSets))
1313 if (elementsInSet (ovrset))
1315 /* output the area informtion */
1316 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1319 for (sym = setFirstItem (ovrset); sym;
1320 sym = setNextItem (ovrset))
1322 /* if extern then it is in the publics table: do nothing */
1323 if (IS_EXTERN (sym->etype))
1326 /* if allocation required check is needed
1327 then check if the symbol really requires
1328 allocation only for local variables */
1329 if (!IS_AGGREGATE (sym->type) &&
1330 !(sym->_isparm && !IS_REGPARM (sym->etype))
1331 && !sym->allocreq && sym->level)
1334 /* if global variable & not static or extern
1335 and addPublics allowed then add it to the public set */
1336 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1337 && !IS_STATIC (sym->etype))
1339 addSetHead (&publics, sym);
1342 /* if extern then do nothing or is a function
1344 if (IS_FUNC (sym->type))
1347 /* print extra debug info if required */
1350 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1354 if (IS_STATIC (sym->etype))
1355 fprintf (afile, "F%s$", moduleName); /* scope is file */
1357 fprintf (afile, "G$"); /* scope is global */
1360 /* symbol is local */
1361 fprintf (afile, "L%s$",
1362 (sym->localof ? sym->localof->name : "-null-"));
1363 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1366 /* if is has an absolute address then generate
1367 an equate for this no need to allocate space */
1368 if (SPEC_ABSA (sym->etype))
1372 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1374 fprintf (afile, "%s\t=\t0x%04x\n",
1376 SPEC_ADDR (sym->etype));
1379 int size = getSize(sym->type);
1382 werror(E_UNKNOWN_SIZE,sym->name);
1385 fprintf (afile, "==.\n");
1387 /* allocate space */
1388 tfprintf (afile, "!labeldef\n", sym->rname);
1389 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1396 /*-----------------------------------------------------------------*/
1397 /* glue - the final glue that hold the whole thing together */
1398 /*-----------------------------------------------------------------*/
1404 FILE *ovrFile = tempfile ();
1406 addSetHead (&tmpfileSet, ovrFile);
1407 /* print the global struct definitions */
1409 cdbStructBlock (0, cdbFile);
1411 vFile = tempfile ();
1412 /* PENDING: this isnt the best place but it will do */
1413 if (port->general.glue_up_main)
1415 /* create the interrupt vector table */
1416 createInterruptVect (vFile);
1419 addSetHead (&tmpfileSet, vFile);
1421 /* emit code for the all the variables declared */
1423 /* do the overlay segments */
1424 emitOverlay (ovrFile);
1426 /* now put it all together into the assembler file */
1427 /* create the assembler file name */
1429 if (!options.c1mode)
1431 sprintf (scratchFileName, srcFileName);
1432 strcat (scratchFileName, port->assembler.file_ext);
1436 strcpy (scratchFileName, options.out_name);
1439 if (!(asmFile = fopen (scratchFileName, "w")))
1441 werror (E_FILE_OPEN_ERR, scratchFileName);
1445 /* initial comments */
1446 initialComments (asmFile);
1448 /* print module name */
1449 tfprintf (asmFile, "\t!module\n", moduleName);
1450 tfprintf (asmFile, "\t!fileprelude\n");
1452 /* Let the port generate any global directives, etc. */
1453 if (port->genAssemblerPreamble)
1455 port->genAssemblerPreamble (asmFile);
1458 /* print the global variables in this module */
1459 printPublics (asmFile);
1460 if (port->assembler.externGlobal)
1461 printExterns (asmFile);
1463 /* copy the sfr segment */
1464 fprintf (asmFile, "%s", iComments2);
1465 fprintf (asmFile, "; special function registers\n");
1466 fprintf (asmFile, "%s", iComments2);
1467 copyFile (asmFile, sfr->oFile);
1469 /* copy the sbit segment */
1470 fprintf (asmFile, "%s", iComments2);
1471 fprintf (asmFile, "; special function bits \n");
1472 fprintf (asmFile, "%s", iComments2);
1473 copyFile (asmFile, sfrbit->oFile);
1475 /* copy the data segment */
1476 fprintf (asmFile, "%s", iComments2);
1477 fprintf (asmFile, "; internal ram data\n");
1478 fprintf (asmFile, "%s", iComments2);
1479 copyFile (asmFile, data->oFile);
1482 /* create the overlay segments */
1484 fprintf (asmFile, "%s", iComments2);
1485 fprintf (asmFile, "; overlayable items in internal ram \n");
1486 fprintf (asmFile, "%s", iComments2);
1487 copyFile (asmFile, ovrFile);
1490 /* create the stack segment MOF */
1491 if (mainf && IFFUNC_HASBODY(mainf->type))
1493 fprintf (asmFile, "%s", iComments2);
1494 fprintf (asmFile, "; Stack segment in internal ram \n");
1495 fprintf (asmFile, "%s", iComments2);
1496 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1497 "__start__stack:\n\t.ds\t1\n\n");
1500 /* create the idata segment */
1502 fprintf (asmFile, "%s", iComments2);
1503 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1504 fprintf (asmFile, "%s", iComments2);
1505 copyFile (asmFile, idata->oFile);
1508 /* copy the bit segment */
1509 fprintf (asmFile, "%s", iComments2);
1510 fprintf (asmFile, "; bit data\n");
1511 fprintf (asmFile, "%s", iComments2);
1512 copyFile (asmFile, bit->oFile);
1514 /* if external stack then reserve space of it */
1515 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1517 fprintf (asmFile, "%s", iComments2);
1518 fprintf (asmFile, "; external stack \n");
1519 fprintf (asmFile, "%s", iComments2);
1520 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1521 fprintf (asmFile, "\t.ds 256\n");
1525 /* copy xtern ram data */
1526 fprintf (asmFile, "%s", iComments2);
1527 fprintf (asmFile, "; external ram data\n");
1528 fprintf (asmFile, "%s", iComments2);
1529 copyFile (asmFile, xdata->oFile);
1531 /* copy xternal initialized ram data */
1532 fprintf (asmFile, "%s", iComments2);
1533 fprintf (asmFile, "; external initialized ram data\n");
1534 fprintf (asmFile, "%s", iComments2);
1535 copyFile (asmFile, xidata->oFile);
1537 /* copy the interrupt vector table */
1538 if (mainf && IFFUNC_HASBODY(mainf->type))
1540 fprintf (asmFile, "%s", iComments2);
1541 fprintf (asmFile, "; interrupt vector \n");
1542 fprintf (asmFile, "%s", iComments2);
1543 copyFile (asmFile, vFile);
1546 /* copy global & static initialisations */
1547 fprintf (asmFile, "%s", iComments2);
1548 fprintf (asmFile, "; global & static initialisations\n");
1549 fprintf (asmFile, "%s", iComments2);
1551 /* Everywhere we generate a reference to the static_name area,
1552 * (which is currently only here), we immediately follow it with a
1553 * definition of the post_static_name area. This guarantees that
1554 * the post_static_name area will immediately follow the static_name
1557 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1558 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1559 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1561 if (mainf && IFFUNC_HASBODY(mainf->type))
1563 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1564 /* if external stack is specified then the
1565 higher order byte of the xdatalocation is
1566 going into P2 and the lower order going into
1568 if (options.useXstack)
1570 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1571 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1572 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1573 (unsigned int) options.xdata_loc & 0xff);
1576 /* initialise the stack pointer */
1577 /* if the user specified a value then use it */
1578 if (options.stack_loc)
1579 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff);
1581 /* no: we have to compute it */
1582 if (!options.stackOnData && maxRegBank <= 3)
1583 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1585 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1587 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1588 fprintf (asmFile, "\tmov\ta,dpl\n");
1589 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1590 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1591 fprintf (asmFile, "__sdcc_init_data:\n");
1593 // if the port can copy the XINIT segment to XISEG
1594 if (port->genXINIT) {
1595 port->genXINIT(asmFile);
1599 copyFile (asmFile, statsg->oFile);
1601 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1603 /* This code is generated in the post-static area.
1604 * This area is guaranteed to follow the static area
1605 * by the ugly shucking and jiving about 20 lines ago.
1607 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1608 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1614 "%s", iComments2, iComments2);
1615 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1616 copyFile (asmFile, home->oFile);
1618 /* copy over code */
1619 fprintf (asmFile, "%s", iComments2);
1620 fprintf (asmFile, "; code\n");
1621 fprintf (asmFile, "%s", iComments2);
1622 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1623 if (mainf && IFFUNC_HASBODY(mainf->type))
1626 /* entry point @ start of CSEG */
1627 fprintf (asmFile, "__sdcc_program_startup:\n");
1629 /* put in the call to main */
1630 fprintf (asmFile, "\tlcall\t_main\n");
1631 if (options.mainreturn)
1634 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1635 fprintf (asmFile, "\tret\n");
1641 fprintf (asmFile, ";\treturn from main will lock up\n");
1642 fprintf (asmFile, "\tsjmp .\n");
1645 copyFile (asmFile, code->oFile);
1647 if (port->genAssemblerEnd) {
1648 port->genAssemblerEnd(asmFile);
1651 applyToSet (tmpfileSet, closeTmpFiles);
1652 applyToSet (tmpfileNameSet, rmTmpFiles);
1655 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1659 applyToSet (tmpfileSet, closeTmpFiles);
1660 applyToSet (tmpfileNameSet, rmTmpFiles);
1664 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1665 in cygwin wrt c:\tmp.
1666 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1671 #if !defined(_MSC_VER)
1672 const char *tmpdir = NULL;
1674 tmpdir = getenv ("TMP");
1675 else if (getenv ("TEMP"))
1676 tmpdir = getenv ("TEMP");
1677 else if (getenv ("TMPDIR"))
1678 tmpdir = getenv ("TMPDIR");
1681 char *name = tempnam (tmpdir, "sdcc");
1688 return tmpnam (NULL);
1691 /** Creates a temporary file a'la tmpfile which avoids the bugs
1692 in cygwin wrt c:\tmp.
1693 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1698 #if !defined(_MSC_VER)
1699 const char *tmpdir = NULL;
1701 tmpdir = getenv ("TMP");
1702 else if (getenv ("TEMP"))
1703 tmpdir = getenv ("TEMP");
1704 else if (getenv ("TMPDIR"))
1705 tmpdir = getenv ("TMPDIR");
1708 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1711 FILE *fp = fopen (name, "w+b");
1714 addSetHead (&tmpfileNameSet, name);