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
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 -------------------------------------------------------------------------*/
26 #include "dbuf_string.h"
27 #include "SDCCbtree.h"
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 /*-----------------------------------------------------------------*/
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 */
83 if (!(map
= Safe_alloc (sizeof (memmap
))))
85 werror (E_OUT_OF_MEM
, __FILE__
, sizeof (memmap
));
89 memset (map
, 0, sizeof (memmap
));
95 map
->codesp
= codemap
;
99 map
->ptrType
= ptrType
;
102 dbuf_init(&map
->oBuf
, 4096);
107 /*-----------------------------------------------------------------*/
108 /* initMem - allocates and initializes all the segments */
109 /*-----------------------------------------------------------------*/
113 /* allocate all the segments */
114 /* xternal stack segment ;
122 POINTER-TYPE - FPOINTER
124 xstack
= allocMap (0, 1, 1, 0, 0, 0, options
.xstack_loc
, XSTACK_NAME
, 'A', PPOINTER
);
126 /* internal stack segment ;
134 POINTER-TYPE - POINTER
136 istack
= allocMap (0, 0, 0, 0, 0, 0, options
.stack_loc
, ISTACK_NAME
, 'B', POINTER
);
146 POINTER-TYPE - CPOINTER
148 code
= allocMap (0, 1, 0, 0, 0, 1, options
.code_loc
, CODE_NAME
, 'C', CPOINTER
);
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 );
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 );
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 ;
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 ;
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 ;
221 POINTER-TYPE - POINTER
224 overlay
= allocMap (0, 0, 0, 1, 0, 0, options
.data_loc
, DATA_NAME
, 'E', POINTER
);
226 /* Xternal paged segment ;
234 POINTER-TYPE - PPOINTER
236 pdata
= allocMap (0, 0, 1, 0, 0, 0, options
.xstack_loc
, PDATA_NAME
, 'P', PPOINTER
);
238 /* Xternal Data segment -
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 ;
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
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
284 POINTER-TYPE - IPOINTER
286 i_abs
= allocMap (0, 0, 0, 0, 0, 0, options
.data_loc
, IABS_NAME
, 'E', IPOINTER
);
296 POINTER-TYPE - _NONE_
298 bit
= allocMap (0, 0, 0, 1, 1, 0, 0, BIT_NAME
, 'H', 0);
300 /* Special function register space :-
308 POINTER-TYPE - _NONE_
310 sfr
= allocMap (1, 0, 0, 1, 0, 0, 0, REG_NAME
, 'I', 0);
320 POINTER-TYPE - _NONE_
322 reg
= allocMap (1, 0, 0, 0, 0, 0, 0, REG_NAME
, ' ', 0);
332 POINTER-TYPE - _NONE_
334 sfrbit
= allocMap (1, 0, 0, 1, 1, 0, 0, REG_NAME
, 'J', 0);
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 /*-----------------------------------------------------------------*/
357 allocIntoSeg (symbol
*sym
)
361 const symbol
*symbolspace
= getAddrspace (sym
->type
);
366 for (nm
= namedspacemaps
; nm
; nm
= nm
->next
)
367 if (!strcmp (nm
->name
, symbolspace
->name
))
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
;
383 addSet (&nm
->map
->syms
, sym
);
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");
393 addSet (&segment
->syms
, sym
);
394 if (segment
== pdata
)
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 /*-----------------------------------------------------------------*/
415 defaultOClass (symbol
*sym
)
417 switch (SPEC_SCLS (sym
->etype
))
420 SPEC_OCLS (sym
->etype
) = sfr
;
423 SPEC_OCLS (sym
->etype
) = sfrbit
;
428 /* if code change to constant */
429 if (sym
->ival
&& SPEC_ABSA (sym
->etype
))
431 SPEC_OCLS(sym
->etype
) = c_abs
;
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
;
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
;
456 SPEC_OCLS (sym
->etype
) = xdata
;
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
;
472 SPEC_OCLS (sym
->etype
) = data
;
476 /* absolute initialized global */
477 if (sym
->ival
&& SPEC_ABSA (sym
->etype
))
479 SPEC_OCLS(sym
->etype
) = i_abs
;
483 SPEC_OCLS (sym
->etype
) = idata
;
488 SPEC_OCLS (sym
->etype
) = pdata
;
492 SPEC_OCLS (sym
->etype
) = bit
;
495 SPEC_OCLS (sym
->etype
) = eeprom
;
503 /*-----------------------------------------------------------------*/
504 /* allocDefault - assigns the output segment based on SCLASS */
505 /*-----------------------------------------------------------------*/
507 allocDefault (struct symbol
*sym
)
509 if (defaultOClass (sym
))
517 /*-----------------------------------------------------------------*/
518 /* allocGlobal - assigns the output segment to a global var */
519 /*-----------------------------------------------------------------*/
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
;
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
);
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 */
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
;
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
;
601 /* set the output class */
602 SPEC_OCLS (sym
->etype
) = port
->mem
.default_globl_map
;
604 /* generate the symbol */
610 if (SPEC_SCLS (sym
->etype
) != S_XDATA
)
611 SPEC_SCLS_IMPLICITINTRINSIC (sym
->etype
) = true;
612 SPEC_SCLS (sym
->etype
) = S_XDATA
;
620 /*-----------------------------------------------------------------*/
621 /* allocParms - parameters are always passed on stack */
622 /*-----------------------------------------------------------------*/
624 allocParms (value
*val
, bool smallc
)
628 int stackParamSizeAdjust
= 0;
632 for (lval
= val
; lval
; lval
= lval
->next
)
634 if (IS_REGPARM (lval
->etype
))
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.
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
))
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
);
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) -
689 (FUNC_ISISR (currFunc
->type
) ? port
->stack
.isr_overhead
: 0);
690 stackPtr
-= paramsize
;
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
=
698 (FUNC_ISISR (currFunc
->type
) ? port
->stack
.isr_overhead
: 0) +
700 stackPtr
+= paramsize
;
703 allocIntoSeg (lval
->sym
);
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
))
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
);
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
) =
741 else if (options
.model
== MODEL_MEDIUM
)
743 SPEC_SCLS (lval
->etype
) = S_PDATA
;
747 SPEC_SCLS (lval
->etype
) = S_XDATA
;
749 allocIntoSeg (lval
->sym
);
753 stackPtr
-= stackParamSizeAdjust
;
758 /*-----------------------------------------------------------------*/
759 /* deallocParms - parameters are always passed on stack */
760 /*-----------------------------------------------------------------*/
762 deallocParms (value
*val
)
766 for (lval
= val
; lval
; lval
= lval
->next
)
768 if (!lval
->sym
) /* Syntax error in declaration */
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 */
815 /*-----------------------------------------------------------------*/
816 /* allocLocal - allocate local variables */
817 /*-----------------------------------------------------------------*/
819 allocLocal (symbol
*sym
)
821 /* generate an unique name */
822 SNPRINTF (sym
->rname
, sizeof(sym
->rname
),
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
);
834 sym
->localof
= currFunc
;
836 /* if this is a static variable */
837 if (IS_STATIC (sym
->etype
))
844 /* if volatile then */
845 if (IS_VOLATILE (sym
->type
))
848 /* this is automatic */
850 /* if it's to be placed on the stack */
851 if (options
.stackAuto
|| reentrant
)
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
);
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
);
871 stackPtr
-= getSize (sym
->type
);
872 SPEC_STAK (sym
->etype
) = sym
->stack
= stackPtr
;
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
;
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
;
897 if ((SPEC_SCLS (sym
->etype
) == S_DATA
) || (SPEC_SCLS (sym
->etype
) == S_REGISTER
))
899 SPEC_OCLS (sym
->etype
) = (options
.noOverlay
? data
: overlay
);
904 if (allocDefault (sym
))
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
);
921 SPEC_OCLS (sym
->etype
) = port
->mem
.default_local_map
;
926 /*-----------------------------------------------------------------*/
927 /* deallocLocal - deallocates the local variables */
928 /*-----------------------------------------------------------------*/
930 deallocLocal (symbol
*csym
)
934 for (sym
= csym
; sym
; sym
= sym
->next
)
939 /* if it is on the stack */
942 if (options
.useXstack
)
943 xstackPtr
-= getSize (sym
->type
);
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 /*-----------------------------------------------------------------*/
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
;
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 /*-----------------------------------------------------------------*/
987 for (sym
= setFirstItem (overlay
->syms
); sym
;
988 sym
= setNextItem (overlay
->syms
))
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
)
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
))
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
;
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
))
1054 /* generate the actual declaration */
1059 stack
+= getSize (csym
->type
);
1064 /* restore the level */
1065 if (IS_EXTERN (csym
->etype
) || IS_FUNC (csym
->type
))
1066 csym
->level
= saveLevel
;
1073 clearStackOffsets (void)
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
)))
1086 currFunc
->stack
-= size
;
1087 SPEC_STAK (currFunc
->etype
) -= size
;
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 /*-----------------------------------------------------------------*/
1103 redoStackOffsets (void)
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
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
)))
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. */
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
;
1143 if (port
->stack
.direction
> 0)
1145 SPEC_STAK (sym
->etype
) = sym
->stack
= (sPtr
+ 1);
1151 SPEC_STAK (sym
->etype
) = sym
->stack
= sPtr
;
1156 if (BTREE_STACK
&& elementsInSet (istack
->syms
))
1162 /* do the same for the external stack */
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
)))
1174 if (IS_AGGREGATE (sym
->type
))
1176 SPEC_STAK (sym
->etype
) = sym
->stack
= (xsPtr
+ 1);
1181 /* if allocation not required then subtract
1182 size from overall stack size & continue */
1185 currFunc
->xstack
-= size
;
1186 SPEC_STAK (currFunc
->etype
) -= size
;
1190 SPEC_STAK (sym
->etype
) = sym
->stack
= (xsPtr
+ 1);
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 /*-----------------------------------------------------------------*/
1202 printAllocInfoSeg (memmap
*map
, symbol
*func
, struct dbuf_s
*oBuf
)
1207 if (!map
|| !map
->syms
)
1210 for (sym
= setFirstItem (map
->syms
); sym
; sym
= setNextItem (map
->syms
))
1212 if (sym
->level
== 0)
1214 if (sym
->localof
!= func
)
1217 dbuf_printf (oBuf
, ";%-13s Allocated ", sym
->name
);
1220 /* if assigned to registers */
1221 if (!sym
->allocreq
&& sym
->reqv
)
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');
1236 sym
= sym
->usl
.spillLoc
;
1243 int stack_offset
= 0;
1245 if (options
.omitFramePtr
)
1247 if (SPEC_OCLS (sym
->etype
)->paged
)
1248 stack_offset
= func
->xstack
;
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
));
1265 /* otherwise give rname */
1266 dbuf_printf (oBuf
, "with name '%s'\n", sym
->rname
);
1272 /*----------------------------------------------------------------------*/
1273 /* canOverlayLocals - returns true if the local variables can overlayed */
1274 /*----------------------------------------------------------------------*/
1276 canOverlayLocals (eBBlock
** ebbs
, int count
)
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
||
1285 (IFFUNC_ISREENT (currFunc
->type
) ||
1286 FUNC_ISISR (currFunc
->type
))) ||
1287 elementsInSet (overlay
->syms
) == 0)
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
))
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
++)
1308 for (ic
= ebbs
[i
]->sch
; ic
; ic
= ic
->next
)
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
)
1324 /* no function calls found return TRUE */
1328 /*-----------------------------------------------------------------*/
1329 /* doOverlays - move the overlay segment to appropriate location */
1330 /*-----------------------------------------------------------------*/
1332 doOverlays (eBBlock
** ebbs
, int count
)
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
1342 if (canOverlayLocals (ebbs
, count
))
1343 /* if we can then put the parameters &
1344 local variables in the overlay set */
1347 /* otherwise put them into data where they belong */
1351 /*-----------------------------------------------------------------*/
1352 /* printAllocInfo - prints allocation information for a function */
1353 /*-----------------------------------------------------------------*/
1355 printAllocInfo (symbol
*func
, struct dbuf_s
*oBuf
)
1357 #define BREAKLINE ";------------------------------------------------------------\n"
1360 set
*tempOverlaySyms
;
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
;
1391 dbuf_append_str (oBuf
, BREAKLINE
);