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