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 // can we copy xidata from xinit?
236 if (port->genXINIT &&
237 SPEC_OCLS(sym->etype)==xdata &&
238 !SPEC_ABSA(sym->etype)) {
240 // create a new "XINIT (CODE)" symbol
241 newSym=copySymbol (sym);
242 SPEC_OCLS(newSym->etype)=xinit;
243 sprintf (newSym->name, "_xinit_%s", sym->name);
244 sprintf (newSym->rname,"_xinit_%s", sym->rname);
245 SPEC_CONST(newSym->etype)=1;
246 //SPEC_STAT(newSym->etype)=1;
247 addSym (SymbolTab, newSym, newSym->name, 0, 0, 1);
249 // add it to the "XINIT (CODE)" segment
250 addSet(&xinit->syms, newSym);
252 // move sym from "XSEG (XDATA)" to "XISEG (XDATA)" segment
253 //deleteSetItem(&xdata->syms, sym);
254 addSet(&xidata->syms, sym);
255 SPEC_OCLS(sym->etype)=xidata;
257 //fprintf (stderr, "moved %s from xdata to xidata\n", sym->rname);
260 if (IS_AGGREGATE (sym->type)) {
261 ival = initAggregates (sym, sym->ival, NULL);
263 if (getNelements(sym->type, sym->ival)>1) {
264 werror (W_EXCESS_INITIALIZERS, "scalar",
265 sym->name, sym->lineDef);
267 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
268 decorateType (resolveSymbols (list2expr (sym->ival))));
270 codeOutFile = statsg->oFile;
273 // set ival's lineno to where the symbol was defined
274 if (ival) ival->lineno=sym->lineDef;
275 eBBlockFromiCode (iCodeFromAst (ival));
279 /* if the ival is a symbol assigned to an aggregate,
280 (bug #458099 -> #462479)
281 we don't need it anymore, so delete it from its segment */
282 if (sym->ival->type == INIT_NODE &&
283 IS_AST_SYM_VALUE(sym->ival->init.node) &&
284 IS_AGGREGATE (sym->type) ) {
285 symIval=AST_SYMBOL(sym->ival->init.node);
286 segment = SPEC_OCLS (symIval->etype);
287 deleteSetItem (&segment->syms, symIval);
293 /* if is has an absolute address then generate
294 an equate for this no need to allocate space */
295 if (SPEC_ABSA (sym->etype))
298 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
300 fprintf (map->oFile, "%s\t=\t0x%04x\n",
302 SPEC_ADDR (sym->etype));
307 // this has been moved to another segment
311 fprintf (map->oFile, "==.\n");
313 if (IS_STATIC (sym->etype))
314 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
316 tfprintf (map->oFile, "!labeldef\n", sym->rname);
317 tfprintf (map->oFile, "\t!ds\n",
318 (unsigned int) getSize (sym->type) & 0xffff);
324 /*-----------------------------------------------------------------*/
325 /* initPointer - pointer initialization code massaging */
326 /*-----------------------------------------------------------------*/
328 initPointer (initList * ilist)
331 ast *expr = list2expr (ilist);
336 /* try it the oldway first */
337 if ((val = constExprValue (expr, FALSE)))
340 /* no then we have to do these cludgy checks */
341 /* pointers can be initialized with address of
342 a variable or address of an array element */
343 if (IS_AST_OP (expr) && expr->opval.op == '&') {
344 /* address of symbol */
345 if (IS_AST_SYM_VALUE (expr->left)) {
346 val = copyValue (AST_VALUE (expr->left));
347 val->type = newLink ();
348 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
349 DCL_TYPE (val->type) = CPOINTER;
350 DCL_PTR_CONST (val->type) = port->mem.code_ro;
352 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
353 DCL_TYPE (val->type) = FPOINTER;
354 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
355 DCL_TYPE (val->type) = PPOINTER;
356 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
357 DCL_TYPE (val->type) = IPOINTER;
358 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
359 DCL_TYPE (val->type) = EEPPOINTER;
361 DCL_TYPE (val->type) = POINTER;
362 val->type->next = expr->left->ftype;
363 val->etype = getSpec (val->type);
367 /* if address of indexed array */
368 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
369 return valForArray (expr->left);
371 /* if address of structure element then
373 if (IS_AST_OP (expr->left) &&
374 expr->left->opval.op == '.') {
375 return valForStructElem (expr->left->left,
380 (&some_struct)->element */
381 if (IS_AST_OP (expr->left) &&
382 expr->left->opval.op == PTR_OP &&
383 IS_ADDRESS_OF_OP (expr->left->left))
384 return valForStructElem (expr->left->left->left,
388 /* case 3. (((char *) &a) +/- constant) */
389 if (IS_AST_OP (expr) &&
390 (expr->opval.op == '+' || expr->opval.op == '-') &&
391 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
392 IS_AST_OP (expr->left->right) &&
393 expr->left->right->opval.op == '&' &&
394 IS_AST_LIT_VALUE (expr->right)) {
396 return valForCastAggr (expr->left->right->left,
397 expr->left->left->opval.lnk,
398 expr->right, expr->opval.op);
402 /* case 4. (char *)(array type) */
403 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
404 IS_ARRAY(expr->right->ftype)) {
406 val = copyValue (AST_VALUE (expr->right));
407 val->type = newLink ();
408 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
409 DCL_TYPE (val->type) = CPOINTER;
410 DCL_PTR_CONST (val->type) = port->mem.code_ro;
412 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
413 DCL_TYPE (val->type) = FPOINTER;
414 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
415 DCL_TYPE (val->type) = PPOINTER;
416 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
417 DCL_TYPE (val->type) = IPOINTER;
418 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
419 DCL_TYPE (val->type) = EEPPOINTER;
421 DCL_TYPE (val->type) = POINTER;
422 val->type->next = expr->right->ftype->next;
423 val->etype = getSpec (val->type);
427 werror (W_INIT_WRONG);
432 /*-----------------------------------------------------------------*/
433 /* printChar - formats and prints a characater string with DB */
434 /*-----------------------------------------------------------------*/
436 printChar (FILE * ofile, char *s, int plen)
439 int len = strlen (s);
444 while (len && pplen < plen)
447 while (i && *s && pplen < plen)
449 if (*s < ' ' || *s == '\"' || *s=='\\')
453 tfprintf (ofile, "\t!ascii\n", buf);
454 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
469 tfprintf (ofile, "\t!ascii\n", buf);
478 tfprintf (ofile, "\t!db !constbyte\n", 0);
481 /*-----------------------------------------------------------------*/
482 /* return the generic pointer high byte for a given pointer type. */
483 /*-----------------------------------------------------------------*/
485 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
493 /* hack - if we get a generic pointer, we just assume
494 * it's an FPOINTER (i.e. in XDATA space).
496 werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
506 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
514 /*-----------------------------------------------------------------*/
515 /* printPointerType - generates ival for pointer type */
516 /*-----------------------------------------------------------------*/
518 _printPointerType (FILE * oFile, const char *name)
520 /* if (TARGET_IS_DS390) */
521 if (options.model == MODEL_FLAT24)
523 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
527 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
531 /*-----------------------------------------------------------------*/
532 /* printPointerType - generates ival for pointer type */
533 /*-----------------------------------------------------------------*/
535 printPointerType (FILE * oFile, const char *name)
537 _printPointerType (oFile, name);
538 fprintf (oFile, "\n");
541 /*-----------------------------------------------------------------*/
542 /* printGPointerType - generates ival for generic pointer type */
543 /*-----------------------------------------------------------------*/
545 printGPointerType (FILE * oFile, const char *iname, const char *oname,
546 const unsigned int type)
548 _printPointerType (oFile, iname);
549 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
552 /*-----------------------------------------------------------------*/
553 /* printIvalType - generates ival for int/char */
554 /*-----------------------------------------------------------------*/
556 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
560 /* if initList is deep */
561 if (ilist->type == INIT_DEEP)
562 ilist = ilist->init.deep;
564 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
565 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
568 val = list2val (ilist);
569 switch (getSize (type)) {
572 tfprintf (oFile, "\t!db !constbyte\n", 0);
574 tfprintf (oFile, "\t!dbs\n",
575 aopLiteral (val, 0));
579 if (port->use_dw_for_init)
580 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
582 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
586 tfprintf (oFile, "\t!dw !constword\n", 0);
587 tfprintf (oFile, "\t!dw !constword\n", 0);
590 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
591 aopLiteral (val, 0), aopLiteral (val, 1),
592 aopLiteral (val, 2), aopLiteral (val, 3));
598 /*-----------------------------------------------------------------*/
599 /* printIvalBitFields - generate initializer for bitfields */
600 /*-----------------------------------------------------------------*/
601 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
605 initList *lilist = *ilist ;
606 unsigned long ival = 0;
612 val = list2val(lilist);
614 if (SPEC_BLEN(lsym->etype) > 8) {
615 size += ((SPEC_BLEN (lsym->etype) / 8) +
616 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
619 size = ((SPEC_BLEN (lsym->etype) / 8) +
620 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
622 i = (unsigned long)floatFromVal(val);
623 i <<= SPEC_BSTR (lsym->etype);
625 if (! ( lsym->next &&
626 (IS_BITFIELD(lsym->next->type)) &&
627 (SPEC_BSTR(lsym->next->etype)))) break;
629 lilist = lilist->next;
633 tfprintf (oFile, "\t!db !constbyte\n",ival);
637 tfprintf (oFile, "\t!dw !constword\n",ival);
640 tfprintf (oFile, "\t!db !constword,!constword\n",
641 (ival >> 8) & 0xffff, (ival & 0xffff));
648 /*-----------------------------------------------------------------*/
649 /* printIvalStruct - generates initial value for structures */
650 /*-----------------------------------------------------------------*/
652 printIvalStruct (symbol * sym, sym_link * type,
653 initList * ilist, FILE * oFile)
658 sflds = SPEC_STRUCT (type)->fields;
659 if (ilist->type != INIT_DEEP) {
660 werror (E_INIT_STRUCT, sym->name);
664 iloop = ilist->init.deep;
666 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
667 if (IS_BITFIELD(sflds->type)) {
668 printIvalBitFields(&sflds,&iloop,oFile);
670 printIval (sym, sflds->type, iloop, oFile);
674 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
679 /*-----------------------------------------------------------------*/
680 /* printIvalChar - generates initital value for character array */
681 /*-----------------------------------------------------------------*/
683 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
691 val = list2val (ilist);
692 /* if the value is a character string */
693 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
695 if (!DCL_ELEM (type))
696 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
698 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
700 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
702 tfprintf (oFile, "\t!db !constbyte\n", 0);
710 printChar (oFile, s, strlen (s) + 1);
714 /*-----------------------------------------------------------------*/
715 /* printIvalArray - generates code for array initialization */
716 /*-----------------------------------------------------------------*/
718 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
722 int lcnt = 0, size = 0;
724 /* take care of the special case */
725 /* array of characters can be init */
727 if (IS_CHAR (type->next))
728 if (printIvalChar (type,
729 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
730 oFile, SPEC_CVAL (sym->etype).v_char))
733 /* not the special case */
734 if (ilist->type != INIT_DEEP)
736 werror (E_INIT_STRUCT, sym->name);
740 iloop = ilist->init.deep;
741 lcnt = DCL_ELEM (type);
746 printIval (sym, type->next, iloop, oFile);
747 iloop = (iloop ? iloop->next : NULL);
750 /* if not array limits given & we */
751 /* are out of initialisers then */
752 if (!DCL_ELEM (type) && !iloop)
755 /* no of elements given and we */
756 /* have generated for all of them */
758 /* if initializers left */
760 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
766 /* if we have not been given a size */
767 if (!DCL_ELEM (type))
768 DCL_ELEM (type) = size;
773 /*-----------------------------------------------------------------*/
774 /* printIvalFuncPtr - generate initial value for function pointers */
775 /*-----------------------------------------------------------------*/
777 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
782 val = list2val (ilist);
783 /* check the types */
784 if ((dLvl = compareType (val->type, type->next)) <= 0)
786 tfprintf (oFile, "\t!dw !constword\n", 0);
790 /* now generate the name */
793 if (port->use_dw_for_init)
795 tfprintf (oFile, "\t!dws\n", val->name);
799 printPointerType (oFile, val->name);
802 else if (port->use_dw_for_init)
804 tfprintf (oFile, "\t!dws\n", val->sym->rname);
808 printPointerType (oFile, val->sym->rname);
814 /*-----------------------------------------------------------------*/
815 /* printIvalCharPtr - generates initial values for character pointers */
816 /*-----------------------------------------------------------------*/
818 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
822 /* PENDING: this is _very_ mcs51 specific, including a magic
824 It's also endin specific.
826 size = getSize (type);
828 if (val->name && strlen (val->name))
830 if (size == 1) /* This appears to be Z80 specific?? */
833 "\t!dbs\n", val->name);
835 else if (size == FPTRSIZE)
837 if (port->use_dw_for_init)
839 tfprintf (oFile, "\t!dws\n", val->name);
843 printPointerType (oFile, val->name);
846 else if (size == GPTRSIZE)
849 if (IS_PTR (val->type)) {
850 type = DCL_TYPE (val->type);
852 type = PTR_TYPE (SPEC_OCLS (val->etype));
854 if (val->sym && val->sym->isstrlit) {
855 // this is a literal string
858 printGPointerType (oFile, val->name, sym->name, type);
862 fprintf (stderr, "*** internal error: unknown size in "
863 "printIvalCharPtr.\n");
868 /* What is this case? Are these pointers? */
872 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
875 if (port->use_dw_for_init)
876 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
878 tfprintf (oFile, "\t.byte %s,%s\n",
879 aopLiteral (val, 0), aopLiteral (val, 1));
882 werror (E_LITERAL_GENERIC);
883 fprintf (oFile, "\t.byte %s,%s,%s\n",
886 aopLiteral (val, 2));
889 werror (E_LITERAL_GENERIC);
890 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
894 aopLiteral (val, 3));
901 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
902 addSet (&statsg->syms, val->sym);
908 /*-----------------------------------------------------------------*/
909 /* printIvalPtr - generates initial value for pointers */
910 /*-----------------------------------------------------------------*/
912 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
918 if (ilist->type == INIT_DEEP)
919 ilist = ilist->init.deep;
921 /* function pointer */
922 if (IS_FUNC (type->next))
924 printIvalFuncPtr (type, ilist, oFile);
928 if (!(val = initPointer (ilist)))
931 /* if character pointer */
932 if (IS_CHAR (type->next))
933 if (printIvalCharPtr (sym, type, val, oFile))
937 if (compareType (type, val->type) == 0)
938 werror (W_INIT_WRONG);
940 /* if val is literal */
941 if (IS_LITERAL (val->etype))
943 switch (getSize (type))
946 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
949 if (port->use_dw_for_init)
950 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
952 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
955 fprintf (oFile, "\t.byte %s,%s,#0x02\n",
956 aopLiteral (val, 0), aopLiteral (val, 1));
962 size = getSize (type);
964 if (size == 1) /* Z80 specific?? */
966 tfprintf (oFile, "\t!dbs\n", val->name);
968 else if (size == FPTRSIZE)
970 if (port->use_dw_for_init) {
971 tfprintf (oFile, "\t!dws\n", val->name);
973 printPointerType (oFile, val->name);
976 else if (size == GPTRSIZE)
978 printGPointerType (oFile, val->name, sym->name,
979 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
980 PTR_TYPE (SPEC_OCLS (val->etype))));
985 /*-----------------------------------------------------------------*/
986 /* printIval - generates code for initial value */
987 /*-----------------------------------------------------------------*/
989 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
994 /* if structure then */
995 if (IS_STRUCT (type))
997 printIvalStruct (sym, type, ilist, oFile);
1001 /* if this is a pointer */
1004 printIvalPtr (sym, type, ilist, oFile);
1008 /* if this is an array */
1009 if (IS_ARRAY (type))
1011 printIvalArray (sym, type, ilist, oFile);
1015 /* if type is SPECIFIER */
1018 printIvalType (sym, type, ilist, oFile);
1023 /*-----------------------------------------------------------------*/
1024 /* emitStaticSeg - emitcode for the static segment */
1025 /*-----------------------------------------------------------------*/
1027 emitStaticSeg (memmap * map, FILE * out)
1031 fprintf(out, "\t.area\t%s\n", map->sname);
1033 /* for all variables in this segment do */
1034 for (sym = setFirstItem (map->syms); sym;
1035 sym = setNextItem (map->syms))
1038 /* if it is "extern" then do nothing */
1039 if (IS_EXTERN (sym->etype))
1042 /* if it is not static add it to the public
1044 if (!IS_STATIC (sym->etype))
1045 addSetHead (&publics, sym);
1047 /* print extra debug info if required */
1048 if (options.debug) {
1049 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1052 if (IS_STATIC (sym->etype))
1053 fprintf (out, "F%s$", moduleName); /* scope is file */
1055 fprintf (out, "G$"); /* scope is global */
1058 /* symbol is local */
1059 fprintf (out, "L%s$",
1060 (sym->localof ? sym->localof->name : "-null-"));
1061 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1064 /* if it has an absolute address */
1065 if (SPEC_ABSA (sym->etype))
1068 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1070 fprintf (out, "%s\t=\t0x%04x\n",
1072 SPEC_ADDR (sym->etype));
1077 fprintf (out, " == .\n");
1079 /* if it has an initial value */
1082 fprintf (out, "%s:\n", sym->rname);
1084 resolveIvalSym (sym->ival);
1085 printIval (sym, sym->type, sym->ival, out);
1090 /* allocate space */
1091 fprintf (out, "%s:\n", sym->rname);
1092 /* special case for character strings */
1093 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1094 SPEC_CVAL (sym->etype).v_char)
1096 SPEC_CVAL (sym->etype).v_char,
1097 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1099 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1105 /*-----------------------------------------------------------------*/
1106 /* emitMaps - emits the code for the data portion the code */
1107 /*-----------------------------------------------------------------*/
1112 /* no special considerations for the following
1113 data, idata & bit & xdata */
1114 emitRegularMap (data, TRUE, TRUE);
1115 emitRegularMap (idata, TRUE, TRUE);
1116 emitRegularMap (bit, TRUE, FALSE);
1117 emitRegularMap (xdata, TRUE, TRUE);
1118 if (port->genXINIT) {
1119 emitRegularMap (xidata, TRUE, TRUE);
1121 emitRegularMap (sfr, FALSE, FALSE);
1122 emitRegularMap (sfrbit, FALSE, FALSE);
1123 emitRegularMap (home, TRUE, FALSE);
1124 emitRegularMap (code, TRUE, FALSE);
1126 emitStaticSeg (statsg, code->oFile);
1127 if (port->genXINIT) {
1128 emitStaticSeg (xinit, code->oFile);
1133 /*-----------------------------------------------------------------*/
1134 /* flushStatics - flush all currently defined statics out to file */
1135 /* and delete. Temporary function */
1136 /*-----------------------------------------------------------------*/
1140 emitStaticSeg (statsg, codeOutFile);
1141 statsg->syms = NULL;
1144 /*-----------------------------------------------------------------*/
1145 /* createInterruptVect - creates the interrupt vector */
1146 /*-----------------------------------------------------------------*/
1148 createInterruptVect (FILE * vFile)
1151 mainf = newSymbol ("main", 0);
1154 /* only if the main function exists */
1155 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1157 if (!options.cc_only && !noAssemble)
1162 /* if the main is only a prototype ie. no body then do nothing */
1163 if (!IFFUNC_HASBODY(mainf->type))
1165 /* if ! compile only then main function should be present */
1166 if (!options.cc_only && !noAssemble)
1171 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1172 fprintf (vFile, "__interrupt_vect:\n");
1175 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1177 /* "generic" interrupt table header (if port doesn't specify one).
1178 * Look suspiciously like 8051 code to me...
1181 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1184 /* now for the other interrupts */
1185 for (; i < maxInterrupts; i++)
1188 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1190 fprintf (vFile, "\treti\n\t.ds\t7\n");
1197 ";--------------------------------------------------------\n"
1198 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1202 ";--------------------------------------------------------\n"};
1205 /*-----------------------------------------------------------------*/
1206 /* initialComments - puts in some initial comments */
1207 /*-----------------------------------------------------------------*/
1209 initialComments (FILE * afile)
1213 fprintf (afile, "%s", iComments1);
1214 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1215 fprintf (afile, "%s", iComments2);
1218 /*-----------------------------------------------------------------*/
1219 /* printPublics - generates .global for publics */
1220 /*-----------------------------------------------------------------*/
1222 printPublics (FILE * afile)
1226 fprintf (afile, "%s", iComments2);
1227 fprintf (afile, "; Public variables in this module\n");
1228 fprintf (afile, "%s", iComments2);
1230 for (sym = setFirstItem (publics); sym;
1231 sym = setNextItem (publics))
1232 tfprintf (afile, "\t!global\n", sym->rname);
1235 /*-----------------------------------------------------------------*/
1236 /* printExterns - generates .global for externs */
1237 /*-----------------------------------------------------------------*/
1239 printExterns (FILE * afile)
1243 fprintf (afile, "%s", iComments2);
1244 fprintf (afile, "; Externals used\n");
1245 fprintf (afile, "%s", iComments2);
1247 for (sym = setFirstItem (externs); sym;
1248 sym = setNextItem (externs))
1249 tfprintf (afile, "\t!global\n", sym->rname);
1252 /*-----------------------------------------------------------------*/
1253 /* emitOverlay - will emit code for the overlay stuff */
1254 /*-----------------------------------------------------------------*/
1256 emitOverlay (FILE * afile)
1260 if (!elementsInSet (ovrSetSets))
1261 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1263 /* for each of the sets in the overlay segment do */
1264 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1265 ovrset = setNextItem (ovrSetSets))
1270 if (elementsInSet (ovrset))
1273 /* this dummy area is used to fool the assembler
1274 otherwise the assembler will append each of these
1275 declarations into one chunk and will not overlay
1277 fprintf (afile, "\t.area _DUMMY\n");
1279 /* not anymore since asmain.c:1.13 */
1281 /* output the area informtion */
1282 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1285 for (sym = setFirstItem (ovrset); sym;
1286 sym = setNextItem (ovrset))
1289 /* if extern then add it to the publics tabledo nothing */
1290 if (IS_EXTERN (sym->etype))
1293 /* if allocation required check is needed
1294 then check if the symbol really requires
1295 allocation only for local variables */
1296 if (!IS_AGGREGATE (sym->type) &&
1297 !(sym->_isparm && !IS_REGPARM (sym->etype))
1298 && !sym->allocreq && sym->level)
1301 /* if global variable & not static or extern
1302 and addPublics allowed then add it to the public set */
1303 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1304 && !IS_STATIC (sym->etype))
1305 addSetHead (&publics, sym);
1307 /* if extern then do nothing or is a function
1309 if (IS_FUNC (sym->type))
1312 /* print extra debug info if required */
1315 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1319 if (IS_STATIC (sym->etype))
1320 fprintf (afile, "F%s$", moduleName); /* scope is file */
1322 fprintf (afile, "G$"); /* scope is global */
1325 /* symbol is local */
1326 fprintf (afile, "L%s$",
1327 (sym->localof ? sym->localof->name : "-null-"));
1328 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1331 /* if is has an absolute address then generate
1332 an equate for this no need to allocate space */
1333 if (SPEC_ABSA (sym->etype))
1337 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1339 fprintf (afile, "%s\t=\t0x%04x\n",
1341 SPEC_ADDR (sym->etype));
1346 fprintf (afile, "==.\n");
1348 /* allocate space */
1349 tfprintf (afile, "!labeldef\n", sym->rname);
1350 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1357 /*-----------------------------------------------------------------*/
1358 /* glue - the final glue that hold the whole thing together */
1359 /*-----------------------------------------------------------------*/
1365 FILE *ovrFile = tempfile ();
1367 addSetHead (&tmpfileSet, ovrFile);
1368 /* print the global struct definitions */
1370 cdbStructBlock (0, cdbFile);
1372 vFile = tempfile ();
1373 /* PENDING: this isnt the best place but it will do */
1374 if (port->general.glue_up_main)
1376 /* create the interrupt vector table */
1377 createInterruptVect (vFile);
1380 addSetHead (&tmpfileSet, vFile);
1382 /* emit code for the all the variables declared */
1384 /* do the overlay segments */
1385 emitOverlay (ovrFile);
1387 /* now put it all together into the assembler file */
1388 /* create the assembler file name */
1390 if (!options.c1mode)
1392 sprintf (scratchFileName, srcFileName);
1393 strcat (scratchFileName, port->assembler.file_ext);
1397 strcpy (scratchFileName, options.out_name);
1400 if (!(asmFile = fopen (scratchFileName, "w")))
1402 werror (E_FILE_OPEN_ERR, scratchFileName);
1406 /* initial comments */
1407 initialComments (asmFile);
1409 /* print module name */
1410 tfprintf (asmFile, "\t!module\n", moduleName);
1411 tfprintf (asmFile, "\t!fileprelude\n");
1413 /* Let the port generate any global directives, etc. */
1414 if (port->genAssemblerPreamble)
1416 port->genAssemblerPreamble (asmFile);
1419 /* print the global variables in this module */
1420 printPublics (asmFile);
1421 if (port->assembler.externGlobal)
1422 printExterns (asmFile);
1424 /* copy the sfr segment */
1425 fprintf (asmFile, "%s", iComments2);
1426 fprintf (asmFile, "; special function registers\n");
1427 fprintf (asmFile, "%s", iComments2);
1428 copyFile (asmFile, sfr->oFile);
1430 /* copy the sbit segment */
1431 fprintf (asmFile, "%s", iComments2);
1432 fprintf (asmFile, "; special function bits \n");
1433 fprintf (asmFile, "%s", iComments2);
1434 copyFile (asmFile, sfrbit->oFile);
1436 /* copy the data segment */
1437 fprintf (asmFile, "%s", iComments2);
1438 fprintf (asmFile, "; internal ram data\n");
1439 fprintf (asmFile, "%s", iComments2);
1440 copyFile (asmFile, data->oFile);
1443 /* create the overlay segments */
1444 fprintf (asmFile, "%s", iComments2);
1445 fprintf (asmFile, "; overlayable items in internal ram \n");
1446 fprintf (asmFile, "%s", iComments2);
1447 copyFile (asmFile, ovrFile);
1449 /* create the stack segment MOF */
1450 if (mainf && IFFUNC_HASBODY(mainf->type))
1452 fprintf (asmFile, "%s", iComments2);
1453 fprintf (asmFile, "; Stack segment in internal ram \n");
1454 fprintf (asmFile, "%s", iComments2);
1455 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1456 "__start__stack:\n\t.ds\t1\n\n");
1459 /* create the idata segment */
1460 fprintf (asmFile, "%s", iComments2);
1461 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1462 fprintf (asmFile, "%s", iComments2);
1463 copyFile (asmFile, idata->oFile);
1465 /* copy the bit segment */
1466 fprintf (asmFile, "%s", iComments2);
1467 fprintf (asmFile, "; bit data\n");
1468 fprintf (asmFile, "%s", iComments2);
1469 copyFile (asmFile, bit->oFile);
1471 /* if external stack then reserve space of it */
1472 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1474 fprintf (asmFile, "%s", iComments2);
1475 fprintf (asmFile, "; external stack \n");
1476 fprintf (asmFile, "%s", iComments2);
1477 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1478 fprintf (asmFile, "\t.ds 256\n");
1482 /* copy xtern ram data */
1483 fprintf (asmFile, "%s", iComments2);
1484 fprintf (asmFile, "; external ram data\n");
1485 fprintf (asmFile, "%s", iComments2);
1486 copyFile (asmFile, xdata->oFile);
1488 /* copy xternal initialized ram data */
1489 fprintf (asmFile, "%s", iComments2);
1490 fprintf (asmFile, "; external initialized ram data\n");
1491 fprintf (asmFile, "%s", iComments2);
1492 copyFile (asmFile, xidata->oFile);
1494 /* copy the interrupt vector table */
1495 if (mainf && IFFUNC_HASBODY(mainf->type))
1497 fprintf (asmFile, "%s", iComments2);
1498 fprintf (asmFile, "; interrupt vector \n");
1499 fprintf (asmFile, "%s", iComments2);
1500 copyFile (asmFile, vFile);
1503 /* copy global & static initialisations */
1504 fprintf (asmFile, "%s", iComments2);
1505 fprintf (asmFile, "; global & static initialisations\n");
1506 fprintf (asmFile, "%s", iComments2);
1508 /* Everywhere we generate a reference to the static_name area,
1509 * (which is currently only here), we immediately follow it with a
1510 * definition of the post_static_name area. This guarantees that
1511 * the post_static_name area will immediately follow the static_name
1514 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1515 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1516 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1518 if (mainf && IFFUNC_HASBODY(mainf->type))
1520 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1521 /* if external stack is specified then the
1522 higher order byte of the xdatalocation is
1523 going into P2 and the lower order going into
1525 if (options.useXstack)
1527 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1528 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1529 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1530 (unsigned int) options.xdata_loc & 0xff);
1533 /* initialise the stack pointer */
1534 /* if the user specified a value then use it */
1535 if (options.stack_loc)
1536 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff);
1538 /* no: we have to compute it */
1539 if (!options.stackOnData && maxRegBank <= 3)
1540 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1542 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1544 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1545 fprintf (asmFile, "\tmov\ta,dpl\n");
1546 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1547 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1548 fprintf (asmFile, "__sdcc_init_data:\n");
1550 // if the port can copy the XINIT segment to XISEG
1551 if (port->genXINIT) {
1552 port->genXINIT(asmFile);
1556 copyFile (asmFile, statsg->oFile);
1558 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1560 /* This code is generated in the post-static area.
1561 * This area is guaranteed to follow the static area
1562 * by the ugly shucking and jiving about 20 lines ago.
1564 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1565 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1571 "%s", iComments2, iComments2);
1572 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1573 copyFile (asmFile, home->oFile);
1575 /* copy over code */
1576 fprintf (asmFile, "%s", iComments2);
1577 fprintf (asmFile, "; code\n");
1578 fprintf (asmFile, "%s", iComments2);
1579 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1580 if (mainf && IFFUNC_HASBODY(mainf->type))
1583 /* entry point @ start of CSEG */
1584 fprintf (asmFile, "__sdcc_program_startup:\n");
1586 /* put in the call to main */
1587 fprintf (asmFile, "\tlcall\t_main\n");
1588 if (options.mainreturn)
1591 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1592 fprintf (asmFile, "\tret\n");
1598 fprintf (asmFile, ";\treturn from main will lock up\n");
1599 fprintf (asmFile, "\tsjmp .\n");
1602 copyFile (asmFile, code->oFile);
1605 applyToSet (tmpfileSet, closeTmpFiles);
1606 applyToSet (tmpfileNameSet, rmTmpFiles);
1609 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1613 applyToSet (tmpfileSet, closeTmpFiles);
1614 applyToSet (tmpfileNameSet, rmTmpFiles);
1618 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1619 in cygwin wrt c:\tmp.
1620 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1625 #if !defined(_MSC_VER)
1626 const char *tmpdir = NULL;
1628 tmpdir = getenv ("TMP");
1629 else if (getenv ("TEMP"))
1630 tmpdir = getenv ("TEMP");
1631 else if (getenv ("TMPDIR"))
1632 tmpdir = getenv ("TMPDIR");
1635 char *name = tempnam (tmpdir, "sdcc");
1642 return tmpnam (NULL);
1645 /** Creates a temporary file a'la tmpfile which avoids the bugs
1646 in cygwin wrt c:\tmp.
1647 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1652 #if !defined(_MSC_VER)
1653 const char *tmpdir = NULL;
1655 tmpdir = getenv ("TMP");
1656 else if (getenv ("TEMP"))
1657 tmpdir = getenv ("TEMP");
1658 else if (getenv ("TMPDIR"))
1659 tmpdir = getenv ("TMPDIR");
1662 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1665 FILE *fp = fopen (name, "w+b");
1668 addSetHead (&tmpfileNameSet, name);