1 /*-----------------------------------------------------------------*/
2 /* SDCCmem.c - 8051 memory management routines */
3 /*-----------------------------------------------------------------*/
12 #include "SDCChasht.h"
14 #include "SDCCicode.h"
18 memmap *xstack= NULL ; /* xternal stack data */
19 memmap *istack= NULL; /* internal stack */
20 memmap *code = NULL; /* code segment */
21 memmap *data = NULL; /* internal data upto 128 */
22 memmap *xdata = NULL; /* external data */
23 memmap *idata = NULL; /* internal data upto 256 */
24 memmap *bit = NULL; /* bit addressable space */
25 memmap *statsg= NULL; /* the constant data segment */
26 memmap *sfr = NULL; /* register space */
27 memmap *reg = NULL; /* register space */
28 memmap *sfrbit= NULL; /* sfr bit space */
29 memmap *generic=NULL; /* is a generic pointer */
30 memmap *overlay=NULL; /* overlay segment */
32 /* this is a set of sets each set containing
33 symbols in a single overlay */
34 set *ovrSetSets = NULL;
36 extern set *operKeyReset ;
37 extern set *tmpfileSet ;
38 extern symbol *interrupts[];
40 int fatalError = 0 ;/* fatal error flag */
42 /*-----------------------------------------------------------------*/
43 /* allocMap - allocates a memory map */
44 /*-----------------------------------------------------------------*/
45 memmap *allocMap (char rspace, /* sfr space */
46 char farmap, /* far or near segment */
47 char paged , /* can this segment be paged */
48 char direct, /* directly addressable */
49 char bitaddr, /* bit addressable space*/
50 char codemap, /* this is code space */
51 unsigned sloc, /* starting location */
52 char *name, /* 2 character name */
58 if (!(map = GC_malloc(sizeof(memmap)))) {
59 werror(E_OUT_OF_MEM,__FILE__,sizeof(memmap));
63 memset(map, ZERO, sizeof(memmap));
67 map->direct = direct ;
68 map->bitsp = bitaddr ;
69 map->codesp = codemap ;
72 map->dbName = dbName ;
73 if (!(map->oFile = tmpfile())) {
74 werror(E_TMPFILE_FAILED);
77 addSetHead (&tmpfileSet,map->oFile);
82 /*-----------------------------------------------------------------*/
83 /* initMem - allocates and initializes all the segments */
84 /*-----------------------------------------------------------------*/
88 /* allocate all the segments */
89 /* xternal stack segment ;
96 xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME,'A');
98 /* internal stack segment ;
105 istack = allocMap (0, 0, 0, 0, 0, 0,options.stack_loc, ISTACK_NAME,'B');
114 code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME,'C');
116 /* Static segment (code for variables );
123 statsg = allocMap (0, 1, 0, 0, 0, 1,0, STATIC_NAME,'D');
125 /* Data segment - internal storage segment ;
132 data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E');
134 /* overlay segment - same as internal storage segment ;
141 overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E');
143 /* Xternal Data segment -
150 xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME,'F' );
152 /* Inderectly addressed internal data segment
159 idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,IDATA_NAME,'G' );
161 /* Static segment (code for variables );
168 bit = allocMap (0, 0, 0, 1, 1, 0,0, BIT_NAME,'H');
170 /* Special function register space :-
177 sfr = allocMap (1,0, 0, 1, 0, 0,0, REG_NAME,'I');
186 reg = allocMap (1,0, 0, 0, 0, 0, 0,REG_NAME,' ');
195 sfrbit = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,'J' );
197 /* the unknown map */
198 generic = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,' ' );
202 /*-----------------------------------------------------------------*/
203 /* allocIntoSeg - puts a symbol into a memory segment */
204 /*-----------------------------------------------------------------*/
205 void allocIntoSeg (symbol *sym)
207 memmap *segment = SPEC_OCLS(sym->etype);
209 addSet (&segment->syms,sym);
212 /*-----------------------------------------------------------------*/
213 /* allocGlobal - aassigns the output segment to a global var */
214 /*-----------------------------------------------------------------*/
215 void allocGlobal ( symbol *sym )
217 /* symbol name is internal name */
218 sprintf (sym->rname,"_%s",sym->name);
220 /* add it to the operandKey reset */
221 addSet(&operKeyReset,sym);
223 /* if this is a literal e.g. enumerated type */
224 /* put it in the data segment & do nothing */
225 if (IS_LITERAL(sym->etype)) {
226 SPEC_OCLS(sym->etype) = data ;
230 /* if this is a function then assign code space */
231 if (IS_FUNC(sym->type)) {
232 SPEC_OCLS(sym->etype) = code ;
233 /* if this is an interrupt service routine
234 then put it in the interrupt service array */
235 if (IS_ISR(sym->etype)) {
237 if (interrupts[SPEC_INTN(sym->etype)])
238 werror(E_INT_DEFINED,
239 SPEC_INTN(sym->etype),
240 interrupts[SPEC_INTN(sym->etype)]->name);
242 interrupts[SPEC_INTN(sym->etype)] = sym;
244 /* automagically extend the maximum interrupts */
245 if (SPEC_INTN(sym->etype) >= maxInterrupts )
246 maxInterrupts = SPEC_INTN(sym->etype) + 1;
248 /* if it is not compiler defined */
255 /* if this is a SFR or SBIT */
256 if ( SPEC_SCLS(sym->etype) == S_SFR ||
257 SPEC_SCLS(sym->etype) == S_SBIT ) {
259 /* if both absolute address & initial */
260 /* value specified then error */
261 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
262 werror(E_SFR_INIT,sym->name);
266 SPEC_OCLS(sym->etype) =
267 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
273 /* if this is a bit variable and no storage class */
274 if ( SPEC_NOUN(sym->etype) == V_BIT
275 && SPEC_SCLS(sym->etype) == S_BIT ) {
276 SPEC_OCLS(sym->etype) = bit ;
281 /* if bit storage class */
282 if ( SPEC_SCLS(sym->etype) == S_SBIT ) {
283 SPEC_OCLS(sym->etype) = bit;
288 /* register storage class ignored changed to FIXED */
289 if ( SPEC_SCLS(sym->etype) == S_REGISTER )
290 SPEC_SCLS(sym->etype) = S_FIXED ;
292 /* if data specified then */
293 if (SPEC_SCLS(sym->etype) == S_DATA) {
294 /* set the output class */
295 SPEC_OCLS(sym->etype) = data ;
296 /* generate the symbol */
301 /* if it is fixed, then allocate depending on the */
302 /* current memory model,same for automatics */
303 if ( SPEC_SCLS(sym->etype) == S_FIXED ||
304 SPEC_SCLS(sym->etype) == S_AUTO ) {
305 /* set the output class */
306 SPEC_OCLS(sym->etype) = ( options.model ? xdata : data ) ;
307 /* generate the symbol */
312 /* if code change to constant */
313 if ( SPEC_SCLS(sym->etype) == S_CODE ||
314 SPEC_SCLS(sym->etype) == S_CONSTANT ) {
315 SPEC_OCLS(sym->etype) = statsg ;
320 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
321 SPEC_OCLS(sym->etype) = xdata ;
326 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
327 SPEC_OCLS(sym->etype) = idata ;
336 /*-----------------------------------------------------------------*/
337 /* allocParms - parameters are always passed on stack */
338 /*-----------------------------------------------------------------*/
339 void allocParms ( value *val )
344 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
346 /* if this is a literal e.g. enumerated type */
347 if (IS_LITERAL(lval->etype)) {
348 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
349 ( options.model ? xdata : data );
352 /* if this a register parm then allocate
353 it as a local variable by adding it
354 to the first block we see in the body */
355 if (IS_REGPARM(lval->etype))
358 /* check the declaration */
359 checkDecl (lval->sym);
361 /* mark it as my parameter */
362 lval->sym->ismyparm = 1;
363 lval->sym->localof = currFunc;
366 /* if automatic variables r 2b stacked */
367 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
370 lval->sym->onStack = 1;
372 /* choose which stack 2 use */
373 /* use xternal stack */
374 if ( options.useXstack ) {
375 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
376 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
377 xstackPtr - getSize(lval->type);
378 xstackPtr -= getSize (lval->type);
380 else { /* use internal stack */
381 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
382 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
383 stackPtr - ( SPEC_BANK(currFunc->etype) ? 1 : 0) -
384 getSize(lval->type) -
385 (IS_ISR(currFunc->etype) ? 4 : 0);
386 stackPtr -= getSize (lval->type);
388 allocIntoSeg(lval->sym);
390 else { /* allocate them in the automatic space */
391 /* generate a unique name */
392 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
393 strcpy (lval->name,lval->sym->rname);
395 /* if declared in external storage */
396 if (SPEC_SCLS(lval->etype) == S_XDATA)
397 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
399 /* other wise depending on the memory model
400 note here that we put it into the overlay segment
401 first, we will remove it from the overlay segment
402 after the overlay determination has been done */
403 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
404 ( options.model ? xdata : (options.noOverlay ? data :overlay ));
406 allocIntoSeg(lval->sym);
413 /*-----------------------------------------------------------------*/
414 /* deallocParms - parameters are always passed on stack */
415 /*-----------------------------------------------------------------*/
416 void deallocParms ( value *val )
420 for ( lval = val ; lval ; lval = lval->next ) {
422 /* unmark is myparm */
423 lval->sym->ismyparm = 0;
424 /* if on stack then depending on which stack */
426 /* delete it from the symbol table */
427 deleteSym (SymbolTab,lval->sym,lval->sym->name);
429 if (!lval->sym->isref) {
430 lval->sym->allocreq = 1;
431 werror(W_NO_REFERENCE,currFunc->name,
432 "function argument",lval->sym->name);
435 /* move the rname if any to the name for both val & sym */
436 /* and leave a copy of it in the symbol table */
437 if (lval->sym->rname[0]) {
438 char buffer[SDCC_NAME_MAX];
439 strcpy(buffer,lval->sym->rname);
440 lval->sym = copySymbol(lval->sym);
441 strcpy(lval->sym->rname,buffer);
442 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
443 addSym (SymbolTab, lval->sym, lval->sym->name,
444 lval->sym->level,lval->sym->block);
445 lval->sym->_isparm = 1;
446 addSet(&operKeyReset,lval->sym);
454 /*-----------------------------------------------------------------*/
455 /* allocLocal - allocate local variables */
456 /*-----------------------------------------------------------------*/
457 void allocLocal ( symbol *sym )
460 /* generate an unique name */
461 sprintf(sym->rname,"_%s_%s_%d_%d",
462 currFunc->name,sym->name,sym->level,sym->block);
465 sym->localof = currFunc;
467 /* if this is a static variable */
468 if ( IS_STATIC (sym->etype)) {
469 SPEC_OCLS(sym->etype) = (options.model ? xdata : data );
475 /* if volatile then */
476 if (IS_VOLATILE(sym->etype))
479 /* this is automatic */
481 /* if it to be placed on the stack */
482 if ( options.stackAuto || reentrant) {
485 if ( options.useXstack ) {
486 SPEC_OCLS(sym->etype) = xstack ;
487 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
488 xstackPtr += getSize (sym->type) ;
491 SPEC_OCLS(sym->etype) = istack ;
492 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
493 stackPtr += getSize (sym->type) ;
499 /* else depending on the storage class specified */
500 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
501 SPEC_OCLS(sym->etype) = xdata ;
506 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
507 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
509 SPEC_OCLS(sym->etype) = statsg ;
514 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
515 SPEC_OCLS(sym->etype) = idata ;
521 /* if this is a function then assign code space */
522 if (IS_FUNC(sym->type)) {
523 SPEC_OCLS(sym->etype) = code ;
527 /* if this is a SFR or SBIT */
528 if ( SPEC_SCLS(sym->etype) == S_SFR ||
529 SPEC_SCLS(sym->etype) == S_SBIT ) {
531 /* if both absolute address & initial */
532 /* value specified then error */
533 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
534 werror(E_SFR_INIT,sym->name);
538 SPEC_OCLS(sym->etype) =
539 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
545 /* if this is a bit variable and no storage class */
546 if ( SPEC_NOUN(sym->etype) == V_BIT
547 && (SPEC_SCLS(sym->etype) == S_BIT)) {
548 SPEC_OCLS(sym->etype) = bit ;
553 /* again note that we have put it into the overlay segment
554 will remove and put into the 'data' segment if required after
555 overlay analysis has been done */
556 SPEC_OCLS(sym->etype) = ( options.model ? xdata :
557 (options.noOverlay ? data : overlay )) ;
561 /*-----------------------------------------------------------------*/
562 /* deallocLocal - deallocates the local variables */
563 /*-----------------------------------------------------------------*/
564 void deallocLocal ( symbol *csym )
568 for ( sym = csym ; sym ; sym = sym->next) {
572 /* if it is on the stack */
574 if (options.useXstack)
575 xstackPtr -= getSize(sym->type);
577 stackPtr -= getSize(sym->type);
579 /* if not used give a warning */
580 if (!sym->isref && !IS_STATIC(sym->etype))
581 werror(W_NO_REFERENCE,currFunc->name,
582 "local variable",sym->name);
583 /* now delete it from the symbol table */
584 deleteSym (SymbolTab,sym,sym->name);
588 /*-----------------------------------------------------------------*/
589 /* overlay2data - moves declarations from the overlay seg to data */
590 /*-----------------------------------------------------------------*/
595 for (sym = setFirstItem(overlay->syms); sym;
596 sym = setNextItem(overlay->syms)) {
598 SPEC_OCLS(sym->etype) = data;
602 setToNull((void **) &overlay->syms);
606 /*-----------------------------------------------------------------*/
607 /* overlay2Set - will add all symbols from the overlay segment to */
608 /* the set of sets containing the overlable symbols */
609 /*-----------------------------------------------------------------*/
615 for (sym = setFirstItem(overlay->syms); sym;
616 sym = setNextItem(overlay->syms)) {
621 setToNull((void **) &overlay->syms);
622 addSet (&ovrSetSets,oset);
626 /*-----------------------------------------------------------------*/
627 /* allocVariables - creates decl & assign storage class for a v */
628 /*-----------------------------------------------------------------*/
629 int allocVariables ( symbol *symChain )
636 /* go thru the symbol chain */
637 for ( sym = symChain ; sym ; sym = sym->next ) {
639 /* if this is a typedef then add it */
640 /* to the typedef table */
641 if (IS_TYPEDEF(sym->etype)) {
642 /* check if the typedef already exists */
643 csym = findSym (TypedefTab, NULL, sym->name );
644 if ( csym && csym->level == sym->level )
645 werror(E_DUPLICATE_TYPEDEF,sym->name);
647 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
648 continue ; /* go to the next one */
650 /* make sure it already exist */
651 csym = findSymWithLevel (SymbolTab, sym);
652 if (! csym || (csym && csym->level != sym->level) )
655 /* check the declaration */
658 /* if this is a function or a pointer to function */
659 /* then args processing */
660 if (funcInChain(csym->type)) {
662 processFuncArgs (csym, 1);
663 /* if register bank specified then update maxRegBank */
664 if (maxRegBank < SPEC_BANK(csym->etype))
665 maxRegBank = SPEC_BANK(csym->etype);
668 /* if this is a extern variable then change the */
669 /* level to zero temporarily */
670 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
671 saveLevel = csym->level ;
675 /* if this is a literal then it is an enumerated */
676 /* type so need not allocate it space for it */
677 if (IS_LITERAL(sym->etype))
680 /* generate the actual declaration */
684 stack += getSize(csym->type) ;
689 /* restore the level */
690 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
691 csym->level = saveLevel;
697 /*-----------------------------------------------------------------*/
698 /* redoStackOffsets :- will reassign the values for stack offsets */
699 /*-----------------------------------------------------------------*/
700 void redoStackOffsets ()
706 /* after register allocation is complete we know
707 which variables will need to be assigned space
708 on the stack. We will eliminate those variables
709 which do not have the allocReq flag thus reducing
711 for ( sym = setFirstItem(istack->syms); sym;
712 sym = setNextItem(istack->syms)) {
714 int size = getSize(sym->type);
715 /* nothing to do with parameters so continue */
716 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
719 if ( IS_AGGREGATE(sym->type)) {
720 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
725 /* if allocation not required then subtract
726 size from overall stack size & continue */
727 if (!sym->allocreq) {
728 currFunc->stack -= size;
729 SPEC_STAK(currFunc->etype) -= size;
733 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
737 /* do the same for the external stack */
739 for ( sym = setFirstItem(xstack->syms); sym;
740 sym = setNextItem(xstack->syms)) {
742 int size = getSize(sym->type);
743 /* nothing to do with parameters so continue */
744 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
747 if (IS_AGGREGATE(sym->type)) {
748 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
753 /* if allocation not required then subtract
754 size from overall stack size & continue */
755 if (!sym->allocreq) {
756 currFunc->xstack -= size;
757 SPEC_STAK(currFunc->etype) -= size;
761 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
765 /* if the debug option is set then output the
766 symbols to the map file */
768 for (sym = setFirstItem(istack->syms); sym;
769 sym = setNextItem(istack->syms))
770 cdbSymbol(sym,cdbFile,FALSE,FALSE);
772 for (sym = setFirstItem(xstack->syms); sym;
773 sym = setNextItem(xstack->syms))
774 cdbSymbol(sym,cdbFile,FALSE,FALSE);