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 unsigned 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 = (unsigned long) 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)
167 /* PENDING: special case here - should remove */
168 if (!strcmp (map->sname, CODE_NAME))
169 tfprintf (map->oFile, "\t!areacode\n", map->sname);
170 else if (!strcmp (map->sname, DATA_NAME))
171 tfprintf (map->oFile, "\t!areadata\n", map->sname);
172 else if (!strcmp (map->sname, HOME_NAME))
173 tfprintf (map->oFile, "\t!areahome\n", map->sname);
175 tfprintf (map->oFile, "\t!area\n", map->sname);
178 /* print the area name */
179 for (sym = setFirstItem (map->syms); sym;
180 sym = setNextItem (map->syms))
183 /* if extern then add it into the extern list */
184 if (IS_EXTERN (sym->etype))
186 addSetHead (&externs, sym);
190 /* if allocation required check is needed
191 then check if the symbol really requires
192 allocation only for local variables */
193 if (arFlag && !IS_AGGREGATE (sym->type) &&
194 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
195 !sym->allocreq && sym->level)
198 /* if global variable & not static or extern
199 and addPublics allowed then add it to the public set */
200 if ((sym->level == 0 ||
201 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
203 !IS_STATIC (sym->etype) &&
204 (sym->used || sym->fbody))
206 addSetHead (&publics, sym);
209 /* if extern then do nothing or is a function
211 if (IS_FUNC (sym->type))
214 /* print extra debug info if required */
216 cdbSymbol (sym, cdbFile, FALSE, FALSE);
217 if (!sym->level) /* global */
218 if (IS_STATIC (sym->etype))
219 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
221 fprintf (map->oFile, "G$"); /* scope is global */
223 /* symbol is local */
224 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
225 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
228 /* if is has an absolute address then generate
229 an equate for this no need to allocate space */
230 if (SPEC_ABSA (sym->etype))
233 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
235 fprintf (map->oFile, "%s\t=\t0x%04x\n",
237 SPEC_ADDR (sym->etype));
243 fprintf (map->oFile, "==.\n");
245 if (IS_STATIC (sym->etype))
246 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
248 tfprintf (map->oFile, "!labeldef\n", sym->rname);
249 tfprintf (map->oFile, "\t!ds\n",
250 (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)
258 if (IS_AGGREGATE (sym->type))
259 ival = initAggregates (sym, sym->ival, NULL);
261 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
262 decorateType (resolveSymbols (list2expr (sym->ival))));
263 codeOutFile = statsg->oFile;
266 // set ival's lineno to where the symbol was defined
267 ival->lineno=sym->lineDef;
269 eBBlockFromiCode (iCodeFromAst (ival));
276 /*-----------------------------------------------------------------*/
277 /* initPointer - pointer initialization code massaging */
278 /*-----------------------------------------------------------------*/
280 initPointer (initList * ilist)
283 ast *expr = list2expr (ilist);
288 /* try it the oldway first */
289 if ((val = constExprValue (expr, FALSE)))
292 /* no then we have to do these cludgy checks */
293 /* pointers can be initialized with address of
294 a variable or address of an array element */
295 if (IS_AST_OP (expr) && expr->opval.op == '&') {
296 /* address of symbol */
297 if (IS_AST_SYM_VALUE (expr->left)) {
298 val = copyValue (AST_VALUE (expr->left));
299 val->type = newLink ();
300 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
301 DCL_TYPE (val->type) = CPOINTER;
302 DCL_PTR_CONST (val->type) = port->mem.code_ro;
304 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
305 DCL_TYPE (val->type) = FPOINTER;
306 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
307 DCL_TYPE (val->type) = PPOINTER;
308 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
309 DCL_TYPE (val->type) = IPOINTER;
310 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
311 DCL_TYPE (val->type) = EEPPOINTER;
313 DCL_TYPE (val->type) = POINTER;
314 val->type->next = expr->left->ftype;
315 val->etype = getSpec (val->type);
319 /* if address of indexed array */
320 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
321 return valForArray (expr->left);
323 /* if address of structure element then
325 if (IS_AST_OP (expr->left) &&
326 expr->left->opval.op == '.') {
327 return valForStructElem (expr->left->left,
332 (&some_struct)->element */
333 if (IS_AST_OP (expr->left) &&
334 expr->left->opval.op == PTR_OP &&
335 IS_ADDRESS_OF_OP (expr->left->left))
336 return valForStructElem (expr->left->left->left,
340 /* case 3. (((char *) &a) +/- constant) */
341 if (IS_AST_OP (expr) &&
342 (expr->opval.op == '+' || expr->opval.op == '-') &&
343 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
344 IS_AST_OP (expr->left->right) &&
345 expr->left->right->opval.op == '&' &&
346 IS_AST_LIT_VALUE (expr->right)) {
348 return valForCastAggr (expr->left->right->left,
349 expr->left->left->opval.lnk,
350 expr->right, expr->opval.op);
354 /* case 4. (char *)(array type) */
355 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
356 IS_ARRAY(expr->right->ftype)) {
358 val = copyValue (AST_VALUE (expr->right));
359 val->type = newLink ();
360 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
361 DCL_TYPE (val->type) = CPOINTER;
362 DCL_PTR_CONST (val->type) = port->mem.code_ro;
364 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
365 DCL_TYPE (val->type) = FPOINTER;
366 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
367 DCL_TYPE (val->type) = PPOINTER;
368 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
369 DCL_TYPE (val->type) = IPOINTER;
370 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
371 DCL_TYPE (val->type) = EEPPOINTER;
373 DCL_TYPE (val->type) = POINTER;
374 val->type->next = expr->right->ftype->next;
375 val->etype = getSpec (val->type);
379 werror (E_INIT_WRONG);
384 /*-----------------------------------------------------------------*/
385 /* printChar - formats and prints a characater string with DB */
386 /*-----------------------------------------------------------------*/
388 printChar (FILE * ofile, char *s, int plen)
391 int len = strlen (s);
396 while (len && pplen < plen)
399 while (i && *s && pplen < plen)
401 if (*s < ' ' || *s == '\"' || *s=='\\')
405 tfprintf (ofile, "\t!ascii\n", buf);
406 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
421 tfprintf (ofile, "\t!ascii\n", buf);
430 tfprintf (ofile, "\t!db !constbyte\n", 0);
433 /*-----------------------------------------------------------------*/
434 /* return the generic pointer high byte for a given pointer type. */
435 /*-----------------------------------------------------------------*/
437 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
445 /* hack - if we get a generic pointer, we just assume
446 * it's an FPOINTER (i.e. in XDATA space).
448 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
458 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
466 /*-----------------------------------------------------------------*/
467 /* printPointerType - generates ival for pointer type */
468 /*-----------------------------------------------------------------*/
470 _printPointerType (FILE * oFile, const char *name)
474 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
478 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
482 /*-----------------------------------------------------------------*/
483 /* printPointerType - generates ival for pointer type */
484 /*-----------------------------------------------------------------*/
486 printPointerType (FILE * oFile, const char *name)
488 _printPointerType (oFile, name);
489 fprintf (oFile, "\n");
492 /*-----------------------------------------------------------------*/
493 /* printGPointerType - generates ival for generic pointer type */
494 /*-----------------------------------------------------------------*/
496 printGPointerType (FILE * oFile, const char *iname, const char *oname,
497 const unsigned int type)
499 _printPointerType (oFile, iname);
500 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
503 /*-----------------------------------------------------------------*/
504 /* printIvalType - generates ival for int/char */
505 /*-----------------------------------------------------------------*/
507 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
511 /* if initList is deep */
512 if (ilist->type == INIT_DEEP)
513 ilist = ilist->init.deep;
515 val = list2val (ilist);
516 switch (getSize (type)) {
519 tfprintf (oFile, "\t!db !constbyte\n", 0);
521 tfprintf (oFile, "\t!dbs\n",
522 aopLiteral (val, 0));
526 if (port->use_dw_for_init)
527 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
529 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
533 tfprintf (oFile, "\t!dw !constword\n", 0);
534 tfprintf (oFile, "\t!dw !constword\n", 0);
537 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
538 aopLiteral (val, 0), aopLiteral (val, 1),
539 aopLiteral (val, 2), aopLiteral (val, 3));
545 /*-----------------------------------------------------------------*/
546 /* printIvalBitFields - generate initializer for bitfields */
547 /*-----------------------------------------------------------------*/
548 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
552 initList *lilist = *ilist ;
553 unsigned long ival = 0;
559 val = list2val(lilist);
561 if (SPEC_BLEN(lsym->etype) > 8) {
562 size += ((SPEC_BLEN (lsym->etype) / 8) +
563 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
566 size = ((SPEC_BLEN (lsym->etype) / 8) +
567 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
569 i = (unsigned long)floatFromVal(val);
570 i <<= SPEC_BSTR (lsym->etype);
572 if (! ( lsym->next &&
573 (IS_BITFIELD(lsym->next->type)) &&
574 (SPEC_BSTR(lsym->next->etype)))) break;
576 lilist = lilist->next;
580 tfprintf (oFile, "\t!db !constbyte\n",ival);
584 tfprintf (oFile, "\t!dw !constword\n",ival);
587 tfprintf (oFile, "\t!db !constword,!constword\n",
588 (ival >> 8) & 0xffff, (ival & 0xffff));
595 /*-----------------------------------------------------------------*/
596 /* printIvalStruct - generates initial value for structures */
597 /*-----------------------------------------------------------------*/
599 printIvalStruct (symbol * sym, sym_link * type,
600 initList * ilist, FILE * oFile)
605 sflds = SPEC_STRUCT (type)->fields;
606 if (ilist->type != INIT_DEEP) {
607 werror (E_INIT_STRUCT, sym->name);
611 iloop = ilist->init.deep;
613 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
614 if (IS_BITFIELD(sflds->type)) {
615 printIvalBitFields(&sflds,&iloop,oFile);
617 printIval (sflds, sflds->type, iloop, oFile);
623 /*-----------------------------------------------------------------*/
624 /* printIvalChar - generates initital value for character array */
625 /*-----------------------------------------------------------------*/
627 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
635 val = list2val (ilist);
636 /* if the value is a character string */
637 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
639 if (!DCL_ELEM (type))
640 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
642 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
644 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
646 tfprintf (oFile, "\t!db !constbyte\n", 0);
654 printChar (oFile, s, strlen (s) + 1);
658 /*-----------------------------------------------------------------*/
659 /* printIvalArray - generates code for array initialization */
660 /*-----------------------------------------------------------------*/
662 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
666 int lcnt = 0, size = 0;
668 /* take care of the special case */
669 /* array of characters can be init */
671 if (IS_CHAR (type->next))
672 if (printIvalChar (type,
673 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
674 oFile, SPEC_CVAL (sym->etype).v_char))
677 /* not the special case */
678 if (ilist->type != INIT_DEEP)
680 werror (E_INIT_STRUCT, sym->name);
684 iloop = ilist->init.deep;
685 lcnt = DCL_ELEM (type);
690 printIval (sym, type->next, iloop, oFile);
691 iloop = (iloop ? iloop->next : NULL);
694 /* if not array limits given & we */
695 /* are out of initialisers then */
696 if (!DCL_ELEM (type) && !iloop)
699 /* no of elements given and we */
700 /* have generated for all of them */
702 /* if initializers left */
704 werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
710 /* if we have not been given a size */
711 if (!DCL_ELEM (type))
712 DCL_ELEM (type) = size;
717 /*-----------------------------------------------------------------*/
718 /* printIvalFuncPtr - generate initial value for function pointers */
719 /*-----------------------------------------------------------------*/
721 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
726 val = list2val (ilist);
727 /* check the types */
728 if ((dLvl = compareType (val->type, type->next)) <= 0)
730 tfprintf (oFile, "\t!dw !constword\n", 0);
734 /* now generate the name */
737 if (port->use_dw_for_init)
739 tfprintf (oFile, "\t!dws\n", val->name);
743 printPointerType (oFile, val->name);
746 else if (port->use_dw_for_init)
748 tfprintf (oFile, "\t!dws\n", val->sym->rname);
752 printPointerType (oFile, val->sym->rname);
758 /*-----------------------------------------------------------------*/
759 /* printIvalCharPtr - generates initial values for character pointers */
760 /*-----------------------------------------------------------------*/
762 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
766 /* PENDING: this is _very_ mcs51 specific, including a magic
768 It's also endin specific.
770 size = getSize (type);
772 if (val->name && strlen (val->name))
774 if (size == 1) /* This appears to be Z80 specific?? */
777 "\t!dbs\n", val->name);
779 else if (size == FPTRSIZE)
781 if (port->use_dw_for_init)
783 tfprintf (oFile, "\t!dws\n", val->name);
787 printPointerType (oFile, val->name);
790 else if (size == GPTRSIZE)
793 if (IS_PTR (val->type)) {
794 type = DCL_TYPE (val->type);
796 type = PTR_TYPE (SPEC_OCLS (val->etype));
798 if (val->sym && val->sym->isstrlit) {
799 // this is a literal string
802 printGPointerType (oFile, val->name, sym->name, type);
806 fprintf (stderr, "*** internal error: unknown size in "
807 "printIvalCharPtr.\n");
812 /* What is this case? Are these pointers? */
816 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
819 if (port->use_dw_for_init)
820 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
822 tfprintf (oFile, "\t.byte %s,%s\n",
823 aopLiteral (val, 0), aopLiteral (val, 1));
826 /* PENDING: 0x02 or 0x%02x, CDATA? */
827 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
828 aopLiteral (val, 0), aopLiteral (val, 1));
835 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
836 addSet (&statsg->syms, val->sym);
842 /*-----------------------------------------------------------------*/
843 /* printIvalPtr - generates initial value for pointers */
844 /*-----------------------------------------------------------------*/
846 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
852 if (ilist->type == INIT_DEEP)
853 ilist = ilist->init.deep;
855 /* function pointer */
856 if (IS_FUNC (type->next))
858 printIvalFuncPtr (type, ilist, oFile);
862 if (!(val = initPointer (ilist)))
865 /* if character pointer */
866 if (IS_CHAR (type->next))
867 if (printIvalCharPtr (sym, type, val, oFile))
871 if (compareType (type, val->type) == 0)
872 werror (E_INIT_WRONG);
874 /* if val is literal */
875 if (IS_LITERAL (val->etype))
877 switch (getSize (type))
880 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
883 if (port->use_dw_for_init)
884 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
886 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
889 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
890 aopLiteral (val, 0), aopLiteral (val, 1));
896 size = getSize (type);
898 if (size == 1) /* Z80 specific?? */
900 tfprintf (oFile, "\t!dbs\n", val->name);
902 else if (size == FPTRSIZE)
904 if (port->use_dw_for_init) {
905 tfprintf (oFile, "\t!dws\n", val->name);
907 printPointerType (oFile, val->name);
910 else if (size == GPTRSIZE)
912 printGPointerType (oFile, val->name, sym->name,
913 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
914 PTR_TYPE (SPEC_OCLS (val->etype))));
919 /*-----------------------------------------------------------------*/
920 /* printIval - generates code for initial value */
921 /*-----------------------------------------------------------------*/
923 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
928 /* if structure then */
929 if (IS_STRUCT (type))
931 printIvalStruct (sym, type, ilist, oFile);
935 /* if this is a pointer */
938 printIvalPtr (sym, type, ilist, oFile);
942 /* if this is an array */
945 printIvalArray (sym, type, ilist, oFile);
949 /* if type is SPECIFIER */
952 printIvalType (type, ilist, oFile);
957 /*-----------------------------------------------------------------*/
958 /* emitStaticSeg - emitcode for the static segment */
959 /*-----------------------------------------------------------------*/
961 emitStaticSeg (memmap * map, FILE * out)
965 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
969 /* for all variables in this segment do */
970 for (sym = setFirstItem (map->syms); sym;
971 sym = setNextItem (map->syms))
974 /* if it is "extern" then do nothing */
975 if (IS_EXTERN (sym->etype))
978 /* if it is not static add it to the public
980 if (!IS_STATIC (sym->etype))
981 addSetHead (&publics, sym);
983 /* print extra debug info if required */
985 cdbSymbol (sym, cdbFile, FALSE, FALSE);
988 if (IS_STATIC (sym->etype))
989 fprintf (out, "F%s$", moduleName); /* scope is file */
991 fprintf (out, "G$"); /* scope is global */
994 /* symbol is local */
995 fprintf (out, "L%s$",
996 (sym->localof ? sym->localof->name : "-null-"));
997 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1000 /* if it has an absolute address */
1001 if (SPEC_ABSA (sym->etype))
1004 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1006 fprintf (out, "%s\t=\t0x%04x\n",
1008 SPEC_ADDR (sym->etype));
1013 fprintf (out, " == .\n");
1015 /* if it has an initial value */
1018 fprintf (out, "%s:\n", sym->rname);
1020 resolveIvalSym (sym->ival);
1021 printIval (sym, sym->type, sym->ival, out);
1026 /* allocate space */
1027 fprintf (out, "%s:\n", sym->rname);
1028 /* special case for character strings */
1029 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1030 SPEC_CVAL (sym->etype).v_char)
1032 SPEC_CVAL (sym->etype).v_char,
1033 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1035 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1041 /*-----------------------------------------------------------------*/
1042 /* emitMaps - emits the code for the data portion the code */
1043 /*-----------------------------------------------------------------*/
1048 /* no special considerations for the following
1049 data, idata & bit & xdata */
1050 emitRegularMap (data, TRUE, TRUE);
1051 emitRegularMap (idata, TRUE, TRUE);
1052 emitRegularMap (bit, TRUE, FALSE);
1053 emitRegularMap (xdata, TRUE, TRUE);
1054 emitRegularMap (sfr, FALSE, FALSE);
1055 emitRegularMap (sfrbit, FALSE, FALSE);
1056 emitRegularMap (home, TRUE, FALSE);
1057 emitRegularMap (code, TRUE, FALSE);
1059 emitStaticSeg (statsg, code->oFile);
1063 /*-----------------------------------------------------------------*/
1064 /* flushStatics - flush all currently defined statics out to file */
1065 /* and delete. Temporary function */
1066 /*-----------------------------------------------------------------*/
1070 emitStaticSeg (statsg, codeOutFile);
1071 statsg->syms = NULL;
1074 /*-----------------------------------------------------------------*/
1075 /* createInterruptVect - creates the interrupt vector */
1076 /*-----------------------------------------------------------------*/
1078 createInterruptVect (FILE * vFile)
1081 mainf = newSymbol ("main", 0);
1084 /* only if the main function exists */
1085 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1087 if (!options.cc_only && !noAssemble)
1092 /* if the main is only a prototype ie. no body then do nothing */
1095 /* if ! compile only then main function should be present */
1096 if (!options.cc_only && !noAssemble)
1101 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1102 fprintf (vFile, "__interrupt_vect:\n");
1105 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1107 /* "generic" interrupt table header (if port doesn't specify one).
1109 * Look suspiciously like 8051 code to me...
1112 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1115 /* now for the other interrupts */
1116 for (; i < maxInterrupts; i++)
1119 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1121 fprintf (vFile, "\treti\n\t.ds\t7\n");
1128 ";--------------------------------------------------------\n"
1129 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1133 ";--------------------------------------------------------\n"};
1136 /*-----------------------------------------------------------------*/
1137 /* initialComments - puts in some initial comments */
1138 /*-----------------------------------------------------------------*/
1140 initialComments (FILE * afile)
1144 fprintf (afile, "%s", iComments1);
1145 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1146 fprintf (afile, "%s", iComments2);
1149 /*-----------------------------------------------------------------*/
1150 /* printPublics - generates .global for publics */
1151 /*-----------------------------------------------------------------*/
1153 printPublics (FILE * afile)
1157 fprintf (afile, "%s", iComments2);
1158 fprintf (afile, "; Public variables in this module\n");
1159 fprintf (afile, "%s", iComments2);
1161 for (sym = setFirstItem (publics); sym;
1162 sym = setNextItem (publics))
1163 tfprintf (afile, "\t!global\n", sym->rname);
1166 /*-----------------------------------------------------------------*/
1167 /* printExterns - generates .global for externs */
1168 /*-----------------------------------------------------------------*/
1170 printExterns (FILE * afile)
1174 fprintf (afile, "%s", iComments2);
1175 fprintf (afile, "; Externals used\n");
1176 fprintf (afile, "%s", iComments2);
1178 for (sym = setFirstItem (externs); sym;
1179 sym = setNextItem (externs))
1180 tfprintf (afile, "\t!global\n", sym->rname);
1183 /*-----------------------------------------------------------------*/
1184 /* emitOverlay - will emit code for the overlay stuff */
1185 /*-----------------------------------------------------------------*/
1187 emitOverlay (FILE * afile)
1191 if (!elementsInSet (ovrSetSets))
1192 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1194 /* for each of the sets in the overlay segment do */
1195 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1196 ovrset = setNextItem (ovrSetSets))
1201 if (elementsInSet (ovrset))
1203 /* this dummy area is used to fool the assembler
1204 otherwise the assembler will append each of these
1205 declarations into one chunk and will not overlay
1207 fprintf (afile, "\t.area _DUMMY\n");
1208 /* output the area informtion */
1209 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1212 for (sym = setFirstItem (ovrset); sym;
1213 sym = setNextItem (ovrset))
1216 /* if extern then add it to the publics tabledo nothing */
1217 if (IS_EXTERN (sym->etype))
1220 /* if allocation required check is needed
1221 then check if the symbol really requires
1222 allocation only for local variables */
1223 if (!IS_AGGREGATE (sym->type) &&
1224 !(sym->_isparm && !IS_REGPARM (sym->etype))
1225 && !sym->allocreq && sym->level)
1228 /* if global variable & not static or extern
1229 and addPublics allowed then add it to the public set */
1230 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1231 && !IS_STATIC (sym->etype))
1232 addSetHead (&publics, sym);
1234 /* if extern then do nothing or is a function
1236 if (IS_FUNC (sym->type))
1239 /* print extra debug info if required */
1242 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1246 if (IS_STATIC (sym->etype))
1247 fprintf (afile, "F%s$", moduleName); /* scope is file */
1249 fprintf (afile, "G$"); /* scope is global */
1252 /* symbol is local */
1253 fprintf (afile, "L%s$",
1254 (sym->localof ? sym->localof->name : "-null-"));
1255 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1258 /* if is has an absolute address then generate
1259 an equate for this no need to allocate space */
1260 if (SPEC_ABSA (sym->etype))
1264 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1266 fprintf (afile, "%s\t=\t0x%04x\n",
1268 SPEC_ADDR (sym->etype));
1273 fprintf (afile, "==.\n");
1275 /* allocate space */
1276 tfprintf (afile, "!labeldef\n", sym->rname);
1277 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1284 /*-----------------------------------------------------------------*/
1285 /* glue - the final glue that hold the whole thing together */
1286 /*-----------------------------------------------------------------*/
1292 FILE *ovrFile = tempfile ();
1294 addSetHead (&tmpfileSet, ovrFile);
1295 /* print the global struct definitions */
1297 cdbStructBlock (0, cdbFile);
1299 vFile = tempfile ();
1300 /* PENDING: this isnt the best place but it will do */
1301 if (port->general.glue_up_main)
1303 /* create the interrupt vector table */
1304 createInterruptVect (vFile);
1307 addSetHead (&tmpfileSet, vFile);
1309 /* emit code for the all the variables declared */
1311 /* do the overlay segments */
1312 emitOverlay (ovrFile);
1314 /* now put it all together into the assembler file */
1315 /* create the assembler file name */
1317 if (!options.c1mode)
1319 sprintf (scratchFileName, srcFileName);
1320 strcat (scratchFileName, port->assembler.file_ext);
1324 strcpy (scratchFileName, options.out_name);
1327 if (!(asmFile = fopen (scratchFileName, "w")))
1329 werror (E_FILE_OPEN_ERR, scratchFileName);
1333 /* initial comments */
1334 initialComments (asmFile);
1336 /* print module name */
1337 tfprintf (asmFile, "\t!module\n", moduleName);
1338 tfprintf (asmFile, "\t!fileprelude\n");
1340 /* Let the port generate any global directives, etc. */
1341 if (port->genAssemblerPreamble)
1343 port->genAssemblerPreamble (asmFile);
1346 /* print the global variables in this module */
1347 printPublics (asmFile);
1348 if (port->assembler.externGlobal)
1349 printExterns (asmFile);
1351 /* copy the sfr segment */
1352 fprintf (asmFile, "%s", iComments2);
1353 fprintf (asmFile, "; special function registers\n");
1354 fprintf (asmFile, "%s", iComments2);
1355 copyFile (asmFile, sfr->oFile);
1357 /* copy the sbit segment */
1358 fprintf (asmFile, "%s", iComments2);
1359 fprintf (asmFile, "; special function bits \n");
1360 fprintf (asmFile, "%s", iComments2);
1361 copyFile (asmFile, sfrbit->oFile);
1363 /* copy the data segment */
1364 fprintf (asmFile, "%s", iComments2);
1365 fprintf (asmFile, "; internal ram data\n");
1366 fprintf (asmFile, "%s", iComments2);
1367 copyFile (asmFile, data->oFile);
1370 /* create the overlay segments */
1371 fprintf (asmFile, "%s", iComments2);
1372 fprintf (asmFile, "; overlayable items in internal ram \n");
1373 fprintf (asmFile, "%s", iComments2);
1374 copyFile (asmFile, ovrFile);
1376 /* create the stack segment MOF */
1377 if (mainf && mainf->fbody)
1379 fprintf (asmFile, "%s", iComments2);
1380 fprintf (asmFile, "; Stack segment in internal ram \n");
1381 fprintf (asmFile, "%s", iComments2);
1382 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1383 "__start__stack:\n\t.ds\t1\n\n");
1386 /* create the idata segment */
1387 fprintf (asmFile, "%s", iComments2);
1388 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1389 fprintf (asmFile, "%s", iComments2);
1390 copyFile (asmFile, idata->oFile);
1392 /* copy the bit segment */
1393 fprintf (asmFile, "%s", iComments2);
1394 fprintf (asmFile, "; bit data\n");
1395 fprintf (asmFile, "%s", iComments2);
1396 copyFile (asmFile, bit->oFile);
1398 /* if external stack then reserve space of it */
1399 if (mainf && mainf->fbody && options.useXstack)
1401 fprintf (asmFile, "%s", iComments2);
1402 fprintf (asmFile, "; external stack \n");
1403 fprintf (asmFile, "%s", iComments2);
1404 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1405 fprintf (asmFile, "\t.ds 256\n");
1409 /* copy xtern ram data */
1410 fprintf (asmFile, "%s", iComments2);
1411 fprintf (asmFile, "; external ram data\n");
1412 fprintf (asmFile, "%s", iComments2);
1413 copyFile (asmFile, xdata->oFile);
1415 /* copy the interrupt vector table */
1416 if (mainf && mainf->fbody)
1418 fprintf (asmFile, "%s", iComments2);
1419 fprintf (asmFile, "; interrupt vector \n");
1420 fprintf (asmFile, "%s", iComments2);
1421 copyFile (asmFile, vFile);
1424 /* copy global & static initialisations */
1425 fprintf (asmFile, "%s", iComments2);
1426 fprintf (asmFile, "; global & static initialisations\n");
1427 fprintf (asmFile, "%s", iComments2);
1429 /* Everywhere we generate a reference to the static_name area,
1430 * (which is currently only here), we immediately follow it with a
1431 * definition of the post_static_name area. This guarantees that
1432 * the post_static_name area will immediately follow the static_name
1435 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1436 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1437 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1439 if (mainf && mainf->fbody)
1441 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1442 /* if external stack is specified then the
1443 higher order byte of the xdatalocation is
1444 going into P2 and the lower order going into
1446 if (options.useXstack)
1448 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1449 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1450 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1451 (unsigned int) options.xdata_loc & 0xff);
1454 /* initialise the stack pointer */
1455 /* if the user specified a value then use it */
1456 if (options.stack_loc)
1457 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1459 /* no: we have to compute it */
1460 if (!options.stackOnData && maxRegBank <= 3)
1461 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1463 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1465 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1466 fprintf (asmFile, "\tmov\ta,dpl\n");
1467 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1468 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1469 fprintf (asmFile, "__sdcc_init_data:\n");
1472 copyFile (asmFile, statsg->oFile);
1474 if (port->general.glue_up_main && mainf && mainf->fbody)
1476 /* This code is generated in the post-static area.
1477 * This area is guaranteed to follow the static area
1478 * by the ugly shucking and jiving about 20 lines ago.
1480 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1481 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1487 "%s", iComments2, iComments2);
1488 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1489 copyFile (asmFile, home->oFile);
1491 /* copy over code */
1492 fprintf (asmFile, "%s", iComments2);
1493 fprintf (asmFile, "; code\n");
1494 fprintf (asmFile, "%s", iComments2);
1495 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1496 if (mainf && mainf->fbody)
1499 /* entry point @ start of CSEG */
1500 fprintf (asmFile, "__sdcc_program_startup:\n");
1502 /* put in the call to main */
1503 fprintf (asmFile, "\tlcall\t_main\n");
1504 if (options.mainreturn)
1507 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1508 fprintf (asmFile, "\tret\n");
1514 fprintf (asmFile, ";\treturn from main will lock up\n");
1515 fprintf (asmFile, "\tsjmp .\n");
1518 copyFile (asmFile, code->oFile);
1521 applyToSet (tmpfileSet, closeTmpFiles);
1522 applyToSet (tmpfileNameSet, rmTmpFiles);
1525 /** Creates a temporary file a'la tmpfile which avoids the bugs
1526 in cygwin wrt c:\tmp.
1527 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1532 #if !defined(_MSC_VER)
1533 const char *tmpdir = NULL;
1535 tmpdir = getenv ("TMP");
1536 else if (getenv ("TEMP"))
1537 tmpdir = getenv ("TEMP");
1538 else if (getenv ("TMPDIR"))
1539 tmpdir = getenv ("TMPDIR");
1542 char *name = tempnam (tmpdir, "sdcc");
1545 FILE *fp = fopen (name, "w+b");
1548 addSetHead (&tmpfileNameSet, name);
1559 gc_strdup (const char *s)
1562 ret = Safe_calloc (1, strlen (s) + 1);