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