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