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