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)
102 /* if it is a float then it gets tricky */
103 /* otherwise it is fairly simple */
104 if (!IS_FLOAT (val->type)) {
105 unsigned long v = (unsigned long) floatFromVal (val);
110 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
113 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
116 /* Hmm. Too big for now. */
119 rs = Safe_calloc (1, strlen (buffer) + 1);
120 return strcpy (rs, buffer);
123 /* PENDING: For now size must be 1 */
126 /* it is type float */
127 fl.f = (float) floatFromVal (val);
129 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
131 tsprintf (buffer, "!immedbyte", fl.c[offset]);
133 rs = Safe_calloc (1, strlen (buffer) + 1);
134 return strcpy (rs, buffer);
137 /*-----------------------------------------------------------------*/
138 /* aopLiteral - string from a literal value */
139 /*-----------------------------------------------------------------*/
141 aopLiteral (value * val, int offset)
143 return aopLiteralLong (val, offset, 1);
146 /*-----------------------------------------------------------------*/
147 /* emitRegularMap - emit code for maps with no special cases */
148 /*-----------------------------------------------------------------*/
150 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
157 /* PENDING: special case here - should remove */
158 if (!strcmp (map->sname, CODE_NAME))
159 tfprintf (map->oFile, "\t!areacode\n", map->sname);
160 else if (!strcmp (map->sname, DATA_NAME))
161 tfprintf (map->oFile, "\t!areadata\n", map->sname);
162 else if (!strcmp (map->sname, HOME_NAME))
163 tfprintf (map->oFile, "\t!areahome\n", map->sname);
165 tfprintf (map->oFile, "\t!area\n", map->sname);
168 /* print the area name */
169 for (sym = setFirstItem (map->syms); sym;
170 sym = setNextItem (map->syms))
173 /* if extern then add it into the extern list */
174 if (IS_EXTERN (sym->etype))
176 addSetHead (&externs, sym);
180 /* if allocation required check is needed
181 then check if the symbol really requires
182 allocation only for local variables */
183 if (arFlag && !IS_AGGREGATE (sym->type) &&
184 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
185 !sym->allocreq && sym->level)
188 /* if global variable & not static or extern
189 and addPublics allowed then add it to the public set */
190 if ((sym->level == 0 ||
191 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
193 !IS_STATIC (sym->etype) &&
194 (sym->used || sym->fbody))
196 addSetHead (&publics, sym);
199 /* if extern then do nothing or is a function
201 if (IS_FUNC (sym->type))
204 /* print extra debug info if required */
206 cdbSymbol (sym, cdbFile, FALSE, FALSE);
207 if (!sym->level) /* global */
208 if (IS_STATIC (sym->etype))
209 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
211 fprintf (map->oFile, "G$"); /* scope is global */
213 /* symbol is local */
214 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
215 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
218 /* if is has an absolute address then generate
219 an equate for this no need to allocate space */
220 if (SPEC_ABSA (sym->etype))
223 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
225 fprintf (map->oFile, "%s\t=\t0x%04x\n",
227 SPEC_ADDR (sym->etype));
233 fprintf (map->oFile, "==.\n");
235 if (IS_STATIC (sym->etype))
236 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
238 tfprintf (map->oFile, "!labeldef\n", sym->rname);
239 tfprintf (map->oFile, "\t!ds\n",
240 (unsigned int) getSize (sym->type) & 0xffff);
243 /* if it has an initial value then do it only if
244 it is a global variable */
245 if (sym->ival && sym->level == 0)
248 if (IS_AGGREGATE (sym->type))
249 ival = initAggregates (sym, sym->ival, NULL);
251 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
252 decorateType (resolveSymbols (list2expr (sym->ival))));
253 codeOutFile = statsg->oFile;
256 // set ival's lineno to where the symbol was defined
257 ival->lineno=sym->lineDef;
259 eBBlockFromiCode (iCodeFromAst (ival));
266 /*-----------------------------------------------------------------*/
267 /* initPointer - pointer initialization code massaging */
268 /*-----------------------------------------------------------------*/
270 initPointer (initList * ilist)
273 ast *expr = list2expr (ilist);
278 /* try it the oldway first */
279 if ((val = constExprValue (expr, FALSE)))
282 /* no then we have to do these cludgy checks */
283 /* pointers can be initialized with address of
284 a variable or address of an array element */
285 if (IS_AST_OP (expr) && expr->opval.op == '&') {
286 /* address of symbol */
287 if (IS_AST_SYM_VALUE (expr->left)) {
288 val = copyValue (AST_VALUE (expr->left));
289 val->type = newLink ();
290 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
291 DCL_TYPE (val->type) = CPOINTER;
292 DCL_PTR_CONST (val->type) = port->mem.code_ro;
294 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
295 DCL_TYPE (val->type) = FPOINTER;
296 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
297 DCL_TYPE (val->type) = PPOINTER;
298 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
299 DCL_TYPE (val->type) = IPOINTER;
300 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
301 DCL_TYPE (val->type) = EEPPOINTER;
303 DCL_TYPE (val->type) = POINTER;
304 val->type->next = expr->left->ftype;
305 val->etype = getSpec (val->type);
309 /* if address of indexed array */
310 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
311 return valForArray (expr->left);
313 /* if address of structure element then
315 if (IS_AST_OP (expr->left) &&
316 expr->left->opval.op == '.') {
317 return valForStructElem (expr->left->left,
322 (&some_struct)->element */
323 if (IS_AST_OP (expr->left) &&
324 expr->left->opval.op == PTR_OP &&
325 IS_ADDRESS_OF_OP (expr->left->left))
326 return valForStructElem (expr->left->left->left,
330 /* case 3. (((char *) &a) +/- constant) */
331 if (IS_AST_OP (expr) &&
332 (expr->opval.op == '+' || expr->opval.op == '-') &&
333 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
334 IS_AST_OP (expr->left->right) &&
335 expr->left->right->opval.op == '&' &&
336 IS_AST_LIT_VALUE (expr->right)) {
338 return valForCastAggr (expr->left->right->left,
339 expr->left->left->opval.lnk,
340 expr->right, expr->opval.op);
344 /* case 4. (char *)(array type) */
345 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
346 IS_ARRAY(expr->right->ftype)) {
348 val = copyValue (AST_VALUE (expr->right));
349 val->type = newLink ();
350 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
351 DCL_TYPE (val->type) = CPOINTER;
352 DCL_PTR_CONST (val->type) = port->mem.code_ro;
354 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
355 DCL_TYPE (val->type) = FPOINTER;
356 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
357 DCL_TYPE (val->type) = PPOINTER;
358 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
359 DCL_TYPE (val->type) = IPOINTER;
360 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
361 DCL_TYPE (val->type) = EEPPOINTER;
363 DCL_TYPE (val->type) = POINTER;
364 val->type->next = expr->right->ftype->next;
365 val->etype = getSpec (val->type);
369 werror (E_INIT_WRONG);
374 /*-----------------------------------------------------------------*/
375 /* printChar - formats and prints a characater string with DB */
376 /*-----------------------------------------------------------------*/
378 printChar (FILE * ofile, char *s, int plen)
381 int len = strlen (s);
386 while (len && pplen < plen)
389 while (i && *s && pplen < plen)
391 if (*s < ' ' || *s == '\"' || *s=='\\')
395 tfprintf (ofile, "\t!ascii\n", buf);
396 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
411 tfprintf (ofile, "\t!ascii\n", buf);
420 tfprintf (ofile, "\t!db !constbyte\n", 0);
423 /*-----------------------------------------------------------------*/
424 /* return the generic pointer high byte for a given pointer type. */
425 /*-----------------------------------------------------------------*/
427 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
435 /* hack - if we get a generic pointer, we just assume
436 * it's an FPOINTER (i.e. in XDATA space).
438 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
448 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
456 /*-----------------------------------------------------------------*/
457 /* printPointerType - generates ival for pointer type */
458 /*-----------------------------------------------------------------*/
460 _printPointerType (FILE * oFile, const char *name)
464 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
468 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
472 /*-----------------------------------------------------------------*/
473 /* printPointerType - generates ival for pointer type */
474 /*-----------------------------------------------------------------*/
476 printPointerType (FILE * oFile, const char *name)
478 _printPointerType (oFile, name);
479 fprintf (oFile, "\n");
482 /*-----------------------------------------------------------------*/
483 /* printGPointerType - generates ival for generic pointer type */
484 /*-----------------------------------------------------------------*/
486 printGPointerType (FILE * oFile, const char *iname, const char *oname,
487 const unsigned int type)
489 _printPointerType (oFile, iname);
490 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
493 /*-----------------------------------------------------------------*/
494 /* printIvalType - generates ival for int/char */
495 /*-----------------------------------------------------------------*/
497 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
501 /* if initList is deep */
502 if (ilist->type == INIT_DEEP)
503 ilist = ilist->init.deep;
505 val = list2val (ilist);
506 switch (getSize (type)) {
509 tfprintf (oFile, "\t!db !constbyte\n", 0);
511 tfprintf (oFile, "\t!dbs\n",
512 aopLiteral (val, 0));
516 if (port->use_dw_for_init)
517 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
519 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
523 tfprintf (oFile, "\t!dw !constword\n", 0);
524 tfprintf (oFile, "\t!dw !constword\n", 0);
527 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
528 aopLiteral (val, 0), aopLiteral (val, 1),
529 aopLiteral (val, 2), aopLiteral (val, 3));
535 /*-----------------------------------------------------------------*/
536 /* printIvalBitFields - generate initializer for bitfields */
537 /*-----------------------------------------------------------------*/
538 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
542 initList *lilist = *ilist ;
543 unsigned long ival = 0;
549 val = list2val(lilist);
551 if (SPEC_BLEN(lsym->etype) > 8) {
552 size += ((SPEC_BLEN (lsym->etype) / 8) +
553 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
556 size = ((SPEC_BLEN (lsym->etype) / 8) +
557 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
559 i = (unsigned long)floatFromVal(val);
560 i <<= SPEC_BSTR (lsym->etype);
562 if (! ( lsym->next &&
563 (IS_BITFIELD(lsym->next->type)) &&
564 (SPEC_BSTR(lsym->next->etype)))) break;
566 lilist = lilist->next;
570 tfprintf (oFile, "\t!db !constbyte\n",ival);
574 tfprintf (oFile, "\t!dw !constword\n",ival);
577 tfprintf (oFile, "\t!db !constword,!constword\n",
578 (ival >> 8) & 0xffff, (ival & 0xffff));
585 /*-----------------------------------------------------------------*/
586 /* printIvalStruct - generates initial value for structures */
587 /*-----------------------------------------------------------------*/
589 printIvalStruct (symbol * sym, sym_link * type,
590 initList * ilist, FILE * oFile)
595 sflds = SPEC_STRUCT (type)->fields;
596 if (ilist->type != INIT_DEEP) {
597 werror (E_INIT_STRUCT, sym->name);
601 iloop = ilist->init.deep;
603 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
604 if (IS_BITFIELD(sflds->type)) {
605 printIvalBitFields(&sflds,&iloop,oFile);
607 printIval (sflds, sflds->type, iloop, oFile);
613 /*-----------------------------------------------------------------*/
614 /* printIvalChar - generates initital value for character array */
615 /*-----------------------------------------------------------------*/
617 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
625 val = list2val (ilist);
626 /* if the value is a character string */
627 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
629 if (!DCL_ELEM (type))
630 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
632 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
634 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
636 tfprintf (oFile, "\t!db !constbyte\n", 0);
644 printChar (oFile, s, strlen (s) + 1);
648 /*-----------------------------------------------------------------*/
649 /* printIvalArray - generates code for array initialization */
650 /*-----------------------------------------------------------------*/
652 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
656 int lcnt = 0, size = 0;
658 /* take care of the special case */
659 /* array of characters can be init */
661 if (IS_CHAR (type->next))
662 if (printIvalChar (type,
663 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
664 oFile, SPEC_CVAL (sym->etype).v_char))
667 /* not the special case */
668 if (ilist->type != INIT_DEEP)
670 werror (E_INIT_STRUCT, sym->name);
674 iloop = ilist->init.deep;
675 lcnt = DCL_ELEM (type);
680 printIval (sym, type->next, iloop, oFile);
681 iloop = (iloop ? iloop->next : NULL);
684 /* if not array limits given & we */
685 /* are out of initialisers then */
686 if (!DCL_ELEM (type) && !iloop)
689 /* no of elements given and we */
690 /* have generated for all of them */
692 /* if initializers left */
694 werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
700 /* if we have not been given a size */
701 if (!DCL_ELEM (type))
702 DCL_ELEM (type) = size;
707 /*-----------------------------------------------------------------*/
708 /* printIvalFuncPtr - generate initial value for function pointers */
709 /*-----------------------------------------------------------------*/
711 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
716 val = list2val (ilist);
717 /* check the types */
718 if ((dLvl = compareType (val->type, type->next)) <= 0)
720 tfprintf (oFile, "\t!dw !constword\n", 0);
724 /* now generate the name */
727 if (port->use_dw_for_init)
729 tfprintf (oFile, "\t!dws\n", val->name);
733 printPointerType (oFile, val->name);
736 else if (port->use_dw_for_init)
738 tfprintf (oFile, "\t!dws\n", val->sym->rname);
742 printPointerType (oFile, val->sym->rname);
748 /*-----------------------------------------------------------------*/
749 /* printIvalCharPtr - generates initial values for character pointers */
750 /*-----------------------------------------------------------------*/
752 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
756 /* PENDING: this is _very_ mcs51 specific, including a magic
758 It's also endin specific.
760 size = getSize (type);
762 if (val->name && strlen (val->name))
764 if (size == 1) /* This appears to be Z80 specific?? */
767 "\t!dbs\n", val->name);
769 else if (size == FPTRSIZE)
771 if (port->use_dw_for_init)
773 tfprintf (oFile, "\t!dws\n", val->name);
777 printPointerType (oFile, val->name);
780 else if (size == GPTRSIZE)
783 if (IS_PTR (val->type)) {
784 type = DCL_TYPE (val->type);
786 type = PTR_TYPE (SPEC_OCLS (val->etype));
788 if (val->sym && val->sym->isstrlit) {
789 // this is a literal string
792 printGPointerType (oFile, val->name, sym->name, type);
796 fprintf (stderr, "*** internal error: unknown size in "
797 "printIvalCharPtr.\n");
802 /* What is this case? Are these pointers? */
806 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
809 if (port->use_dw_for_init)
810 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
812 tfprintf (oFile, "\t.byte %s,%s\n",
813 aopLiteral (val, 0), aopLiteral (val, 1));
816 /* PENDING: 0x02 or 0x%02x, CDATA? */
817 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
818 aopLiteral (val, 0), aopLiteral (val, 1));
825 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
826 addSet (&statsg->syms, val->sym);
832 /*-----------------------------------------------------------------*/
833 /* printIvalPtr - generates initial value for pointers */
834 /*-----------------------------------------------------------------*/
836 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
842 if (ilist->type == INIT_DEEP)
843 ilist = ilist->init.deep;
845 /* function pointer */
846 if (IS_FUNC (type->next))
848 printIvalFuncPtr (type, ilist, oFile);
852 if (!(val = initPointer (ilist)))
855 /* if character pointer */
856 if (IS_CHAR (type->next))
857 if (printIvalCharPtr (sym, type, val, oFile))
861 if (compareType (type, val->type) == 0)
862 werror (E_INIT_WRONG);
864 /* if val is literal */
865 if (IS_LITERAL (val->etype))
867 switch (getSize (type))
870 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
873 if (port->use_dw_for_init)
874 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
876 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
879 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
880 aopLiteral (val, 0), aopLiteral (val, 1));
886 size = getSize (type);
888 if (size == 1) /* Z80 specific?? */
890 tfprintf (oFile, "\t!dbs\n", val->name);
892 else if (size == FPTRSIZE)
894 if (port->use_dw_for_init) {
895 tfprintf (oFile, "\t!dws\n", val->name);
897 printPointerType (oFile, val->name);
900 else if (size == GPTRSIZE)
902 printGPointerType (oFile, val->name, sym->name,
903 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
904 PTR_TYPE (SPEC_OCLS (val->etype))));
909 /*-----------------------------------------------------------------*/
910 /* printIval - generates code for initial value */
911 /*-----------------------------------------------------------------*/
913 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
918 /* if structure then */
919 if (IS_STRUCT (type))
921 printIvalStruct (sym, type, ilist, oFile);
925 /* if this is a pointer */
928 printIvalPtr (sym, type, ilist, oFile);
932 /* if this is an array */
935 printIvalArray (sym, type, ilist, oFile);
939 /* if type is SPECIFIER */
942 printIvalType (type, ilist, oFile);
947 /*-----------------------------------------------------------------*/
948 /* emitStaticSeg - emitcode for the static segment */
949 /*-----------------------------------------------------------------*/
951 emitStaticSeg (memmap * map, FILE * out)
955 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
959 /* for all variables in this segment do */
960 for (sym = setFirstItem (map->syms); sym;
961 sym = setNextItem (map->syms))
964 /* if it is "extern" then do nothing */
965 if (IS_EXTERN (sym->etype))
968 /* if it is not static add it to the public
970 if (!IS_STATIC (sym->etype))
971 addSetHead (&publics, sym);
973 /* print extra debug info if required */
975 cdbSymbol (sym, cdbFile, FALSE, FALSE);
978 if (IS_STATIC (sym->etype))
979 fprintf (out, "F%s$", moduleName); /* scope is file */
981 fprintf (out, "G$"); /* scope is global */
984 /* symbol is local */
985 fprintf (out, "L%s$",
986 (sym->localof ? sym->localof->name : "-null-"));
987 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
990 /* if it has an absolute address */
991 if (SPEC_ABSA (sym->etype))
994 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
996 fprintf (out, "%s\t=\t0x%04x\n",
998 SPEC_ADDR (sym->etype));
1003 fprintf (out, " == .\n");
1005 /* if it has an initial value */
1008 fprintf (out, "%s:\n", sym->rname);
1010 resolveIvalSym (sym->ival);
1011 printIval (sym, sym->type, sym->ival, out);
1016 /* allocate space */
1017 fprintf (out, "%s:\n", sym->rname);
1018 /* special case for character strings */
1019 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1020 SPEC_CVAL (sym->etype).v_char)
1022 SPEC_CVAL (sym->etype).v_char,
1023 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1025 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1031 /*-----------------------------------------------------------------*/
1032 /* emitMaps - emits the code for the data portion the code */
1033 /*-----------------------------------------------------------------*/
1038 /* no special considerations for the following
1039 data, idata & bit & xdata */
1040 emitRegularMap (data, TRUE, TRUE);
1041 emitRegularMap (idata, TRUE, TRUE);
1042 emitRegularMap (bit, TRUE, FALSE);
1043 emitRegularMap (xdata, TRUE, TRUE);
1044 emitRegularMap (sfr, FALSE, FALSE);
1045 emitRegularMap (sfrbit, FALSE, FALSE);
1046 emitRegularMap (home, TRUE, FALSE);
1047 emitRegularMap (code, TRUE, FALSE);
1049 emitStaticSeg (statsg, code->oFile);
1053 /*-----------------------------------------------------------------*/
1054 /* flushStatics - flush all currently defined statics out to file */
1055 /* and delete. Temporary function */
1056 /*-----------------------------------------------------------------*/
1060 emitStaticSeg (statsg, codeOutFile);
1061 statsg->syms = NULL;
1064 /*-----------------------------------------------------------------*/
1065 /* createInterruptVect - creates the interrupt vector */
1066 /*-----------------------------------------------------------------*/
1068 createInterruptVect (FILE * vFile)
1071 mainf = newSymbol ("main", 0);
1074 /* only if the main function exists */
1075 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1077 if (!options.cc_only && !noAssemble)
1082 /* if the main is only a prototype ie. no body then do nothing */
1085 /* if ! compile only then main function should be present */
1086 if (!options.cc_only && !noAssemble)
1091 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1092 fprintf (vFile, "__interrupt_vect:\n");
1095 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1097 /* "generic" interrupt table header (if port doesn't specify one).
1099 * Look suspiciously like 8051 code to me...
1102 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1105 /* now for the other interrupts */
1106 for (; i < maxInterrupts; i++)
1109 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1111 fprintf (vFile, "\treti\n\t.ds\t7\n");
1118 ";--------------------------------------------------------\n"
1119 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1123 ";--------------------------------------------------------\n"};
1126 /*-----------------------------------------------------------------*/
1127 /* initialComments - puts in some initial comments */
1128 /*-----------------------------------------------------------------*/
1130 initialComments (FILE * afile)
1134 fprintf (afile, "%s", iComments1);
1135 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1136 fprintf (afile, "%s", iComments2);
1139 /*-----------------------------------------------------------------*/
1140 /* printPublics - generates .global for publics */
1141 /*-----------------------------------------------------------------*/
1143 printPublics (FILE * afile)
1147 fprintf (afile, "%s", iComments2);
1148 fprintf (afile, "; Public variables in this module\n");
1149 fprintf (afile, "%s", iComments2);
1151 for (sym = setFirstItem (publics); sym;
1152 sym = setNextItem (publics))
1153 tfprintf (afile, "\t!global\n", sym->rname);
1156 /*-----------------------------------------------------------------*/
1157 /* printExterns - generates .global for externs */
1158 /*-----------------------------------------------------------------*/
1160 printExterns (FILE * afile)
1164 fprintf (afile, "%s", iComments2);
1165 fprintf (afile, "; Externals used\n");
1166 fprintf (afile, "%s", iComments2);
1168 for (sym = setFirstItem (externs); sym;
1169 sym = setNextItem (externs))
1170 tfprintf (afile, "\t!global\n", sym->rname);
1173 /*-----------------------------------------------------------------*/
1174 /* emitOverlay - will emit code for the overlay stuff */
1175 /*-----------------------------------------------------------------*/
1177 emitOverlay (FILE * afile)
1181 if (!elementsInSet (ovrSetSets))
1182 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1184 /* for each of the sets in the overlay segment do */
1185 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1186 ovrset = setNextItem (ovrSetSets))
1191 if (elementsInSet (ovrset))
1193 /* this dummy area is used to fool the assembler
1194 otherwise the assembler will append each of these
1195 declarations into one chunk and will not overlay
1197 fprintf (afile, "\t.area _DUMMY\n");
1198 /* output the area informtion */
1199 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1202 for (sym = setFirstItem (ovrset); sym;
1203 sym = setNextItem (ovrset))
1206 /* if extern then add it to the publics tabledo nothing */
1207 if (IS_EXTERN (sym->etype))
1210 /* if allocation required check is needed
1211 then check if the symbol really requires
1212 allocation only for local variables */
1213 if (!IS_AGGREGATE (sym->type) &&
1214 !(sym->_isparm && !IS_REGPARM (sym->etype))
1215 && !sym->allocreq && sym->level)
1218 /* if global variable & not static or extern
1219 and addPublics allowed then add it to the public set */
1220 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1221 && !IS_STATIC (sym->etype))
1222 addSetHead (&publics, sym);
1224 /* if extern then do nothing or is a function
1226 if (IS_FUNC (sym->type))
1229 /* print extra debug info if required */
1232 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1236 if (IS_STATIC (sym->etype))
1237 fprintf (afile, "F%s$", moduleName); /* scope is file */
1239 fprintf (afile, "G$"); /* scope is global */
1242 /* symbol is local */
1243 fprintf (afile, "L%s$",
1244 (sym->localof ? sym->localof->name : "-null-"));
1245 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1248 /* if is has an absolute address then generate
1249 an equate for this no need to allocate space */
1250 if (SPEC_ABSA (sym->etype))
1254 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1256 fprintf (afile, "%s\t=\t0x%04x\n",
1258 SPEC_ADDR (sym->etype));
1263 fprintf (afile, "==.\n");
1265 /* allocate space */
1266 tfprintf (afile, "!labeldef\n", sym->rname);
1267 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1274 /*-----------------------------------------------------------------*/
1275 /* glue - the final glue that hold the whole thing together */
1276 /*-----------------------------------------------------------------*/
1282 FILE *ovrFile = tempfile ();
1284 addSetHead (&tmpfileSet, ovrFile);
1285 /* print the global struct definitions */
1287 cdbStructBlock (0, cdbFile);
1289 vFile = tempfile ();
1290 /* PENDING: this isnt the best place but it will do */
1291 if (port->general.glue_up_main)
1293 /* create the interrupt vector table */
1294 createInterruptVect (vFile);
1297 addSetHead (&tmpfileSet, vFile);
1299 /* emit code for the all the variables declared */
1301 /* do the overlay segments */
1302 emitOverlay (ovrFile);
1304 /* now put it all together into the assembler file */
1305 /* create the assembler file name */
1307 if (!options.c1mode)
1309 sprintf (scratchFileName, srcFileName);
1310 strcat (scratchFileName, port->assembler.file_ext);
1314 strcpy (scratchFileName, options.out_name);
1317 if (!(asmFile = fopen (scratchFileName, "w")))
1319 werror (E_FILE_OPEN_ERR, scratchFileName);
1323 /* initial comments */
1324 initialComments (asmFile);
1326 /* print module name */
1327 tfprintf (asmFile, "\t!module\n", moduleName);
1328 tfprintf (asmFile, "\t!fileprelude\n");
1330 /* Let the port generate any global directives, etc. */
1331 if (port->genAssemblerPreamble)
1333 port->genAssemblerPreamble (asmFile);
1336 /* print the global variables in this module */
1337 printPublics (asmFile);
1338 if (port->assembler.externGlobal)
1339 printExterns (asmFile);
1341 /* copy the sfr segment */
1342 fprintf (asmFile, "%s", iComments2);
1343 fprintf (asmFile, "; special function registers\n");
1344 fprintf (asmFile, "%s", iComments2);
1345 copyFile (asmFile, sfr->oFile);
1347 /* copy the sbit segment */
1348 fprintf (asmFile, "%s", iComments2);
1349 fprintf (asmFile, "; special function bits \n");
1350 fprintf (asmFile, "%s", iComments2);
1351 copyFile (asmFile, sfrbit->oFile);
1353 /* copy the data segment */
1354 fprintf (asmFile, "%s", iComments2);
1355 fprintf (asmFile, "; internal ram data\n");
1356 fprintf (asmFile, "%s", iComments2);
1357 copyFile (asmFile, data->oFile);
1360 /* create the overlay segments */
1361 fprintf (asmFile, "%s", iComments2);
1362 fprintf (asmFile, "; overlayable items in internal ram \n");
1363 fprintf (asmFile, "%s", iComments2);
1364 copyFile (asmFile, ovrFile);
1366 /* create the stack segment MOF */
1367 if (mainf && mainf->fbody)
1369 fprintf (asmFile, "%s", iComments2);
1370 fprintf (asmFile, "; Stack segment in internal ram \n");
1371 fprintf (asmFile, "%s", iComments2);
1372 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1373 "__start__stack:\n\t.ds\t1\n\n");
1376 /* create the idata segment */
1377 fprintf (asmFile, "%s", iComments2);
1378 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1379 fprintf (asmFile, "%s", iComments2);
1380 copyFile (asmFile, idata->oFile);
1382 /* copy the bit segment */
1383 fprintf (asmFile, "%s", iComments2);
1384 fprintf (asmFile, "; bit data\n");
1385 fprintf (asmFile, "%s", iComments2);
1386 copyFile (asmFile, bit->oFile);
1388 /* if external stack then reserve space of it */
1389 if (mainf && mainf->fbody && options.useXstack)
1391 fprintf (asmFile, "%s", iComments2);
1392 fprintf (asmFile, "; external stack \n");
1393 fprintf (asmFile, "%s", iComments2);
1394 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1395 fprintf (asmFile, "\t.ds 256\n");
1399 /* copy xtern ram data */
1400 fprintf (asmFile, "%s", iComments2);
1401 fprintf (asmFile, "; external ram data\n");
1402 fprintf (asmFile, "%s", iComments2);
1403 copyFile (asmFile, xdata->oFile);
1405 /* copy the interrupt vector table */
1406 if (mainf && mainf->fbody)
1408 fprintf (asmFile, "%s", iComments2);
1409 fprintf (asmFile, "; interrupt vector \n");
1410 fprintf (asmFile, "%s", iComments2);
1411 copyFile (asmFile, vFile);
1414 /* copy global & static initialisations */
1415 fprintf (asmFile, "%s", iComments2);
1416 fprintf (asmFile, "; global & static initialisations\n");
1417 fprintf (asmFile, "%s", iComments2);
1419 /* Everywhere we generate a reference to the static_name area,
1420 * (which is currently only here), we immediately follow it with a
1421 * definition of the post_static_name area. This guarantees that
1422 * the post_static_name area will immediately follow the static_name
1425 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1426 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1427 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1429 if (mainf && mainf->fbody)
1431 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1432 /* if external stack is specified then the
1433 higher order byte of the xdatalocation is
1434 going into P2 and the lower order going into
1436 if (options.useXstack)
1438 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1439 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1440 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1441 (unsigned int) options.xdata_loc & 0xff);
1444 /* initialise the stack pointer */
1445 /* if the user specified a value then use it */
1446 if (options.stack_loc)
1447 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1449 /* no: we have to compute it */
1450 if (!options.stackOnData && maxRegBank <= 3)
1451 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1453 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1455 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1456 fprintf (asmFile, "\tmov\ta,dpl\n");
1457 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1458 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1459 fprintf (asmFile, "__sdcc_init_data:\n");
1462 copyFile (asmFile, statsg->oFile);
1464 if (port->general.glue_up_main && mainf && mainf->fbody)
1466 /* This code is generated in the post-static area.
1467 * This area is guaranteed to follow the static area
1468 * by the ugly shucking and jiving about 20 lines ago.
1470 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1471 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1477 "%s", iComments2, iComments2);
1478 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1479 copyFile (asmFile, home->oFile);
1481 /* copy over code */
1482 fprintf (asmFile, "%s", iComments2);
1483 fprintf (asmFile, "; code\n");
1484 fprintf (asmFile, "%s", iComments2);
1485 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1486 if (mainf && mainf->fbody)
1489 /* entry point @ start of CSEG */
1490 fprintf (asmFile, "__sdcc_program_startup:\n");
1492 /* put in the call to main */
1493 fprintf (asmFile, "\tlcall\t_main\n");
1494 if (options.mainreturn)
1497 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1498 fprintf (asmFile, "\tret\n");
1504 fprintf (asmFile, ";\treturn from main will lock up\n");
1505 fprintf (asmFile, "\tsjmp .\n");
1508 copyFile (asmFile, code->oFile);
1511 applyToSet (tmpfileSet, closeTmpFiles);
1512 applyToSet (tmpfileNameSet, rmTmpFiles);
1515 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1519 applyToSet (tmpfileSet, closeTmpFiles);
1520 applyToSet (tmpfileNameSet, rmTmpFiles);
1524 /** Creates a temporary file a'la tmpfile which avoids the bugs
1525 in cygwin wrt c:\tmp.
1526 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1531 #if !defined(_MSC_VER)
1532 const char *tmpdir = NULL;
1534 tmpdir = getenv ("TMP");
1535 else if (getenv ("TEMP"))
1536 tmpdir = getenv ("TEMP");
1537 else if (getenv ("TMPDIR"))
1538 tmpdir = getenv ("TMPDIR");
1541 char *name = tempnam (tmpdir, "sdcc");
1544 FILE *fp = fopen (name, "w+b");
1547 addSetHead (&tmpfileNameSet, name);
1558 gc_strdup (const char *s)
1561 ret = Safe_calloc (1, strlen (s) + 1);