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 -------------------------------------------------------------------------*/
38 symbol *interrupts[INTNO_MAX+1];
40 void printIval (symbol *, sym_link *, initList *, FILE *);
41 set *publics = NULL; /* public variables */
42 set *externs = NULL; /* Variables that are declared as extern */
44 unsigned maxInterrupts = 0;
47 set *pipeSet = NULL; /* set of pipes */
48 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
49 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
51 /*-----------------------------------------------------------------*/
52 /* closePipes - closes all pipes created by the compiler */
53 /*-----------------------------------------------------------------*/
54 DEFSETFUNC (closePipes)
67 /*-----------------------------------------------------------------*/
68 /* closeTmpFiles - closes all tmp files created by the compiler */
69 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
70 /*-----------------------------------------------------------------*/
71 DEFSETFUNC (closeTmpFiles)
84 /*-----------------------------------------------------------------*/
85 /* rmTmpFiles - unlinks all tmp files created by the compiler */
86 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
87 /*-----------------------------------------------------------------*/
88 DEFSETFUNC (rmTmpFiles)
102 /*-----------------------------------------------------------------*/
103 /* rm_tmpfiles - close and remove temporary files and delete sets */
104 /*-----------------------------------------------------------------*/
108 /* close temporary files */
109 applyToSet (pipeSet, closePipes);
110 /* close temporary files */
111 deleteSet (&pipeSet);
113 applyToSet (tmpfileSet, closeTmpFiles);
114 /* remove temporary files */
115 applyToSet (tmpfileNameSet, rmTmpFiles);
116 /* delete temorary file sets */
117 deleteSet (&tmpfileSet);
118 deleteSet (&tmpfileNameSet);
121 /*-----------------------------------------------------------------*/
122 /* copyFile - copies source file to destination file */
123 /*-----------------------------------------------------------------*/
125 copyFile (FILE * dest, FILE * src)
131 if ((ch = fgetc (src)) != EOF)
136 aopLiteralLong (value * val, int offset, int size)
145 // assuming we have been warned before
149 /* if it is a float then it gets tricky */
150 /* otherwise it is fairly simple */
151 if (!IS_FLOAT (val->type)) {
152 unsigned long v = (unsigned long) floatFromVal (val);
157 tsprintf (buffer, sizeof(buffer),
158 "!immedbyte", (unsigned int) v & 0xff);
161 tsprintf (buffer, sizeof(buffer),
162 "!immedword", (unsigned int) v & 0xffff);
165 /* Hmm. Too big for now. */
168 return Safe_strdup (buffer);
171 /* PENDING: For now size must be 1 */
174 /* it is type float */
175 fl.f = (float) floatFromVal (val);
176 #ifdef WORDS_BIGENDIAN
177 tsprintf (buffer, sizeof(buffer),
178 "!immedbyte", fl.c[3 - offset]);
180 tsprintf (buffer, sizeof(buffer),
181 "!immedbyte", fl.c[offset]);
183 return Safe_strdup (buffer);
186 /*-----------------------------------------------------------------*/
187 /* aopLiteral - string from a literal value */
188 /*-----------------------------------------------------------------*/
190 aopLiteral (value * val, int offset)
192 return aopLiteralLong (val, offset, 1);
195 /*-----------------------------------------------------------------*/
196 /* emitRegularMap - emit code for maps with no special cases */
197 /*-----------------------------------------------------------------*/
199 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
209 /* PENDING: special case here - should remove */
210 if (!strcmp (map->sname, CODE_NAME))
211 tfprintf (map->oFile, "\t!areacode\n", map->sname);
212 else if (!strcmp (map->sname, DATA_NAME))
213 tfprintf (map->oFile, "\t!areadata\n", map->sname);
214 else if (!strcmp (map->sname, HOME_NAME))
215 tfprintf (map->oFile, "\t!areahome\n", map->sname);
217 tfprintf (map->oFile, "\t!area\n", map->sname);
220 for (sym = setFirstItem (map->syms); sym;
221 sym = setNextItem (map->syms))
225 /* if extern then add it into the extern list */
226 if (IS_EXTERN (sym->etype))
228 addSetHead (&externs, sym);
232 /* if allocation required check is needed
233 then check if the symbol really requires
234 allocation only for local variables */
236 if (arFlag && !IS_AGGREGATE (sym->type) &&
237 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
238 !sym->allocreq && sym->level)
241 /* for bitvar locals and parameters */
242 if (!arFlag && !sym->allocreq && sym->level
243 && !SPEC_ABSA (sym->etype)) {
247 /* if global variable & not static or extern
248 and addPublics allowed then add it to the public set */
249 if ((sym->level == 0 ||
250 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
252 !IS_STATIC (sym->etype) &&
253 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
255 addSetHead (&publics, sym);
258 /* if extern then do nothing or is a function
260 if (IS_FUNC (sym->type) && !(sym->isitmp))
263 /* print extra debug info if required */
266 if (!sym->level) /* global */
268 if (IS_STATIC (sym->etype))
269 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
271 fprintf (map->oFile, "G$"); /* scope is global */
275 /* symbol is local */
276 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
278 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
281 /* if it has an initial value then do it only if
282 it is a global variable */
283 if (sym->ival && sym->level == 0) {
284 if ((SPEC_OCLS(sym->etype)==xidata) && !SPEC_ABSA (sym->etype)) {
285 /* create a new "XINIT (CODE)" symbol, that will be emitted later
287 newSym=copySymbol (sym);
288 SPEC_OCLS(newSym->etype)=xinit;
289 SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
290 SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
291 if (IS_SPEC (newSym->type))
292 SPEC_CONST (newSym->type) = 1;
294 DCL_PTR_CONST (newSym->type) = 1;
295 SPEC_STAT(newSym->etype)=1;
296 resolveIvalSym(newSym->ival, newSym->type);
298 // add it to the "XINIT (CODE)" segment
299 addSet(&xinit->syms, newSym);
301 if (!SPEC_ABSA (sym->etype))
303 FILE *tmpFile = tempfile ();
304 addSetHead (&tmpfileSet, tmpFile);
305 // before allocation we must parse the sym->ival tree
306 // but without actually generating initialization code
308 resolveIvalSym (sym->ival, sym->type);
309 printIval (sym, sym->type, sym->ival, tmpFile);
313 if (IS_AGGREGATE (sym->type)) {
314 ival = initAggregates (sym, sym->ival, NULL);
316 if (getNelements(sym->type, sym->ival)>1) {
317 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
320 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
321 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
323 codeOutFile = statsg->oFile;
326 // set ival's lineno to where the symbol was defined
327 setAstLineno (ival, lineno=sym->lineDef);
328 // check if this is not a constant expression
329 if (!constExprTree(ival)) {
330 werror (E_CONST_EXPECTED, "found expression");
331 // but try to do it anyway
334 if (!astErrors(ival))
335 eBBlockFromiCode (iCodeFromAst (ival));
341 /* if it has an absolute address then generate
342 an equate for this no need to allocate space */
343 if (SPEC_ABSA (sym->etype) && !sym->ival)
347 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
349 if (TARGET_IS_XA51) {
352 } else if (map==bit || map==sfrbit) {
356 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
358 SPEC_ADDR (sym->etype));
362 int size = getSize (sym->type) + sym->flexArrayLength;
364 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
368 fprintf (map->oFile, "==.\n");
370 if (SPEC_ABSA (sym->etype))
372 tfprintf (map->oFile, "\t!org\n", SPEC_ADDR (sym->etype));
374 if (IS_STATIC (sym->etype) || sym->level)
375 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
377 tfprintf (map->oFile, "!labeldef\n", sym->rname);
378 tfprintf (map->oFile, "\t!ds\n", (unsigned int) size & 0xffff);
384 /*-----------------------------------------------------------------*/
385 /* initPointer - pointer initialization code massaging */
386 /*-----------------------------------------------------------------*/
388 initPointer (initList * ilist, sym_link *toType)
394 return valCastLiteral(toType, 0.0);
397 expr = list2expr (ilist);
402 /* try it the old way first */
403 if ((val = constExprValue (expr, FALSE)))
406 /* ( ptr + constant ) */
407 if (IS_AST_OP (expr) &&
408 (expr->opval.op == '+' || expr->opval.op == '-') &&
409 IS_AST_SYM_VALUE (expr->left) &&
410 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
411 compareType(toType, expr->left->ftype) &&
412 IS_AST_LIT_VALUE (expr->right)) {
413 return valForCastAggr (expr->left, expr->left->ftype,
419 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
420 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
421 if (compareType(toType, expr->left->ftype)!=1) {
422 werror (W_INIT_WRONG);
423 printFromToType(expr->left->ftype, toType);
429 /* no then we have to do these cludgy checks */
430 /* pointers can be initialized with address of
431 a variable or address of an array element */
432 if (IS_AST_OP (expr) && expr->opval.op == '&') {
433 /* address of symbol */
434 if (IS_AST_SYM_VALUE (expr->left)) {
435 val = AST_VALUE (expr->left);
436 val->type = newLink (DECLARATOR);
437 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
438 DCL_TYPE (val->type) = CPOINTER;
439 DCL_PTR_CONST (val->type) = port->mem.code_ro;
441 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
442 DCL_TYPE (val->type) = FPOINTER;
443 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
444 DCL_TYPE (val->type) = PPOINTER;
445 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
446 DCL_TYPE (val->type) = IPOINTER;
447 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
448 DCL_TYPE (val->type) = EEPPOINTER;
450 DCL_TYPE (val->type) = POINTER;
451 val->type->next = expr->left->ftype;
452 val->etype = getSpec (val->type);
456 /* if address of indexed array */
457 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
458 return valForArray (expr->left);
460 /* if address of structure element then
462 if (IS_AST_OP (expr->left) &&
463 expr->left->opval.op == '.') {
464 return valForStructElem (expr->left->left,
469 (&some_struct)->element */
470 if (IS_AST_OP (expr->left) &&
471 expr->left->opval.op == PTR_OP &&
472 IS_ADDRESS_OF_OP (expr->left->left)) {
473 return valForStructElem (expr->left->left->left,
477 /* case 3. (((char *) &a) +/- constant) */
478 if (IS_AST_OP (expr) &&
479 (expr->opval.op == '+' || expr->opval.op == '-') &&
480 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
481 IS_AST_OP (expr->left->right) &&
482 expr->left->right->opval.op == '&' &&
483 IS_AST_LIT_VALUE (expr->right)) {
485 return valForCastAggr (expr->left->right->left,
486 expr->left->left->opval.lnk,
487 expr->right, expr->opval.op);
490 /* case 4. (char *)(array type) */
491 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
492 IS_ARRAY(expr->right->ftype)) {
494 val = copyValue (AST_VALUE (expr->right));
495 val->type = newLink (DECLARATOR);
496 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
497 DCL_TYPE (val->type) = CPOINTER;
498 DCL_PTR_CONST (val->type) = port->mem.code_ro;
500 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
501 DCL_TYPE (val->type) = FPOINTER;
502 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
503 DCL_TYPE (val->type) = PPOINTER;
504 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
505 DCL_TYPE (val->type) = IPOINTER;
506 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
507 DCL_TYPE (val->type) = EEPPOINTER;
509 DCL_TYPE (val->type) = POINTER;
510 val->type->next = expr->right->ftype->next;
511 val->etype = getSpec (val->type);
516 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
518 werror (E_INCOMPAT_PTYPES);
523 /*-----------------------------------------------------------------*/
524 /* printChar - formats and prints a characater string with DB */
525 /*-----------------------------------------------------------------*/
527 printChar (FILE * ofile, char *s, int plen)
535 while (len && pplen < plen)
538 while (i && pplen < plen)
540 if (*s < ' ' || *s == '\"' || *s=='\\')
544 tfprintf (ofile, "\t!ascii\n", buf);
545 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
560 tfprintf (ofile, "\t!ascii\n", buf);
571 tfprintf (ofile, "\t!db !constbyte\n", 0);
576 /*-----------------------------------------------------------------*/
577 /* return the generic pointer high byte for a given pointer type. */
578 /*-----------------------------------------------------------------*/
580 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
588 werror (E_CANNOT_USE_GENERIC_POINTER,
589 iname ? iname : "<null>",
590 oname ? oname : "<null>");
597 return GPTYPE_XSTACK;
599 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
607 /*-----------------------------------------------------------------*/
608 /* printPointerType - generates ival for pointer type */
609 /*-----------------------------------------------------------------*/
611 _printPointerType (FILE * oFile, const char *name)
613 if (options.model == MODEL_FLAT24)
615 if (port->little_endian)
616 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
618 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
622 if (port->little_endian)
623 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
625 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
629 /*-----------------------------------------------------------------*/
630 /* printPointerType - generates ival for pointer type */
631 /*-----------------------------------------------------------------*/
633 printPointerType (FILE * oFile, const char *name)
635 _printPointerType (oFile, name);
636 fprintf (oFile, "\n");
639 /*-----------------------------------------------------------------*/
640 /* printGPointerType - generates ival for generic pointer type */
641 /*-----------------------------------------------------------------*/
643 printGPointerType (FILE * oFile, const char *iname, const char *oname,
644 const unsigned int type)
646 _printPointerType (oFile, iname);
647 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
650 /*-----------------------------------------------------------------*/
651 /* printIvalType - generates ival for int/char */
652 /*-----------------------------------------------------------------*/
654 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
658 /* if initList is deep */
659 if (ilist && (ilist->type == INIT_DEEP))
660 ilist = ilist->init.deep;
662 if (!(val = list2val (ilist))) {
663 // assuming a warning has been thrown
667 if (val->type != type) {
668 val = valCastLiteral(type, floatFromVal(val));
671 switch (getSize (type)) {
674 tfprintf (oFile, "\t!db !constbyte\n", 0);
676 tfprintf (oFile, "\t!dbs\n",
677 aopLiteral (val, 0));
681 if (port->use_dw_for_init)
682 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
683 else if (port->little_endian)
684 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
686 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
690 tfprintf (oFile, "\t!dw !constword\n", 0);
691 tfprintf (oFile, "\t!dw !constword\n", 0);
693 else if (port->little_endian) {
694 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
695 aopLiteral (val, 0), aopLiteral (val, 1),
696 aopLiteral (val, 2), aopLiteral (val, 3));
699 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
700 aopLiteral (val, 3), aopLiteral (val, 2),
701 aopLiteral (val, 1), aopLiteral (val, 0));
707 /*-----------------------------------------------------------------*/
708 /* printIvalBitFields - generate initializer for bitfields */
709 /*-----------------------------------------------------------------*/
710 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
714 initList *lilist = *ilist ;
715 unsigned long ival = 0;
721 val = list2val(lilist);
723 if (SPEC_BLEN(lsym->etype) > 8) {
724 size += ((SPEC_BLEN (lsym->etype) / 8) +
725 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
728 size = ((SPEC_BLEN (lsym->etype) / 8) +
729 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
731 i = (unsigned long)floatFromVal(val);
732 i <<= SPEC_BSTR (lsym->etype);
734 if (! ( lsym->next &&
735 (IS_BITFIELD(lsym->next->type)) &&
736 (SPEC_BSTR(lsym->next->etype)))) break;
738 lilist = lilist->next;
742 tfprintf (oFile, "\t!db !constbyte\n",ival);
746 tfprintf (oFile, "\t!dw !constword\n",ival);
748 case 4: /* EEP: why is this db and not dw? */
749 tfprintf (oFile, "\t!db !constword,!constword\n",
750 (ival >> 8) & 0xffff, (ival & 0xffff));
757 /*-----------------------------------------------------------------*/
758 /* printIvalStruct - generates initial value for structures */
759 /*-----------------------------------------------------------------*/
761 printIvalStruct (symbol * sym, sym_link * type,
762 initList * ilist, FILE * oFile)
765 initList *iloop = NULL;
767 sflds = SPEC_STRUCT (type)->fields;
770 if (ilist->type != INIT_DEEP) {
771 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
775 iloop = ilist->init.deep;
778 if (SPEC_STRUCT (type)->type == UNION) {
779 printIval (sym, sflds->type, iloop, oFile);
782 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
783 if (IS_BITFIELD(sflds->type)) {
784 printIvalBitFields(&sflds,&iloop,oFile);
786 printIval (sym, sflds->type, iloop, oFile);
791 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
796 /*-----------------------------------------------------------------*/
797 /* printIvalChar - generates initital value for character array */
798 /*-----------------------------------------------------------------*/
800 printIvalChar (symbol * sym, sym_link * type, initList * ilist, FILE * oFile, char *s)
803 unsigned int size = DCL_ELEM (type);
807 val = list2val (ilist);
808 /* if the value is a character string */
809 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
813 /* we have not been given a size, but now we know it */
814 size = strlen (SPEC_CVAL (val->etype).v_char) + 1;
815 /* but first check, if it's a flexible array */
816 if (sym && IS_STRUCT (sym->type))
817 sym->flexArrayLength = size;
819 DCL_ELEM (type) = size;
822 printChar (oFile, SPEC_CVAL (val->etype).v_char, size);
830 printChar (oFile, s, strlen (s) + 1);
834 /*-----------------------------------------------------------------*/
835 /* printIvalArray - generates code for array initialization */
836 /*-----------------------------------------------------------------*/
838 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
843 unsigned int size = 0;
846 /* take care of the special case */
847 /* array of characters can be init */
849 if (IS_CHAR (type->next)) {
850 val = list2val(ilist);
852 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
855 if (!IS_LITERAL(val->etype)) {
856 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
859 if (printIvalChar (sym, type,
860 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
861 oFile, SPEC_CVAL (sym->etype).v_char))
864 /* not the special case */
865 if (ilist->type != INIT_DEEP) {
866 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
870 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
871 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
872 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
875 printIval (sym, type->next, iloop, oFile);
879 if (DCL_ELEM(type)) {
880 // pad with zeros if needed
881 if (size<DCL_ELEM(type)) {
882 size = (DCL_ELEM(type) - size) * getSize(type->next);
884 tfprintf (oFile, "\t!db !constbyte\n", 0);
888 /* we have not been given a size, but now we know it */
889 /* but first check, if it's a flexible array */
890 if (IS_STRUCT (sym->type))
891 sym->flexArrayLength = size * getSize (type->next);
893 DCL_ELEM (type) = size;
899 /*-----------------------------------------------------------------*/
900 /* printIvalFuncPtr - generate initial value for function pointers */
901 /*-----------------------------------------------------------------*/
903 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
909 val = list2val (ilist);
911 val = valCastLiteral(type, 0.0);
914 // an error has been thrown already
918 if (IS_LITERAL(val->etype)) {
919 if (compareType(type, val->etype) == 0) {
920 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
921 printFromToType (val->type, type);
923 printIvalCharPtr (NULL, type, val, oFile);
927 /* check the types */
928 if ((dLvl = compareType (val->type, type->next)) <= 0)
930 tfprintf (oFile, "\t!dw !constword\n", 0);
934 /* now generate the name */
937 if (port->use_dw_for_init)
939 tfprintf (oFile, "\t!dws\n", val->name);
943 printPointerType (oFile, val->name);
946 else if (port->use_dw_for_init)
948 tfprintf (oFile, "\t!dws\n", val->sym->rname);
952 printPointerType (oFile, val->sym->rname);
958 /*-----------------------------------------------------------------*/
959 /* printIvalCharPtr - generates initial values for character pointers */
960 /*-----------------------------------------------------------------*/
962 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
966 /* PENDING: this is _very_ mcs51 specific, including a magic
968 It's also endin specific.
970 size = getSize (type);
972 if (val->name && strlen (val->name))
974 if (size == 1) /* This appears to be Z80 specific?? */
977 "\t!dbs\n", val->name);
979 else if (size == FPTRSIZE)
981 if (port->use_dw_for_init)
983 tfprintf (oFile, "\t!dws\n", val->name);
987 printPointerType (oFile, val->name);
990 else if (size == GPTRSIZE)
993 if (IS_PTR (val->type)) {
994 type = DCL_TYPE (val->type);
996 type = PTR_TYPE (SPEC_OCLS (val->etype));
998 if (val->sym && val->sym->isstrlit) {
999 // this is a literal string
1002 printGPointerType (oFile, val->name, sym->name, type);
1006 fprintf (stderr, "*** internal error: unknown size in "
1007 "printIvalCharPtr.\n");
1012 // these are literals assigned to pointers
1016 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
1019 if (port->use_dw_for_init)
1020 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
1021 else if (port->little_endian)
1022 tfprintf (oFile, "\t.byte %s,%s\n",
1023 aopLiteral (val, 0), aopLiteral (val, 1));
1025 tfprintf (oFile, "\t.byte %s,%s\n",
1026 aopLiteral (val, 1), aopLiteral (val, 0));
1029 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1030 // non-zero mcs51 generic pointer
1031 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1033 if (port->little_endian) {
1034 fprintf (oFile, "\t.byte %s,%s,%s\n",
1035 aopLiteral (val, 0),
1036 aopLiteral (val, 1),
1037 aopLiteral (val, 2));
1039 fprintf (oFile, "\t.byte %s,%s,%s\n",
1040 aopLiteral (val, 2),
1041 aopLiteral (val, 1),
1042 aopLiteral (val, 0));
1046 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1047 // non-zero ds390 generic pointer
1048 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1050 if (port->little_endian) {
1051 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1052 aopLiteral (val, 0),
1053 aopLiteral (val, 1),
1054 aopLiteral (val, 2),
1055 aopLiteral (val, 3));
1057 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1058 aopLiteral (val, 3),
1059 aopLiteral (val, 2),
1060 aopLiteral (val, 1),
1061 aopLiteral (val, 0));
1069 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1070 addSet (&statsg->syms, val->sym);
1076 /*-----------------------------------------------------------------*/
1077 /* printIvalPtr - generates initial value for pointers */
1078 /*-----------------------------------------------------------------*/
1080 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1086 if (ilist && (ilist->type == INIT_DEEP))
1087 ilist = ilist->init.deep;
1089 /* function pointer */
1090 if (IS_FUNC (type->next))
1092 printIvalFuncPtr (type, ilist, oFile);
1096 if (!(val = initPointer (ilist, type)))
1099 /* if character pointer */
1100 if (IS_CHAR (type->next))
1101 if (printIvalCharPtr (sym, type, val, oFile))
1104 /* check the type */
1105 if (compareType (type, val->type) == 0) {
1106 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1107 printFromToType (val->type, type);
1110 /* if val is literal */
1111 if (IS_LITERAL (val->etype))
1113 switch (getSize (type))
1116 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1119 if (port->use_dw_for_init)
1120 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1121 else if (port->little_endian)
1122 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1124 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1126 case 3: // how about '390??
1127 fprintf (oFile, "; generic printIvalPtr\n");
1128 if (port->little_endian)
1130 fprintf (oFile, "\t.byte %s,%s",
1131 aopLiteral (val, 0), aopLiteral (val, 1));
1135 fprintf (oFile, "\t.byte %s,%s",
1136 aopLiteral (val, 1), aopLiteral (val, 0));
1138 if (IS_GENPTR (val->type))
1139 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1140 else if (IS_PTR (val->type))
1141 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1143 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1149 size = getSize (type);
1151 if (size == 1) /* Z80 specific?? */
1153 tfprintf (oFile, "\t!dbs\n", val->name);
1155 else if (size == FPTRSIZE)
1157 if (port->use_dw_for_init) {
1158 tfprintf (oFile, "\t!dws\n", val->name);
1160 printPointerType (oFile, val->name);
1163 else if (size == GPTRSIZE)
1165 printGPointerType (oFile, val->name, sym->name,
1166 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1167 PTR_TYPE (SPEC_OCLS (val->etype))));
1172 /*-----------------------------------------------------------------*/
1173 /* printIval - generates code for initial value */
1174 /*-----------------------------------------------------------------*/
1176 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1180 /* if structure then */
1181 if (IS_STRUCT (type))
1183 printIvalStruct (sym, type, ilist, oFile);
1187 /* if this is an array */
1188 if (IS_ARRAY (type))
1190 printIvalArray (sym, type, ilist, oFile);
1196 // not an aggregate, ilist must be a node
1197 if (ilist->type!=INIT_NODE) {
1198 // or a 1-element list
1199 if (ilist->init.deep->next) {
1200 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1203 ilist=ilist->init.deep;
1207 // and the type must match
1208 itype=ilist->init.node->ftype;
1210 if (compareType(type, itype)==0) {
1211 // special case for literal strings
1212 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1213 // which are really code pointers
1214 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1217 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1218 printFromToType(itype, type);
1223 /* if this is a pointer */
1226 printIvalPtr (sym, type, ilist, oFile);
1230 /* if type is SPECIFIER */
1233 printIvalType (sym, type, ilist, oFile);
1238 /*-----------------------------------------------------------------*/
1239 /* emitStaticSeg - emitcode for the static segment */
1240 /*-----------------------------------------------------------------*/
1242 emitStaticSeg (memmap * map, FILE * out)
1246 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1248 /* for all variables in this segment do */
1249 for (sym = setFirstItem (map->syms); sym;
1250 sym = setNextItem (map->syms))
1253 /* if it is "extern" then do nothing */
1254 if (IS_EXTERN (sym->etype))
1257 /* if it is not static add it to the public table */
1258 if (!IS_STATIC (sym->etype))
1260 addSetHead (&publics, sym);
1263 /* print extra debug info if required */
1264 if (options.debug) {
1268 if (IS_STATIC (sym->etype))
1269 fprintf (out, "F%s$", moduleName); /* scope is file */
1271 fprintf (out, "G$"); /* scope is global */
1274 /* symbol is local */
1275 fprintf (out, "L%s$",
1276 (sym->localof ? sym->localof->name : "-null-"));
1277 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1280 /* if it has an absolute address and no initializer */
1281 if (SPEC_ABSA (sym->etype) && !sym->ival)
1284 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1286 fprintf (out, "%s\t=\t0x%04x\n",
1288 SPEC_ADDR (sym->etype));
1293 fprintf (out, " == .\n");
1295 /* if it has an initial value */
1298 if (SPEC_ABSA (sym->etype))
1300 tfprintf (out, "\t!org\n", SPEC_ADDR (sym->etype));
1302 fprintf (out, "%s:\n", sym->rname);
1304 resolveIvalSym (sym->ival, sym->type);
1305 printIval (sym, sym->type, sym->ival, out);
1307 /* if sym is a simple string and sym->ival is a string,
1308 WE don't need it anymore */
1309 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1310 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1311 list2val(sym->ival)->sym->isstrlit) {
1312 freeStringSymbol(list2val(sym->ival)->sym);
1316 /* allocate space */
1317 int size = getSize (sym->type);
1320 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1322 fprintf (out, "%s:\n", sym->rname);
1323 /* special case for character strings */
1324 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1325 SPEC_CVAL (sym->etype).v_char)
1327 SPEC_CVAL (sym->etype).v_char,
1330 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1336 /*-----------------------------------------------------------------*/
1337 /* emitMaps - emits the code for the data portion the code */
1338 /*-----------------------------------------------------------------*/
1342 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1343 /* ports but let's be conservative - EEP */
1346 /* no special considerations for the following
1347 data, idata & bit & xdata */
1348 emitRegularMap (data, TRUE, TRUE);
1349 emitRegularMap (idata, TRUE, TRUE);
1350 emitRegularMap (d_abs, TRUE, TRUE);
1351 emitRegularMap (i_abs, TRUE, TRUE);
1352 emitRegularMap (bit, TRUE, TRUE);
1353 emitRegularMap (pdata, TRUE, TRUE);
1354 emitRegularMap (xdata, TRUE, TRUE);
1355 if (port->genXINIT) {
1356 emitRegularMap (xidata, TRUE, TRUE);
1358 emitRegularMap (sfr, publicsfr, FALSE);
1359 emitRegularMap (sfrbit, publicsfr, FALSE);
1360 emitRegularMap (home, TRUE, FALSE);
1361 emitRegularMap (code, TRUE, FALSE);
1363 if (options.const_seg) {
1364 tfprintf (code->oFile, "\t!area\n", options.const_seg);
1366 emitStaticSeg (statsg, code->oFile);
1367 if (port->genXINIT) {
1368 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1369 emitStaticSeg (xinit, code->oFile);
1371 tfprintf (code->oFile, "\t!area\n", c_abs->sname);
1372 emitStaticSeg (c_abs, code->oFile);
1376 /*-----------------------------------------------------------------*/
1377 /* flushStatics - flush all currently defined statics out to file */
1378 /* and delete. Temporary function */
1379 /*-----------------------------------------------------------------*/
1383 emitStaticSeg (statsg, codeOutFile);
1384 statsg->syms = NULL;
1387 /*-----------------------------------------------------------------*/
1388 /* createInterruptVect - creates the interrupt vector */
1389 /*-----------------------------------------------------------------*/
1391 createInterruptVect (FILE * vFile)
1393 mainf = newSymbol ("main", 0);
1396 /* only if the main function exists */
1397 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1399 if (!options.cc_only && !noAssemble && !options.c1mode)
1404 /* if the main is only a prototype ie. no body then do nothing */
1405 if (!IFFUNC_HASBODY(mainf->type))
1407 /* if ! compile only then main function should be present */
1408 if (!options.cc_only && !noAssemble)
1413 tfprintf (vFile, "\t!areacode\n", HOME_NAME);
1414 fprintf (vFile, "__interrupt_vect:\n");
1417 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1419 /* There's no such thing as a "generic" interrupt table header. */
1426 ";--------------------------------------------------------\n"
1427 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1431 ";--------------------------------------------------------\n"};
1434 /*-----------------------------------------------------------------*/
1435 /* initialComments - puts in some initial comments */
1436 /*-----------------------------------------------------------------*/
1438 initialComments (FILE * afile)
1442 fprintf (afile, "%s", iComments1);
1443 fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber(), __DATE__);
1444 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1445 fprintf (afile, "%s", iComments2);
1448 /*-----------------------------------------------------------------*/
1449 /* printPublics - generates .global for publics */
1450 /*-----------------------------------------------------------------*/
1452 printPublics (FILE * afile)
1456 fprintf (afile, "%s", iComments2);
1457 fprintf (afile, "; Public variables in this module\n");
1458 fprintf (afile, "%s", iComments2);
1460 for (sym = setFirstItem (publics); sym;
1461 sym = setNextItem (publics))
1462 tfprintf (afile, "\t!global\n", sym->rname);
1465 /*-----------------------------------------------------------------*/
1466 /* printExterns - generates .global for externs */
1467 /*-----------------------------------------------------------------*/
1469 printExterns (FILE * afile)
1473 fprintf (afile, "%s", iComments2);
1474 fprintf (afile, "; Externals used\n");
1475 fprintf (afile, "%s", iComments2);
1477 for (sym = setFirstItem (externs); sym;
1478 sym = setNextItem (externs))
1479 tfprintf (afile, "\t!extern\n", sym->rname);
1482 /*-----------------------------------------------------------------*/
1483 /* emitOverlay - will emit code for the overlay stuff */
1484 /*-----------------------------------------------------------------*/
1486 emitOverlay (FILE * afile)
1490 if (!elementsInSet (ovrSetSets))
1491 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1493 /* for each of the sets in the overlay segment do */
1494 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1495 ovrset = setNextItem (ovrSetSets))
1500 if (elementsInSet (ovrset))
1502 /* output the area informtion */
1503 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1506 for (sym = setFirstItem (ovrset); sym;
1507 sym = setNextItem (ovrset))
1509 /* if extern then it is in the publics table: do nothing */
1510 if (IS_EXTERN (sym->etype))
1513 /* if allocation required check is needed
1514 then check if the symbol really requires
1515 allocation only for local variables */
1516 if (!IS_AGGREGATE (sym->type) &&
1517 !(sym->_isparm && !IS_REGPARM (sym->etype))
1518 && !sym->allocreq && sym->level)
1521 /* if global variable & not static or extern
1522 and addPublics allowed then add it to the public set */
1523 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1524 && !IS_STATIC (sym->etype))
1526 addSetHead (&publics, sym);
1529 /* if extern then do nothing or is a function
1531 if (IS_FUNC (sym->type))
1534 /* print extra debug info if required */
1539 if (IS_STATIC (sym->etype))
1540 fprintf (afile, "F%s$", moduleName); /* scope is file */
1542 fprintf (afile, "G$"); /* scope is global */
1545 /* symbol is local */
1546 fprintf (afile, "L%s$",
1547 (sym->localof ? sym->localof->name : "-null-"));
1548 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1551 /* if is has an absolute address then generate
1552 an equate for this no need to allocate space */
1553 if (SPEC_ABSA (sym->etype))
1557 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1559 fprintf (afile, "%s\t=\t0x%04x\n",
1561 SPEC_ADDR (sym->etype));
1564 int size = getSize(sym->type);
1567 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1570 fprintf (afile, "==.\n");
1572 /* allocate space */
1573 tfprintf (afile, "!labeldef\n", sym->rname);
1574 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1582 /*-----------------------------------------------------------------*/
1583 /* spacesToUnderscores - replace spaces with underscores */
1584 /*-----------------------------------------------------------------*/
1586 spacesToUnderscores (char *dest, const char *src, size_t len)
1591 assert(dest != NULL);
1592 assert(src != NULL);
1596 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1597 *p++ = isspace((unsigned char)*src) ? '_' : *src;
1605 /*-----------------------------------------------------------------*/
1606 /* glue - the final glue that hold the whole thing together */
1607 /*-----------------------------------------------------------------*/
1613 FILE *ovrFile = tempfile ();
1614 char moduleBuf[PATH_MAX];
1617 if(port->general.glue_up_main &&
1618 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1620 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1627 addSetHead (&tmpfileSet, ovrFile);
1628 /* print the global struct definitions */
1632 vFile = tempfile ();
1633 /* PENDING: this isn't the best place but it will do */
1634 if (port->general.glue_up_main)
1636 /* create the interrupt vector table */
1637 createInterruptVect (vFile);
1640 addSetHead (&tmpfileSet, vFile);
1642 /* emit code for the all the variables declared */
1644 /* do the overlay segments */
1645 emitOverlay (ovrFile);
1647 outputDebugSymbols();
1649 /* now put it all together into the assembler file */
1650 /* create the assembler file name */
1652 /* -o option overrides default name? */
1653 if ((noAssemble || options.c1mode) && fullDstFileName)
1655 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1659 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1660 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1663 if (!(asmFile = fopen (scratchFileName, "w")))
1665 werror (E_FILE_OPEN_ERR, scratchFileName);
1669 /* initial comments */
1670 initialComments (asmFile);
1672 /* print module name */
1673 tfprintf (asmFile, "\t!module\n",
1674 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1677 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1679 switch(options.model)
1681 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1682 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1683 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1684 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1685 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1686 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1689 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1690 if(options.useXstack) fprintf (asmFile, " --xstack");
1691 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1692 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1693 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1694 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1695 fprintf (asmFile, "\n");
1697 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1699 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1702 tfprintf (asmFile, "\t!fileprelude\n");
1704 /* Let the port generate any global directives, etc. */
1705 if (port->genAssemblerPreamble)
1707 port->genAssemblerPreamble (asmFile);
1710 /* print the global variables in this module */
1711 printPublics (asmFile);
1712 if (port->assembler.externGlobal)
1713 printExterns (asmFile);
1716 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1718 /* copy the sfr segment */
1719 fprintf (asmFile, "%s", iComments2);
1720 fprintf (asmFile, "; special function registers\n");
1721 fprintf (asmFile, "%s", iComments2);
1722 copyFile (asmFile, sfr->oFile);
1727 /* copy the sbit segment */
1728 fprintf (asmFile, "%s", iComments2);
1729 fprintf (asmFile, "; special function bits\n");
1730 fprintf (asmFile, "%s", iComments2);
1731 copyFile (asmFile, sfrbit->oFile);
1733 /*JCF: Create the areas for the register banks*/
1734 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1736 fprintf (asmFile, "%s", iComments2);
1737 fprintf (asmFile, "; overlayable register banks\n");
1738 fprintf (asmFile, "%s", iComments2);
1740 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1741 if(RegBankUsed[1]||options.parms_in_bank1)
1742 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1744 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1746 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1750 fprintf (asmFile, "%s", iComments2);
1751 fprintf (asmFile, "; overlayable bit register bank\n");
1752 fprintf (asmFile, "%s", iComments2);
1753 fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
1754 fprintf (asmFile, "bits:\n\t.ds 1\n");
1755 fprintf (asmFile, "\tb0 = bits[0]\n");
1756 fprintf (asmFile, "\tb1 = bits[1]\n");
1757 fprintf (asmFile, "\tb2 = bits[2]\n");
1758 fprintf (asmFile, "\tb3 = bits[3]\n");
1759 fprintf (asmFile, "\tb4 = bits[4]\n");
1760 fprintf (asmFile, "\tb5 = bits[5]\n");
1761 fprintf (asmFile, "\tb6 = bits[6]\n");
1762 fprintf (asmFile, "\tb7 = bits[7]\n");
1766 /* copy the data segment */
1767 fprintf (asmFile, "%s", iComments2);
1768 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1769 fprintf (asmFile, "%s", iComments2);
1770 copyFile (asmFile, data->oFile);
1773 /* create the overlay segments */
1775 fprintf (asmFile, "%s", iComments2);
1776 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1777 fprintf (asmFile, "%s", iComments2);
1778 copyFile (asmFile, ovrFile);
1781 /* create the stack segment MOF */
1782 if (mainf && IFFUNC_HASBODY(mainf->type))
1784 fprintf (asmFile, "%s", iComments2);
1785 fprintf (asmFile, "; Stack segment in internal ram \n");
1786 fprintf (asmFile, "%s", iComments2);
1787 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1788 "__start__stack:\n\t.ds\t1\n\n");
1791 /* create the idata segment */
1792 if ( (idata) && (mcs51_like) ) {
1793 fprintf (asmFile, "%s", iComments2);
1794 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1795 fprintf (asmFile, "%s", iComments2);
1796 copyFile (asmFile, idata->oFile);
1799 /* create the absolute idata/data segment */
1800 if ( (i_abs) && (mcs51_like) ) {
1801 fprintf (asmFile, "%s", iComments2);
1802 fprintf (asmFile, "; absolute internal ram data\n");
1803 fprintf (asmFile, "%s", iComments2);
1804 copyFile (asmFile, d_abs->oFile);
1805 copyFile (asmFile, i_abs->oFile);
1808 /* copy the bit segment */
1810 fprintf (asmFile, "%s", iComments2);
1811 fprintf (asmFile, "; bit data\n");
1812 fprintf (asmFile, "%s", iComments2);
1813 copyFile (asmFile, bit->oFile);
1816 /* copy paged external ram data */
1819 fprintf (asmFile, "%s", iComments2);
1820 fprintf (asmFile, "; paged external ram data\n");
1821 fprintf (asmFile, "%s", iComments2);
1822 copyFile (asmFile, pdata->oFile);
1825 /* if external stack then reserve space for it */
1826 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1828 fprintf (asmFile, "%s", iComments2);
1829 fprintf (asmFile, "; external stack \n");
1830 fprintf (asmFile, "%s", iComments2);
1831 fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
1832 "__start__xstack:\n\t.ds\t1\n\n");
1835 /* copy external ram data */
1837 fprintf (asmFile, "%s", iComments2);
1838 fprintf (asmFile, "; external ram data\n");
1839 fprintf (asmFile, "%s", iComments2);
1840 copyFile (asmFile, xdata->oFile);
1843 /* copy external initialized ram data */
1844 fprintf (asmFile, "%s", iComments2);
1845 fprintf (asmFile, "; external initialized ram data\n");
1846 fprintf (asmFile, "%s", iComments2);
1847 copyFile (asmFile, xidata->oFile);
1849 /* If the port wants to generate any extra areas, let it do so. */
1850 if (port->extraAreas.genExtraAreaDeclaration)
1852 port->extraAreas.genExtraAreaDeclaration(asmFile,
1853 mainf && IFFUNC_HASBODY(mainf->type));
1856 /* copy the interrupt vector table */
1857 if (mainf && IFFUNC_HASBODY(mainf->type))
1859 fprintf (asmFile, "%s", iComments2);
1860 fprintf (asmFile, "; interrupt vector \n");
1861 fprintf (asmFile, "%s", iComments2);
1862 copyFile (asmFile, vFile);
1865 /* copy global & static initialisations */
1866 fprintf (asmFile, "%s", iComments2);
1867 fprintf (asmFile, "; global & static initialisations\n");
1868 fprintf (asmFile, "%s", iComments2);
1870 /* Everywhere we generate a reference to the static_name area,
1871 * (which is currently only here), we immediately follow it with a
1872 * definition of the post_static_name area. This guarantees that
1873 * the post_static_name area will immediately follow the static_name
1876 tfprintf (asmFile, "\t!area\n", port->mem.home_name);
1877 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1878 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1879 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1881 if (mainf && IFFUNC_HASBODY(mainf->type))
1883 if (port->genInitStartup)
1885 port->genInitStartup(asmFile);
1889 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1890 /* if external stack is specified then the
1891 higher order byte of the xdatalocation is
1892 going into P2 and the lower order going into
1894 if (options.useXstack)
1896 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1897 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1898 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1899 (unsigned int) options.xdata_loc & 0xff);
1902 // This should probably be a port option, but I'm being lazy.
1903 // on the 400, the firmware boot loader gives us a valid stack
1904 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1905 if (!TARGET_IS_DS400)
1907 /* initialise the stack pointer. JCF: aslink takes care of the location */
1908 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1911 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1912 fprintf (asmFile, "\tmov\ta,dpl\n");
1913 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1914 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1915 fprintf (asmFile, "__sdcc_init_data:\n");
1917 // if the port can copy the XINIT segment to XISEG
1920 port->genXINIT(asmFile);
1925 copyFile (asmFile, statsg->oFile);
1927 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1929 /* This code is generated in the post-static area.
1930 * This area is guaranteed to follow the static area
1931 * by the ugly shucking and jiving about 20 lines ago.
1933 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1934 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1940 "%s", iComments2, iComments2);
1941 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1942 copyFile (asmFile, home->oFile);
1944 if (mainf && IFFUNC_HASBODY(mainf->type))
1946 /* entry point @ start of HOME */
1947 fprintf (asmFile, "__sdcc_program_startup:\n");
1949 /* put in jump or call to main */
1950 if (options.mainreturn)
1952 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1953 fprintf (asmFile, ";\treturn from main will return to caller\n");
1957 fprintf (asmFile, "\tlcall\t_main\n");
1958 fprintf (asmFile, ";\treturn from main will lock up\n");
1959 fprintf (asmFile, "\tsjmp .\n");
1962 /* copy over code */
1963 fprintf (asmFile, "%s", iComments2);
1964 fprintf (asmFile, "; code\n");
1965 fprintf (asmFile, "%s", iComments2);
1966 tfprintf (asmFile, "\t!areacode\n", options.code_seg);
1967 copyFile (asmFile, code->oFile);
1969 if (port->genAssemblerEnd) {
1970 port->genAssemblerEnd(asmFile);
1978 /** Creates a temporary file with unique file name
1980 - TMP, TEMP, TMPDIR env. variables
1981 - if Un*x system: /tmp and /var/tmp
1982 - root directory using mkstemp() if available
1983 - default location using tempnam()
1986 tempfileandname(char *fname, size_t len)
1988 #define TEMPLATE "sdccXXXXXX"
1989 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1991 const char *tmpdir = NULL;
1994 if ((tmpdir = getenv ("TMP")) == NULL)
1995 if ((tmpdir = getenv ("TEMP")) == NULL)
1996 tmpdir = getenv ("TMPDIR");
2000 static int warning_emitted;
2005 if (!warning_emitted)
2007 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
2008 warning_emitted = 1;
2014 /* try with /tmp and /var/tmp on Un*x systems */
2015 struct stat statbuf;
2017 if (tmpdir == NULL) {
2018 if (stat("/tmp", &statbuf) != -1)
2020 else if (stat("/var/tmp", &statbuf) != -1)
2021 tmpdir = "/var/tmp";
2028 char fnamebuf[PATH_MAX];
2031 if (fname == NULL || len == 0) {
2033 len = sizeof fnamebuf;
2037 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
2039 assert(name_len < len);
2040 if (!(name_len < len)) /* in NDEBUG is defined */
2041 return -1; /* buffer too small, temporary file can not be created */
2043 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
2046 name_len = TEMPLATE_LEN;
2048 assert(name_len < len);
2049 if (!(name_len < len)) /* in NDEBUG is defined */
2050 return -1; /* buffer too small, temporary file can not be created */
2052 strcpy(fname, TEMPLATE);
2055 fd = mkstemp(fname);
2059 char *name = tempnam(tmpdir, "sdcc");
2062 perror("Can't create temporary file name");
2066 assert(strlen(name) < len);
2067 if (!(strlen(name) < len)) /* in NDEBUG is defined */
2068 return -1; /* buffer too small, temporary file can not be created */
2070 strcpy(fname, name);
2072 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2074 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2080 perror("Can't create temporary file");
2088 /** Create a temporary file name
2094 static char fnamebuf[PATH_MAX];
2096 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2097 fprintf(stderr, "Can't create temporary file name!");
2108 /** Create a temporary file and add it to tmpfileNameSet,
2109 so that it is removed explicitly by rm_tmpfiles()
2110 or implicitly at program extit.
2118 char fnamebuf[PATH_MAX];
2120 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2121 fprintf(stderr, "Can't create temporary file!");
2125 tmp = Safe_strdup(fnamebuf);
2127 addSetHead(&tmpfileNameSet, tmp);
2129 if ((fp = fdopen(fd, "w+b")) == NULL) {
2130 perror("Can't create temporary file!");