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