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