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