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