* as/mcs51/lkarea.c: removed old K&R style,
[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-ACESS     -   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-ACESS     -   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-ACESS     -   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-ACESS     -   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-ACESS     -   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-ACESS     -   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-ACESS     -   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      -   YES
182      PAGED          -   YES
183      DIRECT-ACCESS  -   NO
184      BIT-ACCESS     -   NO
185      CODE-ACESS     -   NO 
186      DEBUG-NAME     -   'P'
187      POINTER-TYPE   -   PPOINTER
188    */
189   if (PDATA_NAME) {
190     pdata = allocMap (0, 1, 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-ACESS     -   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-ACESS     -   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   /* Static segment (code for variables );
227      SFRSPACE       -   NO
228      FAR-SPACE      -   NO
229      PAGED          -   NO
230      DIRECT-ACCESS  -   YES
231      BIT-ACCESS     -   YES
232      CODE-ACESS     -   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-ACESS     -   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-ACESS     -   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-ACESS     -   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 bit space 
275      SFRSPACE       -   NO
276      FAR-SPACE      -   YES
277      PAGED          -   NO
278      DIRECT-ACCESS  -   NO
279      BIT-ACCESS     -   NO
280      CODE-ACESS     -   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 /*                 firest 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 /*-----------------------------------------------------------------*/
315 /* allocGlobal - assigns the output segment to a global var       */
316 /*-----------------------------------------------------------------*/
317 void 
318 allocGlobal (symbol * sym)
319 {
320
321   /* symbol name is internal name  */
322   if (!sym->level)              /* local statics can come here */
323     SNPRINTF (sym->rname, sizeof(sym->rname), 
324               "%s%s", port->fun_prefix, sym->name);
325
326   /* add it to the operandKey reset */
327   if (!isinSet (operKeyReset, sym)) {
328     addSet(&operKeyReset, sym);
329   }
330
331   /* if this is a literal e.g. enumerated type */
332   /* put it in the data segment & do nothing   */
333   if (IS_LITERAL (sym->etype))
334     {
335       SPEC_OCLS (sym->etype) = data;
336       return;
337     }
338
339   /* if this is a function then assign code space    */
340   if (IS_FUNC (sym->type))
341     {
342       SPEC_OCLS (sym->etype) = code;
343       /* if this is an interrupt service routine
344          then put it in the interrupt service array */
345       if (FUNC_ISISR (sym->type) && !options.noiv
346           && (FUNC_INTNO (sym->type) != INTNO_UNSPEC))
347         {
348           if (interrupts[FUNC_INTNO (sym->type)])
349             werror (E_INT_DEFINED,
350                     FUNC_INTNO (sym->type),
351                     interrupts[FUNC_INTNO (sym->type)]->name);
352           else
353             interrupts[FUNC_INTNO (sym->type)] = sym;
354
355           /* automagically extend the maximum interrupts */
356           if (FUNC_INTNO (sym->type) >= maxInterrupts)
357             maxInterrupts = FUNC_INTNO (sym->type) + 1;
358             }
359       /* if it is not compiler defined */
360       if (!sym->cdef)
361         allocIntoSeg (sym);
362
363       return;
364     }
365
366   /* if this is a  SFR or SBIT */
367   if (SPEC_SCLS (sym->etype) == S_SFR ||
368       SPEC_SCLS (sym->etype) == S_SBIT)
369     {
370
371       SPEC_OCLS (sym->etype) =
372         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
373
374       allocIntoSeg (sym);
375       return;
376     }
377
378   /* if this is a bit variable and no storage class */
379   if (SPEC_NOUN (sym->etype) == V_BIT
380       && SPEC_SCLS (sym->etype) == S_BIT)
381     {
382       SPEC_OCLS (sym->etype) = bit;
383       allocIntoSeg (sym);
384       return;
385     }
386
387   /* if bit storage class */
388   if (SPEC_SCLS (sym->etype) == S_SBIT)
389     {
390       SPEC_OCLS (sym->etype) = bit;
391       allocIntoSeg (sym);
392       return;
393     }
394
395   if(!TARGET_IS_PIC16 || (TARGET_IS_PIC16 && sym->level))
396   /* register storage class ignored changed to FIXED */
397     if (SPEC_SCLS (sym->etype) == S_REGISTER)
398       SPEC_SCLS (sym->etype) = S_FIXED;
399
400   /* if data specified then  */
401   if (SPEC_SCLS (sym->etype) == S_DATA)
402     {
403       /* set the output class */
404       SPEC_OCLS (sym->etype) = data;
405       /* generate the symbol  */
406       allocIntoSeg (sym);
407       return;
408     }
409
410   /* if it is fixed, then allocate depending on the  */
411   /* current memory model, same for automatics        */
412   if (SPEC_SCLS (sym->etype) == S_FIXED ||
413       (TARGET_IS_PIC16 && (SPEC_SCLS (sym->etype) == S_REGISTER) && (sym->level==0)) ||
414       SPEC_SCLS (sym->etype) == S_AUTO) {
415     if (port->mem.default_globl_map != xdata) {
416       /* set the output class */
417       SPEC_OCLS (sym->etype) = port->mem.default_globl_map;
418       /* generate the symbol  */
419       allocIntoSeg (sym);
420       return;
421     } else {
422       SPEC_SCLS (sym->etype) = S_XDATA;
423     }
424   }
425
426   /* if code change to constant */
427   if (SPEC_SCLS (sym->etype) == S_CODE) {
428     SPEC_OCLS (sym->etype) = statsg;
429     allocIntoSeg (sym);
430     return;
431   }
432
433   if (SPEC_SCLS (sym->etype) == S_XDATA)
434     {
435       // should we move this to the initialized data segment?
436       if (port->genXINIT &&
437           sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) {
438         SPEC_OCLS(sym->etype)=xidata;
439       } else {
440         SPEC_OCLS (sym->etype) = xdata;
441       }
442       allocIntoSeg (sym);
443       return;
444     }
445
446   if (SPEC_SCLS (sym->etype) == S_IDATA)
447     {
448       SPEC_OCLS (sym->etype) = idata;
449       sym->iaccess = 1;
450       allocIntoSeg (sym);
451       return;
452     }
453
454   if (SPEC_SCLS (sym->etype) == S_PDATA)
455     {
456       SPEC_OCLS (sym->etype) = pdata;
457       sym->iaccess = 1;
458       allocIntoSeg (sym);
459       return;
460     }
461
462   if (SPEC_SCLS (sym->etype) == S_EEPROM)
463     {
464       SPEC_OCLS (sym->etype) = eeprom;
465       allocIntoSeg (sym);
466       return;
467     }
468
469   return;
470 }
471
472 /*-----------------------------------------------------------------*/
473 /* allocParms - parameters are always passed on stack              */
474 /*-----------------------------------------------------------------*/
475 void 
476 allocParms (value * val)
477 {
478   value *lval;
479   int pNum = 1;
480
481   for (lval = val; lval; lval = lval->next, pNum++)
482     {
483
484       /* check the declaration */
485       checkDecl (lval->sym, 0);
486
487       /* if this a register parm then allocate
488          it as a local variable by adding it
489          to the first block we see in the body */
490       if (IS_REGPARM (lval->etype))
491         continue;
492
493       /* mark it as my parameter */
494       lval->sym->ismyparm = 1;
495       lval->sym->localof = currFunc;
496
497
498       /* if automatic variables r 2b stacked */
499       if (options.stackAuto || IFFUNC_ISREENT (currFunc->type))
500         {
501
502           if (lval->sym)
503             lval->sym->onStack = 1;
504
505           /* choose which stack 2 use   */
506           /*  use xternal stack */
507           if (options.useXstack)
508             {
509           /* PENDING: stack direction support */
510           SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
511           SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
512             xstackPtr - getSize (lval->type);
513           xstackPtr -= getSize (lval->type);
514             }
515           else
516             {                   /* use internal stack   */
517               SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
518               if (port->stack.direction > 0)
519                 {
520                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
521                     stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
522                     getSize (lval->type) -
523                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
524                   stackPtr -= getSize (lval->type);
525                 }
526               else
527                 {
528                   /* This looks like the wrong order but it turns out OK... */
529                   /* PENDING: isr, bank overhead, ... */
530                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
531                     stackPtr +
532                     ((IFFUNC_ISBANKEDCALL (currFunc->type) && !SPEC_STAT(getSpec(currFunc->etype)))? port->stack.banked_overhead : 0) +
533                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
534                     0;
535                   stackPtr += getSize (lval->type);
536                 }
537             }
538           allocIntoSeg (lval->sym);
539         }
540       else
541         { /* allocate them in the automatic space */
542           /* generate a unique name  */
543           SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
544                     "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
545           strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
546           
547           /* if declared in external storage */
548           if (SPEC_SCLS (lval->etype) == S_XDATA)
549             SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
550           else
551             /* other wise depending on the memory model 
552                note here that we put it into the overlay segment
553                first, we will remove it from the overlay segment
554                after the overlay determination has been done */
555             if (options.model == MODEL_SMALL)
556               {
557                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
558                   (options.noOverlay ? port->mem.default_local_map
559                    : overlay);
560               }
561             else
562               {
563                 SPEC_SCLS (lval->etype) = S_XDATA;
564                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
565               }
566           allocIntoSeg (lval->sym);
567         }
568     }
569
570   return;
571 }
572
573 /*-----------------------------------------------------------------*/
574 /* deallocParms - parameters are always passed on stack                */
575 /*-----------------------------------------------------------------*/
576 void 
577 deallocParms (value * val)
578 {
579   value *lval;
580
581   for (lval = val; lval; lval = lval->next)
582     {
583
584       /* unmark is myparm */
585       lval->sym->ismyparm = 0;
586
587       /* delete it from the symbol table  */
588       deleteSym (SymbolTab, lval->sym, lval->sym->name);
589
590       if (!lval->sym->isref)
591         {
592           lval->sym->allocreq = 0;
593             werror (W_NO_REFERENCE, 
594                     currFunc ? currFunc->name : "(unknown)",
595                     "function argument", lval->sym->name);
596         }
597
598       /* move the rname if any to the name for both val & sym */
599       /* and leave a copy of it in the symbol table           */
600       if (lval->sym->rname[0])
601         {
602           char buffer[SDCC_NAME_MAX];
603           strncpyz (buffer, lval->sym->rname, sizeof(buffer));
604           lval->sym = copySymbol (lval->sym);
605           strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
606           strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
607           strncpyz (lval->name, buffer, sizeof(lval->name)); 
608           addSym (SymbolTab, lval->sym, lval->sym->name,
609                   lval->sym->level, lval->sym->block, 1);
610           lval->sym->_isparm = 1;
611           if (!isinSet (operKeyReset, lval->sym)) {
612             addSet(&operKeyReset, lval->sym);
613           }
614         }
615
616     }
617
618   return;
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* allocLocal - allocate local variables                           */
623 /*-----------------------------------------------------------------*/
624 void 
625 allocLocal (symbol * sym)
626 {
627
628   /* generate an unique name */
629   SNPRINTF (sym->rname, sizeof(sym->rname), 
630             "%s%s_%s_%d_%d",
631             port->fun_prefix,
632             currFunc->name, sym->name, sym->level, sym->block);
633
634   sym->islocal = 1;
635   sym->localof = currFunc;
636
637   /* if this is a static variable */
638   if (IS_STATIC (sym->etype))
639     {
640       allocGlobal (sym);
641       sym->allocreq = 1;
642       return;
643     }
644
645   /* if volatile then */
646   if (IS_VOLATILE (sym->etype))
647     sym->allocreq = 1;
648
649   /* this is automatic           */
650
651   /* if it's to be placed on the stack */
652   if (options.stackAuto || reentrant) {
653     sym->onStack = 1;
654     if (options.useXstack) {
655       /* PENDING: stack direction for xstack */
656       SPEC_OCLS (sym->etype) = xstack;
657       SPEC_STAK (sym->etype) = sym->stack = (xstackPtr + 1);
658       xstackPtr += getSize (sym->type);
659     } else {
660       SPEC_OCLS (sym->etype) = istack;
661       if (port->stack.direction > 0) {
662         SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
663         stackPtr += getSize (sym->type);
664       } else {
665         stackPtr -= getSize (sym->type);
666         SPEC_STAK (sym->etype) = sym->stack = stackPtr;
667       }
668     }
669     allocIntoSeg (sym);
670     return;
671   }
672   
673   /* else depending on the storage class specified */
674   if (SPEC_SCLS (sym->etype) == S_XDATA)
675     {
676       SPEC_OCLS (sym->etype) = xdata;
677       allocIntoSeg (sym);
678       return;
679     }
680
681   if (SPEC_SCLS (sym->etype) == S_CODE && !sym->_isparm) {
682     SPEC_OCLS (sym->etype) = statsg;
683     allocIntoSeg (sym);
684     return;
685   }
686   
687   if (SPEC_SCLS (sym->etype) == S_IDATA)
688     {
689       SPEC_OCLS (sym->etype) = idata;
690       sym->iaccess = 1;
691       allocIntoSeg (sym);
692       return;
693     }
694
695   /* if this is a function then assign code space    */
696   if (IS_FUNC (sym->type))
697     {
698       SPEC_OCLS (sym->etype) = code;
699       return;
700     }
701
702   /* if this is a  SFR or SBIT */
703   if (SPEC_SCLS (sym->etype) == S_SFR ||
704       SPEC_SCLS (sym->etype) == S_SBIT)
705     {
706       SPEC_OCLS (sym->etype) =
707         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
708
709       allocIntoSeg (sym);
710       return;
711     }
712
713   /* if this is a bit variable and no storage class */
714   if (SPEC_NOUN (sym->etype) == V_BIT
715       && (SPEC_SCLS (sym->etype) == S_BIT))
716     {
717       SPEC_OCLS (sym->etype) = bit;
718       allocIntoSeg (sym);
719       return;
720     }
721
722   if (SPEC_SCLS (sym->etype) == S_DATA)
723     {
724       SPEC_OCLS (sym->etype) = (options.noOverlay ? data : overlay);
725       allocIntoSeg (sym);
726       return;
727     }
728
729   if (SPEC_SCLS (sym->etype) == S_EEPROM)
730     {
731       SPEC_OCLS (sym->etype) = eeprom;
732       allocIntoSeg (sym);
733       return;
734     }
735
736   /* again note that we have put it into the overlay segment
737      will remove and put into the 'data' segment if required after 
738      overlay  analysis has been done */
739   if (options.model == MODEL_SMALL) {
740       SPEC_OCLS (sym->etype) = 
741         (options.noOverlay ? port->mem.default_local_map
742          : overlay);
743   } else {
744       SPEC_OCLS (sym->etype) = port->mem.default_local_map;
745   }
746   allocIntoSeg (sym);
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* deallocLocal - deallocates the local variables                  */
751 /*-----------------------------------------------------------------*/
752 void 
753 deallocLocal (symbol * csym)
754 {
755   symbol *sym;
756
757   for (sym = csym; sym; sym = sym->next)
758     {
759       if (sym->_isparm) 
760         continue;
761
762       /* if it is on the stack */
763       if (sym->onStack)
764         {
765           if (options.useXstack)
766             xstackPtr -= getSize (sym->type);
767           else
768             stackPtr -= getSize (sym->type);
769         }
770       /* if not used give a warning */
771       if (!sym->isref && !IS_STATIC (sym->etype))
772         werror (W_NO_REFERENCE, 
773                 currFunc ? currFunc->name : "(unknown)",
774                 "local variable", sym->name);
775       /* now delete it from the symbol table */
776       deleteSym (SymbolTab, sym, sym->name);
777     }
778 }
779
780 /*-----------------------------------------------------------------*/
781 /* overlay2data - moves declarations from the overlay seg to data  */
782 /*-----------------------------------------------------------------*/
783 void 
784 overlay2data ()
785 {
786   symbol *sym;
787
788   for (sym = setFirstItem (overlay->syms); sym;
789        sym = setNextItem (overlay->syms))
790     {
791
792       SPEC_OCLS (sym->etype) = data;
793       allocIntoSeg (sym);
794     }
795
796   setToNull ((void *) &overlay->syms);
797
798 }
799
800 /*-----------------------------------------------------------------*/
801 /* overlay2Set - will add all symbols from the overlay segment to  */
802 /*               the set of sets containing the overlable symbols  */
803 /*-----------------------------------------------------------------*/
804 void 
805 overlay2Set ()
806 {
807   symbol *sym;
808   set *oset = NULL;
809
810   for (sym = setFirstItem (overlay->syms); sym;
811        sym = setNextItem (overlay->syms))
812     {
813
814       addSet (&oset, sym);
815     }
816
817   setToNull ((void *) &overlay->syms);
818   addSet (&ovrSetSets, oset);
819
820 }
821
822 /*-----------------------------------------------------------------*/
823 /* allocVariables - creates decl & assign storage class for a v    */
824 /*-----------------------------------------------------------------*/
825 int 
826 allocVariables (symbol * symChain)
827 {
828   symbol *sym;
829   symbol *csym;
830   int stack = 0;
831   int saveLevel = 0;
832
833   /* go thru the symbol chain   */
834   for (sym = symChain; sym; sym = sym->next)
835     {
836
837       /* if this is a typedef then add it */
838       /* to the typedef table             */
839       if (IS_TYPEDEF (sym->etype))
840         {
841           /* check if the typedef already exists    */
842           csym = findSym (TypedefTab, NULL, sym->name);
843           if (csym && csym->level == sym->level)
844             werror (E_DUPLICATE_TYPEDEF, sym->name);
845
846           SPEC_EXTR (sym->etype) = 0;
847           addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
848           continue;             /* go to the next one         */
849         }
850       /* make sure it already exist */
851       csym = findSymWithLevel (SymbolTab, sym);
852       if (!csym || (csym && csym->level != sym->level))
853         csym = sym;
854
855       /* check the declaration */
856       checkDecl (csym,0);
857
858       /* if this is a function or a pointer to function */
859       /* then args  processing  */
860       if (funcInChain (csym->type))
861         {
862           processFuncArgs (csym);
863
864           /* if register bank specified then update maxRegBank */
865           if (maxRegBank < FUNC_REGBANK (csym->type))
866             maxRegBank = FUNC_REGBANK (csym->type);
867           /*JCF: Mark the register bank as used*/
868           RegBankUsed[FUNC_REGBANK(csym->type)]=1;
869         }
870
871       /* if this is a extern variable then change the */
872       /* level to zero temporarily                                    */
873       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
874         {
875           saveLevel = csym->level;
876           csym->level = 0;
877         }
878
879       /* if this is a literal then it is an enumerated */
880       /* type so need not allocate it space for it     */
881       if (IS_LITERAL (sym->etype))
882         continue;
883
884       /* generate the actual declaration  */
885       if (csym->level)
886         {
887           allocLocal (csym);
888           if (csym->onStack)
889             stack += getSize (csym->type);
890         }
891       else
892         allocGlobal (csym);
893
894       /* restore the level */
895       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
896         csym->level = saveLevel;
897     }
898
899   return stack;
900 }
901
902 /*-----------------------------------------------------------------*/
903 /* redoStackOffsets :- will reassign the values for stack offsets  */
904 /*-----------------------------------------------------------------*/
905 void 
906 redoStackOffsets (void)
907 {
908   symbol *sym;
909   int sPtr = 0;
910   int xsPtr = -1;
911
912   /* after register allocation is complete we know
913      which variables will need to be assigned space
914      on the stack. We will eliminate those variables
915      which do not have the allocReq flag thus reducing
916      the stack space */
917   for (sym = setFirstItem (istack->syms); sym;
918        sym = setNextItem (istack->syms))
919     {
920
921       int size = getSize (sym->type);
922       /* nothing to do with parameters so continue */
923       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
924         continue;
925
926       if (IS_AGGREGATE (sym->type))
927         {
928           if (port->stack.direction > 0)
929             {
930               SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
931               sPtr += size;
932             }
933           else
934             {
935               sPtr -= size;
936               SPEC_STAK (sym->etype) = sym->stack = sPtr;
937             }
938           continue;
939         }
940
941       /* if allocation not required then subtract
942          size from overall stack size & continue */
943       if (!sym->allocreq)
944         {
945           currFunc->stack -= size;
946           SPEC_STAK (currFunc->etype) -= size;
947           continue;
948         }
949
950       if (port->stack.direction > 0)
951         {
952           SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
953           sPtr += size;
954         }
955       else
956         {
957           sPtr -= size;
958           SPEC_STAK (sym->etype) = sym->stack = sPtr;
959         }
960     }
961
962   /* do the same for the external stack */
963
964   for (sym = setFirstItem (xstack->syms); sym;
965        sym = setNextItem (xstack->syms))
966     {
967
968       int size = getSize (sym->type);
969       /* nothing to do with parameters so continue */
970       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
971         continue;
972
973       if (IS_AGGREGATE (sym->type))
974         {
975           SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
976           xsPtr += size;
977           continue;
978         }
979
980       /* if allocation not required then subtract
981          size from overall stack size & continue */
982       if (!sym->allocreq)
983         {
984           currFunc->xstack -= size;
985           SPEC_STAK (currFunc->etype) -= size;
986           continue;
987         }
988
989       SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
990       xsPtr += size;
991     }
992
993 }
994
995 /*-----------------------------------------------------------------*/
996 /* printAllocInfoSeg- print the allocation for a given section     */
997 /*-----------------------------------------------------------------*/
998 static void 
999 printAllocInfoSeg (memmap * map, symbol * func, FILE * of)
1000 {
1001   symbol *sym;
1002
1003   if (!map)
1004     return;
1005   if (!map->syms)
1006     return;
1007   
1008   for (sym = setFirstItem (map->syms); sym;
1009        sym = setNextItem (map->syms))
1010     {
1011
1012       if (sym->level == 0)
1013         continue;
1014       if (sym->localof != func)
1015         continue;
1016       
1017       fprintf (of, ";%-25s Allocated ", sym->name);
1018
1019       /* if assigned to registers */
1020       if (!sym->allocreq && sym->reqv)
1021         {
1022           int i;
1023
1024           sym = OP_SYMBOL (sym->reqv);
1025           if (!sym->isspilt || sym->remat)
1026             {
1027               fprintf (of, "to registers ");
1028               for (i = 0; i < 4 && sym->regs[i]; i++)
1029                 fprintf (of, "%s ", port->getRegName (sym->regs[i]));
1030               fprintf (of, "\n");
1031               continue;
1032             }
1033           else
1034             {
1035               sym = sym->usl.spillLoc;
1036             }
1037         }
1038
1039       /* if on stack */
1040       if (sym->onStack)
1041         {
1042           fprintf (of, "to stack - offset %d\n", sym->stack);
1043           continue;
1044         }
1045
1046       /* otherwise give rname */
1047       fprintf (of, "with name '%s'\n", sym->rname);
1048     }
1049 }
1050
1051 /*-----------------------------------------------------------------*/
1052 /* canOverlayLocals - returns true if the local variables can overlayed */
1053 /*-----------------------------------------------------------------*/
1054 static bool 
1055 canOverlayLocals (eBBlock ** ebbs, int count)
1056 {
1057   int i;
1058   /* if staticAuto is in effect or the current function
1059      being compiled is reentrant or the overlay segment
1060      is empty or no overlay option is in effect then */
1061   if (options.noOverlay ||
1062       options.stackAuto ||
1063       (currFunc &&
1064        (IFFUNC_ISREENT (currFunc->type) ||
1065         FUNC_ISISR (currFunc->type))) ||
1066       elementsInSet (overlay->syms) == 0)
1067
1068     return FALSE;
1069
1070   /* if this is a forces overlay */
1071   if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE;
1072
1073   /* otherwise do thru the blocks and see if there
1074      any function calls if found then return false */
1075   for (i = 0; i < count; i++)
1076     {
1077       iCode *ic;
1078
1079       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1080           if (ic) {
1081               if (ic->op == CALL) {
1082                   sym_link *ftype = operandType(IC_LEFT(ic));
1083                   /* builtins only can use overlays */
1084                   if (!IFFUNC_ISBUILTIN(ftype)) return FALSE; 
1085               } else if (ic->op == PCALL) return FALSE;
1086           }
1087     }
1088
1089   /* no function calls found return TRUE */
1090   return TRUE;
1091 }
1092
1093 /*-----------------------------------------------------------------*/
1094 /* doOverlays - move the overlay segment to appropriate location   */
1095 /*-----------------------------------------------------------------*/
1096 void 
1097 doOverlays (eBBlock ** ebbs, int count)
1098 {
1099   if (!overlay) {
1100     return;
1101   }
1102
1103   /* check if the parameters and local variables
1104      of this function can be put in the overlay segment
1105      This check is essentially to see if the function
1106      calls any other functions if yes then we cannot
1107      overlay */
1108   if (canOverlayLocals (ebbs, count))
1109     /* if we can then put the parameters &
1110        local variables in the overlay set */
1111     overlay2Set ();
1112   else
1113     /* otherwise put them into data where
1114        they belong */
1115     overlay2data ();
1116 }
1117
1118 /*-----------------------------------------------------------------*/
1119 /* printAllocInfo - prints allocation information for a function   */
1120 /*-----------------------------------------------------------------*/
1121 void 
1122 printAllocInfo (symbol * func, FILE * of)
1123 {
1124   if (!func)
1125         return;
1126     
1127   if (!of)
1128     of = stdout;
1129
1130   /* must be called after register allocation is complete */
1131   fprintf (of, ";------------------------------------------------------------\n");
1132   fprintf (of, ";Allocation info for local variables in function '%s'\n", func->name);
1133   fprintf (of, ";------------------------------------------------------------\n");
1134
1135   printAllocInfoSeg (xstack, func, of);
1136   printAllocInfoSeg (istack, func, of);
1137   printAllocInfoSeg (code, func, of);
1138   printAllocInfoSeg (data, func, of);
1139   printAllocInfoSeg (xdata, func, of);
1140   printAllocInfoSeg (idata, func, of);
1141   printAllocInfoSeg (sfr, func, of);
1142   printAllocInfoSeg (sfrbit, func, of);
1143   
1144   {
1145     set *ovrset;
1146     set *tempOverlaySyms = overlay->syms;
1147     
1148     /* search the set of overlay sets for local variables/parameters */
1149     for (ovrset = setFirstItem (ovrSetSets); ovrset;
1150          ovrset = setNextItem (ovrSetSets))
1151       {
1152         overlay->syms = ovrset;
1153         printAllocInfoSeg (overlay, func, of);
1154       }
1155     overlay->syms = tempOverlaySyms;
1156   }
1157   
1158   fprintf (of, ";------------------------------------------------------------\n");
1159 }