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