* as/mcs51/asexpr.c (expr): disabled warning "not in .flat24 mode",
[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 this is a function then assign code space    */
698   if (IS_FUNC (sym->type))
699     {
700       SPEC_OCLS (sym->etype) = code;
701       return;
702     }
703
704   /* if this is a  SFR or SBIT */
705   if (SPEC_SCLS (sym->etype) == S_SFR ||
706       SPEC_SCLS (sym->etype) == S_SBIT)
707     {
708       SPEC_OCLS (sym->etype) =
709         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
710
711       allocIntoSeg (sym);
712       return;
713     }
714
715   /* if this is a bit variable and no storage class */
716   if (SPEC_NOUN (sym->etype) == V_BIT
717       && (SPEC_SCLS (sym->etype) == S_BIT))
718     {
719       SPEC_OCLS (sym->etype) = bit;
720       allocIntoSeg (sym);
721       return;
722     }
723
724   if (SPEC_SCLS (sym->etype) == S_DATA)
725     {
726       SPEC_OCLS (sym->etype) = (options.noOverlay ? data : overlay);
727       allocIntoSeg (sym);
728       return;
729     }
730
731   if (SPEC_SCLS (sym->etype) == S_EEPROM)
732     {
733       SPEC_OCLS (sym->etype) = eeprom;
734       allocIntoSeg (sym);
735       return;
736     }
737
738   /* again note that we have put it into the overlay segment
739      will remove and put into the 'data' segment if required after
740      overlay  analysis has been done */
741   if (options.model == MODEL_SMALL) {
742       SPEC_OCLS (sym->etype) =
743         (options.noOverlay ? port->mem.default_local_map
744          : overlay);
745   } else {
746       SPEC_OCLS (sym->etype) = port->mem.default_local_map;
747   }
748   allocIntoSeg (sym);
749 }
750
751 /*-----------------------------------------------------------------*/
752 /* deallocLocal - deallocates the local variables                  */
753 /*-----------------------------------------------------------------*/
754 void
755 deallocLocal (symbol * csym)
756 {
757   symbol *sym;
758
759   for (sym = csym; sym; sym = sym->next)
760     {
761       if (sym->_isparm)
762         continue;
763
764       /* if it is on the stack */
765       if (sym->onStack)
766         {
767           if (options.useXstack)
768             xstackPtr -= getSize (sym->type);
769           else
770             stackPtr -= getSize (sym->type);
771         }
772       /* if not used give a warning */
773       if (!sym->isref && !IS_STATIC (sym->etype))
774         werror (W_NO_REFERENCE,
775                 currFunc ? currFunc->name : "(unknown)",
776                 "local variable", sym->name);
777       /* now delete it from the symbol table */
778       deleteSym (SymbolTab, sym, sym->name);
779     }
780 }
781
782 /*-----------------------------------------------------------------*/
783 /* overlay2data - moves declarations from the overlay seg to data  */
784 /*-----------------------------------------------------------------*/
785 void
786 overlay2data ()
787 {
788   symbol *sym;
789
790   for (sym = setFirstItem (overlay->syms); sym;
791        sym = setNextItem (overlay->syms))
792     {
793
794       SPEC_OCLS (sym->etype) = data;
795       allocIntoSeg (sym);
796     }
797
798   setToNull ((void *) &overlay->syms);
799
800 }
801
802 /*-----------------------------------------------------------------*/
803 /* overlay2Set - will add all symbols from the overlay segment to  */
804 /*               the set of sets containing the overlable symbols  */
805 /*-----------------------------------------------------------------*/
806 void
807 overlay2Set ()
808 {
809   symbol *sym;
810   set *oset = NULL;
811
812   for (sym = setFirstItem (overlay->syms); sym;
813        sym = setNextItem (overlay->syms))
814     {
815
816       addSet (&oset, sym);
817     }
818
819   setToNull ((void *) &overlay->syms);
820   addSet (&ovrSetSets, oset);
821
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* allocVariables - creates decl & assign storage class for a v    */
826 /*-----------------------------------------------------------------*/
827 int
828 allocVariables (symbol * symChain)
829 {
830   symbol *sym;
831   symbol *csym;
832   int stack = 0;
833   int saveLevel = 0;
834
835   /* go thru the symbol chain   */
836   for (sym = symChain; sym; sym = sym->next)
837     {
838
839       /* if this is a typedef then add it */
840       /* to the typedef table             */
841       if (IS_TYPEDEF (sym->etype))
842         {
843           /* check if the typedef already exists    */
844           csym = findSym (TypedefTab, NULL, sym->name);
845           if (csym && csym->level == sym->level)
846             werror (E_DUPLICATE_TYPEDEF, sym->name);
847
848           SPEC_EXTR (sym->etype) = 0;
849           addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
850           continue;             /* go to the next one         */
851         }
852       /* make sure it already exist */
853       csym = findSymWithLevel (SymbolTab, sym);
854       if (!csym || (csym && csym->level != sym->level))
855         csym = sym;
856
857       /* check the declaration */
858       checkDecl (csym,0);
859
860       /* if this is a function or a pointer to function */
861       /* then args  processing  */
862       if (funcInChain (csym->type))
863         {
864           processFuncArgs (csym);
865
866           /* if register bank specified then update maxRegBank */
867           if (maxRegBank < FUNC_REGBANK (csym->type))
868             maxRegBank = FUNC_REGBANK (csym->type);
869           /*JCF: Mark the register bank as used*/
870           RegBankUsed[FUNC_REGBANK(csym->type)]=1;
871         }
872
873       /* if this is a extern variable then change the */
874       /* level to zero temporarily                                    */
875       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
876         {
877           saveLevel = csym->level;
878           csym->level = 0;
879         }
880
881       /* if this is a literal then it is an enumerated */
882       /* type so need not allocate it space for it     */
883       if (IS_LITERAL (sym->etype))
884         continue;
885
886       /* generate the actual declaration  */
887       if (csym->level)
888         {
889           allocLocal (csym);
890           if (csym->onStack)
891             stack += getSize (csym->type);
892         }
893       else
894         allocGlobal (csym);
895
896       /* restore the level */
897       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
898         csym->level = saveLevel;
899     }
900
901   return stack;
902 }
903
904 /*-----------------------------------------------------------------*/
905 /* redoStackOffsets :- will reassign the values for stack offsets  */
906 /*-----------------------------------------------------------------*/
907 void
908 redoStackOffsets (void)
909 {
910   symbol *sym;
911   int sPtr = 0;
912   int xsPtr = -1;
913
914   /* after register allocation is complete we know
915      which variables will need to be assigned space
916      on the stack. We will eliminate those variables
917      which do not have the allocReq flag thus reducing
918      the stack space */
919   for (sym = setFirstItem (istack->syms); sym;
920        sym = setNextItem (istack->syms))
921     {
922
923       int size = getSize (sym->type);
924       /* nothing to do with parameters so continue */
925       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
926         continue;
927
928       if (IS_AGGREGATE (sym->type))
929         {
930           if (port->stack.direction > 0)
931             {
932               SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
933               sPtr += size;
934             }
935           else
936             {
937               sPtr -= size;
938               SPEC_STAK (sym->etype) = sym->stack = sPtr;
939             }
940           continue;
941         }
942
943       /* if allocation not required then subtract
944          size from overall stack size & continue */
945       if (!sym->allocreq)
946         {
947           currFunc->stack -= size;
948           SPEC_STAK (currFunc->etype) -= size;
949           continue;
950         }
951
952       if (port->stack.direction > 0)
953         {
954           SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
955           sPtr += size;
956         }
957       else
958         {
959           sPtr -= size;
960           SPEC_STAK (sym->etype) = sym->stack = sPtr;
961         }
962     }
963
964   /* do the same for the external stack */
965
966   for (sym = setFirstItem (xstack->syms); sym;
967        sym = setNextItem (xstack->syms))
968     {
969
970       int size = getSize (sym->type);
971       /* nothing to do with parameters so continue */
972       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
973         continue;
974
975       if (IS_AGGREGATE (sym->type))
976         {
977           SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
978           xsPtr += size;
979           continue;
980         }
981
982       /* if allocation not required then subtract
983          size from overall stack size & continue */
984       if (!sym->allocreq)
985         {
986           currFunc->xstack -= size;
987           SPEC_STAK (currFunc->etype) -= size;
988           continue;
989         }
990
991       SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
992       xsPtr += size;
993     }
994
995 }
996
997 /*-----------------------------------------------------------------*/
998 /* printAllocInfoSeg- print the allocation for a given section     */
999 /*-----------------------------------------------------------------*/
1000 static void
1001 printAllocInfoSeg (memmap * map, symbol * func, FILE * of)
1002 {
1003   symbol *sym;
1004
1005   if (!map)
1006     return;
1007   if (!map->syms)
1008     return;
1009
1010   for (sym = setFirstItem (map->syms); sym;
1011        sym = setNextItem (map->syms))
1012     {
1013
1014       if (sym->level == 0)
1015         continue;
1016       if (sym->localof != func)
1017         continue;
1018
1019       fprintf (of, ";%-25s Allocated ", sym->name);
1020
1021       /* if assigned to registers */
1022       if (!sym->allocreq && sym->reqv)
1023         {
1024           int i;
1025
1026           sym = OP_SYMBOL (sym->reqv);
1027           if (!sym->isspilt || sym->remat)
1028             {
1029               fprintf (of, "to registers ");
1030               for (i = 0; i < 4 && sym->regs[i]; i++)
1031                 fprintf (of, "%s ", port->getRegName (sym->regs[i]));
1032               fprintf (of, "\n");
1033               continue;
1034             }
1035           else
1036             {
1037               sym = sym->usl.spillLoc;
1038             }
1039         }
1040
1041       /* if on stack */
1042       if (sym->onStack)
1043         {
1044           fprintf (of, "to stack - offset %d\n", sym->stack);
1045           continue;
1046         }
1047
1048       /* otherwise give rname */
1049       fprintf (of, "with name '%s'\n", sym->rname);
1050     }
1051 }
1052
1053 /*-----------------------------------------------------------------*/
1054 /* canOverlayLocals - returns true if the local variables can overlayed */
1055 /*-----------------------------------------------------------------*/
1056 static bool
1057 canOverlayLocals (eBBlock ** ebbs, int count)
1058 {
1059   int i;
1060   /* if staticAuto is in effect or the current function
1061      being compiled is reentrant or the overlay segment
1062      is empty or no overlay option is in effect then */
1063   if (options.noOverlay ||
1064       options.stackAuto ||
1065       (currFunc &&
1066        (IFFUNC_ISREENT (currFunc->type) ||
1067         FUNC_ISISR (currFunc->type))) ||
1068       elementsInSet (overlay->syms) == 0)
1069
1070     return FALSE;
1071
1072   /* if this is a forces overlay */
1073   if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE;
1074
1075   /* otherwise do thru the blocks and see if there
1076      any function calls if found then return false */
1077   for (i = 0; i < count; i++)
1078     {
1079       iCode *ic;
1080
1081       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1082           if (ic) {
1083               if (ic->op == CALL) {
1084                   sym_link *ftype = operandType(IC_LEFT(ic));
1085                   /* builtins only can use overlays */
1086                   if (!IFFUNC_ISBUILTIN(ftype)) return FALSE;
1087               } else if (ic->op == PCALL) return FALSE;
1088           }
1089     }
1090
1091   /* no function calls found return TRUE */
1092   return TRUE;
1093 }
1094
1095 /*-----------------------------------------------------------------*/
1096 /* doOverlays - move the overlay segment to appropriate location   */
1097 /*-----------------------------------------------------------------*/
1098 void
1099 doOverlays (eBBlock ** ebbs, int count)
1100 {
1101   if (!overlay) {
1102     return;
1103   }
1104
1105   /* check if the parameters and local variables
1106      of this function can be put in the overlay segment
1107      This check is essentially to see if the function
1108      calls any other functions if yes then we cannot
1109      overlay */
1110   if (canOverlayLocals (ebbs, count))
1111     /* if we can then put the parameters &
1112        local variables in the overlay set */
1113     overlay2Set ();
1114   else
1115     /* otherwise put them into data where
1116        they belong */
1117     overlay2data ();
1118 }
1119
1120 /*-----------------------------------------------------------------*/
1121 /* printAllocInfo - prints allocation information for a function   */
1122 /*-----------------------------------------------------------------*/
1123 void
1124 printAllocInfo (symbol * func, FILE * of)
1125 {
1126   if (!func)
1127         return;
1128
1129   if (!of)
1130     of = stdout;
1131
1132   /* must be called after register allocation is complete */
1133   fprintf (of, ";------------------------------------------------------------\n");
1134   fprintf (of, ";Allocation info for local variables in function '%s'\n", func->name);
1135   fprintf (of, ";------------------------------------------------------------\n");
1136
1137   printAllocInfoSeg (xstack, func, of);
1138   printAllocInfoSeg (istack, func, of);
1139   printAllocInfoSeg (code, func, of);
1140   printAllocInfoSeg (data, func, of);
1141   printAllocInfoSeg (xdata, func, of);
1142   printAllocInfoSeg (idata, func, of);
1143   printAllocInfoSeg (sfr, func, of);
1144   printAllocInfoSeg (sfrbit, func, of);
1145
1146   {
1147     set *ovrset;
1148     set *tempOverlaySyms = overlay->syms;
1149
1150     /* search the set of overlay sets for local variables/parameters */
1151     for (ovrset = setFirstItem (ovrSetSets); ovrset;
1152          ovrset = setNextItem (ovrSetSets))
1153       {
1154         overlay->syms = ovrset;
1155         printAllocInfoSeg (overlay, func, of);
1156       }
1157     overlay->syms = tempOverlaySyms;
1158   }
1159
1160   fprintf (of, ";------------------------------------------------------------\n");
1161 }