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