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 - unlinks all tmp files created by the compiler */
64 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
65 /*-----------------------------------------------------------------*/
66 DEFSETFUNC (rmTmpFiles)
78 /*-----------------------------------------------------------------*/
79 /* rm_tmpfiles - close and remove temporary files and delete sets */
80 /*-----------------------------------------------------------------*/
84 /* close temporary files */
85 applyToSet (tmpfileSet, closeTmpFiles);
86 /* remove temporary files */
87 applyToSet (tmpfileNameSet, rmTmpFiles);
88 /* delete temorary file sets */
89 deleteSet (&tmpfileSet);
90 deleteSet (&tmpfileNameSet);
93 /*-----------------------------------------------------------------*/
94 /* copyFile - copies source file to destination file */
95 /*-----------------------------------------------------------------*/
97 copyFile (FILE * dest, FILE * src)
103 if ((ch = fgetc (src)) != EOF)
108 aopLiteralLong (value * val, int offset, int size)
118 // assuming we have been warned before
122 /* if it is a float then it gets tricky */
123 /* otherwise it is fairly simple */
124 if (!IS_FLOAT (val->type)) {
125 unsigned long v = (unsigned long) floatFromVal (val);
130 tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
133 tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
136 /* Hmm. Too big for now. */
139 rs = Safe_calloc (1, strlen (buffer) + 1);
140 return strcpy (rs, buffer);
143 /* PENDING: For now size must be 1 */
146 /* it is type float */
147 fl.f = (float) floatFromVal (val);
149 tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
151 tsprintf (buffer, "!immedbyte", fl.c[offset]);
153 rs = Safe_calloc (1, strlen (buffer) + 1);
154 return strcpy (rs, buffer);
157 /*-----------------------------------------------------------------*/
158 /* aopLiteral - string from a literal value */
159 /*-----------------------------------------------------------------*/
161 aopLiteral (value * val, int offset)
163 return aopLiteralLong (val, offset, 1);
166 /*-----------------------------------------------------------------*/
167 /* emitRegularMap - emit code for maps with no special cases */
168 /*-----------------------------------------------------------------*/
170 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
180 /* PENDING: special case here - should remove */
181 if (!strcmp (map->sname, CODE_NAME))
182 tfprintf (map->oFile, "\t!areacode\n", map->sname);
183 else if (!strcmp (map->sname, DATA_NAME))
184 tfprintf (map->oFile, "\t!areadata\n", map->sname);
185 else if (!strcmp (map->sname, HOME_NAME))
186 tfprintf (map->oFile, "\t!areahome\n", map->sname);
188 tfprintf (map->oFile, "\t!area\n", map->sname);
191 for (sym = setFirstItem (map->syms); sym;
192 sym = setNextItem (map->syms))
196 /* if extern then add it into the extern list */
197 if (IS_EXTERN (sym->etype))
199 addSetHead (&externs, sym);
203 /* if allocation required check is needed
204 then check if the symbol really requires
205 allocation only for local variables */
207 if (arFlag && !IS_AGGREGATE (sym->type) &&
208 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
209 !sym->allocreq && sym->level)
212 /* for bitvar locals and parameters */
213 if (!arFlag && !sym->allocreq && sym->level
214 && !SPEC_ABSA (sym->etype)) {
218 /* if global variable & not static or extern
219 and addPublics allowed then add it to the public set */
220 if ((sym->level == 0 ||
221 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
223 !IS_STATIC (sym->etype) &&
224 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
226 addSetHead (&publics, sym);
229 /* if extern then do nothing or is a function
231 if (IS_FUNC (sym->type))
234 /* print extra debug info if required */
236 cdbSymbol (sym, cdbFile, FALSE, FALSE);
237 if (!sym->level) /* global */
238 if (IS_STATIC (sym->etype))
239 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
241 fprintf (map->oFile, "G$"); /* scope is global */
243 /* symbol is local */
244 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
245 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
248 /* if it has an initial value then do it only if
249 it is a global variable */
250 if (sym->ival && sym->level == 0) {
251 if (SPEC_OCLS(sym->etype)==xidata) {
252 // create a new "XINIT (CODE)" symbol, that will be emitted later
253 newSym=copySymbol (sym);
254 SPEC_OCLS(newSym->etype)=xinit;
255 sprintf (newSym->name, "__xinit_%s", sym->name);
256 sprintf (newSym->rname,"__xinit_%s", sym->rname);
257 SPEC_CONST(newSym->etype)=1;
258 SPEC_STAT(newSym->etype)=1;
259 resolveIvalSym(newSym->ival);
261 // add it to the "XINIT (CODE)" segment
262 addSet(&xinit->syms, newSym);
265 if (IS_AGGREGATE (sym->type)) {
266 ival = initAggregates (sym, sym->ival, NULL);
268 if (getNelements(sym->type, sym->ival)>1) {
269 werror (W_EXCESS_INITIALIZERS, "scalar",
270 sym->name, sym->lineDef);
272 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
273 decorateType (resolveSymbols (list2expr (sym->ival))));
275 codeOutFile = statsg->oFile;
278 // set ival's lineno to where the symbol was defined
279 setAstLineno (ival, lineno=sym->lineDef);
280 // check if this is not a constant expression
281 if (!constExprTree(ival)) {
282 werror (E_CONST_EXPECTED, "found expression");
283 // but try to do it anyway
286 eBBlockFromiCode (iCodeFromAst (ival));
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))
299 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
301 if (TARGET_IS_XA51) {
304 } else if (map==bit || map==sfrbit) {
308 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
310 SPEC_ADDR (sym->etype));
313 int size = getSize (sym->type);
315 werror(E_UNKNOWN_SIZE,sym->name);
319 fprintf (map->oFile, "==.\n");
321 if (IS_STATIC (sym->etype))
322 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
324 tfprintf (map->oFile, "!labeldef\n", sym->rname);
325 tfprintf (map->oFile, "\t!ds\n",
326 (unsigned int) size & 0xffff);
331 /*-----------------------------------------------------------------*/
332 /* initPointer - pointer initialization code massaging */
333 /*-----------------------------------------------------------------*/
335 initPointer (initList * ilist, sym_link *toType)
338 ast *expr = list2expr (ilist);
343 /* try it the oldway first */
344 if ((val = constExprValue (expr, FALSE)))
347 /* ( ptr + constant ) */
348 if (IS_AST_OP (expr) &&
349 (expr->opval.op == '+' || expr->opval.op == '-') &&
350 IS_AST_SYM_VALUE (expr->left) &&
351 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
352 compareType(toType, expr->left->ftype) &&
353 IS_AST_LIT_VALUE (expr->right)) {
354 return valForCastAggr (expr->left, expr->left->ftype,
360 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
361 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
362 if (compareType(toType, expr->left->ftype)!=1) {
363 werror (W_INIT_WRONG);
364 printFromToType(expr->left->ftype, toType);
370 /* no then we have to do these cludgy checks */
371 /* pointers can be initialized with address of
372 a variable or address of an array element */
373 if (IS_AST_OP (expr) && expr->opval.op == '&') {
374 /* address of symbol */
375 if (IS_AST_SYM_VALUE (expr->left)) {
376 val = copyValue (AST_VALUE (expr->left));
377 val->type = newLink ();
378 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
379 DCL_TYPE (val->type) = CPOINTER;
380 DCL_PTR_CONST (val->type) = port->mem.code_ro;
382 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
383 DCL_TYPE (val->type) = FPOINTER;
384 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
385 DCL_TYPE (val->type) = PPOINTER;
386 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
387 DCL_TYPE (val->type) = IPOINTER;
388 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
389 DCL_TYPE (val->type) = EEPPOINTER;
391 DCL_TYPE (val->type) = POINTER;
392 val->type->next = expr->left->ftype;
393 val->etype = getSpec (val->type);
397 /* if address of indexed array */
398 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
399 return valForArray (expr->left);
401 /* if address of structure element then
403 if (IS_AST_OP (expr->left) &&
404 expr->left->opval.op == '.') {
405 return valForStructElem (expr->left->left,
410 (&some_struct)->element */
411 if (IS_AST_OP (expr->left) &&
412 expr->left->opval.op == PTR_OP &&
413 IS_ADDRESS_OF_OP (expr->left->left)) {
414 return valForStructElem (expr->left->left->left,
418 /* case 3. (((char *) &a) +/- constant) */
419 if (IS_AST_OP (expr) &&
420 (expr->opval.op == '+' || expr->opval.op == '-') &&
421 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
422 IS_AST_OP (expr->left->right) &&
423 expr->left->right->opval.op == '&' &&
424 IS_AST_LIT_VALUE (expr->right)) {
426 return valForCastAggr (expr->left->right->left,
427 expr->left->left->opval.lnk,
428 expr->right, expr->opval.op);
431 /* case 4. (char *)(array type) */
432 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
433 IS_ARRAY(expr->right->ftype)) {
435 val = copyValue (AST_VALUE (expr->right));
436 val->type = newLink ();
437 if (SPEC_SCLS (expr->right->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->right->etype) == S_XDATA)
442 DCL_TYPE (val->type) = FPOINTER;
443 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
444 DCL_TYPE (val->type) = PPOINTER;
445 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
446 DCL_TYPE (val->type) = IPOINTER;
447 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
448 DCL_TYPE (val->type) = EEPPOINTER;
450 DCL_TYPE (val->type) = POINTER;
451 val->type->next = expr->right->ftype->next;
452 val->etype = getSpec (val->type);
456 werror (E_INCOMPAT_PTYPES);
461 /*-----------------------------------------------------------------*/
462 /* printChar - formats and prints a characater string with DB */
463 /*-----------------------------------------------------------------*/
465 printChar (FILE * ofile, char *s, int plen)
468 int len = strlen (s);
473 while (len && pplen < plen)
476 while (i && *s && pplen < plen)
478 if (*s < ' ' || *s == '\"' || *s=='\\')
482 tfprintf (ofile, "\t!ascii\n", buf);
483 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
498 tfprintf (ofile, "\t!ascii\n", buf);
507 tfprintf (ofile, "\t!db !constbyte\n", 0);
510 /*-----------------------------------------------------------------*/
511 /* return the generic pointer high byte for a given pointer type. */
512 /*-----------------------------------------------------------------*/
514 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
522 werror (E_CANNOT_USE_GENERIC_POINTER,
523 iname ? iname : "<null>",
524 oname ? oname : "<null>");
531 return GPTYPE_XSTACK;
533 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
541 /*-----------------------------------------------------------------*/
542 /* printPointerType - generates ival for pointer type */
543 /*-----------------------------------------------------------------*/
545 _printPointerType (FILE * oFile, const char *name)
547 /* if (TARGET_IS_DS390) */
548 if (options.model == MODEL_FLAT24)
550 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
554 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
558 /*-----------------------------------------------------------------*/
559 /* printPointerType - generates ival for pointer type */
560 /*-----------------------------------------------------------------*/
562 printPointerType (FILE * oFile, const char *name)
564 _printPointerType (oFile, name);
565 fprintf (oFile, "\n");
568 /*-----------------------------------------------------------------*/
569 /* printGPointerType - generates ival for generic pointer type */
570 /*-----------------------------------------------------------------*/
572 printGPointerType (FILE * oFile, const char *iname, const char *oname,
573 const unsigned int type)
575 _printPointerType (oFile, iname);
576 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
579 /*-----------------------------------------------------------------*/
580 /* printIvalType - generates ival for int/char */
581 /*-----------------------------------------------------------------*/
583 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
587 /* if initList is deep */
588 if (ilist->type == INIT_DEEP)
589 ilist = ilist->init.deep;
591 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
592 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
595 if (!(val = list2val (ilist))) {
596 // assuming a warning has been thrown
600 if (val->type != type) {
601 val = valCastLiteral(type, floatFromVal(val));
604 switch (getSize (type)) {
607 tfprintf (oFile, "\t!db !constbyte\n", 0);
609 tfprintf (oFile, "\t!dbs\n",
610 aopLiteral (val, 0));
614 if (port->use_dw_for_init)
615 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
617 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
621 tfprintf (oFile, "\t!dw !constword\n", 0);
622 tfprintf (oFile, "\t!dw !constword\n", 0);
625 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
626 aopLiteral (val, 0), aopLiteral (val, 1),
627 aopLiteral (val, 2), aopLiteral (val, 3));
633 /*-----------------------------------------------------------------*/
634 /* printIvalBitFields - generate initializer for bitfields */
635 /*-----------------------------------------------------------------*/
636 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
640 initList *lilist = *ilist ;
641 unsigned long ival = 0;
647 val = list2val(lilist);
649 if (SPEC_BLEN(lsym->etype) > 8) {
650 size += ((SPEC_BLEN (lsym->etype) / 8) +
651 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
654 size = ((SPEC_BLEN (lsym->etype) / 8) +
655 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
657 i = (unsigned long)floatFromVal(val);
658 i <<= SPEC_BSTR (lsym->etype);
660 if (! ( lsym->next &&
661 (IS_BITFIELD(lsym->next->type)) &&
662 (SPEC_BSTR(lsym->next->etype)))) break;
664 lilist = lilist->next;
668 tfprintf (oFile, "\t!db !constbyte\n",ival);
672 tfprintf (oFile, "\t!dw !constword\n",ival);
675 tfprintf (oFile, "\t!db !constword,!constword\n",
676 (ival >> 8) & 0xffff, (ival & 0xffff));
683 /*-----------------------------------------------------------------*/
684 /* printIvalStruct - generates initial value for structures */
685 /*-----------------------------------------------------------------*/
687 printIvalStruct (symbol * sym, sym_link * type,
688 initList * ilist, FILE * oFile)
693 sflds = SPEC_STRUCT (type)->fields;
694 if (ilist->type != INIT_DEEP) {
695 werror (E_INIT_STRUCT, sym->name);
699 iloop = ilist->init.deep;
701 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
702 if (IS_BITFIELD(sflds->type)) {
703 printIvalBitFields(&sflds,&iloop,oFile);
705 printIval (sym, sflds->type, iloop, oFile);
709 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
714 /*-----------------------------------------------------------------*/
715 /* printIvalChar - generates initital value for character array */
716 /*-----------------------------------------------------------------*/
718 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
726 val = list2val (ilist);
727 /* if the value is a character string */
728 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
730 if (!DCL_ELEM (type))
731 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
733 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
735 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
737 tfprintf (oFile, "\t!db !constbyte\n", 0);
745 printChar (oFile, s, strlen (s) + 1);
749 /*-----------------------------------------------------------------*/
750 /* printIvalArray - generates code for array initialization */
751 /*-----------------------------------------------------------------*/
753 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
757 int lcnt = 0, size = 0;
760 /* take care of the special case */
761 /* array of characters can be init */
763 if (IS_CHAR (type->next)) {
764 if (!IS_LITERAL(list2val(ilist)->etype)) {
765 werror (E_CONST_EXPECTED);
768 if (printIvalChar (type,
769 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
770 oFile, SPEC_CVAL (sym->etype).v_char))
773 /* not the special case */
774 if (ilist->type != INIT_DEEP)
776 werror (E_INIT_STRUCT, sym->name);
780 iloop = ilist->init.deep;
781 lcnt = DCL_ELEM (type);
782 for (last_type = type->next; last_type && DCL_ELEM (last_type); last_type = last_type->next)
783 lcnt *= DCL_ELEM (last_type);
788 printIval (sym, type->next, iloop, oFile);
789 iloop = (iloop ? iloop->next : NULL);
792 /* if not array limits given & we */
793 /* are out of initialisers then */
794 if (!DCL_ELEM (type) && !iloop)
797 /* no of elements given and we */
798 /* have generated for all of them */
800 /* if initializers left */
802 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
808 /* if we have not been given a size */
809 if (!DCL_ELEM (type))
810 DCL_ELEM (type) = size;
815 /*-----------------------------------------------------------------*/
816 /* printIvalFuncPtr - generate initial value for function pointers */
817 /*-----------------------------------------------------------------*/
819 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
824 val = list2val (ilist);
827 // an error has been thrown allready
831 if (IS_LITERAL(val->etype)) {
832 if (compareType(type,val->etype)==0) {
833 werror (E_INCOMPAT_TYPES);
834 printFromToType (val->type, type);
836 printIvalCharPtr (NULL, type, val, oFile);
840 /* check the types */
841 if ((dLvl = compareType (val->type, type->next)) <= 0)
843 tfprintf (oFile, "\t!dw !constword\n", 0);
847 /* now generate the name */
850 if (port->use_dw_for_init)
852 tfprintf (oFile, "\t!dws\n", val->name);
856 printPointerType (oFile, val->name);
859 else if (port->use_dw_for_init)
861 tfprintf (oFile, "\t!dws\n", val->sym->rname);
865 printPointerType (oFile, val->sym->rname);
871 /*-----------------------------------------------------------------*/
872 /* printIvalCharPtr - generates initial values for character pointers */
873 /*-----------------------------------------------------------------*/
875 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
879 /* PENDING: this is _very_ mcs51 specific, including a magic
881 It's also endin specific.
883 size = getSize (type);
885 if (val->name && strlen (val->name))
887 if (size == 1) /* This appears to be Z80 specific?? */
890 "\t!dbs\n", val->name);
892 else if (size == FPTRSIZE)
894 if (port->use_dw_for_init)
896 tfprintf (oFile, "\t!dws\n", val->name);
900 printPointerType (oFile, val->name);
903 else if (size == GPTRSIZE)
906 if (IS_PTR (val->type)) {
907 type = DCL_TYPE (val->type);
909 type = PTR_TYPE (SPEC_OCLS (val->etype));
911 if (val->sym && val->sym->isstrlit) {
912 // this is a literal string
915 printGPointerType (oFile, val->name, sym->name, type);
919 fprintf (stderr, "*** internal error: unknown size in "
920 "printIvalCharPtr.\n");
925 // these are literals assigned to pointers
929 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
932 if (port->use_dw_for_init)
933 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
935 tfprintf (oFile, "\t.byte %s,%s\n",
936 aopLiteral (val, 0), aopLiteral (val, 1));
939 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
940 // non-zero mcs51 generic pointer
941 werror (E_LITERAL_GENERIC);
943 fprintf (oFile, "\t.byte %s,%s,%s\n",
946 aopLiteral (val, 2));
949 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
950 // non-zero ds390 generic pointer
951 werror (E_LITERAL_GENERIC);
953 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
957 aopLiteral (val, 3));
964 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
965 addSet (&statsg->syms, val->sym);
971 /*-----------------------------------------------------------------*/
972 /* printIvalPtr - generates initial value for pointers */
973 /*-----------------------------------------------------------------*/
975 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
981 if (ilist->type == INIT_DEEP)
982 ilist = ilist->init.deep;
984 /* function pointer */
985 if (IS_FUNC (type->next))
987 printIvalFuncPtr (type, ilist, oFile);
991 if (!(val = initPointer (ilist, type)))
994 /* if character pointer */
995 if (IS_CHAR (type->next))
996 if (printIvalCharPtr (sym, type, val, oFile))
1000 if (compareType (type, val->type) == 0) {
1001 werror (W_INIT_WRONG);
1002 printFromToType (val->type, type);
1005 /* if val is literal */
1006 if (IS_LITERAL (val->etype))
1008 switch (getSize (type))
1011 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1014 if (port->use_dw_for_init)
1015 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1017 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1019 case 3: // how about '390??
1020 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1021 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1027 size = getSize (type);
1029 if (size == 1) /* Z80 specific?? */
1031 tfprintf (oFile, "\t!dbs\n", val->name);
1033 else if (size == FPTRSIZE)
1035 if (port->use_dw_for_init) {
1036 tfprintf (oFile, "\t!dws\n", val->name);
1038 printPointerType (oFile, val->name);
1041 else if (size == GPTRSIZE)
1043 printGPointerType (oFile, val->name, sym->name,
1044 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1045 PTR_TYPE (SPEC_OCLS (val->etype))));
1050 /*-----------------------------------------------------------------*/
1051 /* printIval - generates code for initial value */
1052 /*-----------------------------------------------------------------*/
1054 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1059 /* update line number for error msgs */
1060 lineno=sym->lineDef;
1062 /* if structure then */
1063 if (IS_STRUCT (type))
1065 printIvalStruct (sym, type, ilist, oFile);
1069 /* if this is a pointer */
1072 printIvalPtr (sym, type, ilist, oFile);
1076 /* if this is an array */
1077 if (IS_ARRAY (type))
1079 printIvalArray (sym, type, ilist, oFile);
1083 /* if type is SPECIFIER */
1086 printIvalType (sym, type, ilist, oFile);
1091 /*-----------------------------------------------------------------*/
1092 /* emitStaticSeg - emitcode for the static segment */
1093 /*-----------------------------------------------------------------*/
1095 emitStaticSeg (memmap * map, FILE * out)
1099 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1101 /* for all variables in this segment do */
1102 for (sym = setFirstItem (map->syms); sym;
1103 sym = setNextItem (map->syms))
1106 /* if it is "extern" then do nothing */
1107 if (IS_EXTERN (sym->etype))
1110 /* if it is not static add it to the public
1112 if (!IS_STATIC (sym->etype))
1114 addSetHead (&publics, sym);
1117 /* print extra debug info if required */
1118 if (options.debug) {
1119 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1122 if (IS_STATIC (sym->etype))
1123 fprintf (out, "F%s$", moduleName); /* scope is file */
1125 fprintf (out, "G$"); /* scope is global */
1128 /* symbol is local */
1129 fprintf (out, "L%s$",
1130 (sym->localof ? sym->localof->name : "-null-"));
1131 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1134 /* if it has an absolute address */
1135 if (SPEC_ABSA (sym->etype))
1138 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1140 fprintf (out, "%s\t=\t0x%04x\n",
1142 SPEC_ADDR (sym->etype));
1147 fprintf (out, " == .\n");
1149 /* if it has an initial value */
1152 fprintf (out, "%s:\n", sym->rname);
1154 resolveIvalSym (sym->ival);
1155 printIval (sym, sym->type, sym->ival, out);
1159 /* allocate space */
1160 int size = getSize (sym->type);
1163 werror(E_UNKNOWN_SIZE,sym->name);
1165 fprintf (out, "%s:\n", sym->rname);
1166 /* special case for character strings */
1167 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1168 SPEC_CVAL (sym->etype).v_char)
1170 SPEC_CVAL (sym->etype).v_char,
1171 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1173 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1179 /*-----------------------------------------------------------------*/
1180 /* emitMaps - emits the code for the data portion the code */
1181 /*-----------------------------------------------------------------*/
1186 /* no special considerations for the following
1187 data, idata & bit & xdata */
1188 emitRegularMap (data, TRUE, TRUE);
1189 emitRegularMap (idata, TRUE, TRUE);
1190 emitRegularMap (bit, TRUE, FALSE);
1191 emitRegularMap (xdata, TRUE, TRUE);
1192 if (port->genXINIT) {
1193 emitRegularMap (xidata, TRUE, TRUE);
1195 emitRegularMap (sfr, FALSE, FALSE);
1196 emitRegularMap (sfrbit, FALSE, FALSE);
1197 emitRegularMap (home, TRUE, FALSE);
1198 emitRegularMap (code, TRUE, FALSE);
1200 emitStaticSeg (statsg, code->oFile);
1201 if (port->genXINIT) {
1202 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1203 emitStaticSeg (xinit, code->oFile);
1208 /*-----------------------------------------------------------------*/
1209 /* flushStatics - flush all currently defined statics out to file */
1210 /* and delete. Temporary function */
1211 /*-----------------------------------------------------------------*/
1215 emitStaticSeg (statsg, codeOutFile);
1216 statsg->syms = NULL;
1219 /*-----------------------------------------------------------------*/
1220 /* createInterruptVect - creates the interrupt vector */
1221 /*-----------------------------------------------------------------*/
1223 createInterruptVect (FILE * vFile)
1226 mainf = newSymbol ("main", 0);
1229 /* only if the main function exists */
1230 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1232 if (!options.cc_only && !noAssemble)
1237 /* if the main is only a prototype ie. no body then do nothing */
1238 if (!IFFUNC_HASBODY(mainf->type))
1240 /* if ! compile only then main function should be present */
1241 if (!options.cc_only && !noAssemble)
1246 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1247 fprintf (vFile, "__interrupt_vect:\n");
1250 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1252 /* "generic" interrupt table header (if port doesn't specify one).
1253 * Look suspiciously like 8051 code to me...
1256 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1259 /* now for the other interrupts */
1260 for (; i < maxInterrupts; i++)
1263 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1265 fprintf (vFile, "\treti\n\t.ds\t7\n");
1272 ";--------------------------------------------------------\n"
1273 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1277 ";--------------------------------------------------------\n"};
1280 /*-----------------------------------------------------------------*/
1281 /* initialComments - puts in some initial comments */
1282 /*-----------------------------------------------------------------*/
1284 initialComments (FILE * afile)
1288 fprintf (afile, "%s", iComments1);
1289 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1290 fprintf (afile, "%s", iComments2);
1293 /*-----------------------------------------------------------------*/
1294 /* printPublics - generates .global for publics */
1295 /*-----------------------------------------------------------------*/
1297 printPublics (FILE * afile)
1301 fprintf (afile, "%s", iComments2);
1302 fprintf (afile, "; Public variables in this module\n");
1303 fprintf (afile, "%s", iComments2);
1305 for (sym = setFirstItem (publics); sym;
1306 sym = setNextItem (publics))
1307 tfprintf (afile, "\t!global\n", sym->rname);
1310 /*-----------------------------------------------------------------*/
1311 /* printExterns - generates .global for externs */
1312 /*-----------------------------------------------------------------*/
1314 printExterns (FILE * afile)
1318 fprintf (afile, "%s", iComments2);
1319 fprintf (afile, "; Externals used\n");
1320 fprintf (afile, "%s", iComments2);
1322 for (sym = setFirstItem (externs); sym;
1323 sym = setNextItem (externs))
1324 tfprintf (afile, "\t!extern\n", sym->rname);
1327 /*-----------------------------------------------------------------*/
1328 /* emitOverlay - will emit code for the overlay stuff */
1329 /*-----------------------------------------------------------------*/
1331 emitOverlay (FILE * afile)
1335 if (!elementsInSet (ovrSetSets))
1336 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1338 /* for each of the sets in the overlay segment do */
1339 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1340 ovrset = setNextItem (ovrSetSets))
1345 if (elementsInSet (ovrset))
1347 /* output the area informtion */
1348 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1351 for (sym = setFirstItem (ovrset); sym;
1352 sym = setNextItem (ovrset))
1354 /* if extern then it is in the publics table: do nothing */
1355 if (IS_EXTERN (sym->etype))
1358 /* if allocation required check is needed
1359 then check if the symbol really requires
1360 allocation only for local variables */
1361 if (!IS_AGGREGATE (sym->type) &&
1362 !(sym->_isparm && !IS_REGPARM (sym->etype))
1363 && !sym->allocreq && sym->level)
1366 /* if global variable & not static or extern
1367 and addPublics allowed then add it to the public set */
1368 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1369 && !IS_STATIC (sym->etype))
1371 addSetHead (&publics, sym);
1374 /* if extern then do nothing or is a function
1376 if (IS_FUNC (sym->type))
1379 /* print extra debug info if required */
1382 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1386 if (IS_STATIC (sym->etype))
1387 fprintf (afile, "F%s$", moduleName); /* scope is file */
1389 fprintf (afile, "G$"); /* scope is global */
1392 /* symbol is local */
1393 fprintf (afile, "L%s$",
1394 (sym->localof ? sym->localof->name : "-null-"));
1395 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1398 /* if is has an absolute address then generate
1399 an equate for this no need to allocate space */
1400 if (SPEC_ABSA (sym->etype))
1404 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1406 fprintf (afile, "%s\t=\t0x%04x\n",
1408 SPEC_ADDR (sym->etype));
1411 int size = getSize(sym->type);
1414 werror(E_UNKNOWN_SIZE,sym->name);
1417 fprintf (afile, "==.\n");
1419 /* allocate space */
1420 tfprintf (afile, "!labeldef\n", sym->rname);
1421 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1428 /*-----------------------------------------------------------------*/
1429 /* glue - the final glue that hold the whole thing together */
1430 /*-----------------------------------------------------------------*/
1436 FILE *ovrFile = tempfile ();
1438 addSetHead (&tmpfileSet, ovrFile);
1439 /* print the global struct definitions */
1441 cdbStructBlock (0, cdbFile);
1443 vFile = tempfile ();
1444 /* PENDING: this isnt the best place but it will do */
1445 if (port->general.glue_up_main)
1447 /* create the interrupt vector table */
1448 createInterruptVect (vFile);
1451 addSetHead (&tmpfileSet, vFile);
1453 /* emit code for the all the variables declared */
1455 /* do the overlay segments */
1456 emitOverlay (ovrFile);
1458 /* now put it all together into the assembler file */
1459 /* create the assembler file name */
1461 if (!options.c1mode)
1463 sprintf (scratchFileName, srcFileName);
1464 strcat (scratchFileName, port->assembler.file_ext);
1468 strcpy (scratchFileName, options.out_name);
1471 if (!(asmFile = fopen (scratchFileName, "w")))
1473 werror (E_FILE_OPEN_ERR, scratchFileName);
1477 /* initial comments */
1478 initialComments (asmFile);
1480 /* print module name */
1481 tfprintf (asmFile, "\t!module\n", moduleName);
1482 tfprintf (asmFile, "\t!fileprelude\n");
1484 /* Let the port generate any global directives, etc. */
1485 if (port->genAssemblerPreamble)
1487 port->genAssemblerPreamble (asmFile);
1490 /* print the global variables in this module */
1491 printPublics (asmFile);
1492 if (port->assembler.externGlobal)
1493 printExterns (asmFile);
1495 /* copy the sfr segment */
1496 fprintf (asmFile, "%s", iComments2);
1497 fprintf (asmFile, "; special function registers\n");
1498 fprintf (asmFile, "%s", iComments2);
1499 copyFile (asmFile, sfr->oFile);
1501 /* copy the sbit segment */
1502 fprintf (asmFile, "%s", iComments2);
1503 fprintf (asmFile, "; special function bits \n");
1504 fprintf (asmFile, "%s", iComments2);
1505 copyFile (asmFile, sfrbit->oFile);
1507 /* copy the data segment */
1508 fprintf (asmFile, "%s", iComments2);
1509 fprintf (asmFile, "; internal ram data\n");
1510 fprintf (asmFile, "%s", iComments2);
1511 copyFile (asmFile, data->oFile);
1514 /* create the overlay segments */
1516 fprintf (asmFile, "%s", iComments2);
1517 fprintf (asmFile, "; overlayable items in internal ram \n");
1518 fprintf (asmFile, "%s", iComments2);
1519 copyFile (asmFile, ovrFile);
1522 /* create the stack segment MOF */
1523 if (mainf && IFFUNC_HASBODY(mainf->type))
1525 fprintf (asmFile, "%s", iComments2);
1526 fprintf (asmFile, "; Stack segment in internal ram \n");
1527 fprintf (asmFile, "%s", iComments2);
1528 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1529 "__start__stack:\n\t.ds\t1\n\n");
1532 /* create the idata segment */
1534 fprintf (asmFile, "%s", iComments2);
1535 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1536 fprintf (asmFile, "%s", iComments2);
1537 copyFile (asmFile, idata->oFile);
1540 /* copy the bit segment */
1541 fprintf (asmFile, "%s", iComments2);
1542 fprintf (asmFile, "; bit data\n");
1543 fprintf (asmFile, "%s", iComments2);
1544 copyFile (asmFile, bit->oFile);
1546 /* if external stack then reserve space of it */
1547 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1549 fprintf (asmFile, "%s", iComments2);
1550 fprintf (asmFile, "; external stack \n");
1551 fprintf (asmFile, "%s", iComments2);
1552 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1553 fprintf (asmFile, "\t.ds 256\n");
1557 /* copy xtern ram data */
1558 fprintf (asmFile, "%s", iComments2);
1559 fprintf (asmFile, "; external ram data\n");
1560 fprintf (asmFile, "%s", iComments2);
1561 copyFile (asmFile, xdata->oFile);
1563 /* copy xternal initialized ram data */
1564 fprintf (asmFile, "%s", iComments2);
1565 fprintf (asmFile, "; external initialized ram data\n");
1566 fprintf (asmFile, "%s", iComments2);
1567 copyFile (asmFile, xidata->oFile);
1569 /* copy the interrupt vector table */
1570 if (mainf && IFFUNC_HASBODY(mainf->type))
1572 fprintf (asmFile, "%s", iComments2);
1573 fprintf (asmFile, "; interrupt vector \n");
1574 fprintf (asmFile, "%s", iComments2);
1575 copyFile (asmFile, vFile);
1578 /* copy global & static initialisations */
1579 fprintf (asmFile, "%s", iComments2);
1580 fprintf (asmFile, "; global & static initialisations\n");
1581 fprintf (asmFile, "%s", iComments2);
1583 /* Everywhere we generate a reference to the static_name area,
1584 * (which is currently only here), we immediately follow it with a
1585 * definition of the post_static_name area. This guarantees that
1586 * the post_static_name area will immediately follow the static_name
1589 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1590 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1591 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1593 if (mainf && IFFUNC_HASBODY(mainf->type))
1595 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1596 /* if external stack is specified then the
1597 higher order byte of the xdatalocation is
1598 going into P2 and the lower order going into
1600 if (options.useXstack)
1602 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1603 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1604 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1605 (unsigned int) options.xdata_loc & 0xff);
1608 /* initialise the stack pointer */
1609 /* if the user specified a value then use it */
1610 if (options.stack_loc)
1611 fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff);
1613 /* no: we have to compute it */
1614 if (!options.stackOnData && maxRegBank <= 3)
1615 fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1617 fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */
1619 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1620 fprintf (asmFile, "\tmov\ta,dpl\n");
1621 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1622 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1623 fprintf (asmFile, "__sdcc_init_data:\n");
1625 // if the port can copy the XINIT segment to XISEG
1626 if (port->genXINIT) {
1627 port->genXINIT(asmFile);
1631 copyFile (asmFile, statsg->oFile);
1633 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1635 /* This code is generated in the post-static area.
1636 * This area is guaranteed to follow the static area
1637 * by the ugly shucking and jiving about 20 lines ago.
1639 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1640 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1646 "%s", iComments2, iComments2);
1647 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1648 copyFile (asmFile, home->oFile);
1650 /* copy over code */
1651 fprintf (asmFile, "%s", iComments2);
1652 fprintf (asmFile, "; code\n");
1653 fprintf (asmFile, "%s", iComments2);
1654 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1655 if (mainf && IFFUNC_HASBODY(mainf->type))
1658 /* entry point @ start of CSEG */
1659 fprintf (asmFile, "__sdcc_program_startup:\n");
1661 /* put in the call to main */
1662 fprintf (asmFile, "\tlcall\t_main\n");
1663 if (options.mainreturn)
1666 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1667 fprintf (asmFile, "\tret\n");
1673 fprintf (asmFile, ";\treturn from main will lock up\n");
1674 fprintf (asmFile, "\tsjmp .\n");
1677 copyFile (asmFile, code->oFile);
1679 if (port->genAssemblerEnd) {
1680 port->genAssemblerEnd(asmFile);
1687 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1688 in cygwin wrt c:\tmp.
1689 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
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 = tempnam (tmpdir, "sdcc");
1709 return tmpnam (NULL);
1712 /** Creates a temporary file a'la tmpfile which avoids the bugs
1713 in cygwin wrt c:\tmp.
1714 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1719 const char *tmpdir = NULL;
1721 tmpdir = getenv ("TMP");
1722 else if (getenv ("TEMP"))
1723 tmpdir = getenv ("TEMP");
1724 else if (getenv ("TMPDIR"))
1725 tmpdir = getenv ("TMPDIR");
1728 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1731 FILE *fp = fopen (name, "w+b");
1734 addSetHead (&tmpfileNameSet, name);