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)
157 symbol *sym, *symIval;
163 /* PENDING: special case here - should remove */
164 if (!strcmp (map->sname, CODE_NAME))
165 tfprintf (map->oFile, "\t!areacode\n", map->sname);
166 else if (!strcmp (map->sname, DATA_NAME))
167 tfprintf (map->oFile, "\t!areadata\n", map->sname);
168 else if (!strcmp (map->sname, HOME_NAME))
169 tfprintf (map->oFile, "\t!areahome\n", map->sname);
171 tfprintf (map->oFile, "\t!area\n", map->sname);
174 /* print the area name */
175 for (sym = setFirstItem (map->syms); sym;
176 sym = setNextItem (map->syms))
179 /* if extern then add it into the extern list */
180 if (IS_EXTERN (sym->etype))
182 addSetHead (&externs, sym);
186 /* if allocation required check is needed
187 then check if the symbol really requires
188 allocation only for local variables */
190 if (arFlag && !IS_AGGREGATE (sym->type) &&
191 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
192 !sym->allocreq && sym->level)
195 /* if global variable & not static or extern
196 and addPublics allowed then add it to the public set */
197 if ((sym->level == 0 ||
198 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
200 !IS_STATIC (sym->etype) &&
201 (IS_FUNC(sym->type) ? (sym->used || sym->fbody) : 1))
203 addSetHead (&publics, sym);
206 /* if extern then do nothing or is a function
208 if (IS_FUNC (sym->type))
211 /* print extra debug info if required */
213 cdbSymbol (sym, cdbFile, FALSE, FALSE);
214 if (!sym->level) /* global */
215 if (IS_STATIC (sym->etype))
216 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
218 fprintf (map->oFile, "G$"); /* scope is global */
220 /* symbol is local */
221 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
222 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
225 /* if is has an absolute address then generate
226 an equate for this no need to allocate space */
227 if (SPEC_ABSA (sym->etype))
230 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
232 fprintf (map->oFile, "%s\t=\t0x%04x\n",
234 SPEC_ADDR (sym->etype));
240 fprintf (map->oFile, "==.\n");
242 if (IS_STATIC (sym->etype))
243 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
245 tfprintf (map->oFile, "!labeldef\n", sym->rname);
246 tfprintf (map->oFile, "\t!ds\n",
247 (unsigned int) getSize (sym->type) & 0xffff);
250 /* if it has an initial value then do it only if
251 it is a global variable */
252 if (sym->ival && sym->level == 0)
254 if (IS_AGGREGATE (sym->type)) {
255 ival = initAggregates (sym, sym->ival, NULL);
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 if (ival) ival->lineno=sym->lineDef;
265 eBBlockFromiCode (iCodeFromAst (ival));
268 /* if the ival is a symbol assigned to an aggregate,
269 (bug #458099 -> #462479)
270 we don't need it anymore, so delete it from its segment */
271 if (IS_AST_SYM_VALUE(sym->ival->init.node) &&
272 IS_AGGREGATE (sym->type) ) {
273 symIval=AST_SYMBOL(sym->ival->init.node);
274 segment = SPEC_OCLS (symIval->etype);
275 deleteSetItem (&segment->syms, symIval);
283 /*-----------------------------------------------------------------*/
284 /* initPointer - pointer initialization code massaging */
285 /*-----------------------------------------------------------------*/
287 initPointer (initList * ilist)
290 ast *expr = list2expr (ilist);
295 /* try it the oldway first */
296 if ((val = constExprValue (expr, FALSE)))
299 /* no then we have to do these cludgy checks */
300 /* pointers can be initialized with address of
301 a variable or address of an array element */
302 if (IS_AST_OP (expr) && expr->opval.op == '&') {
303 /* address of symbol */
304 if (IS_AST_SYM_VALUE (expr->left)) {
305 val = copyValue (AST_VALUE (expr->left));
306 val->type = newLink ();
307 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
308 DCL_TYPE (val->type) = CPOINTER;
309 DCL_PTR_CONST (val->type) = port->mem.code_ro;
311 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
312 DCL_TYPE (val->type) = FPOINTER;
313 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
314 DCL_TYPE (val->type) = PPOINTER;
315 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
316 DCL_TYPE (val->type) = IPOINTER;
317 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
318 DCL_TYPE (val->type) = EEPPOINTER;
320 DCL_TYPE (val->type) = POINTER;
321 val->type->next = expr->left->ftype;
322 val->etype = getSpec (val->type);
326 /* if address of indexed array */
327 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
328 return valForArray (expr->left);
330 /* if address of structure element then
332 if (IS_AST_OP (expr->left) &&
333 expr->left->opval.op == '.') {
334 return valForStructElem (expr->left->left,
339 (&some_struct)->element */
340 if (IS_AST_OP (expr->left) &&
341 expr->left->opval.op == PTR_OP &&
342 IS_ADDRESS_OF_OP (expr->left->left))
343 return valForStructElem (expr->left->left->left,
347 /* case 3. (((char *) &a) +/- constant) */
348 if (IS_AST_OP (expr) &&
349 (expr->opval.op == '+' || expr->opval.op == '-') &&
350 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
351 IS_AST_OP (expr->left->right) &&
352 expr->left->right->opval.op == '&' &&
353 IS_AST_LIT_VALUE (expr->right)) {
355 return valForCastAggr (expr->left->right->left,
356 expr->left->left->opval.lnk,
357 expr->right, expr->opval.op);
361 /* case 4. (char *)(array type) */
362 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
363 IS_ARRAY(expr->right->ftype)) {
365 val = copyValue (AST_VALUE (expr->right));
366 val->type = newLink ();
367 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
368 DCL_TYPE (val->type) = CPOINTER;
369 DCL_PTR_CONST (val->type) = port->mem.code_ro;
371 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
372 DCL_TYPE (val->type) = FPOINTER;
373 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
374 DCL_TYPE (val->type) = PPOINTER;
375 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
376 DCL_TYPE (val->type) = IPOINTER;
377 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
378 DCL_TYPE (val->type) = EEPPOINTER;
380 DCL_TYPE (val->type) = POINTER;
381 val->type->next = expr->right->ftype->next;
382 val->etype = getSpec (val->type);
386 werror (W_INIT_WRONG);
391 /*-----------------------------------------------------------------*/
392 /* printChar - formats and prints a characater string with DB */
393 /*-----------------------------------------------------------------*/
395 printChar (FILE * ofile, char *s, int plen)
398 int len = strlen (s);
403 while (len && pplen < plen)
406 while (i && *s && pplen < plen)
408 if (*s < ' ' || *s == '\"' || *s=='\\')
412 tfprintf (ofile, "\t!ascii\n", buf);
413 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
428 tfprintf (ofile, "\t!ascii\n", buf);
437 tfprintf (ofile, "\t!db !constbyte\n", 0);
440 /*-----------------------------------------------------------------*/
441 /* return the generic pointer high byte for a given pointer type. */
442 /*-----------------------------------------------------------------*/
444 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
452 /* hack - if we get a generic pointer, we just assume
453 * it's an FPOINTER (i.e. in XDATA space).
455 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
465 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
473 /*-----------------------------------------------------------------*/
474 /* printPointerType - generates ival for pointer type */
475 /*-----------------------------------------------------------------*/
477 _printPointerType (FILE * oFile, const char *name)
479 /* if (TARGET_IS_DS390) */
480 if (options.model == MODEL_FLAT24)
482 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
486 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
490 /*-----------------------------------------------------------------*/
491 /* printPointerType - generates ival for pointer type */
492 /*-----------------------------------------------------------------*/
494 printPointerType (FILE * oFile, const char *name)
496 _printPointerType (oFile, name);
497 fprintf (oFile, "\n");
500 /*-----------------------------------------------------------------*/
501 /* printGPointerType - generates ival for generic pointer type */
502 /*-----------------------------------------------------------------*/
504 printGPointerType (FILE * oFile, const char *iname, const char *oname,
505 const unsigned int type)
507 _printPointerType (oFile, iname);
508 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
511 /*-----------------------------------------------------------------*/
512 /* printIvalType - generates ival for int/char */
513 /*-----------------------------------------------------------------*/
515 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
519 /* if initList is deep */
520 if (ilist->type == INIT_DEEP)
521 ilist = ilist->init.deep;
523 val = list2val (ilist);
524 switch (getSize (type)) {
527 tfprintf (oFile, "\t!db !constbyte\n", 0);
529 tfprintf (oFile, "\t!dbs\n",
530 aopLiteral (val, 0));
534 if (port->use_dw_for_init)
535 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
537 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
541 tfprintf (oFile, "\t!dw !constword\n", 0);
542 tfprintf (oFile, "\t!dw !constword\n", 0);
545 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
546 aopLiteral (val, 0), aopLiteral (val, 1),
547 aopLiteral (val, 2), aopLiteral (val, 3));
553 /*-----------------------------------------------------------------*/
554 /* printIvalBitFields - generate initializer for bitfields */
555 /*-----------------------------------------------------------------*/
556 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
560 initList *lilist = *ilist ;
561 unsigned long ival = 0;
567 val = list2val(lilist);
569 if (SPEC_BLEN(lsym->etype) > 8) {
570 size += ((SPEC_BLEN (lsym->etype) / 8) +
571 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
574 size = ((SPEC_BLEN (lsym->etype) / 8) +
575 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
577 i = (unsigned long)floatFromVal(val);
578 i <<= SPEC_BSTR (lsym->etype);
580 if (! ( lsym->next &&
581 (IS_BITFIELD(lsym->next->type)) &&
582 (SPEC_BSTR(lsym->next->etype)))) break;
584 lilist = lilist->next;
588 tfprintf (oFile, "\t!db !constbyte\n",ival);
592 tfprintf (oFile, "\t!dw !constword\n",ival);
595 tfprintf (oFile, "\t!db !constword,!constword\n",
596 (ival >> 8) & 0xffff, (ival & 0xffff));
603 /*-----------------------------------------------------------------*/
604 /* printIvalStruct - generates initial value for structures */
605 /*-----------------------------------------------------------------*/
607 printIvalStruct (symbol * sym, sym_link * type,
608 initList * ilist, FILE * oFile)
613 sflds = SPEC_STRUCT (type)->fields;
614 if (ilist->type != INIT_DEEP) {
615 werror (E_INIT_STRUCT, sym->name);
619 iloop = ilist->init.deep;
621 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
622 if (IS_BITFIELD(sflds->type)) {
623 printIvalBitFields(&sflds,&iloop,oFile);
625 printIval (sflds, sflds->type, iloop, oFile);
631 /*-----------------------------------------------------------------*/
632 /* printIvalChar - generates initital value for character array */
633 /*-----------------------------------------------------------------*/
635 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
643 val = list2val (ilist);
644 /* if the value is a character string */
645 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
647 if (!DCL_ELEM (type))
648 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
650 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
652 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
654 tfprintf (oFile, "\t!db !constbyte\n", 0);
662 printChar (oFile, s, strlen (s) + 1);
666 /*-----------------------------------------------------------------*/
667 /* printIvalArray - generates code for array initialization */
668 /*-----------------------------------------------------------------*/
670 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
674 int lcnt = 0, size = 0;
676 /* take care of the special case */
677 /* array of characters can be init */
679 if (IS_CHAR (type->next))
680 if (printIvalChar (type,
681 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
682 oFile, SPEC_CVAL (sym->etype).v_char))
685 /* not the special case */
686 if (ilist->type != INIT_DEEP)
688 werror (E_INIT_STRUCT, sym->name);
692 iloop = ilist->init.deep;
693 lcnt = DCL_ELEM (type);
698 printIval (sym, type->next, iloop, oFile);
699 iloop = (iloop ? iloop->next : NULL);
702 /* if not array limits given & we */
703 /* are out of initialisers then */
704 if (!DCL_ELEM (type) && !iloop)
707 /* no of elements given and we */
708 /* have generated for all of them */
710 /* if initializers left */
712 werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
718 /* if we have not been given a size */
719 if (!DCL_ELEM (type))
720 DCL_ELEM (type) = size;
725 /*-----------------------------------------------------------------*/
726 /* printIvalFuncPtr - generate initial value for function pointers */
727 /*-----------------------------------------------------------------*/
729 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
734 val = list2val (ilist);
735 /* check the types */
736 if ((dLvl = compareType (val->type, type->next)) <= 0)
738 tfprintf (oFile, "\t!dw !constword\n", 0);
742 /* now generate the name */
745 if (port->use_dw_for_init)
747 tfprintf (oFile, "\t!dws\n", val->name);
751 printPointerType (oFile, val->name);
754 else if (port->use_dw_for_init)
756 tfprintf (oFile, "\t!dws\n", val->sym->rname);
760 printPointerType (oFile, val->sym->rname);
766 /*-----------------------------------------------------------------*/
767 /* printIvalCharPtr - generates initial values for character pointers */
768 /*-----------------------------------------------------------------*/
770 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
774 /* PENDING: this is _very_ mcs51 specific, including a magic
776 It's also endin specific.
778 size = getSize (type);
780 if (val->name && strlen (val->name))
782 if (size == 1) /* This appears to be Z80 specific?? */
785 "\t!dbs\n", val->name);
787 else if (size == FPTRSIZE)
789 if (port->use_dw_for_init)
791 tfprintf (oFile, "\t!dws\n", val->name);
795 printPointerType (oFile, val->name);
798 else if (size == GPTRSIZE)
801 if (IS_PTR (val->type)) {
802 type = DCL_TYPE (val->type);
804 type = PTR_TYPE (SPEC_OCLS (val->etype));
806 if (val->sym && val->sym->isstrlit) {
807 // this is a literal string
810 printGPointerType (oFile, val->name, sym->name, type);
814 fprintf (stderr, "*** internal error: unknown size in "
815 "printIvalCharPtr.\n");
820 /* What is this case? Are these pointers? */
824 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
827 if (port->use_dw_for_init)
828 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
830 tfprintf (oFile, "\t.byte %s,%s\n",
831 aopLiteral (val, 0), aopLiteral (val, 1));
834 /* PENDING: 0x02 or 0x%02x, CDATA? */
835 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
836 aopLiteral (val, 0), aopLiteral (val, 1));
843 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
844 addSet (&statsg->syms, val->sym);
850 /*-----------------------------------------------------------------*/
851 /* printIvalPtr - generates initial value for pointers */
852 /*-----------------------------------------------------------------*/
854 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
860 if (ilist->type == INIT_DEEP)
861 ilist = ilist->init.deep;
863 /* function pointer */
864 if (IS_FUNC (type->next))
866 printIvalFuncPtr (type, ilist, oFile);
870 if (!(val = initPointer (ilist)))
873 /* if character pointer */
874 if (IS_CHAR (type->next))
875 if (printIvalCharPtr (sym, type, val, oFile))
879 if (compareType (type, val->type) == 0)
880 werror (W_INIT_WRONG);
882 /* if val is literal */
883 if (IS_LITERAL (val->etype))
885 switch (getSize (type))
888 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
891 if (port->use_dw_for_init)
892 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
894 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
897 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
898 aopLiteral (val, 0), aopLiteral (val, 1));
904 size = getSize (type);
906 if (size == 1) /* Z80 specific?? */
908 tfprintf (oFile, "\t!dbs\n", val->name);
910 else if (size == FPTRSIZE)
912 if (port->use_dw_for_init) {
913 tfprintf (oFile, "\t!dws\n", val->name);
915 printPointerType (oFile, val->name);
918 else if (size == GPTRSIZE)
920 printGPointerType (oFile, val->name, sym->name,
921 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
922 PTR_TYPE (SPEC_OCLS (val->etype))));
927 /*-----------------------------------------------------------------*/
928 /* printIval - generates code for initial value */
929 /*-----------------------------------------------------------------*/
931 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
936 /* if structure then */
937 if (IS_STRUCT (type))
939 printIvalStruct (sym, type, ilist, oFile);
943 /* if this is a pointer */
946 printIvalPtr (sym, type, ilist, oFile);
950 /* if this is an array */
953 printIvalArray (sym, type, ilist, oFile);
957 /* if type is SPECIFIER */
960 printIvalType (type, ilist, oFile);
965 /*-----------------------------------------------------------------*/
966 /* emitStaticSeg - emitcode for the static segment */
967 /*-----------------------------------------------------------------*/
969 emitStaticSeg (memmap * map, FILE * out)
973 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
977 /* for all variables in this segment do */
978 for (sym = setFirstItem (map->syms); sym;
979 sym = setNextItem (map->syms))
982 /* if it is "extern" then do nothing */
983 if (IS_EXTERN (sym->etype))
986 /* if it is not static add it to the public
988 if (!IS_STATIC (sym->etype))
989 addSetHead (&publics, sym);
991 /* print extra debug info if required */
993 cdbSymbol (sym, cdbFile, FALSE, FALSE);
996 if (IS_STATIC (sym->etype))
997 fprintf (out, "F%s$", moduleName); /* scope is file */
999 fprintf (out, "G$"); /* scope is global */
1002 /* symbol is local */
1003 fprintf (out, "L%s$",
1004 (sym->localof ? sym->localof->name : "-null-"));
1005 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1008 /* if it has an absolute address */
1009 if (SPEC_ABSA (sym->etype))
1012 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1014 fprintf (out, "%s\t=\t0x%04x\n",
1016 SPEC_ADDR (sym->etype));
1021 fprintf (out, " == .\n");
1023 /* if it has an initial value */
1026 fprintf (out, "%s:\n", sym->rname);
1028 resolveIvalSym (sym->ival);
1029 printIval (sym, sym->type, sym->ival, out);
1034 /* allocate space */
1035 fprintf (out, "%s:\n", sym->rname);
1036 /* special case for character strings */
1037 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1038 SPEC_CVAL (sym->etype).v_char)
1040 SPEC_CVAL (sym->etype).v_char,
1041 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1043 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1049 /*-----------------------------------------------------------------*/
1050 /* emitMaps - emits the code for the data portion the code */
1051 /*-----------------------------------------------------------------*/
1056 /* no special considerations for the following
1057 data, idata & bit & xdata */
1058 emitRegularMap (data, TRUE, TRUE);
1059 emitRegularMap (idata, TRUE, TRUE);
1060 emitRegularMap (bit, TRUE, FALSE);
1061 emitRegularMap (xdata, TRUE, TRUE);
1062 emitRegularMap (sfr, FALSE, FALSE);
1063 emitRegularMap (sfrbit, FALSE, FALSE);
1064 emitRegularMap (home, TRUE, FALSE);
1065 emitRegularMap (code, TRUE, FALSE);
1067 emitStaticSeg (statsg, code->oFile);
1071 /*-----------------------------------------------------------------*/
1072 /* flushStatics - flush all currently defined statics out to file */
1073 /* and delete. Temporary function */
1074 /*-----------------------------------------------------------------*/
1078 emitStaticSeg (statsg, codeOutFile);
1079 statsg->syms = NULL;
1082 /*-----------------------------------------------------------------*/
1083 /* createInterruptVect - creates the interrupt vector */
1084 /*-----------------------------------------------------------------*/
1086 createInterruptVect (FILE * vFile)
1089 mainf = newSymbol ("main", 0);
1092 /* only if the main function exists */
1093 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1095 if (!options.cc_only && !noAssemble)
1100 /* if the main is only a prototype ie. no body then do nothing */
1103 /* if ! compile only then main function should be present */
1104 if (!options.cc_only && !noAssemble)
1109 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1110 fprintf (vFile, "__interrupt_vect:\n");
1113 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1115 /* "generic" interrupt table header (if port doesn't specify one).
1117 * Look suspiciously like 8051 code to me...
1120 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1123 /* now for the other interrupts */
1124 for (; i < maxInterrupts; i++)
1127 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1129 fprintf (vFile, "\treti\n\t.ds\t7\n");
1136 ";--------------------------------------------------------\n"
1137 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1141 ";--------------------------------------------------------\n"};
1144 /*-----------------------------------------------------------------*/
1145 /* initialComments - puts in some initial comments */
1146 /*-----------------------------------------------------------------*/
1148 initialComments (FILE * afile)
1152 fprintf (afile, "%s", iComments1);
1153 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1154 fprintf (afile, "%s", iComments2);
1157 /*-----------------------------------------------------------------*/
1158 /* printPublics - generates .global for publics */
1159 /*-----------------------------------------------------------------*/
1161 printPublics (FILE * afile)
1165 fprintf (afile, "%s", iComments2);
1166 fprintf (afile, "; Public variables in this module\n");
1167 fprintf (afile, "%s", iComments2);
1169 for (sym = setFirstItem (publics); sym;
1170 sym = setNextItem (publics))
1171 tfprintf (afile, "\t!global\n", sym->rname);
1174 /*-----------------------------------------------------------------*/
1175 /* printExterns - generates .global for externs */
1176 /*-----------------------------------------------------------------*/
1178 printExterns (FILE * afile)
1182 fprintf (afile, "%s", iComments2);
1183 fprintf (afile, "; Externals used\n");
1184 fprintf (afile, "%s", iComments2);
1186 for (sym = setFirstItem (externs); sym;
1187 sym = setNextItem (externs))
1188 tfprintf (afile, "\t!global\n", sym->rname);
1191 /*-----------------------------------------------------------------*/
1192 /* emitOverlay - will emit code for the overlay stuff */
1193 /*-----------------------------------------------------------------*/
1195 emitOverlay (FILE * afile)
1199 if (!elementsInSet (ovrSetSets))
1200 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1202 /* for each of the sets in the overlay segment do */
1203 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1204 ovrset = setNextItem (ovrSetSets))
1209 if (elementsInSet (ovrset))
1211 /* this dummy area is used to fool the assembler
1212 otherwise the assembler will append each of these
1213 declarations into one chunk and will not overlay
1215 fprintf (afile, "\t.area _DUMMY\n");
1216 /* output the area informtion */
1217 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1220 for (sym = setFirstItem (ovrset); sym;
1221 sym = setNextItem (ovrset))
1224 /* if extern then add it to the publics tabledo nothing */
1225 if (IS_EXTERN (sym->etype))
1228 /* if allocation required check is needed
1229 then check if the symbol really requires
1230 allocation only for local variables */
1231 if (!IS_AGGREGATE (sym->type) &&
1232 !(sym->_isparm && !IS_REGPARM (sym->etype))
1233 && !sym->allocreq && sym->level)
1236 /* if global variable & not static or extern
1237 and addPublics allowed then add it to the public set */
1238 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1239 && !IS_STATIC (sym->etype))
1240 addSetHead (&publics, sym);
1242 /* if extern then do nothing or is a function
1244 if (IS_FUNC (sym->type))
1247 /* print extra debug info if required */
1250 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1254 if (IS_STATIC (sym->etype))
1255 fprintf (afile, "F%s$", moduleName); /* scope is file */
1257 fprintf (afile, "G$"); /* scope is global */
1260 /* symbol is local */
1261 fprintf (afile, "L%s$",
1262 (sym->localof ? sym->localof->name : "-null-"));
1263 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1266 /* if is has an absolute address then generate
1267 an equate for this no need to allocate space */
1268 if (SPEC_ABSA (sym->etype))
1272 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1274 fprintf (afile, "%s\t=\t0x%04x\n",
1276 SPEC_ADDR (sym->etype));
1281 fprintf (afile, "==.\n");
1283 /* allocate space */
1284 tfprintf (afile, "!labeldef\n", sym->rname);
1285 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1292 /*-----------------------------------------------------------------*/
1293 /* glue - the final glue that hold the whole thing together */
1294 /*-----------------------------------------------------------------*/
1300 FILE *ovrFile = tempfile ();
1302 addSetHead (&tmpfileSet, ovrFile);
1303 /* print the global struct definitions */
1305 cdbStructBlock (0, cdbFile);
1307 vFile = tempfile ();
1308 /* PENDING: this isnt the best place but it will do */
1309 if (port->general.glue_up_main)
1311 /* create the interrupt vector table */
1312 createInterruptVect (vFile);
1315 addSetHead (&tmpfileSet, vFile);
1317 /* emit code for the all the variables declared */
1319 /* do the overlay segments */
1320 emitOverlay (ovrFile);
1322 /* now put it all together into the assembler file */
1323 /* create the assembler file name */
1325 if (!options.c1mode)
1327 sprintf (scratchFileName, srcFileName);
1328 strcat (scratchFileName, port->assembler.file_ext);
1332 strcpy (scratchFileName, options.out_name);
1335 if (!(asmFile = fopen (scratchFileName, "w")))
1337 werror (E_FILE_OPEN_ERR, scratchFileName);
1341 /* initial comments */
1342 initialComments (asmFile);
1344 /* print module name */
1345 tfprintf (asmFile, "\t!module\n", moduleName);
1346 tfprintf (asmFile, "\t!fileprelude\n");
1348 /* Let the port generate any global directives, etc. */
1349 if (port->genAssemblerPreamble)
1351 port->genAssemblerPreamble (asmFile);
1354 /* print the global variables in this module */
1355 printPublics (asmFile);
1356 if (port->assembler.externGlobal)
1357 printExterns (asmFile);
1359 /* copy the sfr segment */
1360 fprintf (asmFile, "%s", iComments2);
1361 fprintf (asmFile, "; special function registers\n");
1362 fprintf (asmFile, "%s", iComments2);
1363 copyFile (asmFile, sfr->oFile);
1365 /* copy the sbit segment */
1366 fprintf (asmFile, "%s", iComments2);
1367 fprintf (asmFile, "; special function bits \n");
1368 fprintf (asmFile, "%s", iComments2);
1369 copyFile (asmFile, sfrbit->oFile);
1371 /* copy the data segment */
1372 fprintf (asmFile, "%s", iComments2);
1373 fprintf (asmFile, "; internal ram data\n");
1374 fprintf (asmFile, "%s", iComments2);
1375 copyFile (asmFile, data->oFile);
1378 /* create the overlay segments */
1379 fprintf (asmFile, "%s", iComments2);
1380 fprintf (asmFile, "; overlayable items in internal ram \n");
1381 fprintf (asmFile, "%s", iComments2);
1382 copyFile (asmFile, ovrFile);
1384 /* create the stack segment MOF */
1385 if (mainf && mainf->fbody)
1387 fprintf (asmFile, "%s", iComments2);
1388 fprintf (asmFile, "; Stack segment in internal ram \n");
1389 fprintf (asmFile, "%s", iComments2);
1390 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1391 "__start__stack:\n\t.ds\t1\n\n");
1394 /* create the idata segment */
1395 fprintf (asmFile, "%s", iComments2);
1396 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1397 fprintf (asmFile, "%s", iComments2);
1398 copyFile (asmFile, idata->oFile);
1400 /* copy the bit segment */
1401 fprintf (asmFile, "%s", iComments2);
1402 fprintf (asmFile, "; bit data\n");
1403 fprintf (asmFile, "%s", iComments2);
1404 copyFile (asmFile, bit->oFile);
1406 /* if external stack then reserve space of it */
1407 if (mainf && mainf->fbody && options.useXstack)
1409 fprintf (asmFile, "%s", iComments2);
1410 fprintf (asmFile, "; external stack \n");
1411 fprintf (asmFile, "%s", iComments2);
1412 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1413 fprintf (asmFile, "\t.ds 256\n");
1417 /* copy xtern ram data */
1418 fprintf (asmFile, "%s", iComments2);
1419 fprintf (asmFile, "; external ram data\n");
1420 fprintf (asmFile, "%s", iComments2);
1421 copyFile (asmFile, xdata->oFile);
1423 /* copy the interrupt vector table */
1424 if (mainf && mainf->fbody)
1426 fprintf (asmFile, "%s", iComments2);
1427 fprintf (asmFile, "; interrupt vector \n");
1428 fprintf (asmFile, "%s", iComments2);
1429 copyFile (asmFile, vFile);
1432 /* copy global & static initialisations */
1433 fprintf (asmFile, "%s", iComments2);
1434 fprintf (asmFile, "; global & static initialisations\n");
1435 fprintf (asmFile, "%s", iComments2);
1437 /* Everywhere we generate a reference to the static_name area,
1438 * (which is currently only here), we immediately follow it with a
1439 * definition of the post_static_name area. This guarantees that
1440 * the post_static_name area will immediately follow the static_name
1443 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1444 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1445 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1447 if (mainf && mainf->fbody)
1449 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1450 /* if external stack is specified then the
1451 higher order byte of the xdatalocation is
1452 going into P2 and the lower order going into
1454 if (options.useXstack)
1456 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1457 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1458 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1459 (unsigned int) options.xdata_loc & 0xff);
1462 /* initialise the stack pointer */
1463 /* if the user specified a value then use it */
1464 if (options.stack_loc)
1465 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1467 /* no: we have to compute it */
1468 if (!options.stackOnData && maxRegBank <= 3)
1469 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1471 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1473 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1474 fprintf (asmFile, "\tmov\ta,dpl\n");
1475 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1476 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1477 fprintf (asmFile, "__sdcc_init_data:\n");
1480 copyFile (asmFile, statsg->oFile);
1482 if (port->general.glue_up_main && mainf && mainf->fbody)
1484 /* This code is generated in the post-static area.
1485 * This area is guaranteed to follow the static area
1486 * by the ugly shucking and jiving about 20 lines ago.
1488 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1489 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1495 "%s", iComments2, iComments2);
1496 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1497 copyFile (asmFile, home->oFile);
1499 /* copy over code */
1500 fprintf (asmFile, "%s", iComments2);
1501 fprintf (asmFile, "; code\n");
1502 fprintf (asmFile, "%s", iComments2);
1503 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1504 if (mainf && mainf->fbody)
1507 /* entry point @ start of CSEG */
1508 fprintf (asmFile, "__sdcc_program_startup:\n");
1510 /* put in the call to main */
1511 fprintf (asmFile, "\tlcall\t_main\n");
1512 if (options.mainreturn)
1515 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1516 fprintf (asmFile, "\tret\n");
1522 fprintf (asmFile, ";\treturn from main will lock up\n");
1523 fprintf (asmFile, "\tsjmp .\n");
1526 copyFile (asmFile, code->oFile);
1529 applyToSet (tmpfileSet, closeTmpFiles);
1530 applyToSet (tmpfileNameSet, rmTmpFiles);
1533 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1537 applyToSet (tmpfileSet, closeTmpFiles);
1538 applyToSet (tmpfileNameSet, rmTmpFiles);
1542 /** Creates a temporary file a'la tmpfile which avoids the bugs
1543 in cygwin wrt c:\tmp.
1544 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1549 #if !defined(_MSC_VER)
1550 const char *tmpdir = NULL;
1552 tmpdir = getenv ("TMP");
1553 else if (getenv ("TEMP"))
1554 tmpdir = getenv ("TEMP");
1555 else if (getenv ("TMPDIR"))
1556 tmpdir = getenv ("TMPDIR");
1559 char *name = tempnam (tmpdir, "sdcc");
1562 FILE *fp = fopen (name, "w+b");
1565 addSetHead (&tmpfileNameSet, name);