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 for (sym = setFirstItem (map->syms); sym;
175 sym = setNextItem (map->syms))
180 /* if extern then add it into the extern list */
181 if (IS_EXTERN (sym->etype))
183 addSetHead (&externs, sym);
187 /* if allocation required check is needed
188 then check if the symbol really requires
189 allocation only for local variables */
191 if (arFlag && !IS_AGGREGATE (sym->type) &&
192 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
193 !sym->allocreq && sym->level)
196 /* for bitvar locals and parameters */
197 if (!arFlag && !sym->allocreq && sym->level
198 && !SPEC_ABSA (sym->etype)) {
202 /* if global variable & not static or extern
203 and addPublics allowed then add it to the public set */
204 if ((sym->level == 0 ||
205 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
207 !IS_STATIC (sym->etype) &&
208 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
210 addSetHead (&publics, sym);
213 /* if extern then do nothing or is a function
215 if (IS_FUNC (sym->type))
218 /* print extra debug info if required */
220 cdbSymbol (sym, cdbFile, FALSE, FALSE);
221 if (!sym->level) /* global */
222 if (IS_STATIC (sym->etype))
223 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
225 fprintf (map->oFile, "G$"); /* scope is global */
227 /* symbol is local */
228 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
229 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
232 /* if it has an initial value then do it only if
233 it is a global variable */
234 if (sym->ival && sym->level == 0) {
235 if (SPEC_OCLS(sym->etype)==xidata) {
236 // create a new "XINIT (CODE)" symbol, that will be emitted later
237 newSym=copySymbol (sym);
238 SPEC_OCLS(newSym->etype)=xinit;
239 sprintf (newSym->name, "_xinit_%s", sym->name);
240 sprintf (newSym->rname,"_xinit_%s", sym->rname);
241 SPEC_CONST(newSym->etype)=1;
242 //SPEC_STAT(newSym->etype)=1;
243 addSym (SymbolTab, newSym, newSym->name, 0, 0, 1);
245 // add it to the "XINIT (CODE)" segment
246 addSet(&xinit->syms, newSym);
248 //fprintf (stderr, "moved %s from xdata to xidata\n", sym->rname);
251 if (IS_AGGREGATE (sym->type)) {
252 ival = initAggregates (sym, sym->ival, NULL);
254 if (getNelements(sym->type, sym->ival)>1) {
255 werror (W_EXCESS_INITIALIZERS, "scalar",
256 sym->name, sym->lineDef);
258 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
259 decorateType (resolveSymbols (list2expr (sym->ival))));
261 codeOutFile = statsg->oFile;
265 // set ival's lineno to where the symbol was defined
266 lineno=ival->lineno=sym->lineDef;
268 eBBlockFromiCode (iCodeFromAst (ival));
273 // set ival's lineno to where the symbol was defined
274 lineno=ival->lineno=sym->lineDef;
275 // check if this is a constant expression
276 if (constExprTree(ival->right)) {
278 eBBlockFromiCode (iCodeFromAst (ival));
281 werror (E_CONST_EXPECTED, "found expression");
287 /* if the ival is a symbol assigned to an aggregate,
288 (bug #458099 -> #462479)
289 we don't need it anymore, so delete it from its segment */
290 if (sym->ival->type == INIT_NODE &&
291 IS_AST_SYM_VALUE(sym->ival->init.node) &&
292 IS_AGGREGATE (sym->type) ) {
293 symIval=AST_SYMBOL(sym->ival->init.node);
294 segment = SPEC_OCLS (symIval->etype);
295 deleteSetItem (&segment->syms, symIval);
301 /* if is has an absolute address then generate
302 an equate for this no need to allocate space */
303 if (SPEC_ABSA (sym->etype))
306 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
308 fprintf (map->oFile, "%s\t=\t0x%04x\n",
310 SPEC_ADDR (sym->etype));
314 // this has been moved to another segment
316 int size = getSize (sym->type);
318 werror(E_UNKNOWN_SIZE,sym->name);
322 fprintf (map->oFile, "==.\n");
324 if (IS_STATIC (sym->etype))
325 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
327 tfprintf (map->oFile, "!labeldef\n", sym->rname);
328 tfprintf (map->oFile, "\t!ds\n",
329 (unsigned int) size & 0xffff);
335 /*-----------------------------------------------------------------*/
336 /* initPointer - pointer initialization code massaging */
337 /*-----------------------------------------------------------------*/
339 initPointer (initList * ilist)
342 ast *expr = list2expr (ilist);
347 /* try it the oldway first */
348 if ((val = constExprValue (expr, FALSE)))
351 /* no then we have to do these cludgy checks */
352 /* pointers can be initialized with address of
353 a variable or address of an array element */
354 if (IS_AST_OP (expr) && expr->opval.op == '&') {
355 /* address of symbol */
356 if (IS_AST_SYM_VALUE (expr->left)) {
357 val = copyValue (AST_VALUE (expr->left));
358 val->type = newLink ();
359 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
360 DCL_TYPE (val->type) = CPOINTER;
361 DCL_PTR_CONST (val->type) = port->mem.code_ro;
363 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
364 DCL_TYPE (val->type) = FPOINTER;
365 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
366 DCL_TYPE (val->type) = PPOINTER;
367 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
368 DCL_TYPE (val->type) = IPOINTER;
369 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
370 DCL_TYPE (val->type) = EEPPOINTER;
372 DCL_TYPE (val->type) = POINTER;
373 val->type->next = expr->left->ftype;
374 val->etype = getSpec (val->type);
378 /* if address of indexed array */
379 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
380 return valForArray (expr->left);
382 /* if address of structure element then
384 if (IS_AST_OP (expr->left) &&
385 expr->left->opval.op == '.') {
386 return valForStructElem (expr->left->left,
391 (&some_struct)->element */
392 if (IS_AST_OP (expr->left) &&
393 expr->left->opval.op == PTR_OP &&
394 IS_ADDRESS_OF_OP (expr->left->left))
395 return valForStructElem (expr->left->left->left,
399 /* case 3. (((char *) &a) +/- constant) */
400 if (IS_AST_OP (expr) &&
401 (expr->opval.op == '+' || expr->opval.op == '-') &&
402 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
403 IS_AST_OP (expr->left->right) &&
404 expr->left->right->opval.op == '&' &&
405 IS_AST_LIT_VALUE (expr->right)) {
407 return valForCastAggr (expr->left->right->left,
408 expr->left->left->opval.lnk,
409 expr->right, expr->opval.op);
413 /* case 4. (char *)(array type) */
414 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
415 IS_ARRAY(expr->right->ftype)) {
417 val = copyValue (AST_VALUE (expr->right));
418 val->type = newLink ();
419 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
420 DCL_TYPE (val->type) = CPOINTER;
421 DCL_PTR_CONST (val->type) = port->mem.code_ro;
423 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
424 DCL_TYPE (val->type) = FPOINTER;
425 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
426 DCL_TYPE (val->type) = PPOINTER;
427 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
428 DCL_TYPE (val->type) = IPOINTER;
429 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
430 DCL_TYPE (val->type) = EEPPOINTER;
432 DCL_TYPE (val->type) = POINTER;
433 val->type->next = expr->right->ftype->next;
434 val->etype = getSpec (val->type);
438 werror (W_INIT_WRONG);
443 /*-----------------------------------------------------------------*/
444 /* printChar - formats and prints a characater string with DB */
445 /*-----------------------------------------------------------------*/
447 printChar (FILE * ofile, char *s, int plen)
450 int len = strlen (s);
455 while (len && pplen < plen)
458 while (i && *s && pplen < plen)
460 if (*s < ' ' || *s == '\"' || *s=='\\')
464 tfprintf (ofile, "\t!ascii\n", buf);
465 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
480 tfprintf (ofile, "\t!ascii\n", buf);
489 tfprintf (ofile, "\t!db !constbyte\n", 0);
492 /*-----------------------------------------------------------------*/
493 /* return the generic pointer high byte for a given pointer type. */
494 /*-----------------------------------------------------------------*/
496 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
504 /* hack - if we get a generic pointer, we just assume
505 * it's an FPOINTER (i.e. in XDATA space).
507 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
517 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
525 /*-----------------------------------------------------------------*/
526 /* printPointerType - generates ival for pointer type */
527 /*-----------------------------------------------------------------*/
529 _printPointerType (FILE * oFile, const char *name)
531 /* if (TARGET_IS_DS390) */
532 if (options.model == MODEL_FLAT24)
534 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
538 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
542 /*-----------------------------------------------------------------*/
543 /* printPointerType - generates ival for pointer type */
544 /*-----------------------------------------------------------------*/
546 printPointerType (FILE * oFile, const char *name)
548 _printPointerType (oFile, name);
549 fprintf (oFile, "\n");
552 /*-----------------------------------------------------------------*/
553 /* printGPointerType - generates ival for generic pointer type */
554 /*-----------------------------------------------------------------*/
556 printGPointerType (FILE * oFile, const char *iname, const char *oname,
557 const unsigned int type)
559 _printPointerType (oFile, iname);
560 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
563 /*-----------------------------------------------------------------*/
564 /* printIvalType - generates ival for int/char */
565 /*-----------------------------------------------------------------*/
567 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
571 /* if initList is deep */
572 if (ilist->type == INIT_DEEP)
573 ilist = ilist->init.deep;
575 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
576 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
579 if (!(val = list2val (ilist))) {
580 // assuming a warning has been thrown
584 if (val->type != type) {
585 val = valCastLiteral(type, floatFromVal(val));
588 switch (getSize (type)) {
591 tfprintf (oFile, "\t!db !constbyte\n", 0);
593 tfprintf (oFile, "\t!dbs\n",
594 aopLiteral (val, 0));
598 if (port->use_dw_for_init)
599 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
601 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
605 tfprintf (oFile, "\t!dw !constword\n", 0);
606 tfprintf (oFile, "\t!dw !constword\n", 0);
609 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
610 aopLiteral (val, 0), aopLiteral (val, 1),
611 aopLiteral (val, 2), aopLiteral (val, 3));
617 /*-----------------------------------------------------------------*/
618 /* printIvalBitFields - generate initializer for bitfields */
619 /*-----------------------------------------------------------------*/
620 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
624 initList *lilist = *ilist ;
625 unsigned long ival = 0;
631 val = list2val(lilist);
633 if (SPEC_BLEN(lsym->etype) > 8) {
634 size += ((SPEC_BLEN (lsym->etype) / 8) +
635 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
638 size = ((SPEC_BLEN (lsym->etype) / 8) +
639 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
641 i = (unsigned long)floatFromVal(val);
642 i <<= SPEC_BSTR (lsym->etype);
644 if (! ( lsym->next &&
645 (IS_BITFIELD(lsym->next->type)) &&
646 (SPEC_BSTR(lsym->next->etype)))) break;
648 lilist = lilist->next;
652 tfprintf (oFile, "\t!db !constbyte\n",ival);
656 tfprintf (oFile, "\t!dw !constword\n",ival);
659 tfprintf (oFile, "\t!db !constword,!constword\n",
660 (ival >> 8) & 0xffff, (ival & 0xffff));
667 /*-----------------------------------------------------------------*/
668 /* printIvalStruct - generates initial value for structures */
669 /*-----------------------------------------------------------------*/
671 printIvalStruct (symbol * sym, sym_link * type,
672 initList * ilist, FILE * oFile)
677 sflds = SPEC_STRUCT (type)->fields;
678 if (ilist->type != INIT_DEEP) {
679 werror (E_INIT_STRUCT, sym->name);
683 iloop = ilist->init.deep;
685 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
686 if (IS_BITFIELD(sflds->type)) {
687 printIvalBitFields(&sflds,&iloop,oFile);
689 printIval (sym, sflds->type, iloop, oFile);
693 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
698 /*-----------------------------------------------------------------*/
699 /* printIvalChar - generates initital value for character array */
700 /*-----------------------------------------------------------------*/
702 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
710 val = list2val (ilist);
711 /* if the value is a character string */
712 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
714 if (!DCL_ELEM (type))
715 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
717 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
719 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
721 tfprintf (oFile, "\t!db !constbyte\n", 0);
729 printChar (oFile, s, strlen (s) + 1);
733 /*-----------------------------------------------------------------*/
734 /* printIvalArray - generates code for array initialization */
735 /*-----------------------------------------------------------------*/
737 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
741 int lcnt = 0, size = 0;
743 /* take care of the special case */
744 /* array of characters can be init */
746 if (IS_CHAR (type->next))
747 if (printIvalChar (type,
748 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
749 oFile, SPEC_CVAL (sym->etype).v_char))
752 /* not the special case */
753 if (ilist->type != INIT_DEEP)
755 werror (E_INIT_STRUCT, sym->name);
759 iloop = ilist->init.deep;
760 lcnt = DCL_ELEM (type);
765 printIval (sym, type->next, iloop, oFile);
766 iloop = (iloop ? iloop->next : NULL);
769 /* if not array limits given & we */
770 /* are out of initialisers then */
771 if (!DCL_ELEM (type) && !iloop)
774 /* no of elements given and we */
775 /* have generated for all of them */
777 /* if initializers left */
779 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
785 /* if we have not been given a size */
786 if (!DCL_ELEM (type))
787 DCL_ELEM (type) = size;
792 /*-----------------------------------------------------------------*/
793 /* printIvalFuncPtr - generate initial value for function pointers */
794 /*-----------------------------------------------------------------*/
796 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
801 val = list2val (ilist);
802 /* check the types */
803 if ((dLvl = compareType (val->type, type->next)) <= 0)
805 tfprintf (oFile, "\t!dw !constword\n", 0);
809 /* now generate the name */
812 if (port->use_dw_for_init)
814 tfprintf (oFile, "\t!dws\n", val->name);
818 printPointerType (oFile, val->name);
821 else if (port->use_dw_for_init)
823 tfprintf (oFile, "\t!dws\n", val->sym->rname);
827 printPointerType (oFile, val->sym->rname);
833 /*-----------------------------------------------------------------*/
834 /* printIvalCharPtr - generates initial values for character pointers */
835 /*-----------------------------------------------------------------*/
837 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
841 /* PENDING: this is _very_ mcs51 specific, including a magic
843 It's also endin specific.
845 size = getSize (type);
847 if (val->name && strlen (val->name))
849 if (size == 1) /* This appears to be Z80 specific?? */
852 "\t!dbs\n", val->name);
854 else if (size == FPTRSIZE)
856 if (port->use_dw_for_init)
858 tfprintf (oFile, "\t!dws\n", val->name);
862 printPointerType (oFile, val->name);
865 else if (size == GPTRSIZE)
868 if (IS_PTR (val->type)) {
869 type = DCL_TYPE (val->type);
871 type = PTR_TYPE (SPEC_OCLS (val->etype));
873 if (val->sym && val->sym->isstrlit) {
874 // this is a literal string
877 printGPointerType (oFile, val->name, sym->name, type);
881 fprintf (stderr, "*** internal error: unknown size in "
882 "printIvalCharPtr.\n");
887 // these are literals assigned to pointers
891 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
894 if (port->use_dw_for_init)
895 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
897 tfprintf (oFile, "\t.byte %s,%s\n",
898 aopLiteral (val, 0), aopLiteral (val, 1));
901 // mcs51 generic pointer
902 if (floatFromVal(val)!=0) {
903 werror (E_LITERAL_GENERIC);
905 fprintf (oFile, "\t.byte %s,%s,%s\n",
908 aopLiteral (val, 2));
911 // ds390 generic pointer
912 if (floatFromVal(val)!=0) {
913 werror (E_LITERAL_GENERIC);
915 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
919 aopLiteral (val, 3));
926 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
927 addSet (&statsg->syms, val->sym);
933 /*-----------------------------------------------------------------*/
934 /* printIvalPtr - generates initial value for pointers */
935 /*-----------------------------------------------------------------*/
937 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
943 if (ilist->type == INIT_DEEP)
944 ilist = ilist->init.deep;
946 /* function pointer */
947 if (IS_FUNC (type->next))
949 printIvalFuncPtr (type, ilist, oFile);
953 if (!(val = initPointer (ilist)))
956 /* if character pointer */
957 if (IS_CHAR (type->next))
958 if (printIvalCharPtr (sym, type, val, oFile))
962 if (compareType (type, val->type) == 0)
963 werror (W_INIT_WRONG);
965 /* if val is literal */
966 if (IS_LITERAL (val->etype))
968 switch (getSize (type))
971 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
974 if (port->use_dw_for_init)
975 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
977 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
980 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
981 aopLiteral (val, 0), aopLiteral (val, 1));
987 size = getSize (type);
989 if (size == 1) /* Z80 specific?? */
991 tfprintf (oFile, "\t!dbs\n", val->name);
993 else if (size == FPTRSIZE)
995 if (port->use_dw_for_init) {
996 tfprintf (oFile, "\t!dws\n", val->name);
998 printPointerType (oFile, val->name);
1001 else if (size == GPTRSIZE)
1003 printGPointerType (oFile, val->name, sym->name,
1004 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1005 PTR_TYPE (SPEC_OCLS (val->etype))));
1010 /*-----------------------------------------------------------------*/
1011 /* printIval - generates code for initial value */
1012 /*-----------------------------------------------------------------*/
1014 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1019 /* if structure then */
1020 if (IS_STRUCT (type))
1022 printIvalStruct (sym, type, ilist, oFile);
1026 /* if this is a pointer */
1029 printIvalPtr (sym, type, ilist, oFile);
1033 /* if this is an array */
1034 if (IS_ARRAY (type))
1036 printIvalArray (sym, type, ilist, oFile);
1040 /* if type is SPECIFIER */
1043 printIvalType (sym, type, ilist, oFile);
1048 /*-----------------------------------------------------------------*/
1049 /* emitStaticSeg - emitcode for the static segment */
1050 /*-----------------------------------------------------------------*/
1052 emitStaticSeg (memmap * map, FILE * out)
1056 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1058 /* for all variables in this segment do */
1059 for (sym = setFirstItem (map->syms); sym;
1060 sym = setNextItem (map->syms))
1063 /* if it is "extern" then do nothing */
1064 if (IS_EXTERN (sym->etype))
1067 /* if it is not static add it to the public
1069 if (!IS_STATIC (sym->etype))
1071 addSetHead (&publics, sym);
1074 /* print extra debug info if required */
1075 if (options.debug) {
1076 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1079 if (IS_STATIC (sym->etype))
1080 fprintf (out, "F%s$", moduleName); /* scope is file */
1082 fprintf (out, "G$"); /* scope is global */
1085 /* symbol is local */
1086 fprintf (out, "L%s$",
1087 (sym->localof ? sym->localof->name : "-null-"));
1088 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1091 /* if it has an absolute address */
1092 if (SPEC_ABSA (sym->etype))
1095 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1097 fprintf (out, "%s\t=\t0x%04x\n",
1099 SPEC_ADDR (sym->etype));
1104 fprintf (out, " == .\n");
1106 /* if it has an initial value */
1109 fprintf (out, "%s:\n", sym->rname);
1111 resolveIvalSym (sym->ival);
1112 printIval (sym, sym->type, sym->ival, out);
1116 /* allocate space */
1117 int size = getSize (sym->type);
1120 werror(E_UNKNOWN_SIZE,sym->name);
1122 fprintf (out, "%s:\n", sym->rname);
1123 /* special case for character strings */
1124 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1125 SPEC_CVAL (sym->etype).v_char)
1127 SPEC_CVAL (sym->etype).v_char,
1128 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1130 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1136 /*-----------------------------------------------------------------*/
1137 /* emitMaps - emits the code for the data portion the code */
1138 /*-----------------------------------------------------------------*/
1143 /* no special considerations for the following
1144 data, idata & bit & xdata */
1145 emitRegularMap (data, TRUE, TRUE);
1146 emitRegularMap (idata, TRUE, TRUE);
1147 emitRegularMap (bit, TRUE, FALSE);
1148 emitRegularMap (xdata, TRUE, TRUE);
1149 if (port->genXINIT) {
1150 emitRegularMap (xidata, TRUE, TRUE);
1152 emitRegularMap (sfr, FALSE, FALSE);
1153 emitRegularMap (sfrbit, FALSE, FALSE);
1154 emitRegularMap (home, TRUE, FALSE);
1155 emitRegularMap (code, TRUE, FALSE);
1157 emitStaticSeg (statsg, code->oFile);
1158 if (port->genXINIT) {
1159 fprintf (code->oFile, "\t.area\t%s\n", xinit->sname);
1160 emitStaticSeg (xinit, code->oFile);
1165 /*-----------------------------------------------------------------*/
1166 /* flushStatics - flush all currently defined statics out to file */
1167 /* and delete. Temporary function */
1168 /*-----------------------------------------------------------------*/
1172 emitStaticSeg (statsg, codeOutFile);
1173 statsg->syms = NULL;
1176 /*-----------------------------------------------------------------*/
1177 /* createInterruptVect - creates the interrupt vector */
1178 /*-----------------------------------------------------------------*/
1180 createInterruptVect (FILE * vFile)
1183 mainf = newSymbol ("main", 0);
1186 /* only if the main function exists */
1187 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1189 if (!options.cc_only && !noAssemble)
1194 /* if the main is only a prototype ie. no body then do nothing */
1195 if (!IFFUNC_HASBODY(mainf->type))
1197 /* if ! compile only then main function should be present */
1198 if (!options.cc_only && !noAssemble)
1203 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1204 fprintf (vFile, "__interrupt_vect:\n");
1207 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1209 /* "generic" interrupt table header (if port doesn't specify one).
1210 * Look suspiciously like 8051 code to me...
1213 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1216 /* now for the other interrupts */
1217 for (; i < maxInterrupts; i++)
1220 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1222 fprintf (vFile, "\treti\n\t.ds\t7\n");
1229 ";--------------------------------------------------------\n"
1230 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1234 ";--------------------------------------------------------\n"};
1237 /*-----------------------------------------------------------------*/
1238 /* initialComments - puts in some initial comments */
1239 /*-----------------------------------------------------------------*/
1241 initialComments (FILE * afile)
1245 fprintf (afile, "%s", iComments1);
1246 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1247 fprintf (afile, "%s", iComments2);
1250 /*-----------------------------------------------------------------*/
1251 /* printPublics - generates .global for publics */
1252 /*-----------------------------------------------------------------*/
1254 printPublics (FILE * afile)
1258 fprintf (afile, "%s", iComments2);
1259 fprintf (afile, "; Public variables in this module\n");
1260 fprintf (afile, "%s", iComments2);
1262 for (sym = setFirstItem (publics); sym;
1263 sym = setNextItem (publics))
1264 tfprintf (afile, "\t!global\n", sym->rname);
1267 /*-----------------------------------------------------------------*/
1268 /* printExterns - generates .global for externs */
1269 /*-----------------------------------------------------------------*/
1271 printExterns (FILE * afile)
1275 fprintf (afile, "%s", iComments2);
1276 fprintf (afile, "; Externals used\n");
1277 fprintf (afile, "%s", iComments2);
1279 for (sym = setFirstItem (externs); sym;
1280 sym = setNextItem (externs))
1281 tfprintf (afile, "\t!extern\n", sym->rname);
1284 /*-----------------------------------------------------------------*/
1285 /* emitOverlay - will emit code for the overlay stuff */
1286 /*-----------------------------------------------------------------*/
1288 emitOverlay (FILE * afile)
1292 if (!elementsInSet (ovrSetSets))
1293 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1295 /* for each of the sets in the overlay segment do */
1296 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1297 ovrset = setNextItem (ovrSetSets))
1302 if (elementsInSet (ovrset))
1305 /* this dummy area is used to fool the assembler
1306 otherwise the assembler will append each of these
1307 declarations into one chunk and will not overlay
1309 fprintf (afile, "\t.area _DUMMY\n");
1311 /* not anymore since asmain.c:1.13 */
1313 /* output the area informtion */
1314 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1317 for (sym = setFirstItem (ovrset); sym;
1318 sym = setNextItem (ovrset))
1321 /* if extern then add it to the publics tabledo nothing */
1322 if (IS_EXTERN (sym->etype))
1325 /* if allocation required check is needed
1326 then check if the symbol really requires
1327 allocation only for local variables */
1328 if (!IS_AGGREGATE (sym->type) &&
1329 !(sym->_isparm && !IS_REGPARM (sym->etype))
1330 && !sym->allocreq && sym->level)
1333 /* if global variable & not static or extern
1334 and addPublics allowed then add it to the public set */
1335 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1336 && !IS_STATIC (sym->etype))
1338 addSetHead (&publics, sym);
1341 /* if extern then do nothing or is a function
1343 if (IS_FUNC (sym->type))
1346 /* print extra debug info if required */
1349 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1353 if (IS_STATIC (sym->etype))
1354 fprintf (afile, "F%s$", moduleName); /* scope is file */
1356 fprintf (afile, "G$"); /* scope is global */
1359 /* symbol is local */
1360 fprintf (afile, "L%s$",
1361 (sym->localof ? sym->localof->name : "-null-"));
1362 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1365 /* if is has an absolute address then generate
1366 an equate for this no need to allocate space */
1367 if (SPEC_ABSA (sym->etype))
1371 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1373 fprintf (afile, "%s\t=\t0x%04x\n",
1375 SPEC_ADDR (sym->etype));
1378 int size = getSize(sym->type);
1381 werror(E_UNKNOWN_SIZE,sym->name);
1384 fprintf (afile, "==.\n");
1386 /* allocate space */
1387 tfprintf (afile, "!labeldef\n", sym->rname);
1388 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1395 /*-----------------------------------------------------------------*/
1396 /* glue - the final glue that hold the whole thing together */
1397 /*-----------------------------------------------------------------*/
1403 FILE *ovrFile = tempfile ();
1405 addSetHead (&tmpfileSet, ovrFile);
1406 /* print the global struct definitions */
1408 cdbStructBlock (0, cdbFile);
1410 vFile = tempfile ();
1411 /* PENDING: this isnt the best place but it will do */
1412 if (port->general.glue_up_main)
1414 /* create the interrupt vector table */
1415 createInterruptVect (vFile);
1418 addSetHead (&tmpfileSet, vFile);
1420 /* emit code for the all the variables declared */
1422 /* do the overlay segments */
1423 emitOverlay (ovrFile);
1425 /* now put it all together into the assembler file */
1426 /* create the assembler file name */
1428 if (!options.c1mode)
1430 sprintf (scratchFileName, srcFileName);
1431 strcat (scratchFileName, port->assembler.file_ext);
1435 strcpy (scratchFileName, options.out_name);
1438 if (!(asmFile = fopen (scratchFileName, "w")))
1440 werror (E_FILE_OPEN_ERR, scratchFileName);
1444 /* initial comments */
1445 initialComments (asmFile);
1447 /* print module name */
1448 tfprintf (asmFile, "\t!module\n", moduleName);
1449 tfprintf (asmFile, "\t!fileprelude\n");
1451 /* Let the port generate any global directives, etc. */
1452 if (port->genAssemblerPreamble)
1454 port->genAssemblerPreamble (asmFile);
1457 /* print the global variables in this module */
1458 printPublics (asmFile);
1459 if (port->assembler.externGlobal)
1460 printExterns (asmFile);
1462 /* copy the sfr segment */
1463 fprintf (asmFile, "%s", iComments2);
1464 fprintf (asmFile, "; special function registers\n");
1465 fprintf (asmFile, "%s", iComments2);
1466 copyFile (asmFile, sfr->oFile);
1468 /* copy the sbit segment */
1469 fprintf (asmFile, "%s", iComments2);
1470 fprintf (asmFile, "; special function bits \n");
1471 fprintf (asmFile, "%s", iComments2);
1472 copyFile (asmFile, sfrbit->oFile);
1474 /* copy the data segment */
1475 fprintf (asmFile, "%s", iComments2);
1476 fprintf (asmFile, "; internal ram data\n");
1477 fprintf (asmFile, "%s", iComments2);
1478 copyFile (asmFile, data->oFile);
1481 /* create the overlay segments */
1482 fprintf (asmFile, "%s", iComments2);
1483 fprintf (asmFile, "; overlayable items in internal ram \n");
1484 fprintf (asmFile, "%s", iComments2);
1485 copyFile (asmFile, ovrFile);
1487 /* create the stack segment MOF */
1488 if (mainf && IFFUNC_HASBODY(mainf->type))
1490 fprintf (asmFile, "%s", iComments2);
1491 fprintf (asmFile, "; Stack segment in internal ram \n");
1492 fprintf (asmFile, "%s", iComments2);
1493 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1494 "__start__stack:\n\t.ds\t1\n\n");
1497 /* create the idata segment */
1498 fprintf (asmFile, "%s", iComments2);
1499 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1500 fprintf (asmFile, "%s", iComments2);
1501 copyFile (asmFile, idata->oFile);
1503 /* copy the bit segment */
1504 fprintf (asmFile, "%s", iComments2);
1505 fprintf (asmFile, "; bit data\n");
1506 fprintf (asmFile, "%s", iComments2);
1507 copyFile (asmFile, bit->oFile);
1509 /* if external stack then reserve space of it */
1510 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1512 fprintf (asmFile, "%s", iComments2);
1513 fprintf (asmFile, "; external stack \n");
1514 fprintf (asmFile, "%s", iComments2);
1515 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1516 fprintf (asmFile, "\t.ds 256\n");
1520 /* copy xtern ram data */
1521 fprintf (asmFile, "%s", iComments2);
1522 fprintf (asmFile, "; external ram data\n");
1523 fprintf (asmFile, "%s", iComments2);
1524 copyFile (asmFile, xdata->oFile);
1526 /* copy xternal initialized ram data */
1527 fprintf (asmFile, "%s", iComments2);
1528 fprintf (asmFile, "; external initialized ram data\n");
1529 fprintf (asmFile, "%s", iComments2);
1530 copyFile (asmFile, xidata->oFile);
1532 /* copy the interrupt vector table */
1533 if (mainf && IFFUNC_HASBODY(mainf->type))
1535 fprintf (asmFile, "%s", iComments2);
1536 fprintf (asmFile, "; interrupt vector \n");
1537 fprintf (asmFile, "%s", iComments2);
1538 copyFile (asmFile, vFile);
1541 /* copy global & static initialisations */
1542 fprintf (asmFile, "%s", iComments2);
1543 fprintf (asmFile, "; global & static initialisations\n");
1544 fprintf (asmFile, "%s", iComments2);
1546 /* Everywhere we generate a reference to the static_name area,
1547 * (which is currently only here), we immediately follow it with a
1548 * definition of the post_static_name area. This guarantees that
1549 * the post_static_name area will immediately follow the static_name
1552 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1553 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1554 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1556 if (mainf && IFFUNC_HASBODY(mainf->type))
1558 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1559 /* if external stack is specified then the
1560 higher order byte of the xdatalocation is
1561 going into P2 and the lower order going into
1563 if (options.useXstack)
1565 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1566 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1567 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1568 (unsigned int) options.xdata_loc & 0xff);
1571 /* initialise the stack pointer */
1572 /* if the user specified a value then use it */
1573 if (options.stack_loc)
1574 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff);
1576 /* no: we have to compute it */
1577 if (!options.stackOnData && maxRegBank <= 3)
1578 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1580 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1582 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1583 fprintf (asmFile, "\tmov\ta,dpl\n");
1584 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1585 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1586 fprintf (asmFile, "__sdcc_init_data:\n");
1588 // if the port can copy the XINIT segment to XISEG
1589 if (port->genXINIT) {
1590 port->genXINIT(asmFile);
1594 copyFile (asmFile, statsg->oFile);
1596 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1598 /* This code is generated in the post-static area.
1599 * This area is guaranteed to follow the static area
1600 * by the ugly shucking and jiving about 20 lines ago.
1602 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1603 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1609 "%s", iComments2, iComments2);
1610 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1611 copyFile (asmFile, home->oFile);
1613 /* copy over code */
1614 fprintf (asmFile, "%s", iComments2);
1615 fprintf (asmFile, "; code\n");
1616 fprintf (asmFile, "%s", iComments2);
1617 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1618 if (mainf && IFFUNC_HASBODY(mainf->type))
1621 /* entry point @ start of CSEG */
1622 fprintf (asmFile, "__sdcc_program_startup:\n");
1624 /* put in the call to main */
1625 fprintf (asmFile, "\tlcall\t_main\n");
1626 if (options.mainreturn)
1629 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1630 fprintf (asmFile, "\tret\n");
1636 fprintf (asmFile, ";\treturn from main will lock up\n");
1637 fprintf (asmFile, "\tsjmp .\n");
1640 copyFile (asmFile, code->oFile);
1642 if (port->genAssemblerEnd) {
1643 port->genAssemblerEnd(asmFile);
1646 applyToSet (tmpfileSet, closeTmpFiles);
1647 applyToSet (tmpfileNameSet, rmTmpFiles);
1650 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1654 applyToSet (tmpfileSet, closeTmpFiles);
1655 applyToSet (tmpfileNameSet, rmTmpFiles);
1659 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1660 in cygwin wrt c:\tmp.
1661 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1666 #if !defined(_MSC_VER)
1667 const char *tmpdir = NULL;
1669 tmpdir = getenv ("TMP");
1670 else if (getenv ("TEMP"))
1671 tmpdir = getenv ("TEMP");
1672 else if (getenv ("TMPDIR"))
1673 tmpdir = getenv ("TMPDIR");
1676 char *name = tempnam (tmpdir, "sdcc");
1683 return tmpnam (NULL);
1686 /** Creates a temporary file a'la tmpfile which avoids the bugs
1687 in cygwin wrt c:\tmp.
1688 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1693 #if !defined(_MSC_VER)
1694 const char *tmpdir = NULL;
1696 tmpdir = getenv ("TMP");
1697 else if (getenv ("TEMP"))
1698 tmpdir = getenv ("TEMP");
1699 else if (getenv ("TMPDIR"))
1700 tmpdir = getenv ("TMPDIR");
1703 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1706 FILE *fp = fopen (name, "w+b");
1709 addSetHead (&tmpfileNameSet, name);