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