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)
31 #if 0 /* This should no longer be necessary. */
32 // This is a bit messy because we define link ourself
41 // No unistd.h in Borland C++
44 symbol *interrupts[256];
46 void printIval (symbol *, sym_link *, initList *, FILE *);
47 set *publics = NULL; /* public variables */
48 set *externs = NULL; /* Varibles that are declared as extern */
50 /* TODO: this should be configurable (DS803C90 uses more than 6) */
51 int maxInterrupts = 6;
54 extern char *VersionString;
55 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
56 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
58 /*-----------------------------------------------------------------*/
59 /* closeTmpFiles - closes all tmp files created by the compiler */
60 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
61 /*-----------------------------------------------------------------*/
62 DEFSETFUNC (closeTmpFiles)
72 /*-----------------------------------------------------------------*/
73 /* rmTmpFiles - closes all tmp files created by the compiler */
74 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
75 /*-----------------------------------------------------------------*/
76 DEFSETFUNC (rmTmpFiles)
88 /*-----------------------------------------------------------------*/
89 /* copyFile - copies source file to destination file */
90 /*-----------------------------------------------------------------*/
92 copyFile (FILE * dest, FILE * src)
98 if ((ch = fgetc (src)) != EOF)
103 aopLiteralLong (value * val, int offset, int size)
112 /* if it is a float then it gets tricky */
113 /* otherwise it is fairly simple */
114 if (!IS_FLOAT (val->type)) {
115 unsigned long v = floatFromVal (val);
120 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
123 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
126 /* Hmm. Too big for now. */
129 rs = Safe_calloc (1, strlen (buffer) + 1);
130 return strcpy (rs, buffer);
133 /* PENDING: For now size must be 1 */
136 /* it is type float */
137 fl.f = (float) floatFromVal (val);
139 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
141 tsprintf (buffer, "!immedbyte", fl.c[offset]);
143 rs = Safe_calloc (1, strlen (buffer) + 1);
144 return strcpy (rs, buffer);
147 /*-----------------------------------------------------------------*/
148 /* aopLiteral - string from a literal value */
149 /*-----------------------------------------------------------------*/
151 aopLiteral (value * val, int offset)
153 return aopLiteralLong (val, offset, 1);
156 /*-----------------------------------------------------------------*/
157 /* emitRegularMap - emit code for maps with no special cases */
158 /*-----------------------------------------------------------------*/
160 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
166 /* PENDING: special case here - should remove */
167 if (!strcmp (map->sname, CODE_NAME))
168 tfprintf (map->oFile, "\t!areacode\n", map->sname);
169 else if (!strcmp (map->sname, DATA_NAME))
170 tfprintf (map->oFile, "\t!areadata\n", map->sname);
171 else if (!strcmp (map->sname, HOME_NAME))
172 tfprintf (map->oFile, "\t!areahome\n", map->sname);
174 tfprintf (map->oFile, "\t!area\n", map->sname);
177 /* print the area name */
178 for (sym = setFirstItem (map->syms); sym;
179 sym = setNextItem (map->syms))
182 /* if extern then add it into the extern list */
183 if (IS_EXTERN (sym->etype))
185 addSetHead (&externs, sym);
189 /* if allocation required check is needed
190 then check if the symbol really requires
191 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 /* if global variable & not static or extern
198 and addPublics allowed then add it to the public set */
199 if ((sym->level == 0 ||
200 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
202 !IS_STATIC (sym->etype) &&
203 (sym->used || sym->fbody))
205 addSetHead (&publics, sym);
208 /* if extern then do nothing or is a function
210 if (IS_FUNC (sym->type))
213 /* print extra debug info if required */
214 if ((options.debug || sym->level == 0) && !options.nodebug)
217 cdbSymbol (sym, cdbFile, FALSE, FALSE);
219 if (!sym->level) /* global */
220 if (IS_STATIC (sym->etype))
221 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
223 fprintf (map->oFile, "G$"); /* scope is global */
225 /* symbol is local */
226 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
227 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
230 /* if is has an absolute address then generate
231 an equate for this no need to allocate space */
232 if (SPEC_ABSA (sym->etype))
234 if ((options.debug || sym->level == 0) && !options.nodebug)
235 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
237 fprintf (map->oFile, "%s\t=\t0x%04x\n",
239 SPEC_ADDR (sym->etype));
244 if ((options.debug || sym->level == 0) && !options.nodebug)
245 fprintf (map->oFile, "==.\n");
246 if (IS_STATIC (sym->etype))
247 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
249 tfprintf (map->oFile, "!labeldef\n", sym->rname);
250 tfprintf (map->oFile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
253 /* if it has an initial value then do it only if
254 it is a global variable */
255 if (sym->ival && sym->level == 0)
259 if (IS_AGGREGATE (sym->type))
260 ival = initAggregates (sym, sym->ival, NULL);
262 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
263 decorateType (resolveSymbols (list2expr (sym->ival))));
264 codeOutFile = statsg->oFile;
266 eBBlockFromiCode (iCodeFromAst (ival));
273 /*-----------------------------------------------------------------*/
274 /* initPointer - pointer initialization code massaging */
275 /*-----------------------------------------------------------------*/
277 initPointer (initList * ilist)
280 ast *expr = list2expr (ilist);
285 /* try it the oldway first */
286 if ((val = constExprValue (expr, FALSE)))
289 /* no then we have to do these cludgy checks */
290 /* pointers can be initialized with address of
291 a variable or address of an array element */
292 if (IS_AST_OP (expr) && expr->opval.op == '&') {
293 /* address of symbol */
294 if (IS_AST_SYM_VALUE (expr->left)) {
295 val = copyValue (AST_VALUE (expr->left));
296 val->type = newLink ();
297 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
298 DCL_TYPE (val->type) = CPOINTER;
299 DCL_PTR_CONST (val->type) = port->mem.code_ro;
301 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
302 DCL_TYPE (val->type) = FPOINTER;
303 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
304 DCL_TYPE (val->type) = PPOINTER;
305 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
306 DCL_TYPE (val->type) = IPOINTER;
307 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
308 DCL_TYPE (val->type) = EEPPOINTER;
310 DCL_TYPE (val->type) = POINTER;
311 val->type->next = expr->left->ftype;
312 val->etype = getSpec (val->type);
316 /* if address of indexed array */
317 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
318 return valForArray (expr->left);
320 /* if address of structure element then
322 if (IS_AST_OP (expr->left) &&
323 expr->left->opval.op == '.') {
324 return valForStructElem (expr->left->left,
329 (&some_struct)->element */
330 if (IS_AST_OP (expr->left) &&
331 expr->left->opval.op == PTR_OP &&
332 IS_ADDRESS_OF_OP (expr->left->left))
333 return valForStructElem (expr->left->left->left,
337 /* case 3. (((char *) &a) +/- constant) */
338 if (IS_AST_OP (expr) &&
339 (expr->opval.op == '+' || expr->opval.op == '-') &&
340 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
341 IS_AST_OP (expr->left->right) &&
342 expr->left->right->opval.op == '&' &&
343 IS_AST_LIT_VALUE (expr->right)) {
345 return valForCastAggr (expr->left->right->left,
346 expr->left->left->opval.lnk,
347 expr->right, expr->opval.op);
351 /* case 4. (char *)(array type) */
352 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
353 IS_ARRAY(expr->right->ftype)) {
355 val = copyValue (AST_VALUE (expr->right));
356 val->type = newLink ();
357 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
358 DCL_TYPE (val->type) = CPOINTER;
359 DCL_PTR_CONST (val->type) = port->mem.code_ro;
361 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
362 DCL_TYPE (val->type) = FPOINTER;
363 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
364 DCL_TYPE (val->type) = PPOINTER;
365 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
366 DCL_TYPE (val->type) = IPOINTER;
367 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
368 DCL_TYPE (val->type) = EEPPOINTER;
370 DCL_TYPE (val->type) = POINTER;
371 val->type->next = expr->right->ftype->next;
372 val->etype = getSpec (val->type);
376 werror (E_INIT_WRONG);
381 /*-----------------------------------------------------------------*/
382 /* printChar - formats and prints a characater string with DB */
383 /*-----------------------------------------------------------------*/
385 printChar (FILE * ofile, char *s, int plen)
388 int len = strlen (s);
393 while (len && pplen < plen)
396 while (i && *s && pplen < plen)
398 if (*s < ' ' || *s == '\"')
402 tfprintf (ofile, "\t!ascii\n", buf);
403 tfprintf (ofile, "\t!db !constbyte\n", *s);
418 tfprintf (ofile, "\t!ascii\n", buf);
427 tfprintf (ofile, "\t!db !constbyte\n", 0);
430 /*-----------------------------------------------------------------*/
431 /* return the generic pointer high byte for a given pointer type. */
432 /*-----------------------------------------------------------------*/
434 pointerTypeToGPByte (const int p_type)
442 /* hack - if we get a generic pointer, we just assume
443 * it's an FPOINTER (i.e. in XDATA space).
452 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
460 /*-----------------------------------------------------------------*/
461 /* printPointerType - generates ival for pointer type */
462 /*-----------------------------------------------------------------*/
464 _printPointerType (FILE * oFile, const char *name)
468 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
472 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
476 /*-----------------------------------------------------------------*/
477 /* printPointerType - generates ival for pointer type */
478 /*-----------------------------------------------------------------*/
480 printPointerType (FILE * oFile, const char *name)
482 _printPointerType (oFile, name);
483 fprintf (oFile, "\n");
486 /*-----------------------------------------------------------------*/
487 /* printGPointerType - generates ival for generic pointer type */
488 /*-----------------------------------------------------------------*/
490 printGPointerType (FILE * oFile, const char *name,
491 const unsigned int type)
493 _printPointerType (oFile, name);
494 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type));
497 /*-----------------------------------------------------------------*/
498 /* printIvalType - generates ival for int/char */
499 /*-----------------------------------------------------------------*/
501 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
505 /* if initList is deep */
506 if (ilist->type == INIT_DEEP)
507 ilist = ilist->init.deep;
509 val = list2val (ilist);
510 switch (getSize (type)) {
513 tfprintf (oFile, "\t!db !constbyte\n", 0);
515 tfprintf (oFile, "\t!dbs\n",
516 aopLiteral (val, 0));
520 if (port->use_dw_for_init)
521 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
523 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
527 tfprintf (oFile, "\t!dw !constword\n", 0);
528 tfprintf (oFile, "\t!dw !constword\n", 0);
531 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
532 aopLiteral (val, 0), aopLiteral (val, 1),
533 aopLiteral (val, 2), aopLiteral (val, 3));
539 /*-----------------------------------------------------------------*/
540 /* printIvalBitFields - generate initializer for bitfields */
541 /*-----------------------------------------------------------------*/
542 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
546 initList *lilist = *ilist ;
547 unsigned long ival = 0;
553 val = list2val(lilist);
555 if (SPEC_BLEN(lsym->etype) > 8) {
556 size += ((SPEC_BLEN (lsym->etype) / 8) +
557 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
560 size = ((SPEC_BLEN (lsym->etype) / 8) +
561 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
563 i = (unsigned long)floatFromVal(val);
564 i <<= SPEC_BSTR (lsym->etype);
566 if (! ( lsym->next &&
567 (IS_BITFIELD(lsym->next->type)) &&
568 (SPEC_BSTR(lsym->next->etype)))) break;
570 lilist = lilist->next;
574 tfprintf (oFile, "\t!db !constbyte\n",ival);
578 tfprintf (oFile, "\t!dw !constword\n",ival);
581 tfprintf (oFile, "\t!db !constword,!constword\n",
582 (ival >> 8) & 0xffff, (ival & 0xffff));
589 /*-----------------------------------------------------------------*/
590 /* printIvalStruct - generates initial value for structures */
591 /*-----------------------------------------------------------------*/
593 printIvalStruct (symbol * sym, sym_link * type,
594 initList * ilist, FILE * oFile)
599 sflds = SPEC_STRUCT (type)->fields;
600 if (ilist->type != INIT_DEEP) {
601 werror (E_INIT_STRUCT, sym->name);
605 iloop = ilist->init.deep;
607 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
608 if (IS_BITFIELD(sflds->type)) {
609 printIvalBitFields(&sflds,&iloop,oFile);
611 printIval (sflds, sflds->type, iloop, oFile);
617 /*-----------------------------------------------------------------*/
618 /* printIvalChar - generates initital value for character array */
619 /*-----------------------------------------------------------------*/
621 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
629 val = list2val (ilist);
630 /* if the value is a character string */
631 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
633 if (!DCL_ELEM (type))
634 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
636 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
638 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
640 tfprintf (oFile, "\t!db !constbyte\n", 0);
648 printChar (oFile, s, strlen (s) + 1);
652 /*-----------------------------------------------------------------*/
653 /* printIvalArray - generates code for array initialization */
654 /*-----------------------------------------------------------------*/
656 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
660 int lcnt = 0, size = 0;
662 /* take care of the special case */
663 /* array of characters can be init */
665 if (IS_CHAR (type->next))
666 if (printIvalChar (type,
667 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
668 oFile, SPEC_CVAL (sym->etype).v_char))
671 /* not the special case */
672 if (ilist->type != INIT_DEEP)
674 werror (E_INIT_STRUCT, sym->name);
678 iloop = ilist->init.deep;
679 lcnt = DCL_ELEM (type);
684 printIval (sym, type->next, iloop, oFile);
685 iloop = (iloop ? iloop->next : NULL);
688 /* if not array limits given & we */
689 /* are out of initialisers then */
690 if (!DCL_ELEM (type) && !iloop)
693 /* no of elements given and we */
694 /* have generated for all of them */
699 /* if we have not been given a size */
700 if (!DCL_ELEM (type))
701 DCL_ELEM (type) = size;
706 /*-----------------------------------------------------------------*/
707 /* printIvalFuncPtr - generate initial value for function pointers */
708 /*-----------------------------------------------------------------*/
710 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
715 val = list2val (ilist);
716 /* check the types */
717 if ((dLvl = checkType (val->type, type->next)) <= 0)
719 tfprintf (oFile, "\t!dw !constword\n", 0);
723 /* now generate the name */
726 if (port->use_dw_for_init)
728 tfprintf (oFile, "\t!dws\n", val->name);
732 printPointerType (oFile, val->name);
735 else if (port->use_dw_for_init)
737 tfprintf (oFile, "\t!dws\n", val->sym->rname);
741 printPointerType (oFile, val->sym->rname);
747 /*-----------------------------------------------------------------*/
748 /* printIvalCharPtr - generates initial values for character pointers */
749 /*-----------------------------------------------------------------*/
751 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
755 /* PENDING: this is _very_ mcs51 specific, including a magic
757 It's also endin specific.
759 size = getSize (type);
761 if (val->name && strlen (val->name))
763 if (size == 1) /* This appears to be Z80 specific?? */
766 "\t!dbs\n", val->name);
768 else if (size == FPTRSIZE)
770 if (port->use_dw_for_init)
772 tfprintf (oFile, "\t!dws\n", val->name);
776 printPointerType (oFile, val->name);
779 else if (size == GPTRSIZE)
781 /* PENDING: 0x02 or 0x%02x, CDATA? */
782 printGPointerType (oFile, val->name,
783 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
784 PTR_TYPE (SPEC_OCLS (val->etype))));
788 fprintf (stderr, "*** internal error: unknown size in "
789 "printIvalCharPtr.\n");
794 /* What is this case? Are these pointers? */
798 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
801 if (port->use_dw_for_init)
802 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
804 tfprintf (oFile, "\t.byte %s,%s\n",
805 aopLiteral (val, 0), aopLiteral (val, 1));
808 /* PENDING: 0x02 or 0x%02x, CDATA? */
809 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
810 aopLiteral (val, 0), aopLiteral (val, 1));
817 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
818 addSet (&statsg->syms, val->sym);
824 /*-----------------------------------------------------------------*/
825 /* printIvalPtr - generates initial value for pointers */
826 /*-----------------------------------------------------------------*/
828 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
834 if (ilist->type == INIT_DEEP)
835 ilist = ilist->init.deep;
837 /* function pointer */
838 if (IS_FUNC (type->next))
840 printIvalFuncPtr (type, ilist, oFile);
844 if (!(val = initPointer (ilist)))
847 /* if character pointer */
848 if (IS_CHAR (type->next))
849 if (printIvalCharPtr (sym, type, val, oFile))
853 if (checkType (type, val->type) == 0)
854 werror (E_INIT_WRONG);
856 /* if val is literal */
857 if (IS_LITERAL (val->etype))
859 switch (getSize (type))
862 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
865 if (port->use_dw_for_init)
866 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
868 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
871 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
872 aopLiteral (val, 0), aopLiteral (val, 1));
878 size = getSize (type);
880 if (size == 1) /* Z80 specific?? */
882 tfprintf (oFile, "\t!dbs\n", val->name);
884 else if (size == FPTRSIZE)
886 tfprintf (oFile, "\t!dws\n", val->name);
888 else if (size == GPTRSIZE)
890 printGPointerType (oFile, val->name,
891 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
892 PTR_TYPE (SPEC_OCLS (val->etype))));
897 /*-----------------------------------------------------------------*/
898 /* printIval - generates code for initial value */
899 /*-----------------------------------------------------------------*/
901 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
906 /* if structure then */
907 if (IS_STRUCT (type))
909 printIvalStruct (sym, type, ilist, oFile);
913 /* if this is a pointer */
916 printIvalPtr (sym, type, ilist, oFile);
920 /* if this is an array */
923 printIvalArray (sym, type, ilist, oFile);
927 /* if type is SPECIFIER */
930 printIvalType (type, ilist, oFile);
935 /*-----------------------------------------------------------------*/
936 /* emitStaticSeg - emitcode for the static segment */
937 /*-----------------------------------------------------------------*/
939 emitStaticSeg (memmap * map, FILE * out)
943 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
947 /* for all variables in this segment do */
948 for (sym = setFirstItem (map->syms); sym;
949 sym = setNextItem (map->syms))
952 /* if it is "extern" then do nothing */
953 if (IS_EXTERN (sym->etype))
956 /* if it is not static add it to the public
958 if (!IS_STATIC (sym->etype))
959 addSetHead (&publics, sym);
961 /* print extra debug info if required */
962 if ((options.debug || sym->level == 0) && !options.nodebug)
965 cdbSymbol (sym, cdbFile, FALSE, FALSE);
969 if (IS_STATIC (sym->etype))
970 fprintf (out, "F%s$", moduleName); /* scope is file */
972 fprintf (out, "G$"); /* scope is global */
975 /* symbol is local */
976 fprintf (out, "L%s$",
977 (sym->localof ? sym->localof->name : "-null-"));
978 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
981 /* if it has an absolute address */
982 if (SPEC_ABSA (sym->etype))
984 if ((options.debug || sym->level == 0) && !options.nodebug)
985 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
987 fprintf (out, "%s\t=\t0x%04x\n",
989 SPEC_ADDR (sym->etype));
993 if ((options.debug || sym->level == 0) && !options.nodebug)
994 fprintf (out, " == .\n");
996 /* if it has an initial value */
999 fprintf (out, "%s:\n", sym->rname);
1001 resolveIvalSym (sym->ival);
1002 printIval (sym, sym->type, sym->ival, out);
1007 /* allocate space */
1008 fprintf (out, "%s:\n", sym->rname);
1009 /* special case for character strings */
1010 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1011 SPEC_CVAL (sym->etype).v_char)
1013 SPEC_CVAL (sym->etype).v_char,
1014 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1016 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1022 /*-----------------------------------------------------------------*/
1023 /* emitMaps - emits the code for the data portion the code */
1024 /*-----------------------------------------------------------------*/
1028 /* no special considerations for the following
1029 data, idata & bit & xdata */
1030 emitRegularMap (data, TRUE, TRUE);
1031 emitRegularMap (idata, TRUE, TRUE);
1032 emitRegularMap (bit, TRUE, FALSE);
1033 emitRegularMap (xdata, TRUE, TRUE);
1034 emitRegularMap (sfr, FALSE, FALSE);
1035 emitRegularMap (sfrbit, FALSE, FALSE);
1036 emitRegularMap (home, TRUE, FALSE);
1037 emitRegularMap (code, TRUE, FALSE);
1039 emitStaticSeg (statsg, code->oFile);
1042 /*-----------------------------------------------------------------*/
1043 /* flushStatics - flush all currently defined statics out to file */
1044 /* and delete. Temporary function */
1045 /*-----------------------------------------------------------------*/
1049 emitStaticSeg (statsg, codeOutFile);
1050 statsg->syms = NULL;
1053 /*-----------------------------------------------------------------*/
1054 /* createInterruptVect - creates the interrupt vector */
1055 /*-----------------------------------------------------------------*/
1057 createInterruptVect (FILE * vFile)
1060 mainf = newSymbol ("main", 0);
1063 /* only if the main function exists */
1064 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1066 if (!options.cc_only)
1071 /* if the main is only a prototype ie. no body then do nothing */
1074 /* if ! compile only then main function should be present */
1075 if (!options.cc_only)
1080 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1081 fprintf (vFile, "__interrupt_vect:\n");
1084 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1086 /* "generic" interrupt table header (if port doesn't specify one).
1088 * Look suspiciously like 8051 code to me...
1091 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1094 /* now for the other interrupts */
1095 for (; i < maxInterrupts; i++)
1098 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1100 fprintf (vFile, "\treti\n\t.ds\t7\n");
1107 ";--------------------------------------------------------\n"
1108 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1112 ";--------------------------------------------------------\n"};
1115 /*-----------------------------------------------------------------*/
1116 /* initialComments - puts in some initial comments */
1117 /*-----------------------------------------------------------------*/
1119 initialComments (FILE * afile)
1123 fprintf (afile, "%s", iComments1);
1124 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1125 fprintf (afile, "%s", iComments2);
1128 /*-----------------------------------------------------------------*/
1129 /* printPublics - generates .global for publics */
1130 /*-----------------------------------------------------------------*/
1132 printPublics (FILE * afile)
1136 fprintf (afile, "%s", iComments2);
1137 fprintf (afile, "; Public variables in this module\n");
1138 fprintf (afile, "%s", iComments2);
1140 for (sym = setFirstItem (publics); sym;
1141 sym = setNextItem (publics))
1142 tfprintf (afile, "\t!global\n", sym->rname);
1145 /*-----------------------------------------------------------------*/
1146 /* printExterns - generates .global for externs */
1147 /*-----------------------------------------------------------------*/
1149 printExterns (FILE * afile)
1153 fprintf (afile, "%s", iComments2);
1154 fprintf (afile, "; Externals used\n");
1155 fprintf (afile, "%s", iComments2);
1157 for (sym = setFirstItem (externs); sym;
1158 sym = setNextItem (externs))
1159 tfprintf (afile, "\t!global\n", sym->rname);
1162 /*-----------------------------------------------------------------*/
1163 /* emitOverlay - will emit code for the overlay stuff */
1164 /*-----------------------------------------------------------------*/
1166 emitOverlay (FILE * afile)
1170 if (!elementsInSet (ovrSetSets))
1171 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1173 /* for each of the sets in the overlay segment do */
1174 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1175 ovrset = setNextItem (ovrSetSets))
1180 if (elementsInSet (ovrset))
1182 /* this dummy area is used to fool the assembler
1183 otherwise the assembler will append each of these
1184 declarations into one chunk and will not overlay
1186 fprintf (afile, "\t.area _DUMMY\n");
1187 /* output the area informtion */
1188 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1191 for (sym = setFirstItem (ovrset); sym;
1192 sym = setNextItem (ovrset))
1195 /* if extern then add it to the publics tabledo nothing */
1196 if (IS_EXTERN (sym->etype))
1199 /* if allocation required check is needed
1200 then check if the symbol really requires
1201 allocation only for local variables */
1202 if (!IS_AGGREGATE (sym->type) &&
1203 !(sym->_isparm && !IS_REGPARM (sym->etype))
1204 && !sym->allocreq && sym->level)
1207 /* if global variable & not static or extern
1208 and addPublics allowed then add it to the public set */
1209 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1210 && !IS_STATIC (sym->etype))
1211 addSetHead (&publics, sym);
1213 /* if extern then do nothing or is a function
1215 if (IS_FUNC (sym->type))
1218 /* print extra debug info if required */
1219 if ((options.debug || sym->level == 0) && !options.nodebug)
1222 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1226 if (IS_STATIC (sym->etype))
1227 fprintf (afile, "F%s$", moduleName); /* scope is file */
1229 fprintf (afile, "G$"); /* scope is global */
1232 /* symbol is local */
1233 fprintf (afile, "L%s$",
1234 (sym->localof ? sym->localof->name : "-null-"));
1235 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1238 /* if is has an absolute address then generate
1239 an equate for this no need to allocate space */
1240 if (SPEC_ABSA (sym->etype))
1243 if ((options.debug || sym->level == 0) && !options.nodebug)
1244 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1246 fprintf (afile, "%s\t=\t0x%04x\n",
1248 SPEC_ADDR (sym->etype));
1252 if ((options.debug || sym->level == 0) && !options.nodebug)
1253 fprintf (afile, "==.\n");
1255 /* allocate space */
1256 tfprintf (afile, "!labeldef\n", sym->rname);
1257 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1264 /*-----------------------------------------------------------------*/
1265 /* glue - the final glue that hold the whole thing together */
1266 /*-----------------------------------------------------------------*/
1272 FILE *ovrFile = tempfile ();
1274 addSetHead (&tmpfileSet, ovrFile);
1275 /* print the global struct definitions */
1276 if (options.debug && !options.nodebug)
1277 cdbStructBlock (0, cdbFile);
1279 vFile = tempfile ();
1280 /* PENDING: this isnt the best place but it will do */
1281 if (port->general.glue_up_main)
1283 /* create the interrupt vector table */
1284 createInterruptVect (vFile);
1287 addSetHead (&tmpfileSet, vFile);
1289 /* emit code for the all the variables declared */
1291 /* do the overlay segments */
1292 emitOverlay (ovrFile);
1294 /* now put it all together into the assembler file */
1295 /* create the assembler file name */
1297 if (!options.c1mode)
1299 sprintf (buffer, srcFileName);
1300 strcat (buffer, port->assembler.file_ext);
1304 strcpy (buffer, options.out_name);
1307 if (!(asmFile = fopen (buffer, "w")))
1309 werror (E_FILE_OPEN_ERR, buffer);
1313 /* initial comments */
1314 initialComments (asmFile);
1316 /* print module name */
1317 tfprintf (asmFile, "\t!module\n", moduleName);
1318 tfprintf (asmFile, "\t!fileprelude\n");
1320 /* Let the port generate any global directives, etc. */
1321 if (port->genAssemblerPreamble)
1323 port->genAssemblerPreamble (asmFile);
1326 /* print the global variables in this module */
1327 printPublics (asmFile);
1328 if (port->assembler.externGlobal)
1329 printExterns (asmFile);
1331 /* copy the sfr segment */
1332 fprintf (asmFile, "%s", iComments2);
1333 fprintf (asmFile, "; special function registers\n");
1334 fprintf (asmFile, "%s", iComments2);
1335 copyFile (asmFile, sfr->oFile);
1337 /* copy the sbit segment */
1338 fprintf (asmFile, "%s", iComments2);
1339 fprintf (asmFile, "; special function bits \n");
1340 fprintf (asmFile, "%s", iComments2);
1341 copyFile (asmFile, sfrbit->oFile);
1343 /* copy the data segment */
1344 fprintf (asmFile, "%s", iComments2);
1345 fprintf (asmFile, "; internal ram data\n");
1346 fprintf (asmFile, "%s", iComments2);
1347 copyFile (asmFile, data->oFile);
1350 /* create the overlay segments */
1351 fprintf (asmFile, "%s", iComments2);
1352 fprintf (asmFile, "; overlayable items in internal ram \n");
1353 fprintf (asmFile, "%s", iComments2);
1354 copyFile (asmFile, ovrFile);
1356 /* create the stack segment MOF */
1357 if (mainf && mainf->fbody)
1359 fprintf (asmFile, "%s", iComments2);
1360 fprintf (asmFile, "; Stack segment in internal ram \n");
1361 fprintf (asmFile, "%s", iComments2);
1362 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1363 "__start__stack:\n\t.ds\t1\n\n");
1366 /* create the idata segment */
1367 fprintf (asmFile, "%s", iComments2);
1368 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1369 fprintf (asmFile, "%s", iComments2);
1370 copyFile (asmFile, idata->oFile);
1372 /* copy the bit segment */
1373 fprintf (asmFile, "%s", iComments2);
1374 fprintf (asmFile, "; bit data\n");
1375 fprintf (asmFile, "%s", iComments2);
1376 copyFile (asmFile, bit->oFile);
1378 /* if external stack then reserve space of it */
1379 if (mainf && mainf->fbody && options.useXstack)
1381 fprintf (asmFile, "%s", iComments2);
1382 fprintf (asmFile, "; external stack \n");
1383 fprintf (asmFile, "%s", iComments2);
1384 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1385 fprintf (asmFile, "\t.ds 256\n");
1389 /* copy xtern ram data */
1390 fprintf (asmFile, "%s", iComments2);
1391 fprintf (asmFile, "; external ram data\n");
1392 fprintf (asmFile, "%s", iComments2);
1393 copyFile (asmFile, xdata->oFile);
1395 /* copy the interrupt vector table */
1396 if (mainf && mainf->fbody)
1398 fprintf (asmFile, "%s", iComments2);
1399 fprintf (asmFile, "; interrupt vector \n");
1400 fprintf (asmFile, "%s", iComments2);
1401 copyFile (asmFile, vFile);
1404 /* copy global & static initialisations */
1405 fprintf (asmFile, "%s", iComments2);
1406 fprintf (asmFile, "; global & static initialisations\n");
1407 fprintf (asmFile, "%s", iComments2);
1409 /* Everywhere we generate a reference to the static_name area,
1410 * (which is currently only here), we immediately follow it with a
1411 * definition of the post_static_name area. This guarantees that
1412 * the post_static_name area will immediately follow the static_name
1415 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1416 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1417 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1419 if (mainf && mainf->fbody)
1421 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1422 /* if external stack is specified then the
1423 higher order byte of the xdatalocation is
1424 going into P2 and the lower order going into
1426 if (options.useXstack)
1428 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1429 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1430 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1431 (unsigned int) options.xdata_loc & 0xff);
1434 /* initialise the stack pointer */
1435 /* if the user specified a value then use it */
1436 if (options.stack_loc)
1437 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1439 /* no: we have to compute it */
1440 if (!options.stackOnData && maxRegBank <= 3)
1441 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1443 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1445 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1446 fprintf (asmFile, "\tmov\ta,dpl\n");
1447 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1448 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1449 fprintf (asmFile, "__sdcc_init_data:\n");
1452 copyFile (asmFile, statsg->oFile);
1454 if (port->general.glue_up_main && mainf && mainf->fbody)
1456 /* This code is generated in the post-static area.
1457 * This area is guaranteed to follow the static area
1458 * by the ugly shucking and jiving about 20 lines ago.
1460 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1461 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1467 "%s", iComments2, iComments2);
1468 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1469 copyFile (asmFile, home->oFile);
1471 /* copy over code */
1472 fprintf (asmFile, "%s", iComments2);
1473 fprintf (asmFile, "; code\n");
1474 fprintf (asmFile, "%s", iComments2);
1475 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1476 if (mainf && mainf->fbody)
1479 /* entry point @ start of CSEG */
1480 fprintf (asmFile, "__sdcc_program_startup:\n");
1482 /* put in the call to main */
1483 fprintf (asmFile, "\tlcall\t_main\n");
1484 if (options.mainreturn)
1487 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1488 fprintf (asmFile, "\tret\n");
1494 fprintf (asmFile, ";\treturn from main will lock up\n");
1495 fprintf (asmFile, "\tsjmp .\n");
1498 copyFile (asmFile, code->oFile);
1501 applyToSet (tmpfileSet, closeTmpFiles);
1502 applyToSet (tmpfileNameSet, rmTmpFiles);
1505 /** Creates a temporary file a'la tmpfile which avoids the bugs
1506 in cygwin wrt c:\tmp.
1507 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1512 #if !defined(_MSC_VER)
1513 const char *tmpdir = NULL;
1515 tmpdir = getenv ("TMP");
1516 else if (getenv ("TEMP"))
1517 tmpdir = getenv ("TEMP");
1518 else if (getenv ("TMPDIR"))
1519 tmpdir = getenv ("TMPDIR");
1522 char *name = tempnam (tmpdir, "sdcc");
1525 FILE *fp = fopen (name, "w+b");
1528 addSetHead (&tmpfileNameSet, name);
1539 gc_strdup (const char *s)
1542 ret = Safe_calloc (1, strlen (s) + 1);