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