Added print Allocation info will print
[fw/sdcc] / src / SDCCglue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.                 
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5                 
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
9    later version.
10    
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.
15    
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.
19    
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 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include "asm.h"
27 #include <time.h>
28
29 symbol *interrupts[256];
30 /*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
31 void printIval (symbol *, link *, initList *, FILE *);
32 extern int noAlloc;
33 set *publics = NULL;            /* public variables */
34 set *externs = NULL;            /* Varibles that are declared as extern */
35
36 /* TODO: this should be configurable (DS803C90 uses more than 6) */
37 int maxInterrupts = 6;
38 int allocInfo = 1;
39 extern int maxRegBank ;
40 symbol *mainf;
41 extern char *VersionString;
42 extern FILE *codeOutFile;
43 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
44 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
45 /*-----------------------------------------------------------------*/
46 /* closeTmpFiles - closes all tmp files created by the compiler    */
47 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
48 /*-----------------------------------------------------------------*/
49 DEFSETFUNC(closeTmpFiles)
50 {
51     FILE *tfile = item;
52
53     if (tfile)
54         fclose(tfile);
55     
56     return 0;
57 }
58
59 /*-----------------------------------------------------------------*/
60 /* rmTmpFiles - closes all tmp files created by the compiler    */
61 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
62 /*-----------------------------------------------------------------*/
63 DEFSETFUNC(rmTmpFiles)
64 {
65     char *name = item;
66
67     if (name) {
68         unlink(name);
69         free(name);
70     }
71     return 0;
72 }
73
74 /*-----------------------------------------------------------------*/
75 /* copyFile - copies source file to destination file               */
76 /*-----------------------------------------------------------------*/
77 void copyFile (FILE * dest, FILE * src)
78 {
79     int ch;
80     
81     rewind (src);
82     while (!feof (src))
83         if ((ch = fgetc (src)) != EOF)
84             fputc (ch, dest);
85 }
86
87 char *aopLiteralLong(value *val, int offset, int size)
88 {
89     char *rs;
90     union {
91         float f;
92         unsigned char c[4];
93     } fl;
94
95     /* if it is a float then it gets tricky */
96     /* otherwise it is fairly simple */
97     if (!IS_FLOAT(val->type)) {
98         unsigned long v = floatFromVal(val);
99
100         v >>= (offset * 8);
101         switch (size) {
102         case 1:
103             tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
104             break;
105         case 2:
106             tsprintf(buffer, "!immedword", (unsigned int)v & 0xffff);
107             break;
108         default:
109             /* Hmm.  Too big for now. */
110             assert(0);
111         }
112         ALLOC_ATOMIC(rs,strlen(buffer)+1);
113         return strcpy (rs,buffer);
114     }
115
116     /* PENDING: For now size must be 1 */
117     assert(size == 1);
118
119     /* it is type float */
120     fl.f = (float) floatFromVal(val);
121 #ifdef _BIG_ENDIAN
122     tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
123 #else
124     tsprintf(buffer, "!immedbyte", fl.c[offset]);
125 #endif
126     ALLOC_ATOMIC(rs,strlen(buffer)+1);
127     return strcpy (rs,buffer);
128 }
129
130 /*-----------------------------------------------------------------*/
131 /* aopLiteral - string from a literal value                        */
132 /*-----------------------------------------------------------------*/
133 char *aopLiteral (value *val, int offset)
134 {
135     return aopLiteralLong(val, offset, 1);
136 }
137
138 /*-----------------------------------------------------------------*/
139 /* emitRegularMap - emit code for maps with no special cases       */
140 /*-----------------------------------------------------------------*/
141 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
142 {
143     symbol *sym;
144     
145     if (addPublics) {
146         /* PENDING: special case here - should remove */
147         if (!strcmp(map->sname, DATA_NAME))
148             tfprintf(map->oFile, "\t!areadata\n", map->sname);
149         else
150             tfprintf(map->oFile, "\t!area\n", map->sname);
151     }
152     
153     /* print the area name */
154     for (sym = setFirstItem (map->syms); sym;
155          sym = setNextItem (map->syms))  {
156         
157         /* if extern then add it into the extern list */
158         if (IS_EXTERN (sym->etype)) {
159             addSetHead (&externs, sym);
160             continue;
161         }
162         
163         /* if allocation required check is needed
164            then check if the symbol really requires
165            allocation only for local variables */
166         if (arFlag && !IS_AGGREGATE(sym->type) &&
167             !(sym->_isparm && !IS_REGPARM(sym->etype)) && 
168               !sym->allocreq && sym->level)
169             continue ;
170         
171         /* if global variable & not static or extern 
172            and addPublics allowed then add it to the public set */
173         if ((sym->level == 0 || 
174              (sym->_isparm && !IS_REGPARM(sym->etype))) &&
175             addPublics &&
176             !IS_STATIC (sym->etype))
177             addSetHead (&publics, sym);
178         
179         /* if extern then do nothing or is a function 
180            then do nothing */
181         if (IS_FUNC (sym->type))
182             continue;
183         
184         /* print extra debug info if required */
185         if ((options.debug || sym->level == 0) && !options.nodebug) {
186
187             cdbSymbol(sym,cdbFile,FALSE,FALSE);
188
189             if (!sym->level) /* global */
190                 if (IS_STATIC(sym->etype))
191                     fprintf(map->oFile,"F%s$",moduleName); /* scope is file */
192                 else
193                     fprintf(map->oFile,"G$"); /* scope is global */
194             else
195                 /* symbol is local */
196                 fprintf(map->oFile,"L%s$",(sym->localof ? sym->localof->name : "-null-"));
197             fprintf(map->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
198         }
199
200         /* if is has an absolute address then generate
201            an equate for this no need to allocate space */
202         if (SPEC_ABSA (sym->etype)) {
203             if ((options.debug || sym->level == 0) && !options.nodebug)
204                 fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));         
205
206             fprintf (map->oFile, "%s\t=\t0x%04x\n",
207                      sym->rname,
208                      SPEC_ADDR (sym->etype));
209         }
210         else {
211             /* allocate space */
212             if ((options.debug || sym->level == 0) && !options.nodebug)
213                 fprintf(map->oFile,"==.\n");
214             if (IS_STATIC(sym->etype))
215                 tfprintf(map->oFile, "!slabeldef\n", sym->rname);
216             else
217                 tfprintf(map->oFile, "!labeldef\n", sym->rname);
218             tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
219         }
220         
221         /* if it has a initial value then do it only if
222            it is a global variable */
223         if (sym->ival && sym->level == 0) {
224             ast *ival = NULL;
225             
226             if (IS_AGGREGATE (sym->type))
227                 ival = initAggregates (sym, sym->ival, NULL);
228             else
229                 ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
230                                 decorateType (resolveSymbols (list2expr (sym->ival))));
231             codeOutFile = statsg->oFile;
232             allocInfo = 0;
233             eBBlockFromiCode (iCodeFromAst (ival));
234             allocInfo = 1;
235             sym->ival = NULL;
236         }
237     }
238 }
239
240
241 /*-----------------------------------------------------------------*/
242 /* initPointer - pointer initialization code massaging             */
243 /*-----------------------------------------------------------------*/
244 value *initPointer (initList *ilist)
245 {
246     value *val;
247     ast *expr = list2expr(ilist);
248
249     if (!expr) 
250         goto wrong;             
251         
252     /* try it the oldway first */
253     if ((val = constExprValue(expr,FALSE)))
254         return val;
255
256     /* no then we have to do these cludgy checks */
257     /* pointers can be initialized with address of
258        a variable or address of an array element */
259     if (IS_AST_OP(expr) && expr->opval.op == '&') {
260         /* address of symbol */
261         if (IS_AST_SYM_VALUE(expr->left)) {
262             val = copyValue(AST_VALUE(expr->left));
263             val->type = newLink();
264             if (SPEC_SCLS(expr->left->etype) == S_CODE) {
265                 DCL_TYPE(val->type) = CPOINTER ;
266                 DCL_PTR_CONST(val->type) = port->mem.code_ro;
267             }
268             else
269                 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
270                     DCL_TYPE(val->type) = FPOINTER;
271                 else
272                     if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
273                         DCL_TYPE(val->type) = PPOINTER ;
274                     else
275                         if (SPEC_SCLS(expr->left->etype) == S_IDATA)
276                             DCL_TYPE(val->type) = IPOINTER ;
277                         else
278                             if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
279                                 DCL_TYPE(val->type) = EEPPOINTER ;
280                             else
281                                 DCL_TYPE(val->type) = POINTER ;
282             val->type->next = expr->left->ftype;
283             val->etype = getSpec(val->type);
284             return val;
285         }
286
287         /* if address of indexed array */
288         if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
289             return valForArray(expr->left);     
290
291         /* if address of structure element then 
292            case 1. a.b ; */
293         if (IS_AST_OP(expr->left) && 
294             expr->left->opval.op == '.' ) {
295                 return valForStructElem(expr->left->left,
296                                         expr->left->right);
297         }
298
299         /* case 2. (&a)->b ; 
300            (&some_struct)->element */
301         if (IS_AST_OP(expr->left) &&
302             expr->left->opval.op == PTR_OP &&
303             IS_ADDRESS_OF_OP(expr->left->left))
304                 return valForStructElem(expr->left->left->left,
305                                         expr->left->right);
306
307     }
308     /* case 3. (((char *) &a) +/- constant) */
309     if (IS_AST_OP(expr) && 
310         (expr->opval.op == '+' || expr->opval.op == '-') &&
311         IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
312         IS_AST_OP(expr->left->right) && 
313         expr->left->right->opval.op == '&' &&
314         IS_AST_LIT_VALUE(expr->right)) {
315         
316         return valForCastAggr(expr->left->right->left,
317                               expr->left->left->opval.lnk,
318                               expr->right,expr->opval.op);
319         
320     }
321
322  wrong:    
323     werror(E_INIT_WRONG);
324     return NULL;
325     
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* printChar - formats and prints a characater string with DB      */
330 /*-----------------------------------------------------------------*/
331 void printChar (FILE * ofile, char *s, int plen)
332 {
333     int i;
334     int len = strlen (s);
335     int pplen = 0;
336     char buf[100];
337     char *p = buf;
338
339     while (len && pplen < plen) {
340         i = 60;
341         while (i && *s && pplen < plen) {
342             if (*s < ' ' || *s == '\"') {
343                 *p = '\0';
344                 if (p != buf) 
345                     tfprintf(ofile, "\t!ascii\n", buf);
346                 tfprintf(ofile, "\t!db\n", *s);
347                 p = buf;
348             }
349             else {
350                 *p = *s;
351                 p++;
352             }
353             s++;
354             pplen++;
355             i--;
356         }
357         if (p != buf) {
358             *p = '\0';
359             tfprintf(ofile, "\t!ascii\n", buf);
360         }
361         
362         if (len > 60)
363             len -= 60;
364         else
365             len = 0;
366     }
367     tfprintf(ofile, "\t!db\n", 0);
368 }
369
370 /*-----------------------------------------------------------------*/
371 /* printIvalType - generates ival for int/char                     */
372 /*-----------------------------------------------------------------*/
373 void printIvalType (link * type, initList * ilist, FILE * oFile)
374 {
375     value *val;
376     
377     /* if initList is deep */
378     if (ilist->type == INIT_DEEP)
379         ilist = ilist->init.deep;
380     
381     val = list2val (ilist);
382     switch (getSize (type)) {
383     case 1:
384         if (!val)
385             tfprintf(oFile, "\t!db\n", 0);
386         else
387             tfprintf(oFile, "\t!dbs\n",
388                      aopLiteral (val, 0));
389         break;
390
391     case 2:
392         fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
393         break;
394     case 4:
395         if (!val) {
396             tfprintf (oFile, "\t!dw\n", 0);
397             tfprintf (oFile, "\t!dw\n", 0);
398         }
399         else {
400             fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
401                      aopLiteral (val, 0), aopLiteral (val, 1),
402                      aopLiteral (val, 2), aopLiteral (val, 3));
403         }
404         break;
405     }
406 }
407
408 /*-----------------------------------------------------------------*/
409 /* printIvalStruct - generates initial value for structures        */
410 /*-----------------------------------------------------------------*/
411 void printIvalStruct (symbol * sym,link * type,
412                       initList * ilist, FILE * oFile)
413 {
414     symbol *sflds;
415     initList *iloop;
416     
417     sflds = SPEC_STRUCT (type)->fields;
418     if (ilist->type != INIT_DEEP) {
419         werror (E_INIT_STRUCT, sym->name);
420         return;
421     }
422     
423     iloop = ilist->init.deep;
424     
425     for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
426         printIval (sflds, sflds->type, iloop, oFile);
427     
428     return;
429 }
430
431 /*-----------------------------------------------------------------*/
432 /* printIvalChar - generates initital value for character array    */
433 /*-----------------------------------------------------------------*/
434 int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
435 {
436     value *val;
437     int remain;
438     
439     if (!s) {
440         
441         val = list2val (ilist);
442         /* if the value is a character string  */
443         if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
444             if (!DCL_ELEM (type))
445                 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
446             
447             /* if size mismatch  */
448 /*          if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
449 /*              werror (E_ARRAY_BOUND); */
450             
451             printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
452             
453             if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
454                 while (remain--)
455                     tfprintf (oFile, "\t!db\n", 0);
456             
457             return 1;
458         }
459         else
460             return 0;
461     }
462     else
463         printChar (oFile, s,strlen(s)+1);
464     return 1;
465 }
466
467 /*-----------------------------------------------------------------*/
468 /* printIvalArray - generates code for array initialization        */
469 /*-----------------------------------------------------------------*/
470 void printIvalArray (symbol * sym, link * type, initList * ilist,
471                      FILE * oFile)
472 {
473     initList *iloop;
474     int lcnt = 0, size = 0;
475     
476     /* take care of the special   case  */
477     /* array of characters can be init  */
478     /* by a string                      */
479     if (IS_CHAR (type->next))
480         if (printIvalChar (type,
481                            (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
482                            oFile, SPEC_CVAL (sym->etype).v_char))
483             return;
484     
485     /* not the special case             */
486     if (ilist->type != INIT_DEEP) {
487         werror (E_INIT_STRUCT, sym->name);
488         return;
489     }
490     
491     iloop = ilist->init.deep;
492     lcnt = DCL_ELEM (type);
493     
494     for (;;) {
495         size++;
496         printIval (sym, type->next, iloop, oFile);
497         iloop = (iloop ? iloop->next : NULL);
498         
499         
500         /* if not array limits given & we */
501         /* are out of initialisers then   */
502         if (!DCL_ELEM (type) && !iloop)
503             break;
504         
505         /* no of elements given and we    */
506         /* have generated for all of them */
507         if (!--lcnt)
508             break;
509     }
510     
511     /* if we have not been given a size  */
512     if (!DCL_ELEM (type))
513         DCL_ELEM (type) = size;
514     
515     return;
516 }
517
518 /*-----------------------------------------------------------------*/
519 /* printIvalFuncPtr - generate initial value for function pointers */
520 /*-----------------------------------------------------------------*/
521 void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
522 {
523     value *val;
524     int dLvl = 0;
525     
526     val = list2val (ilist);
527     /* check the types   */
528     if ((dLvl = checkType (val->type, type->next)) <= 0) {
529         tfprintf(oFile, "\t!dw\n", 0);
530         return;
531     }
532     
533     /* now generate the name */
534     if (!val->sym) {
535         if (port->use_dw_for_init)
536             tfprintf(oFile, "\t!dw %s\n", val->name);
537         else  
538             fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name,val->name);
539     }
540     else
541         if (port->use_dw_for_init)
542             tfprintf(oFile, "\t!dws\n", val->sym->rname);
543         else 
544             fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->sym->rname,val->sym->rname);
545     
546     return;
547 }
548
549 /*-----------------------------------------------------------------*/
550 /* printIvalCharPtr - generates initial values for character pointers */
551 /*-----------------------------------------------------------------*/
552 int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
553 {
554     int size = 0;
555     
556     /* PENDING: this is _very_ mcs51 specific, including a magic
557        number... 
558        It's also endin specific.
559     */
560     size = getSize (type);
561
562     if (val->name && strlen(val->name)) {
563         switch (size) {
564         case 1:
565             tfprintf(oFile,
566                     "\t!dbs\n", val->name) ;
567             break;
568         case 2:
569             if (port->use_dw_for_init)
570                 tfprintf(oFile, "\t!dws\n", val->name);
571             else
572                 fprintf(oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
573             break;
574             /* PENDING: probably just 3 */
575         default:
576             /* PENDING: 0x02 or 0x%02x, CDATA? */
577             fprintf (oFile,
578                      "\t.byte %s,(%s >> 8),#0x%02x\n",
579                      val->name, val->name, (IS_PTR(val->type) ? DCL_TYPE(val->type) :
580                                             PTR_TYPE(SPEC_OCLS(val->etype))));
581         }
582     }
583     else {
584         switch (size) {
585         case 1:
586             tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
587             break;
588         case 2:
589             tfprintf(oFile, "\t.byte %s,%s\n", 
590                     aopLiteral(val, 0),aopLiteral(val, 1));
591             break;
592         case 3:
593             /* PENDING: 0x02 or 0x%02x, CDATA? */
594             fprintf(oFile, "\t.byte %s,%s,#0x02\n",
595                     aopLiteral (val, 0), aopLiteral (val, 1));
596             break;
597         default:
598             assert(0);
599         }
600     }
601
602
603     if (val->sym && val->sym->isstrlit)
604         addSet (&statsg->syms, val->sym);
605     
606     return 1;
607 }
608
609 /*-----------------------------------------------------------------*/
610 /* printIvalPtr - generates initial value for pointers             */
611 /*-----------------------------------------------------------------*/
612 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
613 {
614     value *val;
615     
616     /* if deep then   */
617     if (ilist->type == INIT_DEEP)
618         ilist = ilist->init.deep;
619     
620     /* function pointer     */
621     if (IS_FUNC (type->next)) {
622         printIvalFuncPtr (type, ilist, oFile);
623         return;
624     }
625     
626     if (!(val = initPointer (ilist)))
627         return ;
628
629     /* if character pointer */
630     if (IS_CHAR (type->next))
631         if (printIvalCharPtr (sym, type, val, oFile))
632             return;
633     
634     /* check the type      */
635     if (checkType (type, val->type) != 1)
636         werror (E_INIT_WRONG);
637     
638     /* if val is literal */
639     if (IS_LITERAL (val->etype)) {
640         switch (getSize (type)) {
641         case 1:
642             tfprintf(oFile, "\t!db\n", (unsigned int)floatFromVal(val) & 0xff);
643             break;
644         case 2:
645             tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
646             break;
647         case 3:
648             fprintf (oFile, "\t.byte %s,%s,#0x02\n",
649                      aopLiteral (val, 0), aopLiteral (val, 1));
650         }
651         return;
652     }
653     
654     
655     switch (getSize (type)) {
656     case 1:
657         tfprintf (oFile, "\t!dbs\n", val->name);
658         break;
659     case 2:
660         tfprintf (oFile, "\t!dws\n", val->name);
661         break;
662         
663     case 3:
664         fprintf (oFile, "\t.byte %s,(%s >> 8),#0x%02x\n",
665                  val->name, val->name,(IS_PTR(val->type) ? DCL_TYPE(val->type) :
666                                             PTR_TYPE(SPEC_OCLS(val->etype))));
667     }
668     return;
669 }
670
671 /*-----------------------------------------------------------------*/
672 /* printIval - generates code for initial value                    */
673 /*-----------------------------------------------------------------*/
674 void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
675 {
676     if (!ilist)
677         return;    
678     
679     /* if structure then    */
680     if (IS_STRUCT (type)) {
681         printIvalStruct (sym, type, ilist, oFile);
682         return;
683     }
684     
685     /* if this is a pointer */
686     if (IS_PTR (type)) {
687         printIvalPtr (sym, type, ilist, oFile);
688         return;
689     }
690     
691     /* if this is an array   */
692     if (IS_ARRAY (type)) {
693         printIvalArray (sym, type, ilist, oFile);
694         return;
695     }
696     
697     /* if type is SPECIFIER */
698     if (IS_SPEC (type)) {
699         printIvalType (type, ilist, oFile);
700         return;
701     }
702 }
703
704 /*-----------------------------------------------------------------*/
705 /* emitStaticSeg - emitcode for the static segment                 */
706 /*-----------------------------------------------------------------*/
707 void emitStaticSeg (memmap * map)
708 {
709     symbol *sym;
710     
711     /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
712     
713     
714     /* for all variables in this segment do */
715     for (sym = setFirstItem (map->syms); sym;
716          sym = setNextItem (map->syms)) {
717         
718         /* if it is "extern" then do nothing */
719         if (IS_EXTERN (sym->etype))
720             continue;
721         
722         /* if it is not static add it to the public
723            table */
724         if (!IS_STATIC (sym->etype))
725             addSetHead (&publics, sym);
726
727         /* print extra debug info if required */
728         if ((options.debug || sym->level == 0) && !options.nodebug) {
729
730             cdbSymbol(sym,cdbFile,FALSE,FALSE);
731
732             if (!sym->level) { /* global */
733                 if (IS_STATIC(sym->etype))
734                     fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
735                 else
736                     fprintf(code->oFile,"G$"); /* scope is global */
737             }
738             else
739                 /* symbol is local */
740                 fprintf(code->oFile,"L%s$",
741                         (sym->localof ? sym->localof->name : "-null-"));
742             fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
743         }
744         
745         /* if it has an absolute address */
746         if (SPEC_ABSA (sym->etype)) {
747             if ((options.debug || sym->level == 0) && !options.nodebug)
748                 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
749
750             fprintf (code->oFile, "%s\t=\t0x%04x\n",
751                      sym->rname,
752                      SPEC_ADDR (sym->etype));
753         }
754         else {
755             if ((options.debug || sym->level == 0) && !options.nodebug)
756                 fprintf(code->oFile," == .\n"); 
757
758             /* if it has an initial value */
759             if (sym->ival) {
760                 fprintf (code->oFile, "%s:\n", sym->rname);
761                 noAlloc++;
762                 resolveIvalSym (sym->ival);
763                 printIval (sym, sym->type, sym->ival, code->oFile);
764                 noAlloc--;
765             }
766             else {
767                 /* allocate space */
768                 fprintf (code->oFile, "%s:\n", sym->rname);
769                 /* special case for character strings */
770                 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
771                     SPEC_CVAL (sym->etype).v_char)
772                     printChar (code->oFile,
773                                SPEC_CVAL (sym->etype).v_char,
774                                strlen(SPEC_CVAL (sym->etype).v_char)+1);
775                 else 
776                     tfprintf(code->oFile, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
777             }
778         }
779     }
780 }
781
782 /*-----------------------------------------------------------------*/
783 /* emitMaps - emits the code for the data portion the code         */
784 /*-----------------------------------------------------------------*/
785 void emitMaps ()
786 {
787     /* no special considerations for the following
788        data, idata & bit & xdata */
789     emitRegularMap (data, TRUE, TRUE);
790     emitRegularMap (idata, TRUE,TRUE);
791     emitRegularMap (bit, TRUE,FALSE);
792     emitRegularMap (xdata, TRUE,TRUE);
793     emitRegularMap (sfr, FALSE,FALSE);
794     emitRegularMap (sfrbit, FALSE,FALSE);
795     emitRegularMap (code, TRUE,FALSE);
796     emitStaticSeg (statsg);
797 }
798
799 /*-----------------------------------------------------------------*/
800 /* createInterruptVect - creates the interrupt vector              */
801 /*-----------------------------------------------------------------*/
802 void createInterruptVect (FILE * vFile)
803 {
804     int i = 0;
805     mainf = newSymbol ("main", 0);
806     mainf->block = 0;
807     
808     /* only if the main function exists */
809     if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
810         if (!options.cc_only)
811             werror(E_NO_MAIN);
812         return;
813     }
814     
815     /* if the main is only a prototype ie. no body then do nothing */
816     if (!mainf->fbody) {
817         /* if ! compile only then main function should be present */
818         if (!options.cc_only)
819             werror(E_NO_MAIN);
820         return;
821     }
822     
823     tfprintf(vFile, "\t!areacode\n", CODE_NAME);
824     fprintf (vFile, "__interrupt_vect:\n");
825
826     
827     if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
828     {
829         /* "generic" interrupt table header (if port doesn't specify one).
830          *
831          * Look suspiciously like 8051 code to me...
832          */
833     
834         fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
835     
836     
837         /* now for the other interrupts */
838         for (; i < maxInterrupts; i++) {
839                 if (interrupts[i])
840                         fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
841                 else
842                         fprintf (vFile, "\treti\n\t.ds\t7\n");
843         }
844     }
845 }
846
847 char *iComments1 =
848 {
849     ";--------------------------------------------------------\n"
850     "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
851
852 char *iComments2 =
853 {
854     ";--------------------------------------------------------\n"};
855
856
857 /*-----------------------------------------------------------------*/
858 /* initialComments - puts in some initial comments                 */
859 /*-----------------------------------------------------------------*/
860 void initialComments (FILE * afile)
861 {
862     time_t t;
863     time(&t);
864     fprintf (afile, "%s", iComments1);
865     fprintf (afile, "; Version %s %s\n", VersionString,asctime(localtime(&t)));
866     fprintf (afile, "%s", iComments2);
867 }
868
869 /*-----------------------------------------------------------------*/
870 /* printPublics - generates .global for publics                    */
871 /*-----------------------------------------------------------------*/
872 void printPublics (FILE * afile)
873 {
874     symbol *sym;
875     
876     fprintf (afile, "%s", iComments2);
877     fprintf (afile, "; Public variables in this module\n");
878     fprintf (afile, "%s", iComments2);
879     
880     for (sym = setFirstItem (publics); sym;
881          sym = setNextItem (publics))
882         tfprintf(afile, "\t!global\n", sym->rname);
883 }
884
885 /*-----------------------------------------------------------------*/
886 /* printExterns - generates .global for externs                    */
887 /*-----------------------------------------------------------------*/
888 void printExterns (FILE * afile)
889 {
890     symbol *sym;
891     
892     fprintf (afile, "%s", iComments2);
893     fprintf (afile, "; Externals used\n");
894     fprintf (afile, "%s", iComments2);
895     
896     for (sym = setFirstItem (externs); sym;
897          sym = setNextItem (externs))
898         tfprintf(afile, "\t!global\n", sym->rname);
899 }
900
901 /*-----------------------------------------------------------------*/
902 /* emitOverlay - will emit code for the overlay stuff              */
903 /*-----------------------------------------------------------------*/
904 static void emitOverlay(FILE *afile)
905 {
906     set *ovrset;
907     
908     if (!elementsInSet(ovrSetSets))
909         tfprintf(afile,"\t!area\n", port->mem.overlay_name);
910
911     /* for each of the sets in the overlay segment do */
912     for (ovrset = setFirstItem(ovrSetSets); ovrset;
913          ovrset = setNextItem(ovrSetSets)) {
914
915         symbol *sym ;
916
917         if (elementsInSet(ovrset)) {
918             /* this dummy area is used to fool the assembler
919                otherwise the assembler will append each of these
920                declarations into one chunk and will not overlay 
921                sad but true */
922             fprintf(afile,"\t.area _DUMMY\n");
923             /* output the area informtion */
924             fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
925         }
926         
927         for (sym = setFirstItem(ovrset); sym;
928              sym = setNextItem(ovrset)) {
929
930             /* if extern then add it to the publics tabledo nothing */
931             if (IS_EXTERN (sym->etype))
932                 continue;
933             
934             /* if allocation required check is needed
935                then check if the symbol really requires
936                allocation only for local variables */
937             if (!IS_AGGREGATE(sym->type) &&
938                 !(sym->_isparm && !IS_REGPARM(sym->etype))
939                 && !sym->allocreq && sym->level)
940                 continue ;
941             
942             /* if global variable & not static or extern 
943                and addPublics allowed then add it to the public set */
944             if ((sym->_isparm && !IS_REGPARM(sym->etype))
945                 && !IS_STATIC (sym->etype))
946                 addSetHead (&publics, sym);
947             
948             /* if extern then do nothing or is a function 
949                then do nothing */
950             if (IS_FUNC (sym->type))
951                 continue;
952
953             /* print extra debug info if required */
954             if ((options.debug || sym->level == 0) && !options.nodebug) {
955                 
956                 cdbSymbol(sym,cdbFile,FALSE,FALSE);
957                 
958                 if (!sym->level) { /* global */
959                     if (IS_STATIC(sym->etype))
960                         fprintf(afile,"F%s$",moduleName); /* scope is file */
961                     else
962                         fprintf(afile,"G$"); /* scope is global */
963                 }
964                 else
965                     /* symbol is local */
966                     fprintf(afile,"L%s$",
967                             (sym->localof ? sym->localof->name : "-null-"));
968                 fprintf(afile,"%s$%d$%d",sym->name,sym->level,sym->block);
969             }
970             
971             /* if is has an absolute address then generate
972                an equate for this no need to allocate space */
973             if (SPEC_ABSA (sym->etype)) {
974                 
975                 if ((options.debug || sym->level == 0) && !options.nodebug)
976                     fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));          
977
978                 fprintf (afile, "%s\t=\t0x%04x\n",
979                          sym->rname,
980                          SPEC_ADDR (sym->etype));
981             }
982             else {
983                 if ((options.debug || sym->level == 0) && !options.nodebug)
984                     fprintf(afile,"==.\n");
985         
986                 /* allocate space */
987                 tfprintf(afile, "!labeldef\n", sym->rname);
988                 tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
989             }
990             
991         }
992     }
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* glue - the final glue that hold the whole thing together        */
997 /*-----------------------------------------------------------------*/
998 void glue ()
999 {
1000     FILE *vFile;
1001     FILE *asmFile;
1002     FILE *ovrFile = tempfile();
1003     
1004     addSetHead(&tmpfileSet,ovrFile);
1005     /* print the global struct definitions */
1006     if (options.debug)
1007         cdbStructBlock (0,cdbFile);
1008
1009     vFile = tempfile();
1010     /* PENDING: this isnt the best place but it will do */
1011     if (port->general.glue_up_main) {
1012         /* create the interrupt vector table */
1013         createInterruptVect (vFile);
1014     }
1015
1016     addSetHead(&tmpfileSet,vFile);
1017     
1018     /* emit code for the all the variables declared */
1019     emitMaps ();
1020     /* do the overlay segments */
1021     emitOverlay(ovrFile);
1022
1023     /* now put it all together into the assembler file */
1024     /* create the assembler file name */
1025     
1026     if (!options.c1mode) {
1027         sprintf (buffer, srcFileName);
1028         strcat (buffer, ".asm");
1029     }
1030     else {
1031         strcpy(buffer, options.out_name);
1032     }
1033
1034     if (!(asmFile = fopen (buffer, "w"))) {
1035         werror (E_FILE_OPEN_ERR, buffer);
1036         exit (1);
1037     }
1038     
1039     /* initial comments */
1040     initialComments (asmFile);
1041     
1042     /* print module name */
1043     tfprintf(asmFile, "\t!module\n", moduleName);
1044     tfprintf(asmFile, "\t!fileprelude\n");
1045
1046     /* Let the port generate any global directives, etc. */
1047     if (port->genAssemblerPreamble)
1048     {
1049         port->genAssemblerPreamble(asmFile);
1050     }
1051     
1052     /* print the global variables in this module */
1053     printPublics (asmFile);
1054     if (port->assembler.externGlobal)
1055         printExterns (asmFile);
1056
1057     /* copy the sfr segment */
1058     fprintf (asmFile, "%s", iComments2);
1059     fprintf (asmFile, "; special function registers\n");
1060     fprintf (asmFile, "%s", iComments2);
1061     copyFile (asmFile, sfr->oFile);
1062     
1063     /* copy the sbit segment */
1064     fprintf (asmFile, "%s", iComments2);
1065     fprintf (asmFile, "; special function bits \n");
1066     fprintf (asmFile, "%s", iComments2);
1067     copyFile (asmFile, sfrbit->oFile);
1068     
1069     /* copy the data segment */
1070     fprintf (asmFile, "%s", iComments2);
1071     fprintf (asmFile, "; internal ram data\n");
1072     fprintf (asmFile, "%s", iComments2);
1073     copyFile (asmFile, data->oFile);
1074
1075
1076     /* create the overlay segments */
1077     fprintf (asmFile, "%s", iComments2);
1078     fprintf (asmFile, "; overlayable items in internal ram \n");
1079     fprintf (asmFile, "%s", iComments2);    
1080     copyFile (asmFile, ovrFile);
1081
1082     /* create the stack segment MOF */
1083     if (mainf && mainf->fbody) {
1084         fprintf (asmFile, "%s", iComments2);
1085         fprintf (asmFile, "; Stack segment in internal ram \n");
1086         fprintf (asmFile, "%s", iComments2);
1087         fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1088                  "__start__stack:\n\t.ds\t1\n\n");
1089     }
1090
1091     /* create the idata segment */
1092     fprintf (asmFile, "%s", iComments2);
1093     fprintf (asmFile, "; indirectly addressable internal ram data\n");
1094     fprintf (asmFile, "%s", iComments2);
1095     copyFile (asmFile, idata->oFile);
1096     
1097     /* copy the bit segment */
1098     fprintf (asmFile, "%s", iComments2);
1099     fprintf (asmFile, "; bit data\n");
1100     fprintf (asmFile, "%s", iComments2);
1101     copyFile (asmFile, bit->oFile);
1102
1103     /* if external stack then reserve space of it */
1104     if (mainf && mainf->fbody && options.useXstack ) {
1105         fprintf (asmFile, "%s", iComments2);
1106         fprintf (asmFile, "; external stack \n");
1107         fprintf (asmFile, "%s", iComments2);
1108         fprintf (asmFile,"\t.area XSEG (XDATA)\n"); /* MOF */
1109         fprintf (asmFile,"\t.ds 256\n");
1110     }
1111         
1112         
1113     /* copy xtern ram data */
1114     fprintf (asmFile, "%s", iComments2);
1115     fprintf (asmFile, "; external ram data\n");
1116     fprintf (asmFile, "%s", iComments2);
1117     copyFile (asmFile, xdata->oFile);
1118     
1119     /* copy the interrupt vector table */
1120     if (mainf && mainf->fbody) {
1121         fprintf (asmFile, "%s", iComments2);
1122         fprintf (asmFile, "; interrupt vector \n");
1123         fprintf (asmFile, "%s", iComments2);
1124         copyFile (asmFile, vFile);
1125     }
1126     
1127     /* copy global & static initialisations */
1128     fprintf (asmFile, "%s", iComments2);
1129     fprintf (asmFile, "; global & static initialisations\n");
1130     fprintf (asmFile, "%s", iComments2);
1131     
1132     /* Everywhere we generate a reference to the static_name area, 
1133      * (which is currently only here), we immediately follow it with a 
1134      * definition of the post_static_name area. This guarantees that
1135      * the post_static_name area will immediately follow the static_name
1136      * area.
1137      */
1138     tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1139     tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1140     tfprintf(asmFile, "\t!area\n", port->mem.static_name);
1141     
1142     if (mainf && mainf->fbody) {
1143         fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1144         /* if external stack is specified then the
1145            higher order byte of the xdatalocation is
1146            going into P2 and the lower order going into
1147            spx */
1148         if (options.useXstack) {
1149             fprintf(asmFile,"\tmov\tP2,#0x%02x\n",
1150                     (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1151             fprintf(asmFile,"\tmov\t_spx,#0x%02x\n",
1152                     (unsigned int)options.xdata_loc & 0xff);
1153         }
1154
1155         /* initialise the stack pointer */
1156         /* if the user specified a value then use it */
1157         if (options.stack_loc) 
1158             fprintf(asmFile,"\tmov\tsp,#%d\n",options.stack_loc);
1159         else 
1160             /* no: we have to compute it */
1161             if (!options.stackOnData && maxRegBank <= 3)
1162                 fprintf(asmFile,"\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1); 
1163             else
1164                 fprintf(asmFile,"\tmov\tsp,#__start__stack\n"); /* MOF */
1165
1166         fprintf (asmFile,"\tlcall\t__sdcc_external_startup\n");
1167         fprintf (asmFile,"\tmov\ta,dpl\n");
1168         fprintf (asmFile,"\tjz\t__sdcc_init_data\n");
1169         fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1170         fprintf (asmFile,"__sdcc_init_data:\n");
1171         
1172     }
1173     copyFile (asmFile, statsg->oFile);
1174
1175     if (port->general.glue_up_main && mainf && mainf->fbody)
1176     {
1177         /* This code is generated in the post-static area.
1178          * This area is guaranteed to follow the static area
1179          * by the ugly shucking and jiving about 20 lines ago.
1180          */
1181         tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
1182         fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
1183     }
1184         
1185     /* copy over code */
1186     fprintf (asmFile, "%s", iComments2);
1187     fprintf (asmFile, "; code\n");
1188     fprintf (asmFile, "%s", iComments2);
1189     tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
1190     if (mainf && mainf->fbody) {
1191         
1192         /* entry point @ start of CSEG */
1193         fprintf (asmFile,"__sdcc_program_startup:\n");
1194         
1195         /* put in the call to main */
1196         fprintf(asmFile,"\tlcall\t_main\n");
1197         if (options.mainreturn) {
1198
1199             fprintf(asmFile,";\treturn from main ; will return to caller\n");
1200             fprintf(asmFile,"\tret\n");
1201
1202         } else {
1203                    
1204             fprintf(asmFile,";\treturn from main will lock up\n");
1205             fprintf(asmFile,"\tsjmp     .\n");
1206         }
1207     }
1208     copyFile (asmFile, code->oFile);
1209     
1210     fclose (asmFile);
1211     applyToSet(tmpfileSet,closeTmpFiles);
1212     applyToSet(tmpfileNameSet, rmTmpFiles);
1213 }
1214
1215 /** Creates a temporary file a'la tmpfile which avoids the bugs
1216     in cygwin wrt c:\tmp.
1217     Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1218 */
1219 FILE *tempfile(void)
1220 {
1221     const char *tmpdir = NULL;
1222     if (getenv("TMP"))
1223         tmpdir = getenv("TMP");
1224     else if (getenv("TEMP"))
1225         tmpdir = getenv("TEMP");
1226     else if (getenv("TMPDIR"))
1227         tmpdir = getenv("TMPDIR");
1228     if (tmpdir) {
1229         char *name = tempnam(tmpdir, "sdcc");
1230         if (name) {
1231             FILE *fp = fopen(name, "w+b");
1232             if (fp)
1233                 addSetHead(&tmpfileNameSet, name);
1234             return fp;
1235         }
1236         return NULL;
1237     }
1238     return tmpfile();
1239 }
1240
1241 char *gc_strdup(const char *s)
1242 {
1243     char *ret;
1244     ALLOC_ATOMIC(ret, strlen(s)+1);
1245     strcpy(ret, s);
1246     return ret;
1247 }