More strcpy() strcat() sprintf() squashing
[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   addSet (&operKeyReset, sym);
311
312   /* if this is a literal e.g. enumerated type */
313   /* put it in the data segment & do nothing   */
314   if (IS_LITERAL (sym->etype))
315     {
316       SPEC_OCLS (sym->etype) = data;
317       return;
318     }
319
320   /* if this is a function then assign code space    */
321   if (IS_FUNC (sym->type))
322     {
323       SPEC_OCLS (sym->etype) = code;
324       /* if this is an interrupt service routine
325          then put it in the interrupt service array */
326       if (FUNC_ISISR (sym->type) && !options.noiv)
327         {
328
329           if (interrupts[FUNC_INTNO (sym->type)])
330             werror (E_INT_DEFINED,
331                     FUNC_INTNO (sym->type),
332                     interrupts[FUNC_INTNO (sym->type)]->name);
333           else
334             interrupts[FUNC_INTNO (sym->type)] = sym;
335
336           /* automagically extend the maximum interrupts */
337           if (FUNC_INTNO (sym->type) >= maxInterrupts)
338             maxInterrupts = FUNC_INTNO (sym->type) + 1;
339         }
340       /* if it is not compiler defined */
341       if (!sym->cdef)
342         allocIntoSeg (sym);
343
344       return;
345     }
346
347   /* if this is a  SFR or SBIT */
348   if (SPEC_SCLS (sym->etype) == S_SFR ||
349       SPEC_SCLS (sym->etype) == S_SBIT)
350     {
351
352       /* if both absolute address & initial  */
353       /* value specified then error        */
354       if (IS_ABSOLUTE (sym->etype) && sym->ival)
355         {
356           werror (E_SFR_INIT, sym->name);
357           sym->ival = NULL;
358         }
359
360       SPEC_OCLS (sym->etype) =
361         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
362
363       allocIntoSeg (sym);
364       return;
365     }
366
367   /* if this is a bit variable and no storage class */
368   if (SPEC_NOUN (sym->etype) == V_BIT
369       && SPEC_SCLS (sym->etype) == S_BIT)
370     {
371       SPEC_OCLS (sym->etype) = bit;
372       allocIntoSeg (sym);
373       return;
374     }
375
376   /* if bit storage class */
377   if (SPEC_SCLS (sym->etype) == S_SBIT)
378     {
379       SPEC_OCLS (sym->etype) = bit;
380       allocIntoSeg (sym);
381       return;
382     }
383
384   /* register storage class ignored changed to FIXED */
385   if (SPEC_SCLS (sym->etype) == S_REGISTER)
386     SPEC_SCLS (sym->etype) = S_FIXED;
387
388   /* if data specified then  */
389   if (SPEC_SCLS (sym->etype) == S_DATA)
390     {
391       /* set the output class */
392       SPEC_OCLS (sym->etype) = data;
393       /* generate the symbol  */
394       allocIntoSeg (sym);
395       return;
396     }
397
398   /* if it is fixed, then allocate depending on the  */
399   /* current memory model, same for automatics        */
400   if (SPEC_SCLS (sym->etype) == S_FIXED ||
401       SPEC_SCLS (sym->etype) == S_AUTO) {
402     if (port->mem.default_globl_map != xdata) {
403       /* set the output class */
404       SPEC_OCLS (sym->etype) = port->mem.default_globl_map;
405       /* generate the symbol  */
406       allocIntoSeg (sym);
407       return;
408     } else {
409       SPEC_SCLS (sym->etype) = S_XDATA;
410     }
411   }
412
413   /* if code change to constant */
414   if (SPEC_SCLS (sym->etype) == S_CODE) {
415     SPEC_OCLS (sym->etype) = statsg;
416     allocIntoSeg (sym);
417     return;
418   }
419
420   if (SPEC_SCLS (sym->etype) == S_XDATA)
421     {
422       // should we move this to the initialized data segment?
423       if (port->genXINIT &&
424           sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) {
425         SPEC_OCLS(sym->etype)=xidata;
426       } else {
427         SPEC_OCLS (sym->etype) = xdata;
428       }
429       allocIntoSeg (sym);
430       return;
431     }
432
433   if (SPEC_SCLS (sym->etype) == S_IDATA)
434     {
435       SPEC_OCLS (sym->etype) = idata;
436       sym->iaccess = 1;
437       allocIntoSeg (sym);
438       return;
439     }
440
441   if (SPEC_SCLS (sym->etype) == S_EEPROM)
442     {
443       SPEC_OCLS (sym->etype) = eeprom;
444       allocIntoSeg (sym);
445       return;
446     }
447
448   return;
449 }
450
451 /*-----------------------------------------------------------------*/
452 /* allocParms - parameters are always passed on stack              */
453 /*-----------------------------------------------------------------*/
454 void 
455 allocParms (value * val)
456 {
457   value *lval;
458   int pNum = 1;
459
460   for (lval = val; lval; lval = lval->next, pNum++)
461     {
462
463       /* check the declaration */
464       checkDecl (lval->sym, 0);
465
466       /* if this a register parm then allocate
467          it as a local variable by adding it
468          to the first block we see in the body */
469       if (IS_REGPARM (lval->etype))
470         continue;
471
472       /* mark it as my parameter */
473       lval->sym->ismyparm = 1;
474       lval->sym->localof = currFunc;
475
476
477       /* if automatic variables r 2b stacked */
478       if (options.stackAuto || IFFUNC_ISREENT (currFunc->type))
479         {
480
481           if (lval->sym)
482             lval->sym->onStack = 1;
483
484           /* choose which stack 2 use   */
485           /*  use xternal stack */
486           if (options.useXstack)
487             {
488               /* PENDING: stack direction support */
489               SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
490               SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
491                 xstackPtr - getSize (lval->type);
492               xstackPtr -= getSize (lval->type);
493             }
494           else
495             {                   /* use internal stack   */
496               SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
497               if (port->stack.direction > 0)
498                 {
499                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
500                     stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
501                     getSize (lval->type) -
502                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
503                   stackPtr -= getSize (lval->type);
504                 }
505               else
506                 {
507                   /* This looks like the wrong order but it turns out OK... */
508                   /* PENDING: isr, bank overhead, ... */
509                   SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
510                     stackPtr +
511                     ((IFFUNC_ISBANKEDCALL (currFunc->type) && !SPEC_STAT(getSpec(currFunc->etype)))? port->stack.banked_overhead : 0) +
512                     (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
513                     0;
514                   stackPtr += getSize (lval->type);
515                 }
516             }
517           allocIntoSeg (lval->sym);
518         }
519       else
520         { /* allocate them in the automatic space */
521           /* generate a unique name  */
522           SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
523                     "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
524           strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
525           
526           /* if declared in external storage */
527           if (SPEC_SCLS (lval->etype) == S_XDATA)
528             SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
529           else
530             /* other wise depending on the memory model 
531                note here that we put it into the overlay segment
532                first, we will remove it from the overlay segment
533                after the overlay determination has been done */
534             if (options.model == MODEL_SMALL)
535               {
536                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
537                   (options.noOverlay ? port->mem.default_local_map
538                    : overlay);
539               }
540             else
541               {
542                 SPEC_SCLS (lval->etype) = S_XDATA;
543                 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
544               }
545           allocIntoSeg (lval->sym);
546         }
547     }
548
549   return;
550 }
551
552 /*-----------------------------------------------------------------*/
553 /* deallocParms - parameters are always passed on stack                */
554 /*-----------------------------------------------------------------*/
555 void 
556 deallocParms (value * val)
557 {
558   value *lval;
559
560   for (lval = val; lval; lval = lval->next)
561     {
562
563       /* unmark is myparm */
564       lval->sym->ismyparm = 0;
565
566       /* delete it from the symbol table  */
567       deleteSym (SymbolTab, lval->sym, lval->sym->name);
568
569       if (!lval->sym->isref)
570         {
571           lval->sym->allocreq = 0;
572           werror (W_NO_REFERENCE, currFunc->name,
573                   "function argument", lval->sym->name);
574         }
575
576       /* move the rname if any to the name for both val & sym */
577       /* and leave a copy of it in the symbol table           */
578       if (lval->sym->rname[0])
579         {
580           char buffer[SDCC_NAME_MAX];
581           strncpyz (buffer, lval->sym->rname, sizeof(buffer));
582           lval->sym = copySymbol (lval->sym);
583           strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
584           strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
585           strncpyz (lval->name, buffer, sizeof(lval->name)); 
586           addSym (SymbolTab, lval->sym, lval->sym->name,
587                   lval->sym->level, lval->sym->block, 1);
588           lval->sym->_isparm = 1;
589           addSet (&operKeyReset, lval->sym);
590         }
591
592     }
593
594   return;
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* allocLocal - allocate local variables                           */
599 /*-----------------------------------------------------------------*/
600 void 
601 allocLocal (symbol * sym)
602 {
603
604   /* generate an unique name */
605   SNPRINTF (sym->rname, sizeof(sym->rname), 
606             "%s%s_%s_%d_%d",
607             port->fun_prefix,
608             currFunc->name, sym->name, sym->level, sym->block);
609
610   sym->islocal = 1;
611   sym->localof = currFunc;
612
613   /* if this is a static variable */
614   if (IS_STATIC (sym->etype))
615     {
616       allocGlobal (sym);
617       sym->allocreq = 1;
618       return;
619     }
620
621   /* if volatile then */
622   if (IS_VOLATILE (sym->etype))
623     sym->allocreq = 1;
624
625   /* this is automatic           */
626
627   /* if it to be placed on the stack */
628   if (options.stackAuto || reentrant) {
629     sym->onStack = 1;
630     if (options.useXstack) {
631       /* PENDING: stack direction for xstack */
632       SPEC_OCLS (sym->etype) = xstack;
633       SPEC_STAK (sym->etype) = sym->stack = (xstackPtr + 1);
634       xstackPtr += getSize (sym->type);
635     } else {
636       SPEC_OCLS (sym->etype) = istack;
637       if (port->stack.direction > 0) {
638         SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
639         stackPtr += getSize (sym->type);
640       } else {
641         stackPtr -= getSize (sym->type);
642         SPEC_STAK (sym->etype) = sym->stack = stackPtr;
643       }
644     }
645     allocIntoSeg (sym);
646     return;
647   }
648   
649   /* else depending on the storage class specified */
650   if (SPEC_SCLS (sym->etype) == S_XDATA)
651     {
652       SPEC_OCLS (sym->etype) = xdata;
653       allocIntoSeg (sym);
654       return;
655     }
656
657   if (SPEC_SCLS (sym->etype) == S_CODE && !sym->_isparm) {
658     SPEC_OCLS (sym->etype) = statsg;
659     allocIntoSeg (sym);
660     return;
661   }
662   
663   if (SPEC_SCLS (sym->etype) == S_IDATA)
664     {
665       SPEC_OCLS (sym->etype) = idata;
666       sym->iaccess = 1;
667       allocIntoSeg (sym);
668       return;
669     }
670
671   /* if this is a function then assign code space    */
672   if (IS_FUNC (sym->type))
673     {
674       SPEC_OCLS (sym->etype) = code;
675       return;
676     }
677
678   /* if this is a  SFR or SBIT */
679   if (SPEC_SCLS (sym->etype) == S_SFR ||
680       SPEC_SCLS (sym->etype) == S_SBIT)
681     {
682
683       /* if both absolute address & initial  */
684       /* value specified then error        */
685       if (IS_ABSOLUTE (sym->etype) && sym->ival)
686         {
687           werror (E_SFR_INIT, sym->name);
688           sym->ival = NULL;
689         }
690
691       SPEC_OCLS (sym->etype) =
692         (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
693
694       allocIntoSeg (sym);
695       return;
696     }
697
698   /* if this is a bit variable and no storage class */
699   if (SPEC_NOUN (sym->etype) == V_BIT
700       && (SPEC_SCLS (sym->etype) == S_BIT))
701     {
702       SPEC_OCLS (sym->etype) = bit;
703       allocIntoSeg (sym);
704       return;
705     }
706
707   if (SPEC_SCLS (sym->etype) == S_DATA)
708     {
709       SPEC_OCLS (sym->etype) = (options.noOverlay ? data : overlay);
710       allocIntoSeg (sym);
711       return;
712     }
713
714   if (SPEC_SCLS (sym->etype) == S_EEPROM)
715     {
716       SPEC_OCLS (sym->etype) = eeprom;
717       allocIntoSeg (sym);
718       return;
719     }
720
721   /* again note that we have put it into the overlay segment
722      will remove and put into the 'data' segment if required after 
723      overlay  analysis has been done */
724   if (options.model == MODEL_SMALL) {
725     SPEC_OCLS (sym->etype) = 
726       (options.noOverlay ? port->mem.default_local_map
727        : overlay);
728   } else {
729     SPEC_OCLS (sym->etype) = port->mem.default_local_map;
730   }
731   allocIntoSeg (sym);
732 }
733
734 /*-----------------------------------------------------------------*/
735 /* deallocLocal - deallocates the local variables                  */
736 /*-----------------------------------------------------------------*/
737 void 
738 deallocLocal (symbol * csym)
739 {
740   symbol *sym;
741
742   for (sym = csym; sym; sym = sym->next)
743     {
744       if (sym->_isparm) 
745         continue;
746
747       /* if it is on the stack */
748       if (sym->onStack)
749         {
750           if (options.useXstack)
751             xstackPtr -= getSize (sym->type);
752           else
753             stackPtr -= getSize (sym->type);
754         }
755       /* if not used give a warning */
756       if (!sym->isref && !IS_STATIC (sym->etype))
757         werror (W_NO_REFERENCE, currFunc->name,
758                 "local variable", sym->name);
759       /* now delete it from the symbol table */
760       deleteSym (SymbolTab, sym, sym->name);
761     }
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* overlay2data - moves declarations from the overlay seg to data  */
766 /*-----------------------------------------------------------------*/
767 void 
768 overlay2data ()
769 {
770   symbol *sym;
771
772   for (sym = setFirstItem (overlay->syms); sym;
773        sym = setNextItem (overlay->syms))
774     {
775
776       SPEC_OCLS (sym->etype) = data;
777       allocIntoSeg (sym);
778     }
779
780   setToNull ((void **) &overlay->syms);
781
782 }
783
784 /*-----------------------------------------------------------------*/
785 /* overlay2Set - will add all symbols from the overlay segment to  */
786 /*               the set of sets containing the overlable symbols  */
787 /*-----------------------------------------------------------------*/
788 void 
789 overlay2Set ()
790 {
791   symbol *sym;
792   set *oset = NULL;
793
794   for (sym = setFirstItem (overlay->syms); sym;
795        sym = setNextItem (overlay->syms))
796     {
797
798       addSet (&oset, sym);
799     }
800
801   setToNull ((void **) &overlay->syms);
802   addSet (&ovrSetSets, oset);
803
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* allocVariables - creates decl & assign storage class for a v    */
808 /*-----------------------------------------------------------------*/
809 int 
810 allocVariables (symbol * symChain)
811 {
812   symbol *sym;
813   symbol *csym;
814   int stack = 0;
815   int saveLevel = 0;
816
817   /* go thru the symbol chain   */
818   for (sym = symChain; sym; sym = sym->next)
819     {
820
821       /* if this is a typedef then add it */
822       /* to the typedef table             */
823       if (IS_TYPEDEF (sym->etype))
824         {
825           /* check if the typedef already exists    */
826           csym = findSym (TypedefTab, NULL, sym->name);
827           if (csym && csym->level == sym->level)
828             werror (E_DUPLICATE_TYPEDEF, sym->name);
829
830           addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
831           continue;             /* go to the next one         */
832         }
833       /* make sure it already exist */
834       csym = findSymWithLevel (SymbolTab, sym);
835       if (!csym || (csym && csym->level != sym->level))
836         csym = sym;
837
838       /* check the declaration */
839       checkDecl (csym,0);
840
841       /* if this is a function or a pointer to function */
842       /* then args  processing  */
843       if (funcInChain (csym->type))
844         {
845 #if 1 // jwk: TODO should have been done already in addDecl() (oclass????)
846           processFuncArgs (csym);
847 #endif
848           /* if register bank specified then update maxRegBank */
849           if (maxRegBank < FUNC_REGBANK (csym->type))
850             maxRegBank = FUNC_REGBANK (csym->type);
851           /*JCF: Mark the register bank as used*/
852       RegBankUsed[FUNC_REGBANK(csym->type)]=1;
853         }
854
855       /* if this is a extern variable then change the */
856       /* level to zero temporarily                                    */
857       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
858         {
859           saveLevel = csym->level;
860           csym->level = 0;
861         }
862
863       /* if this is a literal then it is an enumerated */
864       /* type so need not allocate it space for it     */
865       if (IS_LITERAL (sym->etype))
866         continue;
867
868       /* generate the actual declaration  */
869       if (csym->level)
870         {
871           allocLocal (csym);
872           if (csym->onStack)
873             stack += getSize (csym->type);
874         }
875       else
876         allocGlobal (csym);
877
878       /* restore the level */
879       if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
880         csym->level = saveLevel;
881     }
882
883   return stack;
884 }
885
886 /*-----------------------------------------------------------------*/
887 /* redoStackOffsets :- will reassign the values for stack offsets  */
888 /*-----------------------------------------------------------------*/
889 void 
890 redoStackOffsets (void)
891 {
892   symbol *sym;
893   int sPtr = 0;
894   int xsPtr = -1;
895
896   /* after register allocation is complete we know
897      which variables will need to be assigned space
898      on the stack. We will eliminate those variables
899      which do not have the allocReq flag thus reducing
900      the stack space */
901   for (sym = setFirstItem (istack->syms); sym;
902        sym = setNextItem (istack->syms))
903     {
904
905       int size = getSize (sym->type);
906       /* nothing to do with parameters so continue */
907       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
908         continue;
909
910       if (IS_AGGREGATE (sym->type))
911         {
912           if (port->stack.direction > 0)
913             {
914               SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
915               sPtr += size;
916             }
917           else
918             {
919               sPtr -= size;
920               SPEC_STAK (sym->etype) = sym->stack = sPtr;
921             }
922           continue;
923         }
924
925       /* if allocation not required then subtract
926          size from overall stack size & continue */
927       if (!sym->allocreq)
928         {
929           currFunc->stack -= size;
930           SPEC_STAK (currFunc->etype) -= size;
931           continue;
932         }
933
934       if (port->stack.direction > 0)
935         {
936           SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
937           sPtr += size;
938         }
939       else
940         {
941           sPtr -= size;
942           SPEC_STAK (sym->etype) = sym->stack = sPtr;
943         }
944     }
945
946   /* do the same for the external stack */
947
948   for (sym = setFirstItem (xstack->syms); sym;
949        sym = setNextItem (xstack->syms))
950     {
951
952       int size = getSize (sym->type);
953       /* nothing to do with parameters so continue */
954       if ((sym->_isparm && !IS_REGPARM (sym->etype)))
955         continue;
956
957       if (IS_AGGREGATE (sym->type))
958         {
959           SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
960           xsPtr += size;
961           continue;
962         }
963
964       /* if allocation not required then subtract
965          size from overall stack size & continue */
966       if (!sym->allocreq)
967         {
968           currFunc->xstack -= size;
969           SPEC_STAK (currFunc->etype) -= size;
970           continue;
971         }
972
973       SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
974       xsPtr += size;
975     }
976
977   /* if the debug option is set then output the
978      symbols to the map file */
979   if (options.debug)
980     {
981       for (sym = setFirstItem (istack->syms); sym;
982            sym = setNextItem (istack->syms))
983         cdbSymbol (sym, cdbFile, FALSE, FALSE);
984
985       for (sym = setFirstItem (xstack->syms); sym;
986            sym = setNextItem (xstack->syms))
987         cdbSymbol (sym, cdbFile, FALSE, FALSE);
988     }
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* printAllocInfoSeg- print the allocation for a given section     */
993 /*-----------------------------------------------------------------*/
994 static void 
995 printAllocInfoSeg (memmap * map, symbol * func, FILE * of)
996 {
997   symbol *sym;
998
999   if (!map)
1000     return;
1001   if (!map->syms)
1002     return;
1003
1004   for (sym = setFirstItem (map->syms); sym;
1005        sym = setNextItem (map->syms))
1006     {
1007
1008       if (sym->level == 0)
1009         continue;
1010       if (sym->localof != func)
1011         continue;
1012       fprintf (of, ";%-25s Allocated to ", sym->name);
1013
1014       /* if assigned to registers */
1015       if (!sym->allocreq && sym->reqv)
1016         {
1017           int i;
1018           sym = OP_SYMBOL (sym->reqv);
1019           fprintf (of, "registers ");
1020           for (i = 0; i < 4 && sym->regs[i]; i++)
1021             fprintf (of, "%s ", port->getRegName (sym->regs[i]));
1022           fprintf (of, "\n");
1023           continue;
1024         }
1025
1026       /* if on stack */
1027       if (sym->onStack)
1028         {
1029           fprintf (of, "stack - offset %d\n", sym->stack);
1030           continue;
1031         }
1032
1033       /* otherwise give rname */
1034       fprintf (of, "in memory with name '%s'\n", sym->rname);
1035     }
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* canOverlayLocals - returns true if the local variables can overlayed */
1040 /*-----------------------------------------------------------------*/
1041 static bool 
1042 canOverlayLocals (eBBlock ** ebbs, int count)
1043 {
1044   int i;
1045   /* if staticAuto is in effect or the current function
1046      being compiled is reentrant or the overlay segment
1047      is empty or no overlay option is in effect then */
1048   if (options.noOverlay ||
1049       options.stackAuto ||
1050       (currFunc &&
1051        (IFFUNC_ISREENT (currFunc->type) ||
1052         FUNC_ISISR (currFunc->type))) ||
1053       elementsInSet (overlay->syms) == 0)
1054
1055     return FALSE;
1056
1057   /* if this is a forces overlay */
1058   if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE;
1059
1060   /* otherwise do thru the blocks and see if there
1061      any function calls if found then return false */
1062   for (i = 0; i < count; i++)
1063     {
1064       iCode *ic;
1065
1066       for (ic = ebbs[i]->sch; ic; ic = ic->next)
1067           if (ic) {
1068               if (ic->op == CALL) {
1069                   sym_link *ftype = operandType(IC_LEFT(ic));
1070                   /* builtins only can use overlays */
1071                   if (!IFFUNC_ISBUILTIN(ftype)) return FALSE; 
1072               } else if (ic->op == PCALL) return FALSE;
1073           }
1074     }
1075
1076   /* no function calls found return TRUE */
1077   return TRUE;
1078 }
1079
1080 /*-----------------------------------------------------------------*/
1081 /* doOverlays - move the overlay segment to appropriate location   */
1082 /*-----------------------------------------------------------------*/
1083 void 
1084 doOverlays (eBBlock ** ebbs, int count)
1085 {
1086   if (!overlay) {
1087     return;
1088   }
1089
1090   /* check if the parameters and local variables
1091      of this function can be put in the overlay segment
1092      This check is essentially to see if the function
1093      calls any other functions if yes then we cannot
1094      overlay */
1095   if (canOverlayLocals (ebbs, count))
1096     /* if we can then put the parameters &
1097        local variables in the overlay set */
1098     overlay2Set ();
1099   else
1100     /* otherwise put them into data where
1101        they belong */
1102     overlay2data ();
1103 }
1104
1105 /*-----------------------------------------------------------------*/
1106 /* printAllocInfo - prints allocation information for a function   */
1107 /*-----------------------------------------------------------------*/
1108 void 
1109 printAllocInfo (symbol * func, FILE * of)
1110 {
1111   if (!of)
1112     of = stdout;
1113
1114   /* must be called after register allocation is complete */
1115   fprintf (of, ";------------------------------------------------------------\n");
1116   fprintf (of, ";Allocation info for local variables in function '%s'\n", func->name);
1117   fprintf (of, ";------------------------------------------------------------\n");
1118
1119   printAllocInfoSeg (xstack, func, of);
1120   printAllocInfoSeg (istack, func, of);
1121   printAllocInfoSeg (code, func, of);
1122   printAllocInfoSeg (data, func, of);
1123   printAllocInfoSeg (xdata, func, of);
1124   printAllocInfoSeg (idata, func, of);
1125   printAllocInfoSeg (sfr, func, of);
1126   printAllocInfoSeg (sfrbit, func, of);
1127   fprintf (of, ";------------------------------------------------------------\n");
1128 }