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