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