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