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)
462 /* if (TARGET_IS_DS390) */
463 if (options.model == MODEL_FLAT24)
465 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
469 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
473 /*-----------------------------------------------------------------*/
474 /* printPointerType - generates ival for pointer type */
475 /*-----------------------------------------------------------------*/
477 printPointerType (FILE * oFile, const char *name)
479 _printPointerType (oFile, name);
480 fprintf (oFile, "\n");
483 /*-----------------------------------------------------------------*/
484 /* printGPointerType - generates ival for generic pointer type */
485 /*-----------------------------------------------------------------*/
487 printGPointerType (FILE * oFile, const char *iname, const char *oname,
488 const unsigned int type)
490 _printPointerType (oFile, iname);
491 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
494 /*-----------------------------------------------------------------*/
495 /* printIvalType - generates ival for int/char */
496 /*-----------------------------------------------------------------*/
498 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
502 /* if initList is deep */
503 if (ilist->type == INIT_DEEP)
504 ilist = ilist->init.deep;
506 val = list2val (ilist);
507 switch (getSize (type)) {
510 tfprintf (oFile, "\t!db !constbyte\n", 0);
512 tfprintf (oFile, "\t!dbs\n",
513 aopLiteral (val, 0));
517 if (port->use_dw_for_init)
518 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
520 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
524 tfprintf (oFile, "\t!dw !constword\n", 0);
525 tfprintf (oFile, "\t!dw !constword\n", 0);
528 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
529 aopLiteral (val, 0), aopLiteral (val, 1),
530 aopLiteral (val, 2), aopLiteral (val, 3));
536 /*-----------------------------------------------------------------*/
537 /* printIvalBitFields - generate initializer for bitfields */
538 /*-----------------------------------------------------------------*/
539 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
543 initList *lilist = *ilist ;
544 unsigned long ival = 0;
550 val = list2val(lilist);
552 if (SPEC_BLEN(lsym->etype) > 8) {
553 size += ((SPEC_BLEN (lsym->etype) / 8) +
554 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
557 size = ((SPEC_BLEN (lsym->etype) / 8) +
558 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
560 i = (unsigned long)floatFromVal(val);
561 i <<= SPEC_BSTR (lsym->etype);
563 if (! ( lsym->next &&
564 (IS_BITFIELD(lsym->next->type)) &&
565 (SPEC_BSTR(lsym->next->etype)))) break;
567 lilist = lilist->next;
571 tfprintf (oFile, "\t!db !constbyte\n",ival);
575 tfprintf (oFile, "\t!dw !constword\n",ival);
578 tfprintf (oFile, "\t!db !constword,!constword\n",
579 (ival >> 8) & 0xffff, (ival & 0xffff));
586 /*-----------------------------------------------------------------*/
587 /* printIvalStruct - generates initial value for structures */
588 /*-----------------------------------------------------------------*/
590 printIvalStruct (symbol * sym, sym_link * type,
591 initList * ilist, FILE * oFile)
596 sflds = SPEC_STRUCT (type)->fields;
597 if (ilist->type != INIT_DEEP) {
598 werror (E_INIT_STRUCT, sym->name);
602 iloop = ilist->init.deep;
604 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
605 if (IS_BITFIELD(sflds->type)) {
606 printIvalBitFields(&sflds,&iloop,oFile);
608 printIval (sflds, sflds->type, iloop, oFile);
614 /*-----------------------------------------------------------------*/
615 /* printIvalChar - generates initital value for character array */
616 /*-----------------------------------------------------------------*/
618 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
626 val = list2val (ilist);
627 /* if the value is a character string */
628 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
630 if (!DCL_ELEM (type))
631 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
633 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
635 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
637 tfprintf (oFile, "\t!db !constbyte\n", 0);
645 printChar (oFile, s, strlen (s) + 1);
649 /*-----------------------------------------------------------------*/
650 /* printIvalArray - generates code for array initialization */
651 /*-----------------------------------------------------------------*/
653 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
657 int lcnt = 0, size = 0;
659 /* take care of the special case */
660 /* array of characters can be init */
662 if (IS_CHAR (type->next))
663 if (printIvalChar (type,
664 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
665 oFile, SPEC_CVAL (sym->etype).v_char))
668 /* not the special case */
669 if (ilist->type != INIT_DEEP)
671 werror (E_INIT_STRUCT, sym->name);
675 iloop = ilist->init.deep;
676 lcnt = DCL_ELEM (type);
681 printIval (sym, type->next, iloop, oFile);
682 iloop = (iloop ? iloop->next : NULL);
685 /* if not array limits given & we */
686 /* are out of initialisers then */
687 if (!DCL_ELEM (type) && !iloop)
690 /* no of elements given and we */
691 /* have generated for all of them */
693 /* if initializers left */
695 werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
701 /* if we have not been given a size */
702 if (!DCL_ELEM (type))
703 DCL_ELEM (type) = size;
708 /*-----------------------------------------------------------------*/
709 /* printIvalFuncPtr - generate initial value for function pointers */
710 /*-----------------------------------------------------------------*/
712 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
717 val = list2val (ilist);
718 /* check the types */
719 if ((dLvl = compareType (val->type, type->next)) <= 0)
721 tfprintf (oFile, "\t!dw !constword\n", 0);
725 /* now generate the name */
728 if (port->use_dw_for_init)
730 tfprintf (oFile, "\t!dws\n", val->name);
734 printPointerType (oFile, val->name);
737 else if (port->use_dw_for_init)
739 tfprintf (oFile, "\t!dws\n", val->sym->rname);
743 printPointerType (oFile, val->sym->rname);
749 /*-----------------------------------------------------------------*/
750 /* printIvalCharPtr - generates initial values for character pointers */
751 /*-----------------------------------------------------------------*/
753 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
757 /* PENDING: this is _very_ mcs51 specific, including a magic
759 It's also endin specific.
761 size = getSize (type);
763 if (val->name && strlen (val->name))
765 if (size == 1) /* This appears to be Z80 specific?? */
768 "\t!dbs\n", val->name);
770 else if (size == FPTRSIZE)
772 if (port->use_dw_for_init)
774 tfprintf (oFile, "\t!dws\n", val->name);
778 printPointerType (oFile, val->name);
781 else if (size == GPTRSIZE)
784 if (IS_PTR (val->type)) {
785 type = DCL_TYPE (val->type);
787 type = PTR_TYPE (SPEC_OCLS (val->etype));
789 if (val->sym && val->sym->isstrlit) {
790 // this is a literal string
793 printGPointerType (oFile, val->name, sym->name, type);
797 fprintf (stderr, "*** internal error: unknown size in "
798 "printIvalCharPtr.\n");
803 /* What is this case? Are these pointers? */
807 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
810 if (port->use_dw_for_init)
811 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
813 tfprintf (oFile, "\t.byte %s,%s\n",
814 aopLiteral (val, 0), aopLiteral (val, 1));
817 /* PENDING: 0x02 or 0x%02x, CDATA? */
818 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
819 aopLiteral (val, 0), aopLiteral (val, 1));
826 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
827 addSet (&statsg->syms, val->sym);
833 /*-----------------------------------------------------------------*/
834 /* printIvalPtr - generates initial value for pointers */
835 /*-----------------------------------------------------------------*/
837 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
843 if (ilist->type == INIT_DEEP)
844 ilist = ilist->init.deep;
846 /* function pointer */
847 if (IS_FUNC (type->next))
849 printIvalFuncPtr (type, ilist, oFile);
853 if (!(val = initPointer (ilist)))
856 /* if character pointer */
857 if (IS_CHAR (type->next))
858 if (printIvalCharPtr (sym, type, val, oFile))
862 if (compareType (type, val->type) == 0)
863 werror (E_INIT_WRONG);
865 /* if val is literal */
866 if (IS_LITERAL (val->etype))
868 switch (getSize (type))
871 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
874 if (port->use_dw_for_init)
875 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
877 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
880 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
881 aopLiteral (val, 0), aopLiteral (val, 1));
887 size = getSize (type);
889 if (size == 1) /* Z80 specific?? */
891 tfprintf (oFile, "\t!dbs\n", val->name);
893 else if (size == FPTRSIZE)
895 if (port->use_dw_for_init) {
896 tfprintf (oFile, "\t!dws\n", val->name);
898 printPointerType (oFile, val->name);
901 else if (size == GPTRSIZE)
903 printGPointerType (oFile, val->name, sym->name,
904 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
905 PTR_TYPE (SPEC_OCLS (val->etype))));
910 /*-----------------------------------------------------------------*/
911 /* printIval - generates code for initial value */
912 /*-----------------------------------------------------------------*/
914 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
919 /* if structure then */
920 if (IS_STRUCT (type))
922 printIvalStruct (sym, type, ilist, oFile);
926 /* if this is a pointer */
929 printIvalPtr (sym, type, ilist, oFile);
933 /* if this is an array */
936 printIvalArray (sym, type, ilist, oFile);
940 /* if type is SPECIFIER */
943 printIvalType (type, ilist, oFile);
948 /*-----------------------------------------------------------------*/
949 /* emitStaticSeg - emitcode for the static segment */
950 /*-----------------------------------------------------------------*/
952 emitStaticSeg (memmap * map, FILE * out)
956 /* fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
960 /* for all variables in this segment do */
961 for (sym = setFirstItem (map->syms); sym;
962 sym = setNextItem (map->syms))
965 /* if it is "extern" then do nothing */
966 if (IS_EXTERN (sym->etype))
969 /* if it is not static add it to the public
971 if (!IS_STATIC (sym->etype))
972 addSetHead (&publics, sym);
974 /* print extra debug info if required */
976 cdbSymbol (sym, cdbFile, FALSE, FALSE);
979 if (IS_STATIC (sym->etype))
980 fprintf (out, "F%s$", moduleName); /* scope is file */
982 fprintf (out, "G$"); /* scope is global */
985 /* symbol is local */
986 fprintf (out, "L%s$",
987 (sym->localof ? sym->localof->name : "-null-"));
988 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
991 /* if it has an absolute address */
992 if (SPEC_ABSA (sym->etype))
995 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
997 fprintf (out, "%s\t=\t0x%04x\n",
999 SPEC_ADDR (sym->etype));
1004 fprintf (out, " == .\n");
1006 /* if it has an initial value */
1009 fprintf (out, "%s:\n", sym->rname);
1011 resolveIvalSym (sym->ival);
1012 printIval (sym, sym->type, sym->ival, out);
1017 /* allocate space */
1018 fprintf (out, "%s:\n", sym->rname);
1019 /* special case for character strings */
1020 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1021 SPEC_CVAL (sym->etype).v_char)
1023 SPEC_CVAL (sym->etype).v_char,
1024 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1026 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1032 /*-----------------------------------------------------------------*/
1033 /* emitMaps - emits the code for the data portion the code */
1034 /*-----------------------------------------------------------------*/
1039 /* no special considerations for the following
1040 data, idata & bit & xdata */
1041 emitRegularMap (data, TRUE, TRUE);
1042 emitRegularMap (idata, TRUE, TRUE);
1043 emitRegularMap (bit, TRUE, FALSE);
1044 emitRegularMap (xdata, TRUE, TRUE);
1045 emitRegularMap (sfr, FALSE, FALSE);
1046 emitRegularMap (sfrbit, FALSE, FALSE);
1047 emitRegularMap (home, TRUE, FALSE);
1048 emitRegularMap (code, TRUE, FALSE);
1050 emitStaticSeg (statsg, code->oFile);
1054 /*-----------------------------------------------------------------*/
1055 /* flushStatics - flush all currently defined statics out to file */
1056 /* and delete. Temporary function */
1057 /*-----------------------------------------------------------------*/
1061 emitStaticSeg (statsg, codeOutFile);
1062 statsg->syms = NULL;
1065 /*-----------------------------------------------------------------*/
1066 /* createInterruptVect - creates the interrupt vector */
1067 /*-----------------------------------------------------------------*/
1069 createInterruptVect (FILE * vFile)
1072 mainf = newSymbol ("main", 0);
1075 /* only if the main function exists */
1076 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1078 if (!options.cc_only && !noAssemble)
1083 /* if the main is only a prototype ie. no body then do nothing */
1086 /* if ! compile only then main function should be present */
1087 if (!options.cc_only && !noAssemble)
1092 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1093 fprintf (vFile, "__interrupt_vect:\n");
1096 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1098 /* "generic" interrupt table header (if port doesn't specify one).
1100 * Look suspiciously like 8051 code to me...
1103 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1106 /* now for the other interrupts */
1107 for (; i < maxInterrupts; i++)
1110 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1112 fprintf (vFile, "\treti\n\t.ds\t7\n");
1119 ";--------------------------------------------------------\n"
1120 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1124 ";--------------------------------------------------------\n"};
1127 /*-----------------------------------------------------------------*/
1128 /* initialComments - puts in some initial comments */
1129 /*-----------------------------------------------------------------*/
1131 initialComments (FILE * afile)
1135 fprintf (afile, "%s", iComments1);
1136 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1137 fprintf (afile, "%s", iComments2);
1140 /*-----------------------------------------------------------------*/
1141 /* printPublics - generates .global for publics */
1142 /*-----------------------------------------------------------------*/
1144 printPublics (FILE * afile)
1148 fprintf (afile, "%s", iComments2);
1149 fprintf (afile, "; Public variables in this module\n");
1150 fprintf (afile, "%s", iComments2);
1152 for (sym = setFirstItem (publics); sym;
1153 sym = setNextItem (publics))
1154 tfprintf (afile, "\t!global\n", sym->rname);
1157 /*-----------------------------------------------------------------*/
1158 /* printExterns - generates .global for externs */
1159 /*-----------------------------------------------------------------*/
1161 printExterns (FILE * afile)
1165 fprintf (afile, "%s", iComments2);
1166 fprintf (afile, "; Externals used\n");
1167 fprintf (afile, "%s", iComments2);
1169 for (sym = setFirstItem (externs); sym;
1170 sym = setNextItem (externs))
1171 tfprintf (afile, "\t!global\n", sym->rname);
1174 /*-----------------------------------------------------------------*/
1175 /* emitOverlay - will emit code for the overlay stuff */
1176 /*-----------------------------------------------------------------*/
1178 emitOverlay (FILE * afile)
1182 if (!elementsInSet (ovrSetSets))
1183 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1185 /* for each of the sets in the overlay segment do */
1186 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1187 ovrset = setNextItem (ovrSetSets))
1192 if (elementsInSet (ovrset))
1194 /* this dummy area is used to fool the assembler
1195 otherwise the assembler will append each of these
1196 declarations into one chunk and will not overlay
1198 fprintf (afile, "\t.area _DUMMY\n");
1199 /* output the area informtion */
1200 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1203 for (sym = setFirstItem (ovrset); sym;
1204 sym = setNextItem (ovrset))
1207 /* if extern then add it to the publics tabledo nothing */
1208 if (IS_EXTERN (sym->etype))
1211 /* if allocation required check is needed
1212 then check if the symbol really requires
1213 allocation only for local variables */
1214 if (!IS_AGGREGATE (sym->type) &&
1215 !(sym->_isparm && !IS_REGPARM (sym->etype))
1216 && !sym->allocreq && sym->level)
1219 /* if global variable & not static or extern
1220 and addPublics allowed then add it to the public set */
1221 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1222 && !IS_STATIC (sym->etype))
1223 addSetHead (&publics, sym);
1225 /* if extern then do nothing or is a function
1227 if (IS_FUNC (sym->type))
1230 /* print extra debug info if required */
1233 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1237 if (IS_STATIC (sym->etype))
1238 fprintf (afile, "F%s$", moduleName); /* scope is file */
1240 fprintf (afile, "G$"); /* scope is global */
1243 /* symbol is local */
1244 fprintf (afile, "L%s$",
1245 (sym->localof ? sym->localof->name : "-null-"));
1246 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1249 /* if is has an absolute address then generate
1250 an equate for this no need to allocate space */
1251 if (SPEC_ABSA (sym->etype))
1255 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1257 fprintf (afile, "%s\t=\t0x%04x\n",
1259 SPEC_ADDR (sym->etype));
1264 fprintf (afile, "==.\n");
1266 /* allocate space */
1267 tfprintf (afile, "!labeldef\n", sym->rname);
1268 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1275 /*-----------------------------------------------------------------*/
1276 /* glue - the final glue that hold the whole thing together */
1277 /*-----------------------------------------------------------------*/
1283 FILE *ovrFile = tempfile ();
1285 addSetHead (&tmpfileSet, ovrFile);
1286 /* print the global struct definitions */
1288 cdbStructBlock (0, cdbFile);
1290 vFile = tempfile ();
1291 /* PENDING: this isnt the best place but it will do */
1292 if (port->general.glue_up_main)
1294 /* create the interrupt vector table */
1295 createInterruptVect (vFile);
1298 addSetHead (&tmpfileSet, vFile);
1300 /* emit code for the all the variables declared */
1302 /* do the overlay segments */
1303 emitOverlay (ovrFile);
1305 /* now put it all together into the assembler file */
1306 /* create the assembler file name */
1308 if (!options.c1mode)
1310 sprintf (scratchFileName, srcFileName);
1311 strcat (scratchFileName, port->assembler.file_ext);
1315 strcpy (scratchFileName, options.out_name);
1318 if (!(asmFile = fopen (scratchFileName, "w")))
1320 werror (E_FILE_OPEN_ERR, scratchFileName);
1324 /* initial comments */
1325 initialComments (asmFile);
1327 /* print module name */
1328 tfprintf (asmFile, "\t!module\n", moduleName);
1329 tfprintf (asmFile, "\t!fileprelude\n");
1331 /* Let the port generate any global directives, etc. */
1332 if (port->genAssemblerPreamble)
1334 port->genAssemblerPreamble (asmFile);
1337 /* print the global variables in this module */
1338 printPublics (asmFile);
1339 if (port->assembler.externGlobal)
1340 printExterns (asmFile);
1342 /* copy the sfr segment */
1343 fprintf (asmFile, "%s", iComments2);
1344 fprintf (asmFile, "; special function registers\n");
1345 fprintf (asmFile, "%s", iComments2);
1346 copyFile (asmFile, sfr->oFile);
1348 /* copy the sbit segment */
1349 fprintf (asmFile, "%s", iComments2);
1350 fprintf (asmFile, "; special function bits \n");
1351 fprintf (asmFile, "%s", iComments2);
1352 copyFile (asmFile, sfrbit->oFile);
1354 /* copy the data segment */
1355 fprintf (asmFile, "%s", iComments2);
1356 fprintf (asmFile, "; internal ram data\n");
1357 fprintf (asmFile, "%s", iComments2);
1358 copyFile (asmFile, data->oFile);
1361 /* create the overlay segments */
1362 fprintf (asmFile, "%s", iComments2);
1363 fprintf (asmFile, "; overlayable items in internal ram \n");
1364 fprintf (asmFile, "%s", iComments2);
1365 copyFile (asmFile, ovrFile);
1367 /* create the stack segment MOF */
1368 if (mainf && mainf->fbody)
1370 fprintf (asmFile, "%s", iComments2);
1371 fprintf (asmFile, "; Stack segment in internal ram \n");
1372 fprintf (asmFile, "%s", iComments2);
1373 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1374 "__start__stack:\n\t.ds\t1\n\n");
1377 /* create the idata segment */
1378 fprintf (asmFile, "%s", iComments2);
1379 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1380 fprintf (asmFile, "%s", iComments2);
1381 copyFile (asmFile, idata->oFile);
1383 /* copy the bit segment */
1384 fprintf (asmFile, "%s", iComments2);
1385 fprintf (asmFile, "; bit data\n");
1386 fprintf (asmFile, "%s", iComments2);
1387 copyFile (asmFile, bit->oFile);
1389 /* if external stack then reserve space of it */
1390 if (mainf && mainf->fbody && options.useXstack)
1392 fprintf (asmFile, "%s", iComments2);
1393 fprintf (asmFile, "; external stack \n");
1394 fprintf (asmFile, "%s", iComments2);
1395 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1396 fprintf (asmFile, "\t.ds 256\n");
1400 /* copy xtern ram data */
1401 fprintf (asmFile, "%s", iComments2);
1402 fprintf (asmFile, "; external ram data\n");
1403 fprintf (asmFile, "%s", iComments2);
1404 copyFile (asmFile, xdata->oFile);
1406 /* copy the interrupt vector table */
1407 if (mainf && mainf->fbody)
1409 fprintf (asmFile, "%s", iComments2);
1410 fprintf (asmFile, "; interrupt vector \n");
1411 fprintf (asmFile, "%s", iComments2);
1412 copyFile (asmFile, vFile);
1415 /* copy global & static initialisations */
1416 fprintf (asmFile, "%s", iComments2);
1417 fprintf (asmFile, "; global & static initialisations\n");
1418 fprintf (asmFile, "%s", iComments2);
1420 /* Everywhere we generate a reference to the static_name area,
1421 * (which is currently only here), we immediately follow it with a
1422 * definition of the post_static_name area. This guarantees that
1423 * the post_static_name area will immediately follow the static_name
1426 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1427 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1428 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1430 if (mainf && mainf->fbody)
1432 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1433 /* if external stack is specified then the
1434 higher order byte of the xdatalocation is
1435 going into P2 and the lower order going into
1437 if (options.useXstack)
1439 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1440 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1441 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1442 (unsigned int) options.xdata_loc & 0xff);
1445 /* initialise the stack pointer */
1446 /* if the user specified a value then use it */
1447 if (options.stack_loc)
1448 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1450 /* no: we have to compute it */
1451 if (!options.stackOnData && maxRegBank <= 3)
1452 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1454 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1456 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1457 fprintf (asmFile, "\tmov\ta,dpl\n");
1458 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1459 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1460 fprintf (asmFile, "__sdcc_init_data:\n");
1463 copyFile (asmFile, statsg->oFile);
1465 if (port->general.glue_up_main && mainf && mainf->fbody)
1467 /* This code is generated in the post-static area.
1468 * This area is guaranteed to follow the static area
1469 * by the ugly shucking and jiving about 20 lines ago.
1471 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1472 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1478 "%s", iComments2, iComments2);
1479 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1480 copyFile (asmFile, home->oFile);
1482 /* copy over code */
1483 fprintf (asmFile, "%s", iComments2);
1484 fprintf (asmFile, "; code\n");
1485 fprintf (asmFile, "%s", iComments2);
1486 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1487 if (mainf && mainf->fbody)
1490 /* entry point @ start of CSEG */
1491 fprintf (asmFile, "__sdcc_program_startup:\n");
1493 /* put in the call to main */
1494 fprintf (asmFile, "\tlcall\t_main\n");
1495 if (options.mainreturn)
1498 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1499 fprintf (asmFile, "\tret\n");
1505 fprintf (asmFile, ";\treturn from main will lock up\n");
1506 fprintf (asmFile, "\tsjmp .\n");
1509 copyFile (asmFile, code->oFile);
1512 applyToSet (tmpfileSet, closeTmpFiles);
1513 applyToSet (tmpfileNameSet, rmTmpFiles);
1516 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1520 applyToSet (tmpfileSet, closeTmpFiles);
1521 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);