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