An sfr/sbit can have an "at #" AND an initializer
[fw/sdcc] / src / SDCCmem.c
1 /*-----------------------------------------------------------------*/
2 /* SDCCmem.c - 8051 memory management routines                     */
3 /*-----------------------------------------------------------------*/
4
5 #include "common.h"
6
7 /* memory segments */
8 memmap *xstack = NULL;          /* xternal stack data          */
9 memmap *istack = NULL;          /* internal stack              */
10 memmap *code = NULL;            /* code segment                */
11 memmap *data = NULL;            /* internal data upto 128      */
12 memmap *xdata = NULL;           /* external data               */
13 memmap *xidata = NULL;          /* the initialized xdata       */
14 memmap *xinit = NULL;           /* the initializers for xidata */
15 memmap *idata = NULL;           /* internal data upto 256      */
16 memmap *bit = NULL;             /* bit addressable space       */
17 memmap *statsg = NULL;          /* the constant data segment   */
18 memmap *sfr = NULL;             /* register space              */
19 memmap *reg = NULL;             /* register space              */
20 memmap *sfrbit = NULL;          /* sfr bit space               */
21 memmap *generic = NULL;         /* is a generic pointer        */
22 memmap *overlay = NULL;         /* overlay segment             */
23 memmap *eeprom = NULL;          /* eeprom location             */
24 memmap *home = NULL;            /* Unswitchable code bank      */
25
26 /* this is a set of sets each set containing
27    symbols in a single overlay */
28 set *ovrSetSets = NULL;
29
30 int maxRegBank = 0;
31 int fatalError = 0;             /* fatal error flag                   */
32
33 /*-----------------------------------------------------------------*/
34 /* allocMap - allocates a memory map                               */
35 /*-----------------------------------------------------------------*/
36 memmap *
37 allocMap (char rspace,          /* sfr space            */
38           char farmap,          /* far or near segment  */
39           char paged,           /* can this segment be paged  */
40           char direct,          /* directly addressable */
41           char bitaddr,         /* bit addressable space */
42           char codemap,         /* this is code space   */
43           unsigned sloc,        /* starting location    */
44           const char *name,     /* 2 character name     */
45           char dbName,          /* debug name                 */
46           int ptrType           /* pointer type for this space */
47 )
48 {
49   memmap *map;
50
51   if (!(map = Safe_alloc (sizeof (memmap))))
52     {
53       werror (E_OUT_OF_MEM, __FILE__, sizeof (memmap));
54       exit (1);
55     }
56
57   memset (map, ZERO, sizeof (memmap));
58   map->regsp = rspace;
59   map->fmap = farmap;
60   map->paged = paged;
61   map->direct = direct;
62   map->bitsp = bitaddr;
63   map->codesp = codemap;
64   map->sloc = sloc;
65   map->sname = name;
66   map->dbName = dbName;
67   map->ptrType = ptrType;
68   if (!(map->oFile = tempfile ()))
69     {
70       werror (E_TMPFILE_FAILED);
71       exit (1);
72     }
73   addSetHead (&tmpfileSet, map->oFile);
74   map->syms = NULL;
75   return map;
76 }
77
78 /*-----------------------------------------------------------------*/
79 /* initMem - allocates and initializes all the segments            */
80 /*-----------------------------------------------------------------*/
81 void 
82 initMem ()
83 {
84   /* allocate all the segments */
85   /* xternal stack segment ;   
86      SFRSPACE       -   NO
87      FAR-SPACE      -   YES
88      PAGED          -   YES
89      DIRECT-ACCESS  -   NO
90      BIT-ACCESS     -   NO
91      CODE-ACESS     -   NO 
92      DEBUG-NAME     -   'A'
93      POINTER-TYPE   -   FPOINTER
94    */
95   xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME, 'A', PPOINTER);
96
97   /* internal stack segment ;   
98      SFRSPACE       -   NO
99      FAR-SPACE      -   NO
100      PAGED          -   NO
101      DIRECT-ACCESS  -   NO
102      BIT-ACCESS     -   NO
103      CODE-ACESS     -   NO 
104      DEBUG-NAME     -   'B'
105      POINTER-TYPE   -   POINTER
106    */
107   if (ISTACK_NAME) {
108     istack = allocMap (0, 0, 0, 0, 0, 0, options.stack_loc, 
109                        ISTACK_NAME, 'B', POINTER);
110   } else {
111     istack=NULL;
112   }
113
114   /* code  segment ;   
115      SFRSPACE       -   NO
116      FAR-SPACE      -   YES
117      PAGED          -   NO
118      DIRECT-ACCESS  -   NO
119      BIT-ACCESS     -   NO
120      CODE-ACESS     -   YES 
121      DEBUG-NAME     -   'C'
122      POINTER-TYPE   -   CPOINTER
123    */
124   code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME, 'C', CPOINTER);
125
126   /* home  segment ;   
127      SFRSPACE       -   NO
128      FAR-SPACE      -   YES
129      PAGED          -   NO
130      DIRECT-ACCESS  -   NO
131      BIT-ACCESS     -   NO
132      CODE-ACESS     -   YES 
133      DEBUG-NAME     -   'C'
134      POINTER-TYPE   -   CPOINTER
135    */
136   home = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME, 'C', CPOINTER);
137
138   /* Static segment (code for variables );
139      SFRSPACE       -   NO
140      FAR-SPACE      -   YES
141      PAGED          -   NO
142      DIRECT-ACCESS  -   NO
143      BIT-ACCESS     -   NO
144      CODE-ACESS     -   YES 
145      DEBUG-NAME     -   'D'
146      POINTER-TYPE   -   CPOINTER
147    */
148   statsg = allocMap (0, 1, 0, 0, 0, 1, 0, STATIC_NAME, 'D', CPOINTER);
149
150   /* Data segment - internal storage segment ;
151      SFRSPACE       -   NO
152      FAR-SPACE      -   NO
153      PAGED          -   NO
154      DIRECT-ACCESS  -   YES
155      BIT-ACCESS     -   NO
156      CODE-ACESS     -   NO 
157      DEBUG-NAME     -   'E'
158      POINTER-TYPE   -   POINTER
159    */
160   data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME, 'E', POINTER);
161
162   /* overlay segment - same as internal storage segment ;
163      SFRSPACE       -   NO
164      FAR-SPACE      -   NO
165      PAGED          -   NO
166      DIRECT-ACCESS  -   YES
167      BIT-ACCESS     -   NO
168      CODE-ACESS     -   NO 
169      DEBUG-NAME     -   'E'
170      POINTER-TYPE   -   POINTER
171    */
172   if (OVERLAY_NAME) {
173     overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME, 'E', POINTER);
174   } else {
175     overlay = NULL;
176   }
177
178   /* Xternal Data segment - 
179      SFRSPACE       -   NO
180      FAR-SPACE      -   YES
181      PAGED          -   NO
182      DIRECT-ACCESS  -   NO
183      BIT-ACCESS     -   NO
184      CODE-ACESS     -   NO 
185      DEBUG-NAME     -   'F'
186      POINTER-TYPE   -   FPOINTER
187    */
188   xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME, 'F', FPOINTER);
189   xidata = allocMap (0, 1, 0, 0, 0, 0, 0, XIDATA_NAME, 'F', FPOINTER);
190   xinit = allocMap (0, 1, 0, 0, 0, 1, 0, XINIT_NAME, 'C', CPOINTER);
191
192   /* Inderectly addressed internal data segment
193      SFRSPACE       -   NO
194      FAR-SPACE      -   NO
195      PAGED          -   NO
196      DIRECT-ACCESS  -   NO
197      BIT-ACCESS     -   NO
198      CODE-ACESS     -   NO 
199      DEBUG-NAME     -   'G'
200      POINTER-TYPE   -   IPOINTER
201    */
202   if (IDATA_NAME) {
203     idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc, 
204                       IDATA_NAME, 'G', IPOINTER);
205   } else {
206     idata=NULL;
207   }
208
209   /* Static segment (code for variables );
210      SFRSPACE       -   NO
211      FAR-SPACE      -   NO
212      PAGED          -   NO
213      DIRECT-ACCESS  -   YES
214      BIT-ACCESS     -   YES
215      CODE-ACESS     -   NO 
216      DEBUG-NAME     -   'H'
217      POINTER-TYPE   -  _NONE_
218    */
219   bit = allocMap (0, 0, 0, 1, 1, 0, 0, BIT_NAME, 'H', 0);
220
221   /* Special function register space :-
222      SFRSPACE       -   YES
223      FAR-SPACE      -   NO
224      PAGED          -   NO
225      DIRECT-ACCESS  -   YES
226      BIT-ACCESS     -   NO
227      CODE-ACESS     -   NO 
228      DEBUG-NAME     -   'I'
229      POINTER-TYPE   -   _NONE_
230    */
231   sfr = allocMap (1, 0, 0, 1, 0, 0, 0, REG_NAME, 'I', 0);
232
233   /* Register space ;
234      SFRSPACE       -   YES
235      FAR-SPACE      -   NO
236      PAGED          -   NO
237      DIRECT-ACCESS  -   NO
238      BIT-ACCESS     -   NO
239      CODE-ACESS     -   NO 
240      DEBUG-NAME     -   ' '
241      POINTER-TYPE   -   _NONE_
242    */
243   reg = allocMap (1, 0, 0, 0, 0, 0, 0, REG_NAME, ' ', 0);
244
245   /* SFR bit space 
246      SFRSPACE       -   YES
247      FAR-SPACE      -   NO
248      PAGED          -   NO
249      DIRECT-ACCESS  -   YES
250      BIT-ACCESS     -   YES
251      CODE-ACESS     -   NO 
252      DEBUG-NAME     -   'J'
253      POINTER-TYPE   -   _NONE_
254    */
255   sfrbit = allocMap (1, 0, 0, 1, 1, 0, 0, REG_NAME, 'J', 0);
256
257   /* EEPROM bit space 
258      SFRSPACE       -   NO
259      FAR-SPACE      -   YES
260      PAGED          -   NO
261      DIRECT-ACCESS  -   NO
262      BIT-ACCESS     -   NO
263      CODE-ACESS     -   NO 
264      DEBUG-NAME     -   'K'
265      POINTER-TYPE   -   EEPPOINTER
266    */
267   eeprom = allocMap (0, 1, 0, 0, 0, 0, 0, REG_NAME, 'K', EEPPOINTER);
268
269   /* the unknown map */
270   generic = allocMap (1, 0, 0, 1, 1, 0, 0, REG_NAME, ' ', GPOINTER);
271
272 }
273
274 /*-----------------------------------------------------------------*/
275 /* allocIntoSeg - puts a symbol into a memory segment              */
276 /*-----------------------------------------------------------------*/
277 void 
278 allocIntoSeg (symbol * sym)
279 {
280   memmap *segment = SPEC_OCLS (sym->etype);
281   addSet (&segment->syms, sym);
282 }
283
284 /*-----------------------------------------------------------------*/
285 /* deleteFromSeg - deletes a symbol from segment used when a var   */
286 /*                 firest declared as "extern" then no extern      */
287 /*-----------------------------------------------------------------*/
288 void deleteFromSeg(symbol *sym)
289 {
290     if (SPEC_OCLS(sym->etype)) {
291         memmap *segment = SPEC_OCLS (sym->etype);       
292         deleteSetItem(&segment->syms,sym);
293     }
294 }
295
296
297 /*-----------------------------------------------------------------*/
298 /* allocGlobal - assigns the output segment to a global var       */
299 /*-----------------------------------------------------------------*/
300 void 
301 allocGlobal (symbol * sym)
302 {
303
304   /* symbol name is internal name  */
305   if (!sym->level)              /* local statics can come here */
306     SNPRINTF (sym->rname, sizeof(sym->rname), 
307               "%s%s", port->fun_prefix, sym->name);
308
309   /* add it to the operandKey reset */
310   if (!isinSet (operKeyReset, sym)) {
311     addSet(&operKeyReset, sym);
312   }
313
314   /* if this is a literal e.g. enumerated type */
315   /* put it in the data segment & do nothing   */
316   if (IS_LITERAL (sym->etype))
317     {
318       SPEC_OCLS (sym->etype) = data;
319       return;
320     }
321
322   /* if this is a function then assign code space    */
323   if (IS_FUNC (sym->type))
324     {
325       SPEC_OCLS (sym->etype) = code;
326       /* if this is an interrupt service routine
327          then put it in the interrupt service array */
328       if (FUNC_ISISR (sym->type) && !options.noiv)
329         {
330
331           if (interrupts[FUNC_INTNO (sym->type)])
332             werror (E_INT_DEFINED,
333                     FUNC_INTNO (sym->type),
334                     interrupts[FUNC_INTNO (sym->type)]->name);
335           else
336             interrupts[FUNC_INTNO (sym->type)] = sym;
337
338           /* automagically extend the maximum interrupts */
339           if (FUNC_INTNO (sym->type) >= maxInterrupts)
340             maxInterrupts = FUNC_INTNO (sym->type) + 1;
341         }
342       /* if it is not compiler defined */
343       if (!sym->cdef)
344         allocIntoSeg (sym);
345
346       return;
347     }
348
349   /* if this is a  SFR or SBIT */
350   if (SPEC_SCLS (sym->etype) == S_SFR ||
351       SPEC_SCLS (sym->etype) == S_SBIT)
352     {
353
354       SPEC_OCLS (sym->etype) =
355         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
356
357       allocIntoSeg (sym);
358       return;
359     }
360
361   /* if this is a bit variable and no storage class */
362   if (SPEC_NOUN (sym->etype) == V_BIT
363       && SPEC_SCLS (sym->etype) == S_BIT)
364     {
365       SPEC_OCLS (sym->etype) = bit;
366       allocIntoSeg (sym);
367       return;
368     }
369
370   /* if bit storage class */
371   if (SPEC_SCLS (sym->etype) == S_SBIT)
372     {
373       SPEC_OCLS (sym->etype) = bit;
374       allocIntoSeg (sym);
375       return;
376     }
377
378   /* register storage class ignored changed to FIXED */
379   if (SPEC_SCLS (sym->etype) == S_REGISTER)
380     SPEC_SCLS (sym->etype) = S_FIXED;
381
382   /* if data specified then  */
383   if (SPEC_SCLS (sym->etype) == S_DATA)
384     {
385       /* set the output class */
386       SPEC_OCLS (sym->etype) = data;
387       /* generate the symbol  */
388       allocIntoSeg (sym);
389       return;
390     }
391
392   /* if it is fixed, then allocate depending on the  */
393   /* current memory model, same for automatics        */
394   if (SPEC_SCLS (sym->etype) == S_FIXED ||
395       SPEC_SCLS (sym->etype) == S_AUTO) {
396     if (port->mem.default_globl_map != xdata) {
397       /* set the output class */
398       SPEC_OCLS (sym->etype) = port->mem.default_globl_map;
399       /* generate the symbol  */
400       allocIntoSeg (sym);
401       return;
402     } else {
403       SPEC_SCLS (sym->etype) = S_XDATA;
404     }
405   }
406
407   /* if code change to constant */
408   if (SPEC_SCLS (sym->etype) == S_CODE) {
409     SPEC_OCLS (sym->etype) = statsg;
410     allocIntoSeg (sym);
411     return;
412   }
413
414   if (SPEC_SCLS (sym->etype) == S_XDATA)
415     {
416       // should we move this to the initialized data segment?
417       if (port->genXINIT &&
418           sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) {
419         SPEC_OCLS(sym->etype)=xidata;
420       } else {
421         SPEC_OCLS (sym->etype) = xdata;
422       }
423       allocIntoSeg (sym);
424       return;
425     }
426
427   if (SPEC_SCLS (sym->etype) == S_IDATA)
428     {
429       SPEC_OCLS (sym->etype) = idata;
430       sym->iaccess = 1;
431       allocIntoSeg (sym);
432       return;
433     }
434
435   if (SPEC_SCLS (sym->etype) == S_EEPROM)
436     {
437       SPEC_OCLS (sym->etype) = eeprom;
438       allocIntoSeg (sym);
439       return;
440     }
441
442   return;
443 }
444
445 /*-----------------------------------------------------------------*/
446 /* allocParms - parameters are always passed on stack              */
447 /*-----------------------------------------------------------------*/
448 void 
449 allocParms (value * val)
450 {
451   value *lval;
452   int pNum = 1;
453
454   for (lval = val; lval; lval = lval->next, pNum++)
455     {
456
457       /* check the declaration */
458       checkDecl (lval->sym, 0);
459
460       /* if this a register parm then allocate
461          it as a local variable by adding it
462          to the first block we see in the body */
463       if (IS_REGPARM (lval->etype))
464         continue;
465
466       /* mark it as my parameter */
467       lval->sym->ismyparm = 1;
468       lval->sym->localof = currFunc;
469
470
471       /* if automatic variables r 2b stacked */
472       if (options.stackAuto || IFFUNC_ISREENT (currFunc->type))
473         {
474
475           if (lval->sym)
476             lval->sym->onStack = 1;
477
478           /* choose which stack 2 use   */
479           /*  use xternal stack */
480           if (options.useXstack)
481             {
482               /* PENDING: stack direction support */
483               SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
484               SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
485                 xstackPtr - getSize (lval->type);
486               xstackPtr -= getSize (lval->type);
487             }
488           else
489             {                   /* use internal stack   */
490               SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
491               if (port->stack.direction > 0)
492                 {
493                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
494                     stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
495                     getSize (lval->type) -
496                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
497                   stackPtr -= getSize (lval->type);
498                 }
499               else
500                 {
501                   /* This looks like the wrong order but it turns out OK... */
502                   /* PENDING: isr, bank overhead, ... */
503                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
504                     stackPtr +
505                     ((IFFUNC_ISBANKEDCALL (currFunc->type) && !SPEC_STAT(getSpec(currFunc->etype)))? port->stack.banked_overhead : 0) +
506                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
507                     0;
508                   stackPtr += getSize (lval->type);
509                 }
510             }
511           allocIntoSeg (lval->sym);
512         }
513       else
514         { /* allocate them in the automatic space */
515           /* generate a unique name  */
516           SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
517                     "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
518           strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
519           
520           /* if declared in external storage */
521           if (SPEC_SCLS (lval->etype) == S_XDATA)
522             SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
523           else
524             /* other wise depending on the memory model 
525                note here that we put it into the overlay segment
526                first, we will remove it from the overlay segment
527                after the overlay determination has been done */
528             if (options.model == MODEL_SMALL)
529               {
530                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
531                   (options.noOverlay ? port->mem.default_local_map
532                    : overlay);
533               }
534             else
535               {
536                 SPEC_SCLS (lval->etype) = S_XDATA;
537                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
538               }
539           allocIntoSeg (lval->sym);
540         }
541     }
542
543   return;
544 }
545
546 /*-----------------------------------------------------------------*/
547 /* deallocParms - parameters are always passed on stack                */
548 /*-----------------------------------------------------------------*/
549 void 
550 deallocParms (value * val)
551 {
552   value *lval;
553
554   for (lval = val; lval; lval = lval->next)
555     {
556
557       /* unmark is myparm */
558       lval->sym->ismyparm = 0;
559
560       /* delete it from the symbol table  */
561       deleteSym (SymbolTab, lval->sym, lval->sym->name);
562
563       if (!lval->sym->isref)
564         {
565           lval->sym->allocreq = 0;
566           werror (W_NO_REFERENCE, currFunc->name,
567                   "function argument", lval->sym->name);
568         }
569
570       /* move the rname if any to the name for both val & sym */
571       /* and leave a copy of it in the symbol table           */
572       if (lval->sym->rname[0])
573         {
574           char buffer[SDCC_NAME_MAX];
575           strncpyz (buffer, lval->sym->rname, sizeof(buffer));
576           lval->sym = copySymbol (lval->sym);
577           strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
578           strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
579           strncpyz (lval->name, buffer, sizeof(lval->name)); 
580           addSym (SymbolTab, lval->sym, lval->sym->name,
581                   lval->sym->level, lval->sym->block, 1);
582           lval->sym->_isparm = 1;
583           if (!isinSet (operKeyReset, lval->sym)) {
584             addSet(&operKeyReset, lval->sym);
585           }
586         }
587
588     }
589
590   return;
591 }
592
593 /*-----------------------------------------------------------------*/
594 /* allocLocal - allocate local variables                           */
595 /*-----------------------------------------------------------------*/
596 void 
597 allocLocal (symbol * sym)
598 {
599
600   /* generate an unique name */
601   SNPRINTF (sym->rname, sizeof(sym->rname), 
602             "%s%s_%s_%d_%d",
603             port->fun_prefix,
604             currFunc->name, sym->name, sym->level, sym->block);
605
606   sym->islocal = 1;
607   sym->localof = currFunc;
608
609   /* if this is a static variable */
610   if (IS_STATIC (sym->etype))
611     {
612       allocGlobal (sym);
613       sym->allocreq = 1;
614       return;
615     }
616
617   /* if volatile then */
618   if (IS_VOLATILE (sym->etype))
619     sym->allocreq = 1;
620
621   /* this is automatic           */
622
623   /* if it to be placed on the stack */
624   if (options.stackAuto || reentrant) {
625     sym->onStack = 1;
626     if (options.useXstack) {
627       /* PENDING: stack direction for xstack */
628       SPEC_OCLS (sym->etype) = xstack;
629       SPEC_STAK (sym->etype) = sym->stack = (xstackPtr + 1);
630       xstackPtr += getSize (sym->type);
631     } else {
632       SPEC_OCLS (sym->etype) = istack;
633       if (port->stack.direction > 0) {
634         SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
635         stackPtr += getSize (sym->type);
636       } else {
637         stackPtr -= getSize (sym->type);
638         SPEC_STAK (sym->etype) = sym->stack = stackPtr;
639       }
640     }
641     allocIntoSeg (sym);
642     return;
643   }
644   
645   /* else depending on the storage class specified */
646   if (SPEC_SCLS (sym->etype) == S_XDATA)
647     {
648       SPEC_OCLS (sym->etype) = xdata;
649       allocIntoSeg (sym);
650       return;
651     }
652
653   if (SPEC_SCLS (sym->etype) == S_CODE && !sym->_isparm) {
654     SPEC_OCLS (sym->etype) = statsg;
655     allocIntoSeg (sym);
656     return;
657   }
658   
659   if (SPEC_SCLS (sym->etype) == S_IDATA)
660     {
661       SPEC_OCLS (sym->etype) = idata;
662       sym->iaccess = 1;
663       allocIntoSeg (sym);
664       return;
665     }
666
667   /* if this is a function then assign code space    */
668   if (IS_FUNC (sym->type))
669     {
670       SPEC_OCLS (sym->etype) = code;
671       return;
672     }
673
674   /* if this is a  SFR or SBIT */
675   if (SPEC_SCLS (sym->etype) == S_SFR ||
676       SPEC_SCLS (sym->etype) == S_SBIT)
677     {
678       SPEC_OCLS (sym->etype) =
679         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
680
681       allocIntoSeg (sym);
682       return;
683     }
684
685   /* if this is a bit variable and no storage class */
686   if (SPEC_NOUN (sym->etype) == V_BIT
687       && (SPEC_SCLS (sym->etype) == S_BIT))
688     {
689       SPEC_OCLS (sym->etype) = bit;
690       allocIntoSeg (sym);
691       return;
692     }
693
694   if (SPEC_SCLS (sym->etype) == S_DATA)
695     {
696       SPEC_OCLS (sym->etype) = (options.noOverlay ? data : overlay);
697       allocIntoSeg (sym);
698       return;
699     }
700
701   if (SPEC_SCLS (sym->etype) == S_EEPROM)
702     {
703       SPEC_OCLS (sym->etype) = eeprom;
704       allocIntoSeg (sym);
705       return;
706     }
707
708   /* again note that we have put it into the overlay segment
709      will remove and put into the 'data' segment if required after 
710      overlay  analysis has been done */
711   if (options.model == MODEL_SMALL) {
712     SPEC_OCLS (sym->etype) = 
713       (options.noOverlay ? port->mem.default_local_map
714        : overlay);
715   } else {
716     SPEC_OCLS (sym->etype) = port->mem.default_local_map;
717   }
718   allocIntoSeg (sym);
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* deallocLocal - deallocates the local variables                  */
723 /*-----------------------------------------------------------------*/
724 void 
725 deallocLocal (symbol * csym)
726 {
727   symbol *sym;
728
729   for (sym = csym; sym; sym = sym->next)
730     {
731       if (sym->_isparm) 
732         continue;
733
734       /* if it is on the stack */
735       if (sym->onStack)
736         {
737           if (options.useXstack)
738             xstackPtr -= getSize (sym->type);
739           else
740             stackPtr -= getSize (sym->type);
741         }
742       /* if not used give a warning */
743       if (!sym->isref && !IS_STATIC (sym->etype))
744         werror (W_NO_REFERENCE, currFunc->name,
745                 "local variable", sym->name);
746       /* now delete it from the symbol table */
747       deleteSym (SymbolTab, sym, sym->name);
748     }
749 }
750
751 /*-----------------------------------------------------------------*/
752 /* overlay2data - moves declarations from the overlay seg to data  */
753 /*-----------------------------------------------------------------*/
754 void 
755 overlay2data ()
756 {
757   symbol *sym;
758
759   for (sym = setFirstItem (overlay->syms); sym;
760        sym = setNextItem (overlay->syms))
761     {
762
763       SPEC_OCLS (sym->etype) = data;
764       allocIntoSeg (sym);
765     }
766
767   setToNull ((void **) &overlay->syms);
768
769 }
770
771 /*-----------------------------------------------------------------*/
772 /* overlay2Set - will add all symbols from the overlay segment to  */
773 /*               the set of sets containing the overlable symbols  */
774 /*-----------------------------------------------------------------*/
775 void 
776 overlay2Set ()
777 {
778   symbol *sym;
779   set *oset = NULL;
780
781   for (sym = setFirstItem (overlay->syms); sym;
782        sym = setNextItem (overlay->syms))
783     {
784
785       addSet (&oset, sym);
786     }
787
788   setToNull ((void **) &overlay->syms);
789   addSet (&ovrSetSets, oset);
790
791 }
792
793 /*-----------------------------------------------------------------*/
794 /* allocVariables - creates decl & assign storage class for a v    */
795 /*-----------------------------------------------------------------*/
796 int 
797 allocVariables (symbol * symChain)
798 {
799   symbol *sym;
800   symbol *csym;
801   int stack = 0;
802   int saveLevel = 0;
803
804   /* go thru the symbol chain   */
805   for (sym = symChain; sym; sym = sym->next)
806     {
807
808       /* if this is a typedef then add it */
809       /* to the typedef table             */
810       if (IS_TYPEDEF (sym->etype))
811         {
812           /* check if the typedef already exists    */
813           csym = findSym (TypedefTab, NULL, sym->name);
814           if (csym && csym->level == sym->level)
815             werror (E_DUPLICATE_TYPEDEF, sym->name);
816
817           addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
818           continue;             /* go to the next one         */
819         }
820       /* make sure it already exist */
821       csym = findSymWithLevel (SymbolTab, sym);
822       if (!csym || (csym && csym->level != sym->level))
823         csym = sym;
824
825       /* check the declaration */
826       checkDecl (csym,0);
827
828       /* if this is a function or a pointer to function */
829       /* then args  processing  */
830       if (funcInChain (csym->type))
831         {
832           processFuncArgs (csym);
833
834           /* if register bank specified then update maxRegBank */
835           if (maxRegBank < FUNC_REGBANK (csym->type))
836             maxRegBank = FUNC_REGBANK (csym->type);
837           /*JCF: Mark the register bank as used*/
838       RegBankUsed[FUNC_REGBANK(csym->type)]=1;
839         }
840
841       /* if this is a extern variable then change the */
842       /* level to zero temporarily                                    */
843       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
844         {
845           saveLevel = csym->level;
846           csym->level = 0;
847         }
848
849       /* if this is a literal then it is an enumerated */
850       /* type so need not allocate it space for it     */
851       if (IS_LITERAL (sym->etype))
852         continue;
853
854       /* generate the actual declaration  */
855       if (csym->level)
856         {
857           allocLocal (csym);
858           if (csym->onStack)
859             stack += getSize (csym->type);
860         }
861       else
862         allocGlobal (csym);
863
864       /* restore the level */
865       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
866         csym->level = saveLevel;
867     }
868
869   return stack;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* redoStackOffsets :- will reassign the values for stack offsets  */
874 /*-----------------------------------------------------------------*/
875 void 
876 redoStackOffsets (void)
877 {
878   symbol *sym;
879   int sPtr = 0;
880   int xsPtr = -1;
881
882   /* after register allocation is complete we know
883      which variables will need to be assigned space
884      on the stack. We will eliminate those variables
885      which do not have the allocReq flag thus reducing
886      the stack space */
887   for (sym = setFirstItem (istack->syms); sym;
888        sym = setNextItem (istack->syms))
889     {
890
891       int size = getSize (sym->type);
892       /* nothing to do with parameters so continue */
893       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
894         continue;
895
896       if (IS_AGGREGATE (sym->type))
897         {
898           if (port->stack.direction > 0)
899             {
900               SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
901               sPtr += size;
902             }
903           else
904             {
905               sPtr -= size;
906               SPEC_STAK (sym->etype) = sym->stack = sPtr;
907             }
908           continue;
909         }
910
911       /* if allocation not required then subtract
912          size from overall stack size & continue */
913       if (!sym->allocreq)
914         {
915           currFunc->stack -= size;
916           SPEC_STAK (currFunc->etype) -= size;
917           continue;
918         }
919
920       if (port->stack.direction > 0)
921         {
922           SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
923           sPtr += size;
924         }
925       else
926         {
927           sPtr -= size;
928           SPEC_STAK (sym->etype) = sym->stack = sPtr;
929         }
930     }
931
932   /* do the same for the external stack */
933
934   for (sym = setFirstItem (xstack->syms); sym;
935        sym = setNextItem (xstack->syms))
936     {
937
938       int size = getSize (sym->type);
939       /* nothing to do with parameters so continue */
940       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
941         continue;
942
943       if (IS_AGGREGATE (sym->type))
944         {
945           SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
946           xsPtr += size;
947           continue;
948         }
949
950       /* if allocation not required then subtract
951          size from overall stack size & continue */
952       if (!sym->allocreq)
953         {
954           currFunc->xstack -= size;
955           SPEC_STAK (currFunc->etype) -= size;
956           continue;
957         }
958
959       SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
960       xsPtr += size;
961     }
962
963   /* if the debug option is set then output the
964      symbols to the map file */
965   if (options.debug)
966     {
967       for (sym = setFirstItem (istack->syms); sym;
968            sym = setNextItem (istack->syms))
969         cdbSymbol (sym, cdbFile, FALSE, FALSE);
970
971       for (sym = setFirstItem (xstack->syms); sym;
972            sym = setNextItem (xstack->syms))
973         cdbSymbol (sym, cdbFile, FALSE, FALSE);
974     }
975 }
976
977 /*-----------------------------------------------------------------*/
978 /* printAllocInfoSeg- print the allocation for a given section     */
979 /*-----------------------------------------------------------------*/
980 static void 
981 printAllocInfoSeg (memmap * map, symbol * func, FILE * of)
982 {
983   symbol *sym;
984
985   if (!map)
986     return;
987   if (!map->syms)
988     return;
989
990   for (sym = setFirstItem (map->syms); sym;
991        sym = setNextItem (map->syms))
992     {
993
994       if (sym->level == 0)
995         continue;
996       if (sym->localof != func)
997         continue;
998       fprintf (of, ";%-25s Allocated to ", sym->name);
999
1000       /* if assigned to registers */
1001       if (!sym->allocreq && sym->reqv)
1002         {
1003           int i;
1004
1005           sym = OP_SYMBOL (sym->reqv);
1006           fprintf (of, "registers ");
1007           for (i = 0; i < 4 && sym->regs[i]; i++)
1008             fprintf (of, "%s ", port->getRegName (sym->regs[i]));
1009           fprintf (of, "\n");
1010           continue;
1011         }
1012
1013       /* if on stack */
1014       if (sym->onStack)
1015         {
1016           fprintf (of, "stack - offset %d\n", sym->stack);
1017           continue;
1018         }
1019
1020       /* otherwise give rname */
1021       fprintf (of, "in memory with name '%s'\n", sym->rname);
1022     }
1023 }
1024
1025 /*-----------------------------------------------------------------*/
1026 /* canOverlayLocals - returns true if the local variables can overlayed */
1027 /*-----------------------------------------------------------------*/
1028 static bool 
1029 canOverlayLocals (eBBlock ** ebbs, int count)
1030 {
1031   int i;
1032   /* if staticAuto is in effect or the current function
1033      being compiled is reentrant or the overlay segment
1034      is empty or no overlay option is in effect then */
1035   if (options.noOverlay ||
1036       options.stackAuto ||
1037       (currFunc &&
1038        (IFFUNC_ISREENT (currFunc->type) ||
1039         FUNC_ISISR (currFunc->type))) ||
1040       elementsInSet (overlay->syms) == 0)
1041
1042     return FALSE;
1043
1044   /* if this is a forces overlay */
1045   if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE;
1046
1047   /* otherwise do thru the blocks and see if there
1048      any function calls if found then return false */
1049   for (i = 0; i < count; i++)
1050     {
1051       iCode *ic;
1052
1053       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1054           if (ic) {
1055               if (ic->op == CALL) {
1056                   sym_link *ftype = operandType(IC_LEFT(ic));
1057                   /* builtins only can use overlays */
1058                   if (!IFFUNC_ISBUILTIN(ftype)) return FALSE; 
1059               } else if (ic->op == PCALL) return FALSE;
1060           }
1061     }
1062
1063   /* no function calls found return TRUE */
1064   return TRUE;
1065 }
1066
1067 /*-----------------------------------------------------------------*/
1068 /* doOverlays - move the overlay segment to appropriate location   */
1069 /*-----------------------------------------------------------------*/
1070 void 
1071 doOverlays (eBBlock ** ebbs, int count)
1072 {
1073   if (!overlay) {
1074     return;
1075   }
1076
1077   /* check if the parameters and local variables
1078      of this function can be put in the overlay segment
1079      This check is essentially to see if the function
1080      calls any other functions if yes then we cannot
1081      overlay */
1082   if (canOverlayLocals (ebbs, count))
1083     /* if we can then put the parameters &
1084        local variables in the overlay set */
1085     overlay2Set ();
1086   else
1087     /* otherwise put them into data where
1088        they belong */
1089     overlay2data ();
1090 }
1091
1092 /*-----------------------------------------------------------------*/
1093 /* printAllocInfo - prints allocation information for a function   */
1094 /*-----------------------------------------------------------------*/
1095 void 
1096 printAllocInfo (symbol * func, FILE * of)
1097 {
1098   if (!of)
1099     of = stdout;
1100
1101   /* must be called after register allocation is complete */
1102   fprintf (of, ";------------------------------------------------------------\n");
1103   fprintf (of, ";Allocation info for local variables in function '%s'\n", func->name);
1104   fprintf (of, ";------------------------------------------------------------\n");
1105
1106   printAllocInfoSeg (xstack, func, of);
1107   printAllocInfoSeg (istack, func, of);
1108   printAllocInfoSeg (code, func, of);
1109   printAllocInfoSeg (data, func, of);
1110   printAllocInfoSeg (xdata, func, of);
1111   printAllocInfoSeg (idata, func, of);
1112   printAllocInfoSeg (sfr, func, of);
1113   printAllocInfoSeg (sfrbit, func, of);
1114   fprintf (of, ";------------------------------------------------------------\n");
1115 }