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)
117 // assuming we have been warned before
121 /* if it is a float then it gets tricky */
122 /* otherwise it is fairly simple */
123 if (!IS_FLOAT (val->type)) {
124 unsigned long v = (unsigned long) floatFromVal (val);
129 tsprintf (buffer, sizeof(buffer),
130 "!immedbyte", (unsigned int) v & 0xff);
133 tsprintf (buffer, sizeof(buffer),
134 "!immedword", (unsigned int) v & 0xffff);
137 /* Hmm. Too big for now. */
140 return Safe_strdup (buffer);
143 /* PENDING: For now size must be 1 */
146 /* it is type float */
147 fl.f = (float) floatFromVal (val);
149 tsprintf (buffer, sizeof(buffer),
150 "!immedbyte", fl.c[3 - offset]);
152 tsprintf (buffer, sizeof(buffer),
153 "!immedbyte", fl.c[offset]);
155 return Safe_strdup (buffer);
158 /*-----------------------------------------------------------------*/
159 /* aopLiteral - string from a literal value */
160 /*-----------------------------------------------------------------*/
162 aopLiteral (value * val, int offset)
164 return aopLiteralLong (val, offset, 1);
167 /*-----------------------------------------------------------------*/
168 /* emitRegularMap - emit code for maps with no special cases */
169 /*-----------------------------------------------------------------*/
171 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
181 /* PENDING: special case here - should remove */
182 if (!strcmp (map->sname, CODE_NAME))
183 tfprintf (map->oFile, "\t!areacode\n", map->sname);
184 else if (!strcmp (map->sname, DATA_NAME))
185 tfprintf (map->oFile, "\t!areadata\n", map->sname);
186 else if (!strcmp (map->sname, HOME_NAME))
187 tfprintf (map->oFile, "\t!areahome\n", map->sname);
189 tfprintf (map->oFile, "\t!area\n", map->sname);
192 for (sym = setFirstItem (map->syms); sym;
193 sym = setNextItem (map->syms))
197 /* if extern then add it into the extern list */
198 if (IS_EXTERN (sym->etype))
200 addSetHead (&externs, sym);
204 /* if allocation required check is needed
205 then check if the symbol really requires
206 allocation only for local variables */
208 if (arFlag && !IS_AGGREGATE (sym->type) &&
209 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
210 !sym->allocreq && sym->level)
213 /* for bitvar locals and parameters */
214 if (!arFlag && !sym->allocreq && sym->level
215 && !SPEC_ABSA (sym->etype)) {
219 /* if global variable & not static or extern
220 and addPublics allowed then add it to the public set */
221 if ((sym->level == 0 ||
222 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
224 !IS_STATIC (sym->etype) &&
225 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
227 addSetHead (&publics, sym);
230 /* if extern then do nothing or is a function
232 if (IS_FUNC (sym->type))
235 /* print extra debug info if required */
237 cdbSymbol (sym, cdbFile, FALSE, FALSE);
238 if (!sym->level) /* global */
239 if (IS_STATIC (sym->etype))
240 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
242 fprintf (map->oFile, "G$"); /* scope is global */
244 /* symbol is local */
245 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
246 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
249 /* if it has an initial value then do it only if
250 it is a global variable */
251 if (sym->ival && sym->level == 0) {
252 if (SPEC_OCLS(sym->etype)==xidata) {
253 // create a new "XINIT (CODE)" symbol, that will be emitted later
254 newSym=copySymbol (sym);
255 SPEC_OCLS(newSym->etype)=xinit;
256 SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
257 SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
258 SPEC_CONST(newSym->etype)=1;
259 SPEC_STAT(newSym->etype)=1;
260 resolveIvalSym(newSym->ival);
262 // add it to the "XINIT (CODE)" segment
263 addSet(&xinit->syms, newSym);
266 if (IS_AGGREGATE (sym->type)) {
267 ival = initAggregates (sym, sym->ival, NULL);
269 if (getNelements(sym->type, sym->ival)>1) {
270 werror (W_EXCESS_INITIALIZERS, "scalar",
271 sym->name, sym->lineDef);
273 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
274 decorateType (resolveSymbols (list2expr (sym->ival))));
276 codeOutFile = statsg->oFile;
279 // set ival's lineno to where the symbol was defined
280 setAstLineno (ival, lineno=sym->lineDef);
281 // check if this is not a constant expression
282 if (!constExprTree(ival)) {
283 werror (E_CONST_EXPECTED, "found expression");
284 // but try to do it anyway
287 eBBlockFromiCode (iCodeFromAst (ival));
294 /* if is has an absolute address then generate
295 an equate for this no need to allocate space */
296 if (SPEC_ABSA (sym->etype))
300 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
302 if (TARGET_IS_XA51) {
305 } else if (map==bit || map==sfrbit) {
309 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
311 SPEC_ADDR (sym->etype));
314 int size = getSize (sym->type);
316 werror(E_UNKNOWN_SIZE,sym->name);
320 fprintf (map->oFile, "==.\n");
322 if (IS_STATIC (sym->etype))
323 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
325 tfprintf (map->oFile, "!labeldef\n", sym->rname);
326 tfprintf (map->oFile, "\t!ds\n",
327 (unsigned int) size & 0xffff);
332 /*-----------------------------------------------------------------*/
333 /* initPointer - pointer initialization code massaging */
334 /*-----------------------------------------------------------------*/
336 initPointer (initList * ilist, sym_link *toType)
339 ast *expr = list2expr (ilist);
344 /* try it the oldway first */
345 if ((val = constExprValue (expr, FALSE)))
348 /* ( ptr + constant ) */
349 if (IS_AST_OP (expr) &&
350 (expr->opval.op == '+' || expr->opval.op == '-') &&
351 IS_AST_SYM_VALUE (expr->left) &&
352 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
353 compareType(toType, expr->left->ftype) &&
354 IS_AST_LIT_VALUE (expr->right)) {
355 return valForCastAggr (expr->left, expr->left->ftype,
361 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
362 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
363 if (compareType(toType, expr->left->ftype)!=1) {
364 werror (W_INIT_WRONG);
365 printFromToType(expr->left->ftype, toType);
371 /* no then we have to do these cludgy checks */
372 /* pointers can be initialized with address of
373 a variable or address of an array element */
374 if (IS_AST_OP (expr) && expr->opval.op == '&') {
375 /* address of symbol */
376 if (IS_AST_SYM_VALUE (expr->left)) {
377 val = copyValue (AST_VALUE (expr->left));
378 val->type = newLink ();
379 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
380 DCL_TYPE (val->type) = CPOINTER;
381 DCL_PTR_CONST (val->type) = port->mem.code_ro;
383 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
384 DCL_TYPE (val->type) = FPOINTER;
385 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
386 DCL_TYPE (val->type) = PPOINTER;
387 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
388 DCL_TYPE (val->type) = IPOINTER;
389 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
390 DCL_TYPE (val->type) = EEPPOINTER;
392 DCL_TYPE (val->type) = POINTER;
393 val->type->next = expr->left->ftype;
394 val->etype = getSpec (val->type);
398 /* if address of indexed array */
399 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
400 return valForArray (expr->left);
402 /* if address of structure element then
404 if (IS_AST_OP (expr->left) &&
405 expr->left->opval.op == '.') {
406 return valForStructElem (expr->left->left,
411 (&some_struct)->element */
412 if (IS_AST_OP (expr->left) &&
413 expr->left->opval.op == PTR_OP &&
414 IS_ADDRESS_OF_OP (expr->left->left)) {
415 return valForStructElem (expr->left->left->left,
419 /* case 3. (((char *) &a) +/- constant) */
420 if (IS_AST_OP (expr) &&
421 (expr->opval.op == '+' || expr->opval.op == '-') &&
422 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
423 IS_AST_OP (expr->left->right) &&
424 expr->left->right->opval.op == '&' &&
425 IS_AST_LIT_VALUE (expr->right)) {
427 return valForCastAggr (expr->left->right->left,
428 expr->left->left->opval.lnk,
429 expr->right, expr->opval.op);
432 /* case 4. (char *)(array type) */
433 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
434 IS_ARRAY(expr->right->ftype)) {
436 val = copyValue (AST_VALUE (expr->right));
437 val->type = newLink ();
438 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
439 DCL_TYPE (val->type) = CPOINTER;
440 DCL_PTR_CONST (val->type) = port->mem.code_ro;
442 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
443 DCL_TYPE (val->type) = FPOINTER;
444 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
445 DCL_TYPE (val->type) = PPOINTER;
446 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
447 DCL_TYPE (val->type) = IPOINTER;
448 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
449 DCL_TYPE (val->type) = EEPPOINTER;
451 DCL_TYPE (val->type) = POINTER;
452 val->type->next = expr->right->ftype->next;
453 val->etype = getSpec (val->type);
457 werror (E_INCOMPAT_PTYPES);
462 /*-----------------------------------------------------------------*/
463 /* printChar - formats and prints a characater string with DB */
464 /*-----------------------------------------------------------------*/
466 printChar (FILE * ofile, char *s, int plen)
469 int len = strlen (s);
474 while (len && pplen < plen)
477 while (i && *s && pplen < plen)
479 if (*s < ' ' || *s == '\"' || *s=='\\')
483 tfprintf (ofile, "\t!ascii\n", buf);
484 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
499 tfprintf (ofile, "\t!ascii\n", buf);
508 tfprintf (ofile, "\t!db !constbyte\n", 0);
511 /*-----------------------------------------------------------------*/
512 /* return the generic pointer high byte for a given pointer type. */
513 /*-----------------------------------------------------------------*/
515 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
523 werror (E_CANNOT_USE_GENERIC_POINTER,
524 iname ? iname : "<null>",
525 oname ? oname : "<null>");
532 return GPTYPE_XSTACK;
534 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
542 /*-----------------------------------------------------------------*/
543 /* printPointerType - generates ival for pointer type */
544 /*-----------------------------------------------------------------*/
546 _printPointerType (FILE * oFile, const char *name)
548 /* if (TARGET_IS_DS390) */
549 if (options.model == MODEL_FLAT24)
551 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
555 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
559 /*-----------------------------------------------------------------*/
560 /* printPointerType - generates ival for pointer type */
561 /*-----------------------------------------------------------------*/
563 printPointerType (FILE * oFile, const char *name)
565 _printPointerType (oFile, name);
566 fprintf (oFile, "\n");
569 /*-----------------------------------------------------------------*/
570 /* printGPointerType - generates ival for generic pointer type */
571 /*-----------------------------------------------------------------*/
573 printGPointerType (FILE * oFile, const char *iname, const char *oname,
574 const unsigned int type)
576 _printPointerType (oFile, iname);
577 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
580 /*-----------------------------------------------------------------*/
581 /* printIvalType - generates ival for int/char */
582 /*-----------------------------------------------------------------*/
584 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
588 /* if initList is deep */
589 if (ilist->type == INIT_DEEP)
590 ilist = ilist->init.deep;
592 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
593 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
596 if (!(val = list2val (ilist))) {
597 // assuming a warning has been thrown
601 if (val->type != type) {
602 val = valCastLiteral(type, floatFromVal(val));
605 switch (getSize (type)) {
608 tfprintf (oFile, "\t!db !constbyte\n", 0);
610 tfprintf (oFile, "\t!dbs\n",
611 aopLiteral (val, 0));
615 if (port->use_dw_for_init)
616 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
618 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
622 tfprintf (oFile, "\t!dw !constword\n", 0);
623 tfprintf (oFile, "\t!dw !constword\n", 0);
626 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
627 aopLiteral (val, 0), aopLiteral (val, 1),
628 aopLiteral (val, 2), aopLiteral (val, 3));
634 /*-----------------------------------------------------------------*/
635 /* printIvalBitFields - generate initializer for bitfields */
636 /*-----------------------------------------------------------------*/
637 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
641 initList *lilist = *ilist ;
642 unsigned long ival = 0;
648 val = list2val(lilist);
650 if (SPEC_BLEN(lsym->etype) > 8) {
651 size += ((SPEC_BLEN (lsym->etype) / 8) +
652 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
655 size = ((SPEC_BLEN (lsym->etype) / 8) +
656 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
658 i = (unsigned long)floatFromVal(val);
659 i <<= SPEC_BSTR (lsym->etype);
661 if (! ( lsym->next &&
662 (IS_BITFIELD(lsym->next->type)) &&
663 (SPEC_BSTR(lsym->next->etype)))) break;
665 lilist = lilist->next;
669 tfprintf (oFile, "\t!db !constbyte\n",ival);
673 tfprintf (oFile, "\t!dw !constword\n",ival);
676 tfprintf (oFile, "\t!db !constword,!constword\n",
677 (ival >> 8) & 0xffff, (ival & 0xffff));
684 /*-----------------------------------------------------------------*/
685 /* printIvalStruct - generates initial value for structures */
686 /*-----------------------------------------------------------------*/
688 printIvalStruct (symbol * sym, sym_link * type,
689 initList * ilist, FILE * oFile)
694 sflds = SPEC_STRUCT (type)->fields;
695 if (ilist->type != INIT_DEEP) {
696 werror (E_INIT_STRUCT, sym->name);
700 iloop = ilist->init.deep;
702 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
703 if (IS_BITFIELD(sflds->type)) {
704 printIvalBitFields(&sflds,&iloop,oFile);
706 printIval (sym, sflds->type, iloop, oFile);
710 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
715 /*-----------------------------------------------------------------*/
716 /* printIvalChar - generates initital value for character array */
717 /*-----------------------------------------------------------------*/
719 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
727 val = list2val (ilist);
728 /* if the value is a character string */
729 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
731 if (!DCL_ELEM (type))
732 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
734 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
736 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
738 tfprintf (oFile, "\t!db !constbyte\n", 0);
746 printChar (oFile, s, strlen (s) + 1);
750 /*-----------------------------------------------------------------*/
751 /* printIvalArray - generates code for array initialization */
752 /*-----------------------------------------------------------------*/
754 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
758 int lcnt = 0, size = 0;
761 /* take care of the special case */
762 /* array of characters can be init */
764 if (IS_CHAR (type->next)) {
765 if (!IS_LITERAL(list2val(ilist)->etype)) {
766 werror (E_CONST_EXPECTED);
769 if (printIvalChar (type,
770 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
771 oFile, SPEC_CVAL (sym->etype).v_char))
774 /* not the special case */
775 if (ilist->type != INIT_DEEP)
777 werror (E_INIT_STRUCT, sym->name);
781 iloop = ilist->init.deep;
782 lcnt = DCL_ELEM (type);
783 for (last_type = type->next; last_type && DCL_ELEM (last_type); last_type = last_type->next)
784 lcnt *= DCL_ELEM (last_type);
789 printIval (sym, type->next, iloop, oFile);
790 iloop = (iloop ? iloop->next : NULL);
793 /* if not array limits given & we */
794 /* are out of initialisers then */
795 if (!DCL_ELEM (type) && !iloop)
798 /* no of elements given and we */
799 /* have generated for all of them */
801 /* if initializers left */
803 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
809 /* if we have not been given a size */
810 if (!DCL_ELEM (type))
811 DCL_ELEM (type) = size;
816 /*-----------------------------------------------------------------*/
817 /* printIvalFuncPtr - generate initial value for function pointers */
818 /*-----------------------------------------------------------------*/
820 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
825 val = list2val (ilist);
828 // an error has been thrown allready
832 if (IS_LITERAL(val->etype)) {
833 if (compareType(type,val->etype)==0) {
834 werror (E_INCOMPAT_TYPES);
835 printFromToType (val->type, type);
837 printIvalCharPtr (NULL, type, val, oFile);
841 /* check the types */
842 if ((dLvl = compareType (val->type, type->next)) <= 0)
844 tfprintf (oFile, "\t!dw !constword\n", 0);
848 /* now generate the name */
851 if (port->use_dw_for_init)
853 tfprintf (oFile, "\t!dws\n", val->name);
857 printPointerType (oFile, val->name);
860 else if (port->use_dw_for_init)
862 tfprintf (oFile, "\t!dws\n", val->sym->rname);
866 printPointerType (oFile, val->sym->rname);
872 /*-----------------------------------------------------------------*/
873 /* printIvalCharPtr - generates initial values for character pointers */
874 /*-----------------------------------------------------------------*/
876 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
880 /* PENDING: this is _very_ mcs51 specific, including a magic
882 It's also endin specific.
884 size = getSize (type);
886 if (val->name && strlen (val->name))
888 if (size == 1) /* This appears to be Z80 specific?? */
891 "\t!dbs\n", val->name);
893 else if (size == FPTRSIZE)
895 if (port->use_dw_for_init)
897 tfprintf (oFile, "\t!dws\n", val->name);
901 printPointerType (oFile, val->name);
904 else if (size == GPTRSIZE)
907 if (IS_PTR (val->type)) {
908 type = DCL_TYPE (val->type);
910 type = PTR_TYPE (SPEC_OCLS (val->etype));
912 if (val->sym && val->sym->isstrlit) {
913 // this is a literal string
916 printGPointerType (oFile, val->name, sym->name, type);
920 fprintf (stderr, "*** internal error: unknown size in "
921 "printIvalCharPtr.\n");
926 // these are literals assigned to pointers
930 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
933 if (port->use_dw_for_init)
934 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
936 tfprintf (oFile, "\t.byte %s,%s\n",
937 aopLiteral (val, 0), aopLiteral (val, 1));
940 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
941 // non-zero mcs51 generic pointer
942 werror (E_LITERAL_GENERIC);
944 fprintf (oFile, "\t.byte %s,%s,%s\n",
947 aopLiteral (val, 2));
950 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
951 // non-zero ds390 generic pointer
952 werror (E_LITERAL_GENERIC);
954 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
958 aopLiteral (val, 3));
965 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
966 addSet (&statsg->syms, val->sym);
972 /*-----------------------------------------------------------------*/
973 /* printIvalPtr - generates initial value for pointers */
974 /*-----------------------------------------------------------------*/
976 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
982 if (ilist->type == INIT_DEEP)
983 ilist = ilist->init.deep;
985 /* function pointer */
986 if (IS_FUNC (type->next))
988 printIvalFuncPtr (type, ilist, oFile);
992 if (!(val = initPointer (ilist, type)))
995 /* if character pointer */
996 if (IS_CHAR (type->next))
997 if (printIvalCharPtr (sym, type, val, oFile))
1000 /* check the type */
1001 if (compareType (type, val->type) == 0) {
1002 werror (W_INIT_WRONG);
1003 printFromToType (val->type, type);
1006 /* if val is literal */
1007 if (IS_LITERAL (val->etype))
1009 switch (getSize (type))
1012 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1015 if (port->use_dw_for_init)
1016 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1018 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1020 case 3: // how about '390??
1021 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1022 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1028 size = getSize (type);
1030 if (size == 1) /* Z80 specific?? */
1032 tfprintf (oFile, "\t!dbs\n", val->name);
1034 else if (size == FPTRSIZE)
1036 if (port->use_dw_for_init) {
1037 tfprintf (oFile, "\t!dws\n", val->name);
1039 printPointerType (oFile, val->name);
1042 else if (size == GPTRSIZE)
1044 printGPointerType (oFile, val->name, sym->name,
1045 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1046 PTR_TYPE (SPEC_OCLS (val->etype))));
1051 /*-----------------------------------------------------------------*/
1052 /* printIval - generates code for initial value */
1053 /*-----------------------------------------------------------------*/
1055 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1060 /* update line number for error msgs */
1061 lineno=sym->lineDef;
1063 /* if structure then */
1064 if (IS_STRUCT (type))
1066 printIvalStruct (sym, type, ilist, oFile);
1070 /* if this is a pointer */
1073 printIvalPtr (sym, type, ilist, oFile);
1077 /* if this is an array */
1078 if (IS_ARRAY (type))
1080 printIvalArray (sym, type, ilist, oFile);
1084 /* if type is SPECIFIER */
1087 printIvalType (sym, type, ilist, oFile);
1092 /*-----------------------------------------------------------------*/
1093 /* emitStaticSeg - emitcode for the static segment */
1094 /*-----------------------------------------------------------------*/
1096 emitStaticSeg (memmap * map, FILE * out)
1100 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1102 /* for all variables in this segment do */
1103 for (sym = setFirstItem (map->syms); sym;
1104 sym = setNextItem (map->syms))
1107 /* if it is "extern" then do nothing */
1108 if (IS_EXTERN (sym->etype))
1111 /* if it is not static add it to the public
1113 if (!IS_STATIC (sym->etype))
1115 addSetHead (&publics, sym);
1118 /* print extra debug info if required */
1119 if (options.debug) {
1120 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1123 if (IS_STATIC (sym->etype))
1124 fprintf (out, "F%s$", moduleName); /* scope is file */
1126 fprintf (out, "G$"); /* scope is global */
1129 /* symbol is local */
1130 fprintf (out, "L%s$",
1131 (sym->localof ? sym->localof->name : "-null-"));
1132 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1135 /* if it has an absolute address */
1136 if (SPEC_ABSA (sym->etype))
1139 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1141 fprintf (out, "%s\t=\t0x%04x\n",
1143 SPEC_ADDR (sym->etype));
1148 fprintf (out, " == .\n");
1150 /* if it has an initial value */
1153 fprintf (out, "%s:\n", sym->rname);
1155 resolveIvalSym (sym->ival);
1156 printIval (sym, sym->type, sym->ival, out);
1158 // if sym->ival is a string, WE don't need it anymore
1159 if (IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1160 list2val(sym->ival)->sym->isstrlit) {
1161 freeStringSymbol(list2val(sym->ival)->sym);
1165 /* allocate space */
1166 int size = getSize (sym->type);
1169 werror(E_UNKNOWN_SIZE,sym->name);
1171 fprintf (out, "%s:\n", sym->rname);
1172 /* special case for character strings */
1173 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1174 SPEC_CVAL (sym->etype).v_char)
1176 SPEC_CVAL (sym->etype).v_char,
1177 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1179 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1185 /*-----------------------------------------------------------------*/
1186 /* emitMaps - emits the code for the data portion the code */
1187 /*-----------------------------------------------------------------*/
1192 /* no special considerations for the following
1193 data, idata & bit & xdata */
1194 emitRegularMap (data, TRUE, TRUE);
1195 emitRegularMap (idata, TRUE, TRUE);
1196 emitRegularMap (bit, TRUE, FALSE);
1197 emitRegularMap (xdata, TRUE, TRUE);
1198 if (port->genXINIT) {
1199 emitRegularMap (xidata, TRUE, TRUE);
1201 emitRegularMap (sfr, FALSE, FALSE);
1202 emitRegularMap (sfrbit, FALSE, FALSE);
1203 emitRegularMap (home, TRUE, FALSE);
1204 emitRegularMap (code, TRUE, FALSE);
1206 emitStaticSeg (statsg, code->oFile);
1207 if (port->genXINIT) {
1208 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1209 emitStaticSeg (xinit, code->oFile);
1214 /*-----------------------------------------------------------------*/
1215 /* flushStatics - flush all currently defined statics out to file */
1216 /* and delete. Temporary function */
1217 /*-----------------------------------------------------------------*/
1221 emitStaticSeg (statsg, codeOutFile);
1222 statsg->syms = NULL;
1225 /*-----------------------------------------------------------------*/
1226 /* createInterruptVect - creates the interrupt vector */
1227 /*-----------------------------------------------------------------*/
1229 createInterruptVect (FILE * vFile)
1232 mainf = newSymbol ("main", 0);
1235 /* only if the main function exists */
1236 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1238 if (!options.cc_only && !noAssemble && !options.c1mode)
1243 /* if the main is only a prototype ie. no body then do nothing */
1244 if (!IFFUNC_HASBODY(mainf->type))
1246 /* if ! compile only then main function should be present */
1247 if (!options.cc_only && !noAssemble)
1252 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1253 fprintf (vFile, "__interrupt_vect:\n");
1256 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1258 /* "generic" interrupt table header (if port doesn't specify one).
1259 * Look suspiciously like 8051 code to me...
1262 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1265 /* now for the other interrupts */
1266 for (; i < maxInterrupts; i++)
1269 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1271 fprintf (vFile, "\treti\n\t.ds\t7\n");
1278 ";--------------------------------------------------------\n"
1279 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1283 ";--------------------------------------------------------\n"};
1286 /*-----------------------------------------------------------------*/
1287 /* initialComments - puts in some initial comments */
1288 /*-----------------------------------------------------------------*/
1290 initialComments (FILE * afile)
1294 fprintf (afile, "%s", iComments1);
1295 fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1296 fprintf (afile, "%s", iComments2);
1299 /*-----------------------------------------------------------------*/
1300 /* printPublics - generates .global for publics */
1301 /*-----------------------------------------------------------------*/
1303 printPublics (FILE * afile)
1307 fprintf (afile, "%s", iComments2);
1308 fprintf (afile, "; Public variables in this module\n");
1309 fprintf (afile, "%s", iComments2);
1311 for (sym = setFirstItem (publics); sym;
1312 sym = setNextItem (publics))
1313 tfprintf (afile, "\t!global\n", sym->rname);
1316 /*-----------------------------------------------------------------*/
1317 /* printExterns - generates .global for externs */
1318 /*-----------------------------------------------------------------*/
1320 printExterns (FILE * afile)
1324 fprintf (afile, "%s", iComments2);
1325 fprintf (afile, "; Externals used\n");
1326 fprintf (afile, "%s", iComments2);
1328 for (sym = setFirstItem (externs); sym;
1329 sym = setNextItem (externs))
1330 tfprintf (afile, "\t!extern\n", sym->rname);
1333 /*-----------------------------------------------------------------*/
1334 /* emitOverlay - will emit code for the overlay stuff */
1335 /*-----------------------------------------------------------------*/
1337 emitOverlay (FILE * afile)
1341 if (!elementsInSet (ovrSetSets))
1342 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1344 /* for each of the sets in the overlay segment do */
1345 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1346 ovrset = setNextItem (ovrSetSets))
1351 if (elementsInSet (ovrset))
1353 /* output the area informtion */
1354 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1357 for (sym = setFirstItem (ovrset); sym;
1358 sym = setNextItem (ovrset))
1360 /* if extern then it is in the publics table: do nothing */
1361 if (IS_EXTERN (sym->etype))
1364 /* if allocation required check is needed
1365 then check if the symbol really requires
1366 allocation only for local variables */
1367 if (!IS_AGGREGATE (sym->type) &&
1368 !(sym->_isparm && !IS_REGPARM (sym->etype))
1369 && !sym->allocreq && sym->level)
1372 /* if global variable & not static or extern
1373 and addPublics allowed then add it to the public set */
1374 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1375 && !IS_STATIC (sym->etype))
1377 addSetHead (&publics, sym);
1380 /* if extern then do nothing or is a function
1382 if (IS_FUNC (sym->type))
1385 /* print extra debug info if required */
1388 cdbSymbol (sym, cdbFile, FALSE, FALSE);
1392 if (IS_STATIC (sym->etype))
1393 fprintf (afile, "F%s$", moduleName); /* scope is file */
1395 fprintf (afile, "G$"); /* scope is global */
1398 /* symbol is local */
1399 fprintf (afile, "L%s$",
1400 (sym->localof ? sym->localof->name : "-null-"));
1401 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1404 /* if is has an absolute address then generate
1405 an equate for this no need to allocate space */
1406 if (SPEC_ABSA (sym->etype))
1410 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1412 fprintf (afile, "%s\t=\t0x%04x\n",
1414 SPEC_ADDR (sym->etype));
1417 int size = getSize(sym->type);
1420 werror(E_UNKNOWN_SIZE,sym->name);
1423 fprintf (afile, "==.\n");
1425 /* allocate space */
1426 tfprintf (afile, "!labeldef\n", sym->rname);
1427 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1434 /*-----------------------------------------------------------------*/
1435 /* glue - the final glue that hold the whole thing together */
1436 /*-----------------------------------------------------------------*/
1442 FILE *ovrFile = tempfile ();
1444 addSetHead (&tmpfileSet, ovrFile);
1445 /* print the global struct definitions */
1447 cdbStructBlock (0, cdbFile);
1449 vFile = tempfile ();
1450 /* PENDING: this isnt the best place but it will do */
1451 if (port->general.glue_up_main)
1453 /* create the interrupt vector table */
1454 createInterruptVect (vFile);
1457 addSetHead (&tmpfileSet, vFile);
1459 /* emit code for the all the variables declared */
1461 /* do the overlay segments */
1462 emitOverlay (ovrFile);
1464 /* now put it all together into the assembler file */
1465 /* create the assembler file name */
1467 /* -o option overrides default name? */
1468 if ((noAssemble || options.c1mode) && fullDstFileName)
1470 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1474 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1475 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1478 if (!(asmFile = fopen (scratchFileName, "w")))
1480 werror (E_FILE_OPEN_ERR, scratchFileName);
1484 /* initial comments */
1485 initialComments (asmFile);
1487 /* print module name */
1488 tfprintf (asmFile, "\t!module\n", moduleName);
1489 tfprintf (asmFile, "\t!fileprelude\n");
1491 /* Let the port generate any global directives, etc. */
1492 if (port->genAssemblerPreamble)
1494 port->genAssemblerPreamble (asmFile);
1497 /* print the global variables in this module */
1498 printPublics (asmFile);
1499 if (port->assembler.externGlobal)
1500 printExterns (asmFile);
1502 /* copy the sfr segment */
1503 fprintf (asmFile, "%s", iComments2);
1504 fprintf (asmFile, "; special function registers\n");
1505 fprintf (asmFile, "%s", iComments2);
1506 copyFile (asmFile, sfr->oFile);
1508 /* copy the sbit segment */
1509 fprintf (asmFile, "%s", iComments2);
1510 fprintf (asmFile, "; special function bits \n");
1511 fprintf (asmFile, "%s", iComments2);
1512 copyFile (asmFile, sfrbit->oFile);
1514 /*JCF: Create the areas for the register banks*/
1515 if(port->general.glue_up_main &&
1516 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51))
1518 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1520 fprintf (asmFile, "%s", iComments2);
1521 fprintf (asmFile, "; overlayable register banks \n");
1522 fprintf (asmFile, "%s", iComments2);
1524 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1525 if(RegBankUsed[1]||options.parms_in_bank1)
1526 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1528 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1530 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1534 /* copy the data segment */
1535 fprintf (asmFile, "%s", iComments2);
1536 fprintf (asmFile, "; internal ram data\n");
1537 fprintf (asmFile, "%s", iComments2);
1538 copyFile (asmFile, data->oFile);
1541 /* create the overlay segments */
1543 fprintf (asmFile, "%s", iComments2);
1544 fprintf (asmFile, "; overlayable items in internal ram \n");
1545 fprintf (asmFile, "%s", iComments2);
1546 copyFile (asmFile, ovrFile);
1549 /* create the stack segment MOF */
1550 if (mainf && IFFUNC_HASBODY(mainf->type))
1552 fprintf (asmFile, "%s", iComments2);
1553 fprintf (asmFile, "; Stack segment in internal ram \n");
1554 fprintf (asmFile, "%s", iComments2);
1555 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1556 "__start__stack:\n\t.ds\t1\n\n");
1559 /* create the idata segment */
1561 fprintf (asmFile, "%s", iComments2);
1562 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1563 fprintf (asmFile, "%s", iComments2);
1564 copyFile (asmFile, idata->oFile);
1567 /* copy the bit segment */
1568 fprintf (asmFile, "%s", iComments2);
1569 fprintf (asmFile, "; bit data\n");
1570 fprintf (asmFile, "%s", iComments2);
1571 copyFile (asmFile, bit->oFile);
1573 /* if external stack then reserve space of it */
1574 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1576 fprintf (asmFile, "%s", iComments2);
1577 fprintf (asmFile, "; external stack \n");
1578 fprintf (asmFile, "%s", iComments2);
1579 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1580 fprintf (asmFile, "\t.ds 256\n");
1584 /* copy xtern ram data */
1585 fprintf (asmFile, "%s", iComments2);
1586 fprintf (asmFile, "; external ram data\n");
1587 fprintf (asmFile, "%s", iComments2);
1588 copyFile (asmFile, xdata->oFile);
1590 /* copy xternal initialized ram data */
1591 fprintf (asmFile, "%s", iComments2);
1592 fprintf (asmFile, "; external initialized ram data\n");
1593 fprintf (asmFile, "%s", iComments2);
1594 copyFile (asmFile, xidata->oFile);
1596 /* copy the interrupt vector table */
1597 if (mainf && IFFUNC_HASBODY(mainf->type))
1599 fprintf (asmFile, "%s", iComments2);
1600 fprintf (asmFile, "; interrupt vector \n");
1601 fprintf (asmFile, "%s", iComments2);
1602 copyFile (asmFile, vFile);
1605 /* copy global & static initialisations */
1606 fprintf (asmFile, "%s", iComments2);
1607 fprintf (asmFile, "; global & static initialisations\n");
1608 fprintf (asmFile, "%s", iComments2);
1610 /* Everywhere we generate a reference to the static_name area,
1611 * (which is currently only here), we immediately follow it with a
1612 * definition of the post_static_name area. This guarantees that
1613 * the post_static_name area will immediately follow the static_name
1616 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1617 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1618 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1620 if (mainf && IFFUNC_HASBODY(mainf->type))
1622 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1623 /* if external stack is specified then the
1624 higher order byte of the xdatalocation is
1625 going into P2 and the lower order going into
1627 if (options.useXstack)
1629 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1630 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1631 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1632 (unsigned int) options.xdata_loc & 0xff);
1635 /* initialise the stack pointer. JCF: aslink takes care of the location */
1636 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1638 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1639 fprintf (asmFile, "\tmov\ta,dpl\n");
1640 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1641 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1642 fprintf (asmFile, "__sdcc_init_data:\n");
1644 // if the port can copy the XINIT segment to XISEG
1645 if (port->genXINIT) {
1646 port->genXINIT(asmFile);
1650 copyFile (asmFile, statsg->oFile);
1652 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1654 /* This code is generated in the post-static area.
1655 * This area is guaranteed to follow the static area
1656 * by the ugly shucking and jiving about 20 lines ago.
1658 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1659 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1665 "%s", iComments2, iComments2);
1666 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1667 copyFile (asmFile, home->oFile);
1669 /* copy over code */
1670 fprintf (asmFile, "%s", iComments2);
1671 fprintf (asmFile, "; code\n");
1672 fprintf (asmFile, "%s", iComments2);
1673 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1674 if (mainf && IFFUNC_HASBODY(mainf->type))
1677 /* entry point @ start of CSEG */
1678 fprintf (asmFile, "__sdcc_program_startup:\n");
1680 /* put in the call to main */
1681 fprintf (asmFile, "\tlcall\t_main\n");
1682 if (options.mainreturn)
1685 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1686 fprintf (asmFile, "\tret\n");
1692 fprintf (asmFile, ";\treturn from main will lock up\n");
1693 fprintf (asmFile, "\tsjmp .\n");
1696 copyFile (asmFile, code->oFile);
1698 if (port->genAssemblerEnd) {
1699 port->genAssemblerEnd(asmFile);
1706 /** Creates a temporary file name a'la tmpnam which avoids the bugs
1707 in cygwin wrt c:\tmp.
1708 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1713 const char *tmpdir = NULL;
1715 tmpdir = getenv ("TMP");
1716 else if (getenv ("TEMP"))
1717 tmpdir = getenv ("TEMP");
1718 else if (getenv ("TMPDIR"))
1719 tmpdir = getenv ("TMPDIR");
1722 char *name = tempnam (tmpdir, "sdcc");
1728 return tmpnam (NULL);
1731 /** Creates a temporary file a'la tmpfile which avoids the bugs
1732 in cygwin wrt c:\tmp.
1733 Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1738 const char *tmpdir = NULL;
1740 tmpdir = getenv ("TMP");
1741 else if (getenv ("TEMP"))
1742 tmpdir = getenv ("TEMP");
1743 else if (getenv ("TMPDIR"))
1744 tmpdir = getenv ("TMPDIR");
1747 char *name = Safe_strdup( tempnam (tmpdir, "sdcc"));
1750 FILE *fp = fopen (name, "w+b");
1753 addSetHead (&tmpfileNameSet, name);