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