Update svn merge history.
[sdcc.git] / sdcc / src / SDCCmem.c
blob86c0a1aecb88b16f46afc7f099617763159a077d
1 /*-------------------------------------------------------------------------
2 SDCCmem.c - 8051 memory management routines
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
25 #include "common.h"
26 #include "dbuf_string.h"
27 #include "SDCCbtree.h"
29 /* memory segments */
30 memmap *xstack = NULL; /* xternal stack data */
31 memmap *istack = NULL; /* internal stack */
32 memmap *code = NULL; /* code segment */
33 memmap *data = NULL; /* internal data upto 128 */
34 memmap *initialized = NULL; /* initialized data, such as initialized, nonzero globals or local statics. */
35 memmap *initializer = NULL; /* a copz of the values for the initialized data from initialized in code space */
36 memmap *pdata = NULL; /* paged external data */
37 memmap *xdata = NULL; /* external data */
38 memmap *xidata = NULL; /* the initialized xdata */
39 memmap *xinit = NULL; /* the initializers for xidata */
40 memmap *idata = NULL; /* internal data upto 256 */
41 memmap *bit = NULL; /* bit addressable space */
42 memmap *statsg = NULL; /* the constant data segment */
43 memmap *c_abs = NULL; /* constant absolute data */
44 memmap *x_abs = NULL; /* absolute xdata/pdata */
45 memmap *i_abs = NULL; /* absolute idata upto 256 */
46 memmap *d_abs = NULL; /* absolute data upto 128 */
47 memmap *sfr = NULL; /* register space */
48 memmap *reg = NULL; /* register space */
49 memmap *sfrbit = NULL; /* sfr bit space */
50 memmap *generic = NULL; /* is a generic pointer */
51 memmap *overlay = NULL; /* overlay segment */
52 memmap *eeprom = NULL; /* eeprom location */
53 memmap *home = NULL; /* Unswitchable code bank */
54 namedspacemap *namedspacemaps = 0; /* memory segments for named address spaces */
56 /* this is a set of sets each set containing
57 symbols in a single overlay */
58 set *ovrSetSets = NULL;
60 int fatalError = 0; /* fatal error flag */
62 /*-----------------------------------------------------------------*/
63 /* allocMap - allocates a memory map */
64 /*-----------------------------------------------------------------*/
65 memmap *
66 allocMap (char rspace, /* sfr space */
67 char farmap, /* far or near segment */
68 char paged, /* can this segment be paged */
69 char direct, /* directly addressable */
70 char bitaddr, /* bit addressable space */
71 char codemap, /* this is code space */
72 unsigned sloc, /* starting location */
73 const char *name, /* 8 character name */
74 char dbName, /* debug name */
75 int ptrType /* pointer type for this space */
78 memmap *map;
80 if (!name)
81 return NULL;
83 if (!(map = Safe_alloc (sizeof (memmap))))
85 werror (E_OUT_OF_MEM, __FILE__, sizeof (memmap));
86 exit (1);
89 memset (map, 0, sizeof (memmap));
90 map->regsp = rspace;
91 map->fmap = farmap;
92 map->paged = paged;
93 map->direct = direct;
94 map->bitsp = bitaddr;
95 map->codesp = codemap;
96 map->sloc = sloc;
97 map->sname = name;
98 map->dbName = dbName;
99 map->ptrType = ptrType;
100 map->syms = NULL;
102 dbuf_init(&map->oBuf, 4096);
104 return map;
107 /*-----------------------------------------------------------------*/
108 /* initMem - allocates and initializes all the segments */
109 /*-----------------------------------------------------------------*/
110 void
111 initMem (void)
113 /* allocate all the segments */
114 /* xternal stack segment ;
115 SFRSPACE - NO
116 FAR-SPACE - YES
117 PAGED - YES
118 DIRECT-ACCESS - NO
119 BIT-ACCESS - NO
120 CODE-ACCESS - NO
121 DEBUG-NAME - 'A'
122 POINTER-TYPE - FPOINTER
124 xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME, 'A', PPOINTER);
126 /* internal stack segment ;
127 SFRSPACE - NO
128 FAR-SPACE - NO
129 PAGED - NO
130 DIRECT-ACCESS - NO
131 BIT-ACCESS - NO
132 CODE-ACCESS - NO
133 DEBUG-NAME - 'B'
134 POINTER-TYPE - POINTER
136 istack = allocMap (0, 0, 0, 0, 0, 0, options.stack_loc, ISTACK_NAME, 'B', POINTER);
138 /* code segment ;
139 SFRSPACE - NO
140 FAR-SPACE - YES
141 PAGED - NO
142 DIRECT-ACCESS - NO
143 BIT-ACCESS - NO
144 CODE-ACCESS - YES
145 DEBUG-NAME - 'C'
146 POINTER-TYPE - CPOINTER
148 code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME, 'C', CPOINTER);
150 /* home segment ;
151 SFRSPACE - NO
152 FAR-SPACE - YES
153 PAGED - NO
154 DIRECT-ACCESS - NO
155 BIT-ACCESS - NO
156 CODE-ACCESS - YES
157 DEBUG-NAME - 'C'
158 POINTER-TYPE - CPOINTER
160 home = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, HOME_NAME, 'C', CPOINTER);
162 /* Static segment (code for variables );
163 SFRSPACE - NO
164 FAR-SPACE - YES
165 PAGED - NO
166 DIRECT-ACCESS - NO
167 BIT-ACCESS - NO
168 CODE-ACCESS - YES
169 DEBUG-NAME - 'D'
170 POINTER-TYPE - CPOINTER
172 statsg = allocMap (0, 1, 0, 0, 0, 1, 0, STATIC_NAME, 'D', CPOINTER);
174 /* Constant Absolute Data segment (for variables );
175 SFRSPACE - NO
176 FAR-SPACE - YES
177 PAGED - NO
178 DIRECT-ACCESS - NO
179 BIT-ACCESS - NO
180 CODE-ACCESS - YES
181 DEBUG-NAME - 'D'
182 POINTER-TYPE - CPOINTER
184 c_abs = allocMap (0, 1, 0, 0, 0, 1, 0, CABS_NAME, 'D', CPOINTER);
186 /* Data segment - internal storage segment ;
187 SFRSPACE - NO
188 FAR-SPACE - NO
189 PAGED - NO
190 DIRECT-ACCESS - YES
191 BIT-ACCESS - NO
192 CODE-ACCESS - NO
193 DEBUG-NAME - 'E'
194 POINTER-TYPE - POINTER
196 data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME, 'E', POINTER);
198 initialized = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, INITIALIZED_NAME, 'E', POINTER);
199 initializer = allocMap (0, 0, 0, 1, 0, 1, options.code_loc, INITIALIZER_NAME, 'C', CPOINTER);
201 /* Absolute internal storage segment ;
202 SFRSPACE - NO
203 FAR-SPACE - NO
204 PAGED - NO
205 DIRECT-ACCESS - YES
206 BIT-ACCESS - NO
207 CODE-ACCESS - NO
208 DEBUG-NAME - 'E'
209 POINTER-TYPE - POINTER
211 d_abs = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, IABS_NAME, 'E', POINTER);
213 /* overlay segment - same as internal storage segment ;
214 SFRSPACE - NO
215 FAR-SPACE - NO
216 PAGED - NO
217 DIRECT-ACCESS - YES
218 BIT-ACCESS - NO
219 CODE-ACCESS - NO
220 DEBUG-NAME - 'E'
221 POINTER-TYPE - POINTER
223 if (OVERLAY_NAME)
224 overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME, 'E', POINTER);
226 /* Xternal paged segment ;
227 SFRSPACE - NO
228 FAR-SPACE - NO
229 PAGED - YES
230 DIRECT-ACCESS - NO
231 BIT-ACCESS - NO
232 CODE-ACCESS - NO
233 DEBUG-NAME - 'P'
234 POINTER-TYPE - PPOINTER
236 pdata = allocMap (0, 0, 1, 0, 0, 0, options.xstack_loc, PDATA_NAME, 'P', PPOINTER);
238 /* Xternal Data segment -
239 SFRSPACE - NO
240 FAR-SPACE - YES
241 PAGED - NO
242 DIRECT-ACCESS - NO
243 BIT-ACCESS - NO
244 CODE-ACCESS - NO
245 DEBUG-NAME - 'F'
246 POINTER-TYPE - FPOINTER
248 xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME, 'F', FPOINTER);
249 xidata = allocMap (0, 1, 0, 0, 0, 0, 0, XIDATA_NAME, 'F', FPOINTER);
250 xinit = allocMap (0, 1, 0, 0, 0, 1, 0, XINIT_NAME, 'C', CPOINTER);
252 /* Absolute external storage segment ;
253 SFRSPACE - NO
254 FAR-SPACE - YES
255 PAGED - NO
256 DIRECT-ACCESS - NO
257 BIT-ACCESS - NO
258 CODE-ACCESS - NO
259 DEBUG-NAME - 'F'
260 POINTER-TYPE - FPOINTER
262 x_abs = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XABS_NAME, 'F', FPOINTER);
264 /* Indirectly addressed internal data segment
265 SFRSPACE - NO
266 FAR-SPACE - NO
267 PAGED - NO
268 DIRECT-ACCESS - NO
269 BIT-ACCESS - NO
270 CODE-ACCESS - NO
271 DEBUG-NAME - 'G'
272 POINTER-TYPE - IPOINTER
274 idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc, IDATA_NAME, 'G', IPOINTER);
276 /* Indirectly addressed absolute internal segment
277 SFRSPACE - NO
278 FAR-SPACE - NO
279 PAGED - NO
280 DIRECT-ACCESS - NO
281 BIT-ACCESS - NO
282 CODE-ACCESS - NO
283 DEBUG-NAME - 'E'
284 POINTER-TYPE - IPOINTER
286 i_abs = allocMap (0, 0, 0, 0, 0, 0, options.data_loc, IABS_NAME, 'E', IPOINTER);
288 /* Bit space ;
289 SFRSPACE - NO
290 FAR-SPACE - NO
291 PAGED - NO
292 DIRECT-ACCESS - YES
293 BIT-ACCESS - YES
294 CODE-ACCESS - NO
295 DEBUG-NAME - 'H'
296 POINTER-TYPE - _NONE_
298 bit = allocMap (0, 0, 0, 1, 1, 0, 0, BIT_NAME, 'H', 0);
300 /* Special function register space :-
301 SFRSPACE - YES
302 FAR-SPACE - NO
303 PAGED - NO
304 DIRECT-ACCESS - YES
305 BIT-ACCESS - NO
306 CODE-ACCESS - NO
307 DEBUG-NAME - 'I'
308 POINTER-TYPE - _NONE_
310 sfr = allocMap (1, 0, 0, 1, 0, 0, 0, REG_NAME, 'I', 0);
312 /* Register space ;
313 SFRSPACE - YES
314 FAR-SPACE - NO
315 PAGED - NO
316 DIRECT-ACCESS - NO
317 BIT-ACCESS - NO
318 CODE-ACCESS - NO
319 DEBUG-NAME - ' '
320 POINTER-TYPE - _NONE_
322 reg = allocMap (1, 0, 0, 0, 0, 0, 0, REG_NAME, ' ', 0);
324 /* SFR bit space
325 SFRSPACE - YES
326 FAR-SPACE - NO
327 PAGED - NO
328 DIRECT-ACCESS - YES
329 BIT-ACCESS - YES
330 CODE-ACCESS - NO
331 DEBUG-NAME - 'J'
332 POINTER-TYPE - _NONE_
334 sfrbit = allocMap (1, 0, 0, 1, 1, 0, 0, REG_NAME, 'J', 0);
336 /* EEPROM space
337 SFRSPACE - NO
338 FAR-SPACE - YES
339 PAGED - NO
340 DIRECT-ACCESS - NO
341 BIT-ACCESS - NO
342 CODE-ACCESS - NO
343 DEBUG-NAME - 'K'
344 POINTER-TYPE - EEPPOINTER
346 eeprom = allocMap (0, 1, 0, 0, 0, 0, 0, REG_NAME, 'K', EEPPOINTER);
348 /* the unknown map */
349 generic = allocMap (0, 0, 0, 0, 0, 0, 0, DATA_NAME, ' ', GPOINTER);
353 /*-----------------------------------------------------------------*/
354 /* allocIntoSeg - puts a symbol into a memory segment */
355 /*-----------------------------------------------------------------*/
356 void
357 allocIntoSeg (symbol *sym)
359 memmap *segment;
361 const symbol *symbolspace = getAddrspace (sym->type);
363 if (symbolspace)
365 namedspacemap *nm;
366 for (nm = namedspacemaps; nm; nm = nm->next)
367 if (!strcmp (nm->name, symbolspace->name))
368 break;
370 if (!nm)
372 nm = Safe_alloc (sizeof (namedspacemap));
373 nm->name = Safe_alloc (strlen(symbolspace->name) + 1);
374 strcpy (nm->name, symbolspace->name);
375 nm->is_const = (symbolspace->type && SPEC_CONST (symbolspace->type));
376 nm->map = nm->is_const ?
377 allocMap (0, 1, 0, 0, 0, 1, options.code_loc, symbolspace->name, 'C', CPOINTER) :
378 allocMap (0, 0, 0, 1, 0, 0, options.data_loc, symbolspace->name, 'E', POINTER);
379 nm->next = namedspacemaps;
380 namedspacemaps = nm;
383 addSet (&nm->map->syms, sym);
385 return;
387 if (!(segment = SPEC_OCLS (sym->etype)))
389 fprintf (stderr, "Symbol %s:\n", sym->name);
390 wassertl (0, "Failed to allocate symbol to memory segment due to missing output storage class");
391 return;
393 addSet (&segment->syms, sym);
394 if (segment == pdata)
395 sym->iaccess = 1;
398 /*-----------------------------------------------------------------*/
399 /* deleteFromSeg - deletes a symbol from segment used when a var */
400 /* first declared as "extern" then no extern */
401 /*-----------------------------------------------------------------*/
402 void deleteFromSeg(symbol *sym)
404 if (SPEC_OCLS(sym->etype))
406 memmap *segment = SPEC_OCLS (sym->etype);
407 deleteSetItem(&segment->syms, sym);
411 /*-----------------------------------------------------------------*/
412 /* defaultOClass - set the output segment based on SCLASS */
413 /*-----------------------------------------------------------------*/
414 bool
415 defaultOClass (symbol *sym)
417 switch (SPEC_SCLS (sym->etype))
419 case S_SFR:
420 SPEC_OCLS (sym->etype) = sfr;
421 break;
422 case S_SBIT:
423 SPEC_OCLS (sym->etype) = sfrbit;
424 break;
425 case S_CODE:
426 if (sym->_isparm)
427 return FALSE;
428 /* if code change to constant */
429 if (sym->ival && SPEC_ABSA (sym->etype))
431 SPEC_OCLS(sym->etype) = c_abs;
433 else
435 if (!sym->ival && !SPEC_ABSA (sym->etype) && !(IS_EXTERN (sym->etype) || IS_FUNC (sym->type)))
437 sym->ival = newiList(INIT_DEEP, revinit(newiList(INIT_NODE, newAst_VALUE(constIntVal("0"))))); // Default initialization to 0.
438 sym->ival->lineno = sym->lineDef;
440 SPEC_OCLS (sym->etype) = statsg;
442 break;
443 case S_XDATA:
444 /* absolute initialized global */
445 if (sym->ival && SPEC_ABSA (sym->etype))
447 SPEC_OCLS(sym->etype) = x_abs;
449 /* or should we move this to the initialized data segment? */
450 else if (port->genXINIT && sym->ival && (sym->level==0))
452 SPEC_OCLS(sym->etype) = xidata;
454 else
456 SPEC_OCLS (sym->etype) = xdata;
458 break;
459 case S_DATA:
460 /* Absolute initialized global */
461 if (sym->ival && SPEC_ABSA (sym->etype))
463 SPEC_OCLS (sym->etype) = d_abs;
465 /* Other initialized global */
466 else if (sym->ival && port->mem.initialized_name && sym->level == 0)
468 SPEC_OCLS (sym->etype) = initialized;
470 else
472 SPEC_OCLS (sym->etype) = data;
474 break;
475 case S_IDATA:
476 /* absolute initialized global */
477 if (sym->ival && SPEC_ABSA (sym->etype))
479 SPEC_OCLS(sym->etype) = i_abs;
481 else
483 SPEC_OCLS (sym->etype) = idata;
485 sym->iaccess = 1;
486 break;
487 case S_PDATA:
488 SPEC_OCLS (sym->etype) = pdata;
489 sym->iaccess = 1;
490 break;
491 case S_BIT:
492 SPEC_OCLS (sym->etype) = bit;
493 break;
494 case S_EEPROM:
495 SPEC_OCLS (sym->etype) = eeprom;
496 break;
497 default:
498 return FALSE;
500 return TRUE;
503 /*-----------------------------------------------------------------*/
504 /* allocDefault - assigns the output segment based on SCLASS */
505 /*-----------------------------------------------------------------*/
506 bool
507 allocDefault (struct symbol *sym)
509 if (defaultOClass (sym))
511 allocIntoSeg (sym);
512 return TRUE;
514 return FALSE;
517 /*-----------------------------------------------------------------*/
518 /* allocGlobal - assigns the output segment to a global var */
519 /*-----------------------------------------------------------------*/
520 void
521 allocGlobal (symbol *sym)
523 /* symbol name is internal name */
524 if (!sym->level) /* local statics can come here */
525 SNPRINTF (sym->rname, sizeof(sym->rname),
526 "%s%s", port->fun_prefix, sym->name);
528 /* add it to the operandKey reset */
529 if (!isinSet (operKeyReset, sym))
531 addSet(&operKeyReset, sym);
534 /* if this is a literal e.g. enumerated type */
535 /* put it in the data segment & do nothing */
536 if (IS_LITERAL (sym->etype))
538 SPEC_OCLS (sym->etype) = data;
539 return;
542 /* if this is a function then assign code space */
543 if (IS_FUNC (sym->type))
545 SPEC_OCLS (sym->etype) = code;
546 /* if this is an interrupt service routine
547 then put it in the interrupt service array */
548 if (FUNC_ISISR (sym->type) && !options.noiv &&
549 (FUNC_INTNO (sym->type) != INTNO_UNSPEC))
551 if (interrupts[FUNC_INTNO (sym->type)])
552 werror (E_INT_DEFINED,
553 FUNC_INTNO (sym->type),
554 interrupts[FUNC_INTNO (sym->type)]->name);
555 else
556 interrupts[FUNC_INTNO (sym->type)] = sym;
558 /* automagically extend the maximum interrupts */
559 if (FUNC_INTNO (sym->type) >= maxInterrupts && FUNC_INTNO (sym->type)!=INTNO_TRAP)
560 maxInterrupts = FUNC_INTNO (sym->type) + 1;
562 /* if it is not compiler defined */
563 if (!sym->cdef)
564 allocIntoSeg (sym);
566 return;
569 /* if this is a bit variable and no storage class */
570 if (bit && IS_SPEC(sym->type) && SPEC_NOUN (sym->type) == V_BIT)
572 SPEC_OCLS (sym->type) = bit;
573 allocIntoSeg (sym);
574 return;
577 if (!TARGET_IS_PIC16 || sym->level)
578 /* register storage class ignored changed to FIXED */
579 if (SPEC_SCLS (sym->etype) == S_REGISTER)
580 SPEC_SCLS (sym->etype) = S_FIXED;
582 /* if it is fixed, then allocate depending on the */
583 /* current memory model, same for automatics */
584 if (SPEC_SCLS (sym->etype) == S_FIXED ||
585 (TARGET_IS_PIC16 && (SPEC_SCLS (sym->etype) == S_REGISTER) && (sym->level == 0)) ||
586 SPEC_SCLS (sym->etype) == S_AUTO)
588 if (port->mem.default_globl_map != xdata)
590 if (sym->ival && SPEC_ABSA (sym->etype))
592 /* absolute initialized global */
593 SPEC_OCLS (sym->etype) = x_abs;
595 else if (sym->ival && sym->level == 0 && port->mem.initialized_name)
597 SPEC_OCLS (sym->etype) = initialized;
599 else
601 /* set the output class */
602 SPEC_OCLS (sym->etype) = port->mem.default_globl_map;
604 /* generate the symbol */
605 allocIntoSeg (sym);
606 return;
608 else
610 if (SPEC_SCLS (sym->etype) != S_XDATA)
611 SPEC_SCLS_IMPLICITINTRINSIC (sym->etype) = true;
612 SPEC_SCLS (sym->etype) = S_XDATA;
616 allocDefault (sym);
617 return;
620 /*-----------------------------------------------------------------*/
621 /* allocParms - parameters are always passed on stack */
622 /*-----------------------------------------------------------------*/
623 void
624 allocParms (value *val, bool smallc)
626 value *lval;
627 int pNum = 1;
628 int stackParamSizeAdjust = 0;
630 if (smallc)
632 for (lval = val; lval; lval = lval->next)
634 if (IS_REGPARM (lval->etype))
635 continue;
636 stackParamSizeAdjust += getSize (lval->type) + (getSize (lval->type) == 1);
639 stackPtr += stackParamSizeAdjust;
641 for (lval = val; lval; lval = lval->next, pNum++)
643 if (!lval->sym) // Can only happen if there was a syntax error in the declaration.
645 fatalError++;
646 return;
649 /* check the declaration */
650 checkDecl (lval->sym, 0);
652 /* if this a register parm then allocate
653 it as a local variable by adding it
654 to the first block we see in the body */
655 if (IS_REGPARM (lval->etype))
656 continue;
658 /* mark it as my parameter */
659 lval->sym->ismyparm = 1;
660 lval->sym->localof = currFunc;
662 /* if automatic variables r 2b stacked */
663 if (options.stackAuto || IFFUNC_ISREENT (currFunc->type))
665 int paramsize = getSize (lval->type) + (getSize (lval->type) == 1 && smallc) + (getSize (lval->type) % 2 && TARGET_PDK_LIKE);
667 if (lval->sym)
668 lval->sym->onStack = 1;
670 /* choose which stack to use */
671 if (options.useXstack) /* use external stack */
673 /* PENDING: stack direction support */
674 wassertl (!smallc, "SmallC calling convention not yet supported for xstack callee");
675 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
676 SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
677 xstackPtr - paramsize;
678 xstackPtr -= paramsize;
680 else /* use internal stack */
683 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
684 if ((port->stack.direction > 0) != smallc)
686 SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
687 stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
688 paramsize -
689 (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
690 stackPtr -= paramsize;
692 else
694 /* This looks like the wrong order but it turns out OK... */
695 /* PENDING: isr, bank overhead, ... */
696 SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
697 stackPtr +
698 (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
700 stackPtr += paramsize;
703 allocIntoSeg (lval->sym);
705 else
707 /* Do not allocate for inline functions to avoid multiple definitions - see bug report #2591. */
708 if(IFFUNC_ISINLINE (currFunc->type) && !IS_STATIC (currFunc->etype) && !IS_EXTERN (currFunc->etype))
709 continue;
711 /* allocate them in the automatic space */
712 /* generate a unique name */
713 SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
714 "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
715 strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
717 /* if declared in specific storage */
718 if (allocDefault (lval->sym))
720 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype);
721 continue;
724 /* otherwise depending on the memory model */
725 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
726 port->mem.default_local_map;
727 if (options.model == MODEL_SMALL ||
728 /* The test for NO_MODEL was introduced to fix an issue for pdk (pdk has no xdata) maybe it is the right thing to do for pic, too.
729 But I don't know about pic */
730 options.model == NO_MODEL && !TARGET_PIC_LIKE)
732 /* note here that we put it into the overlay segment
733 first, we will remove it from the overlay segment
734 after the overlay determination has been done */
735 if (!options.noOverlay)
737 SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
738 overlay;
741 else if (options.model == MODEL_MEDIUM)
743 SPEC_SCLS (lval->etype) = S_PDATA;
745 else
747 SPEC_SCLS (lval->etype) = S_XDATA;
749 allocIntoSeg (lval->sym);
753 stackPtr -= stackParamSizeAdjust;
755 return;
758 /*-----------------------------------------------------------------*/
759 /* deallocParms - parameters are always passed on stack */
760 /*-----------------------------------------------------------------*/
761 void
762 deallocParms (value *val)
764 value *lval;
766 for (lval = val; lval; lval = lval->next)
768 if (!lval->sym) /* Syntax error in declaration */
769 continue;
771 /* unmark is myparm */
772 lval->sym->ismyparm = 0;
774 /* delete it from the symbol table */
775 deleteSym (SymbolTab, lval->sym, lval->sym->name);
777 if (!lval->sym->isref)
779 lval->sym->allocreq = 0;
780 werror (W_NO_REFERENCE,
781 currFunc ? currFunc->name : "(unknown)",
782 "function argument", lval->sym->name);
785 /* move the rname if any to the name for both val & sym */
786 /* and leave a copy of it in the symbol table */
787 if (lval->sym->rname[0])
789 char buffer[SDCC_NAME_MAX];
790 symbol *argsym = lval->sym;
792 strncpyz (buffer, lval->sym->rname, sizeof(buffer));
793 lval->sym = copySymbol (lval->sym);
794 strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
796 strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
797 /* need to keep the original name for inlining to work */
798 /*strncpyz (lval->name, buffer, sizeof(lval->name)); */
800 addSym (SymbolTab, lval->sym, lval->sym->name,
801 lval->sym->level, lval->sym->block, 1);
802 lval->sym->_isparm = 1;
803 if (!isinSet (operKeyReset, lval->sym))
805 addSet(&operKeyReset, lval->sym);
808 /* restore the original symbol */
809 lval->sym = argsym;
812 return;
815 /*-----------------------------------------------------------------*/
816 /* allocLocal - allocate local variables */
817 /*-----------------------------------------------------------------*/
818 void
819 allocLocal (symbol *sym)
821 /* generate an unique name */
822 SNPRINTF (sym->rname, sizeof(sym->rname),
823 "%s%s_%s_%d_%d",
824 port->fun_prefix,
825 currFunc->name, sym->name, sym->level, sym->block);
827 if (!sym->ismyparm && IS_ARRAY(sym->type) && DCL_ARRAY_VLA (sym->type))
829 werrorfl (sym->fileDef, sym->lineDef, E_VLA_OBJECT);
830 return;
833 sym->islocal = 1;
834 sym->localof = currFunc;
836 /* if this is a static variable */
837 if (IS_STATIC (sym->etype))
839 allocGlobal (sym);
840 sym->allocreq = 1;
841 return;
844 /* if volatile then */
845 if (IS_VOLATILE (sym->type))
846 sym->allocreq = 1;
848 /* this is automatic */
850 /* if it's to be placed on the stack */
851 if (options.stackAuto || reentrant)
853 sym->onStack = 1;
854 if (options.useXstack)
856 /* PENDING: stack direction for xstack */
857 SPEC_OCLS (sym->etype) = xstack;
858 SPEC_STAK (sym->etype) = sym->stack = (xstackPtr + 1);
859 xstackPtr += getSize (sym->type);
861 else
863 SPEC_OCLS (sym->etype) = istack;
864 if (port->stack.direction > 0)
866 SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
867 stackPtr += getSize (sym->type);
869 else
871 stackPtr -= getSize (sym->type);
872 SPEC_STAK (sym->etype) = sym->stack = stackPtr;
875 allocIntoSeg (sym);
876 return;
879 /* else depending on the storage class specified */
881 /* if this is a function then assign code space */
882 if (IS_FUNC (sym->type) && !sym->isitmp)
884 SPEC_OCLS (sym->etype) = code;
885 return;
888 /* if this is a bit variable and no storage class */
889 if (bit && IS_SPEC(sym->type) && SPEC_NOUN (sym->type) == V_BIT)
891 SPEC_SCLS (sym->type) = S_BIT;
892 SPEC_OCLS (sym->type) = bit;
893 allocIntoSeg (sym);
894 return;
897 if ((SPEC_SCLS (sym->etype) == S_DATA) || (SPEC_SCLS (sym->etype) == S_REGISTER))
899 SPEC_OCLS (sym->etype) = (options.noOverlay ? data : overlay);
900 allocIntoSeg (sym);
901 return;
904 if (allocDefault (sym))
906 return;
909 /* again note that we have put it into the overlay segment
910 will remove and put into the 'data' segment if required after
911 overlay analysis has been done */
912 if (options.model == MODEL_SMALL &&
913 // Do not put anything into overlay segment for non-extern, non-static inline function, since it would never get removed (was bug #3030).
914 !(FUNC_ISINLINE (sym->localof->type) && !IS_EXTERN (getSpec (sym->localof->type)) && !IS_STATIC (getSpec (sym->localof->type))))
916 SPEC_OCLS (sym->etype) =
917 (options.noOverlay ? port->mem.default_local_map : overlay);
919 else
921 SPEC_OCLS (sym->etype) = port->mem.default_local_map;
923 allocIntoSeg (sym);
926 /*-----------------------------------------------------------------*/
927 /* deallocLocal - deallocates the local variables */
928 /*-----------------------------------------------------------------*/
929 void
930 deallocLocal (symbol *csym)
932 symbol *sym;
934 for (sym = csym; sym; sym = sym->next)
936 if (sym->_isparm)
937 continue;
939 /* if it is on the stack */
940 if (sym->onStack)
942 if (options.useXstack)
943 xstackPtr -= getSize (sym->type);
944 else
945 stackPtr -= getSize (sym->type);
947 /* if not used give a warning */
948 if (!sym->isref && !IS_STATIC (sym->etype))
949 werror (W_NO_REFERENCE,
950 currFunc ? currFunc->name : "(unknown)",
951 "local variable", sym->name);
952 /* now delete it from the symbol table */
953 deleteSym (SymbolTab, sym, sym->name);
957 /*-----------------------------------------------------------------*/
958 /* overlay2data - moves declarations from the overlay seg to data */
959 /*-----------------------------------------------------------------*/
960 void
961 overlay2data (void)
963 symbol *sym;
965 for (sym = setFirstItem (overlay->syms); sym;
966 sym = setNextItem (overlay->syms))
969 // SPEC_OCLS (sym->etype) = (options.xdata_spill)?xdata:data;
970 SPEC_OCLS (sym->etype) = data;
971 allocIntoSeg (sym);
974 setToNull ((void *) &overlay->syms);
977 /*-----------------------------------------------------------------*/
978 /* overlay2Set - will add all symbols from the overlay segment to */
979 /* the set of sets containing the overlable symbols */
980 /*-----------------------------------------------------------------*/
981 void
982 overlay2Set (void)
984 symbol *sym;
985 set *oset = NULL;
987 for (sym = setFirstItem (overlay->syms); sym;
988 sym = setNextItem (overlay->syms))
991 addSet (&oset, sym);
994 setToNull ((void *) &overlay->syms);
995 addSet (&ovrSetSets, oset);
998 /*-----------------------------------------------------------------*/
999 /* allocVariables - creates decl & assign storage class for a v */
1000 /*-----------------------------------------------------------------*/
1002 allocVariables (symbol *symChain)
1004 symbol *sym;
1005 symbol *csym;
1006 int stack = 0;
1007 long saveLevel = 0;
1009 /* go through the symbol chain */
1010 for (sym = symChain; sym; sym = sym->next)
1012 /* if this is a typedef then add it */
1013 /* to the typedef table */
1014 if (IS_TYPEDEF (sym->etype))
1016 /* check if the typedef already exists */
1017 csym = findSym (TypedefTab, NULL, sym->name);
1018 if (csym && csym->level == sym->level &&
1019 !(options.std_c11 && compareTypeExact (sym->type, csym->type, -1))) /* typedef to same type not allowed before ISO C11 */
1020 werror (E_DUPLICATE_TYPEDEF, sym->name);
1022 SPEC_EXTR (sym->etype) = 0;
1023 addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
1024 continue; /* go to the next one */
1026 /* make sure it already exists */
1027 csym = findSymWithLevel (SymbolTab, sym);
1028 if (!csym || (csym && csym->level != sym->level))
1029 csym = sym;
1031 /* check the declaration */
1032 checkDecl (csym, 0);
1034 /* if this is a function or a pointer to a */
1035 /* function then do args processing */
1036 if (funcInChain (csym->type))
1038 processFuncArgs (csym, NULL);
1041 /* if this is an extern variable then change */
1042 /* the level to zero temporarily */
1043 if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
1045 saveLevel = csym->level;
1046 csym->level = 0;
1049 /* if this is a literal then it is an enumerated */
1050 /* type so need not allocate it space for it */
1051 if (IS_LITERAL (sym->etype))
1052 continue;
1054 /* generate the actual declaration */
1055 if (csym->level)
1057 allocLocal (csym);
1058 if (csym->onStack)
1059 stack += getSize (csym->type);
1061 else
1062 allocGlobal (csym);
1064 /* restore the level */
1065 if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
1066 csym->level = saveLevel;
1069 return stack;
1072 void
1073 clearStackOffsets (void)
1075 const symbol *sym;
1077 for (sym = setFirstItem (istack->syms); sym;
1078 sym = setNextItem (istack->syms))
1080 const int size = getSize (sym->type);
1082 /* nothing to do with parameters so continue */
1083 if ((sym->_isparm && !IS_REGPARM (sym->etype)))
1084 continue;
1086 currFunc->stack -= size;
1087 SPEC_STAK (currFunc->etype) -= size;
1090 if (currFunc)
1092 //wassert(!(currFunc->stack)); // Sometimes some local variable was included in istack->syms.
1093 currFunc->stack = 0;
1097 #define BTREE_STACK 1
1099 /*-----------------------------------------------------------------*/
1100 /* redoStackOffsets :- will reassign the values for stack offsets */
1101 /*-----------------------------------------------------------------*/
1102 void
1103 redoStackOffsets (void)
1105 symbol *sym;
1106 int sPtr = 0;
1107 int xsPtr = -1;
1109 /* after register allocation is complete we know
1110 which variables will need to be assigned space
1111 on the stack. We will eliminate those variables
1112 which do not have the allocReq flag thus reducing
1113 the stack space */
1114 for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms))
1116 int size = getSize (sym->type);
1117 /* nothing to do with parameters so continue */
1118 if ((sym->_isparm && !IS_REGPARM (sym->etype)))
1119 continue;
1121 if (BTREE_STACK)
1123 /* Remove them all, and let btree_alloc() below put them back in more efficiently. */
1124 currFunc->stack -= size;
1125 SPEC_STAK (currFunc->etype) -= size;
1127 if(IS_AGGREGATE (sym->type) || sym->allocreq)
1128 btree_add_symbol (sym);
1130 /* Do it the old way - compared to the btree approach we waste space when allocating
1131 variables that had their address taken, unions and aggregates. */
1132 else
1134 /* if allocation not required then subtract
1135 size from overall stack size & continue */
1136 if (!IS_AGGREGATE (sym->type) && !sym->allocreq)
1138 currFunc->stack -= size;
1139 SPEC_STAK (currFunc->etype) -= size;
1140 continue;
1143 if (port->stack.direction > 0)
1145 SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
1146 sPtr += size;
1148 else
1150 sPtr -= size;
1151 SPEC_STAK (sym->etype) = sym->stack = sPtr;
1156 if (BTREE_STACK && elementsInSet (istack->syms))
1158 btree_alloc ();
1159 btree_clear ();
1162 /* do the same for the external stack */
1164 if (!xstack)
1165 return;
1167 for (sym = setFirstItem (xstack->syms); sym; sym = setNextItem (xstack->syms))
1169 int size = getSize (sym->type);
1170 /* nothing to do with parameters so continue */
1171 if ((sym->_isparm && !IS_REGPARM (sym->etype)))
1172 continue;
1174 if (IS_AGGREGATE (sym->type))
1176 SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
1177 xsPtr += size;
1178 continue;
1181 /* if allocation not required then subtract
1182 size from overall stack size & continue */
1183 if (!sym->allocreq)
1185 currFunc->xstack -= size;
1186 SPEC_STAK (currFunc->etype) -= size;
1187 continue;
1190 SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
1191 xsPtr += size;
1195 #define SP_BP(sp, bp) (options.omitFramePtr ? sp : bp)
1196 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? SP_BP("_spx", "_bpx") : SP_BP("sp", "_bp"))
1198 /*-----------------------------------------------------------------*/
1199 /* printAllocInfoSeg- print the allocation for a given section */
1200 /*-----------------------------------------------------------------*/
1201 static int
1202 printAllocInfoSeg (memmap *map, symbol *func, struct dbuf_s *oBuf)
1204 symbol *sym;
1205 int flg = FALSE;
1207 if (!map || !map->syms)
1208 return 0;
1210 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1212 if (sym->level == 0)
1213 continue;
1214 if (sym->localof != func)
1215 continue;
1217 dbuf_printf (oBuf, ";%-13s Allocated ", sym->name);
1218 flg = TRUE;
1220 /* if assigned to registers */
1221 if (!sym->allocreq && sym->reqv)
1223 int i;
1225 sym = OP_SYMBOL (sym->reqv);
1226 if (!sym->isspilt || sym->remat)
1228 dbuf_append_str (oBuf, "to registers ");
1229 for (i = 0; i < 8 && sym->regs[i]; i++)
1230 dbuf_printf (oBuf, "%s ", port->getRegName (sym->regs[i]));
1231 dbuf_append_char (oBuf, '\n');
1232 continue;
1234 else
1236 sym = sym->usl.spillLoc;
1240 /* if on stack */
1241 if (sym->onStack)
1243 int stack_offset = 0;
1245 if (options.omitFramePtr)
1247 if (SPEC_OCLS (sym->etype)->paged)
1248 stack_offset = func->xstack;
1249 else
1250 stack_offset = func->stack;
1253 // if (IS_STRUCT (func->type->next) && sym->stack < 0)
1254 // stack_offset += GPTRSIZE;
1256 stack_offset += port->stack.offset; /* in case sp/bp points to the next location instead of last */
1258 if (port->stack.direction < 0)
1259 stack_offset = -stack_offset;
1261 dbuf_printf (oBuf, "to stack - %s %+d %+d \n", SYM_BP (sym), sym->stack - stack_offset, getSize (sym->type));
1262 continue;
1265 /* otherwise give rname */
1266 dbuf_printf (oBuf, "with name '%s'\n", sym->rname);
1269 return flg;
1272 /*----------------------------------------------------------------------*/
1273 /* canOverlayLocals - returns true if the local variables can overlayed */
1274 /*----------------------------------------------------------------------*/
1275 static bool
1276 canOverlayLocals (eBBlock ** ebbs, int count)
1278 int i;
1279 /* if staticAuto is in effect or the current function
1280 being compiled is reentrant or the overlay segment
1281 is empty or no overlay option is in effect then */
1282 if (options.noOverlay ||
1283 options.stackAuto ||
1284 (currFunc &&
1285 (IFFUNC_ISREENT (currFunc->type) ||
1286 FUNC_ISISR (currFunc->type))) ||
1287 elementsInSet (overlay->syms) == 0)
1289 return FALSE;
1292 wassert (currFunc);
1294 /* if this is a forces overlay */
1295 if (IFFUNC_ISOVERLAY(currFunc->type)) return TRUE;
1297 // struct / union parameters are written using memcpy, which goes very wrong if they are overlaid with memcpy's parameters.
1298 for (value *arg = FUNC_ARGS (currFunc->type); arg; arg = arg->next)
1299 if (IS_STRUCT (arg->type))
1300 return false;
1302 /* otherwise do thru the blocks and see if there
1303 any function calls if found then return false */
1304 for (i = 0; i < count; i++)
1306 iCode *ic;
1308 for (ic = ebbs[i]->sch; ic; ic = ic->next)
1309 if (ic)
1311 if (ic->op == CALL)
1313 sym_link *ftype = operandType(IC_LEFT(ic));
1314 /* builtins only can use overlays */
1315 if (!IFFUNC_ISBUILTIN(ftype)) return FALSE;
1317 else if (ic->op == PCALL)
1319 return FALSE;
1324 /* no function calls found return TRUE */
1325 return TRUE;
1328 /*-----------------------------------------------------------------*/
1329 /* doOverlays - move the overlay segment to appropriate location */
1330 /*-----------------------------------------------------------------*/
1331 void
1332 doOverlays (eBBlock ** ebbs, int count)
1334 if (!overlay)
1335 return;
1337 /* check if the parameters and local variables
1338 of this function can be put in the overlay segment
1339 This check is essentially to see if the function
1340 calls any other functions if yes then we cannot
1341 overlay */
1342 if (canOverlayLocals (ebbs, count))
1343 /* if we can then put the parameters &
1344 local variables in the overlay set */
1345 overlay2Set ();
1346 else
1347 /* otherwise put them into data where they belong */
1348 overlay2data ();
1351 /*-----------------------------------------------------------------*/
1352 /* printAllocInfo - prints allocation information for a function */
1353 /*-----------------------------------------------------------------*/
1354 void
1355 printAllocInfo (symbol *func, struct dbuf_s *oBuf)
1357 #define BREAKLINE ";------------------------------------------------------------\n"
1358 int cnt = 0;
1359 set *ovrset;
1360 set *tempOverlaySyms;
1362 if (!func)
1363 return;
1365 /* must be called after register allocation is complete */
1366 dbuf_append_str (oBuf, BREAKLINE);
1367 dbuf_printf (oBuf, ";Allocation info for local variables in function '%s'\n", func->name);
1368 dbuf_append_str (oBuf, BREAKLINE);
1370 cnt += printAllocInfoSeg (xstack, func, oBuf);
1371 cnt += printAllocInfoSeg (istack, func, oBuf);
1372 cnt += printAllocInfoSeg (code, func, oBuf);
1373 cnt += printAllocInfoSeg (data, func, oBuf);
1374 cnt += printAllocInfoSeg (xdata, func, oBuf);
1375 cnt += printAllocInfoSeg (idata, func, oBuf);
1376 cnt += printAllocInfoSeg (sfr, func, oBuf);
1377 cnt += printAllocInfoSeg (sfrbit, func, oBuf);
1379 tempOverlaySyms = overlay->syms;
1381 /* search the set of overlay sets for local variables/parameters */
1382 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1383 ovrset = setNextItem (ovrSetSets))
1385 overlay->syms = ovrset;
1386 cnt += printAllocInfoSeg (overlay, func, oBuf);
1388 overlay->syms = tempOverlaySyms;
1390 if (cnt)
1391 dbuf_append_str (oBuf, BREAKLINE);