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