void outputDebugStackSymbols (void) { if (getenv ("SDCC_DEBUG_VAR_STORAGE")) { dumpSymInfo ("XStack", xstack); dumpSymInfo ("IStack", istack); } if (options.debug && debugFile) { symbol *sym; if (xstack) { for (sym = setFirstItem (xstack->syms); sym; sym = setNextItem (xstack->syms)) debugFile->writeSymbol (sym); } if (istack) { for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms)) debugFile->writeSymbol(sym); } } }
/*------------------------------------------------------------------*/ static void markWholeLoop (eBBlock *ebp, int key) { eBBlock *ebpi; /* avoid endless loops */ ebp->visited = 1; /* recurse through all predecessors */ for (ebpi = setFirstItem (ebp->predList); ebpi; ebpi = setNextItem (ebp->predList)) { if (ebpi->visited) continue; /* is the predecessor still in the loop? */ if (ebpi->depth == 0) continue; markWholeLoop (ebpi, key); } /* recurse through all successors */ for (ebpi = setFirstItem (ebp->succList); ebpi; ebpi = setNextItem (ebp->succList)) { if (ebpi->visited) continue; if (ebpi->depth == 0) continue; markWholeLoop (ebpi, key); } markAlive (ebp->sch, ebp->ech, key); }
static void dbg_regusage(set *fregs) { regs *reg; pCode *pcfl; pCode *pc; for (reg = setFirstItem(fregs) ; reg ; reg = setNextItem(fregs)) { if(elementsInSet(reg->reglives.usedpCodes)) { fprintf (stderr, "%s addr=0x%03x rIdx=0x%03x", reg->name, reg->address, reg->rIdx); pcfl = setFirstItem(reg->reglives.usedpFlows); if(pcfl) fprintf(stderr, "\n used in seq"); while(pcfl) { fprintf(stderr," 0x%03x",pcfl->seq); pcfl = setNextItem(reg->reglives.usedpFlows); } pcfl = setFirstItem(reg->reglives.assignedpFlows); if(pcfl) fprintf(stderr, "\n assigned in seq"); while(pcfl) { fprintf(stderr," 0x%03x",pcfl->seq); pcfl = setNextItem(reg->reglives.assignedpFlows); } pc = setFirstItem(reg->reglives.usedpCodes); if(pc) fprintf(stderr, "\n used in instructions "); while(pc) { pcfl = PCODE(PCI(pc)->pcflow); if(pcfl) fprintf(stderr," 0x%03x:",pcfl->seq); fprintf(stderr,"0x%03x",pc->seq); pc = setNextItem(reg->reglives.usedpCodes); } fprintf(stderr, "\n"); } } }
static void visit (set **visited, iCode *ic, const int key) { symbol *lbl; while (ic && !isinSet (*visited, ic) && bitVectBitValue (ic->rlive, key)) { addSet (visited, ic); switch (ic->op) { case GOTO: ic = hTabItemWithKey (labelDef, (IC_LABEL (ic))->key); break; case RETURN: ic = hTabItemWithKey (labelDef, returnLabel->key); break; case JUMPTABLE: for (lbl = setFirstItem (IC_JTLABELS (ic)); lbl; lbl = setNextItem (IC_JTLABELS (ic))) visit (visited, hTabItemWithKey (labelDef, lbl->key), key); break; case IFX: visit (visited, hTabItemWithKey (labelDef, (IC_TRUE(ic) ? IC_TRUE (ic) : IC_FALSE (ic))->key), key); ic = ic->next; break; default: ic = ic->next; if (!POINTER_SET (ic) && IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)) && OP_SYMBOL_CONST (IC_RESULT (ic))->key == key) { addSet (visited, ic); return; } } } }
void dumpSymInfo(char *pcName, memmap *memItem) { symbol *sym; if (!memItem) return; printf("--------------------------------------------\n"); printf(" %s\n", pcName); for(sym = setFirstItem(memItem->syms); sym; sym = setNextItem(memItem->syms)) { printf(" %s, isReqv:%d, reqv:0x%p, onStack:%d, Stack:%d, nRegs:%d, [", sym->rname, sym->isreqv, sym->reqv, sym->onStack, sym->stack, sym->nRegs); if(sym->reqv) { int i; symbol *TempSym = OP_SYMBOL (sym->reqv); for (i = 0; i < 4; i++) if(TempSym->regs[i]) printf("%s,", port->getRegName(TempSym->regs[i])); } printf("]\n"); } printf("\n"); }
static void dbg_dumpFlow(pBlock *pb) { pCode *pcflow; for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); pcflow != NULL; pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { if(!isPCFL(pcflow)) fprintf(stderr, "LinkFlow - pcflow is not a flow object "); fprintf(stderr, "Flow: 0x%x",pcflow->seq); if(PCFL(pcflow) && PCFL(pcflow)->ancestor) fprintf(stderr,", ancestor 0x%x\n", PCFL(pcflow)->ancestor->pc.seq); else { pCodeFlowLink *from = (PCFL(pcflow)->from) ? (PCFLINK(setFirstItem(PCFL(pcflow)->from))) : NULL; fprintf(stderr," no ancestor"); while(from) { fprintf(stderr," (0x%x)",from->pcflow->pc.seq); from = setNextItem(PCFL(pcflow)->from); } fprintf(stderr,"\n"); } } }
void TrackSequenceManager::slotItemAboutToDie(PlaylistItem *item) { if(item == m_playNextItem) { setNextItem(0); } m_iterator->itemAboutToDie(item); }
/*------------------------------------------------------------------*/ static bool findPrevUseSym (eBBlock *ebp, iCode *ic, symbol * sym) { eBBlock * pred; iCode * uic; if (ebp->visited) { /* already visited: this branch must have been succesfull, */ /* because otherwise the search would have been aborted. */ return TRUE; } ebp->visited = 1; /* search backward in the current block */ for (uic = ic; uic; uic = uic->prev) { if (!POINTER_SET (uic) && IS_AUTOSYM (IC_RESULT (uic))) { if (IC_RESULT (uic)->key == sym->key) { /* Ok, found a definition */ return TRUE; } } /* address taken from symbol? */ if (uic->op == ADDRESS_OF && IS_AUTOSYM (IC_LEFT (uic))) { if (IC_LEFT (uic)->key == sym->key) { /* Ok, found a definition */ return TRUE; } } } /* There's no definition in this bblock, */ /* let's have a look at all predecessors. */ pred = setFirstItem (ebp->predList); if (!pred) { /* no more predecessors and nothing found yet :-( */ return FALSE; } for (; pred; pred = setNextItem (ebp->predList)) { /* recurse into all predecessors */ if (!findPrevUseSym (pred, pred->ech, sym)) { /* found nothing: abort */ return FALSE; } } /* Success! Went through all branches with no abort: */ /* all branches end with a definition */ return TRUE; }
/*-----------------------------------------------------------------*/ set * edgesTo (eBBlock * to) { set *result = NULL; edge *loop; for (loop = setFirstItem (graphEdges); loop; loop = setNextItem (graphEdges)) if (loop->to == to && !loop->from->noPath) addSet (&result, loop->from); return result; }
/*-----------------------------------------------------------------*/ static void printAllocInfoSeg (memmap * map, symbol * func, struct dbuf_s *oBuf) { symbol *sym; if (!map) return; if (!map->syms) return; for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) { if (sym->level == 0) continue; if (sym->localof != func) continue; dbuf_printf (oBuf, ";%-25s Allocated ", sym->name); /* if assigned to registers */ if (!sym->allocreq && sym->reqv) { int i; sym = OP_SYMBOL (sym->reqv); if (!sym->isspilt || sym->remat) { dbuf_append_str (oBuf, "to registers "); for (i = 0; i < 4 && sym->regs[i]; i++) dbuf_printf (oBuf, "%s ", port->getRegName (sym->regs[i])); dbuf_append_char (oBuf, '\n'); continue; } else { sym = sym->usl.spillLoc; } } /* if on stack */ if (sym->onStack) { dbuf_printf (oBuf, "to stack - offset %d\n", sym->stack); continue; } /* otherwise give rname */ dbuf_printf (oBuf, "with name '%s'\n", sym->rname); } }
/*-----------------------------------------------------------------*/ void overlay2data () { symbol *sym; for (sym = setFirstItem (overlay->syms); sym; sym = setNextItem (overlay->syms)) { SPEC_OCLS (sym->etype) = data; allocIntoSeg (sym); } setToNull ((void *) &overlay->syms); }
/*-----------------------------------------------------------------*/ void overlay2Set () { symbol *sym; set *oset = NULL; for (sym = setFirstItem (overlay->syms); sym; sym = setNextItem (overlay->syms)) { addSet (&oset, sym); } setToNull ((void *) &overlay->syms); addSet (&ovrSetSets, oset); }
int pic14_stringInSet(const char *str, set **world, int autoAdd) { char *s; if (!str) return 1; assert(world); for (s = setFirstItem(*world); s; s = setNextItem(*world)) { /* found in set */ if (0 == strcmp(s, str)) return 1; } /* not found */ if (autoAdd) addSet(world, Safe_strdup(str)); return 0; }
static void pic14printLocals (struct dbuf_s *oBuf) { set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/, dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ }; regs *reg; int i, is_first = 1; static unsigned sectionNr = 0; /* emit all registers from all possible sets */ for (i = 0; i < 6; i++) { if (allregs[i] == NULL) continue; for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) { if (reg->isEmitted) continue; if (reg->wasUsed && !reg->isExtern) { if (!pic14_stringInSet(reg->name, &emitted, 1)) { if (reg->isFixed) { // Should not happen, really... assert ( !"Compiler-assigned variables should not be pinned... This is a bug." ); dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n", moduleName, sectionNr++, reg->address, reg->name, reg->size); } else { if (getenv("SDCC_PIC14_SPLIT_LOCALS")) { // assign each local register into its own section dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n", moduleName, sectionNr++, reg->name, reg->size); } else { // group all local registers into a single section // This should greatly improve BANKSEL generation... if (is_first) { dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++); is_first = 0; } dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size); } } } } reg->isEmitted = 1; } // for } // for }
PlaylistItem *TrackSequenceManager::nextItem() { if(m_playNextItem) { // Force the iterator to reset state (such as random item lists) m_iterator->reset(); m_iterator->prepareToPlay(m_playNextItem->playlist()); m_iterator->setCurrent(m_playNextItem); // clear pending and the protection for it setNextItem(0); } else if(m_iterator->current()) m_iterator->advance(); else if(m_defaultPlaylist) m_iterator->prepareToPlay(m_defaultPlaylist); else m_iterator->prepareToPlay(CollectionList::instance()); return m_iterator->current(); }
/*-----------------------------------------------------------------*/ eBBlock * immedDom (ebbIndex * ebbi, eBBlock * ebp) { /* first delete self from the list */ set *iset = domSetFromVect (ebbi, ebp->domVect); eBBlock *loop; eBBlock *idom = NULL; deleteSetItem (&iset, ebp); /* then just return the one with the greatest */ /* depthfirst number, this will be the immed dominator */ if ((loop = setFirstItem (iset))) idom = loop; for (; loop; loop = setNextItem (iset)) if (loop->dfnum > idom->dfnum) idom = loop; setToNull ((void *) &iset); return idom; }
/** noOverLap - will iterate through the list looking for over lap */ static int noOverLap (set *itmpStack, symbol *fsym) { symbol *sym; for (sym = setFirstItem (itmpStack); sym; sym = setNextItem (itmpStack)) { if (bitVectBitValue (sym->clashes, fsym->key)) return 0; #if 0 // if sym starts before (or on) our end point // and ends after (or on) our start point, // it is an overlap. if (sym->liveFrom <= fsym->liveTo && sym->liveTo >= fsym->liveFrom) { return 0; } #endif } return 1; }
/*-----------------------------------------------------------------*/ void printAllocInfo (symbol * func, struct dbuf_s * oBuf) { #define BREAKLINE ";------------------------------------------------------------\n" int cnt = 0; set *ovrset; set *tempOverlaySyms; if (!func) return; /* must be called after register allocation is complete */ dbuf_append_str (oBuf, BREAKLINE); dbuf_printf (oBuf, ";Allocation info for local variables in function '%s'\n", func->name); dbuf_append_str (oBuf, BREAKLINE); cnt += printAllocInfoSeg (xstack, func, oBuf); cnt += printAllocInfoSeg (istack, func, oBuf); cnt += printAllocInfoSeg (code, func, oBuf); cnt += printAllocInfoSeg (data, func, oBuf); cnt += printAllocInfoSeg (xdata, func, oBuf); cnt += printAllocInfoSeg (idata, func, oBuf); cnt += printAllocInfoSeg (sfr, func, oBuf); cnt += printAllocInfoSeg (sfrbit, func, oBuf); tempOverlaySyms = overlay->syms; /* search the set of overlay sets for local variables/parameters */ for (ovrset = setFirstItem (ovrSetSets); ovrset; ovrset = setNextItem (ovrSetSets)) { overlay->syms = ovrset; cnt += printAllocInfoSeg (overlay, func, oBuf); } overlay->syms = tempOverlaySyms; if (cnt) dbuf_append_str (oBuf, BREAKLINE); }
/*-----------------------------------------------------------------* * void pic16_pCodeRegMapLiveRanges(pBlock *pb) *-----------------------------------------------------------------*/ void pic16_pCodeRegMapLiveRanges(pBlock *pb) { pCode *pcflow; for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); pcflow != NULL; pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) { if(!isPCFL(pcflow)) { fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object "); continue; } pCodeRegMapLiveRangesInFlow(PCFL(pcflow)); } #if 0 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); pcflow != NULL; pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) { regs *r = setFirstItem(PCFL(pcflow)->registers); fprintf(stderr,"flow seq %d\n", pcflow->seq); while (r) { fprintf(stderr, " %s\n",r->name); r = setNextItem(PCFL(pcflow)->registers); } } #endif #if HAVE_DBGREGUSAGE dbg_dumpregusage(); #endif }
/*-----------------------------------------------------------------*/ static void rlivePoint (eBBlock ** ebbs, int count, bool emitWarnings) { int i, key; eBBlock *succ; bitVect *alive; /* for all blocks do */ for (i = 0; i < count; i++) { iCode *ic; /* for all instructions in this block do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { if (!ic->rlive) ic->rlive = newBitVect (operandKey); if (SKIP_IC2(ic)) continue; if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic))) { incUsed (ic, IC_JTCOND(ic)); if (!IS_AUTOSYM(IC_JTCOND(ic))) continue; findPrevUse (ebbs[i], ic, IC_JTCOND(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_JTCOND(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_JTCOND(ic)->key); findNextUse (ebbs[i], ic->next, IC_JTCOND(ic)); } continue; } if (ic->op == IFX && IS_SYMOP(IC_COND(ic))) { incUsed (ic, IC_COND(ic)); if (!IS_AUTOSYM(IC_COND(ic))) continue; findPrevUse (ebbs[i], ic, IC_COND(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_COND(ic))) { unvisitBlocks (ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_COND(ic)->key); findNextUse (ebbs[i], ic->next, IC_COND(ic)); } continue; } if (IS_SYMOP(IC_LEFT(ic))) { incUsed (ic, IC_LEFT(ic)); if (IS_AUTOSYM(IC_LEFT(ic)) && ic->op != ADDRESS_OF) { findPrevUse (ebbs[i], ic, IC_LEFT(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_LEFT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_LEFT(ic)->key); findNextUse (ebbs[i], ic->next, IC_LEFT(ic)); /* if this is a send extend the LR to the call */ if (ic->op == SEND) { iCode *lic; for (lic = ic; lic; lic = lic->next) { if (lic->op == CALL || lic->op == PCALL) { markAlive (ic, lic->prev, IC_LEFT (ic)->key); break; } } } } } } if (IS_SYMOP(IC_RIGHT(ic))) { incUsed (ic, IC_RIGHT(ic)); if (IS_AUTOSYM(IC_RIGHT(ic))) { findPrevUse (ebbs[i], ic, IC_RIGHT(ic), ebbs, count, emitWarnings); if (IS_ITEMP(IC_RIGHT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_RIGHT(ic)->key); findNextUse (ebbs[i], ic->next, IC_RIGHT(ic)); } } } if (POINTER_SET(ic) && IS_SYMOP(IC_RESULT(ic))) incUsed (ic, IC_RESULT(ic)); if (IS_AUTOSYM(IC_RESULT(ic))) { if (POINTER_SET(ic)) { findPrevUse (ebbs[i], ic, IC_RESULT(ic), ebbs, count, emitWarnings); } if (IS_ITEMP(IC_RESULT(ic))) { unvisitBlocks(ebbs, count); ic->rlive = bitVectSetBit (ic->rlive, IC_RESULT(ic)->key); findNextUse (ebbs[i], ic->next, IC_RESULT(ic)); /* findNextUse sometimes returns 0 here, which means that ic is dead code. Something should be done about this dead code since e.g. register allocation suffers. */ } } if (!POINTER_SET(ic) && IC_RESULT(ic)) ic->defKey = IC_RESULT(ic)->key; } /* check all symbols that are alive in the last instruction */ /* but are not alive in all successors */ succ = setFirstItem (ebbs[i]->succList); if (!succ) continue; alive = succ->sch->rlive; while ((succ = setNextItem (ebbs[i]->succList))) { if (succ->sch) alive = bitVectIntersect (alive, succ->sch->rlive); } if (ebbs[i]->ech) alive = bitVectCplAnd ( bitVectCopy (ebbs[i]->ech->rlive), alive); if(!alive) continue; for (key = 1; key < alive->size; key++) { if (!bitVectBitValue (alive, key)) continue; unvisitBlocks(ebbs, count); findNextUseSym (ebbs[i], NULL, hTabItemWithKey (liveRanges, key)); } } }
/*-----------------------------------------------------------------*/ static int printAllocInfoSeg (memmap * map, symbol * func, struct dbuf_s *oBuf) { symbol *sym; int flg = FALSE; if (!map || !map->syms) return 0; for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) { if (sym->level == 0) continue; if (sym->localof != func) continue; dbuf_printf (oBuf, ";%-25s Allocated ", sym->name); flg = TRUE; /* if assigned to registers */ if (!sym->allocreq && sym->reqv) { int i; sym = OP_SYMBOL (sym->reqv); if (!sym->isspilt || sym->remat) { dbuf_append_str (oBuf, "to registers "); for (i = 0; i < 4 && sym->regs[i]; i++) dbuf_printf (oBuf, "%s ", port->getRegName (sym->regs[i])); dbuf_append_char (oBuf, '\n'); continue; } else { sym = sym->usl.spillLoc; } } /* if on stack */ if (sym->onStack) { int stack_offset = 0; if (options.omitFramePtr) { if (SPEC_OCLS (sym->etype)->paged) stack_offset = func->xstack; else stack_offset = func->stack; } dbuf_printf (oBuf, "to stack - %s %+d\n", SYM_BP (sym), sym->stack - stack_offset); continue; } /* otherwise give rname */ dbuf_printf (oBuf, "with name '%s'\n", sym->rname); } return flg; }
/*-----------------------------------------------------------------*/ void redoStackOffsets (void) { symbol *sym; int sPtr = 0; int xsPtr = -1; /* after register allocation is complete we know which variables will need to be assigned space on the stack. We will eliminate those variables which do not have the allocReq flag thus reducing the stack space */ for (sym = setFirstItem (istack->syms); sym; sym = setNextItem (istack->syms)) { int size = getSize (sym->type); /* nothing to do with parameters so continue */ if ((sym->_isparm && !IS_REGPARM (sym->etype))) continue; if (BTREE_STACK) { /* Remove them all, and let btree_alloc() below put them back in more efficiently. */ currFunc->stack -= size; SPEC_STAK (currFunc->etype) -= size; if(IS_AGGREGATE (sym->type) || sym->allocreq) btree_add_symbol (sym); } /* Do it the old way - compared to the btree approach we waste space when allocating variables that had their address taken, unions and aggregates. */ else { /* if allocation not required then subtract size from overall stack size & continue */ if (!IS_AGGREGATE (sym->type) && !sym->allocreq) { currFunc->stack -= size; SPEC_STAK (currFunc->etype) -= size; continue; } if (port->stack.direction > 0) { SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1); sPtr += size; } else { sPtr -= size; SPEC_STAK (sym->etype) = sym->stack = sPtr; } } } if (BTREE_STACK && elementsInSet (istack->syms)) { btree_alloc (); btree_clear (); } /* do the same for the external stack */ if (!xstack) return; for (sym = setFirstItem (xstack->syms); sym; sym = setNextItem (xstack->syms)) { int size = getSize (sym->type); /* nothing to do with parameters so continue */ if ((sym->_isparm && !IS_REGPARM (sym->etype))) continue; if (IS_AGGREGATE (sym->type)) { SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1); xsPtr += size; continue; } /* if allocation not required then subtract size from overall stack size & continue */ if (!sym->allocreq) { currFunc->xstack -= size; SPEC_STAK (currFunc->etype) -= size; continue; } SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1); xsPtr += size; } }
/*-----------------------------------------------------------------*/ void computeDataFlow (eBBlock ** ebbs, int count) { int i; int change = 1; while (change) { change = 0; /* for all blocks */ for (i = 0; i < count; i++) { set *pred; set *oldOut; int firstTime; eBBlock *pBlock; /* if this is the entry block then continue */ /* since entry block can never have any inExprs */ if (ebbs[i]->noPath) continue; /* get blocks that can come to this block */ pred = edgesTo (ebbs[i]); /* make a copy of the outExpressions : to be */ /* used for iteration */ oldOut = setFromSet (ebbs[i]->outExprs); setToNull ((void **) &ebbs[i]->inDefs); /* indefitions are easy just merge them by union */ /* these are the definitions that can possibly */ /* reach this block */ firstTime = 1; applyToSet (pred, mergeInDefs, ebbs[i], &firstTime); /* if none of the edges coming to this block */ /* dominate this block then add the immediate dominator */ /* of this block to the list of predecessors */ for (pBlock = setFirstItem (pred); pBlock; pBlock = setNextItem (pred)) { if (bitVectBitValue (ebbs[i]->domVect, pBlock->bbnum)) break; } /* get the immediate dominator and put it there */ if (!pBlock) { eBBlock *idom = immedDom (ebbs, ebbs[i]); if (idom) addSetHead (&pred, idom); } /* figure out the incoming expressions */ /* this is a little more complex */ setToNull ((void **) &ebbs[i]->inExprs); if (optimize.global_cse) { firstTime = 1; applyToSet (pred, mergeInExprs, ebbs[i], &firstTime); } setToNull ((void **) &pred); /* do cse with computeOnly flag set to TRUE */ /* this by far the quickest way of computing */ cseBBlock (ebbs[i], TRUE, ebbs, count); /* if it change we will need to iterate */ change += !isSetsEqualWith (ebbs[i]->outExprs, oldOut, isCseDefEqual); } if (!change) /* iterate till no change */ break; } return; }
static void pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf) { memmap *maps[] = { data, sfr, NULL }; int i; hTab *ht = NULL; symbol *sym; set *aliases; int addr, min=-1, max=-1; int size; for (i=0; maps[i] != NULL; i++) { for (sym = (symbol *)setFirstItem (maps[i]->syms); sym; sym = setNextItem (maps[i]->syms)) { if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype)) { addr = SPEC_ADDR(sym->etype); /* handle CONFIG words here */ if (IS_CONFIG_ADDRESS( addr )) { //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr ); //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) ); if (sym->ival) { pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) ); } else { fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name ); } continue; } if (max == -1 || addr > max) max = addr; if (min == -1 || addr < min) min = addr; //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr); aliases = hTabItemWithKey (ht, addr); if (aliases) { /* May not use addSetHead, as we cannot update the * list's head in the hastable `ht'. */ addSet (&aliases, sym); #if 0 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n", __FUNCTION__, elementsInSet(aliases), sym->name, addr); #endif } else { addSet (&aliases, sym); hTabAddItem (&ht, addr, aliases); } // if } // if } // for sym } // for i /* now emit definitions for all absolute symbols */ dbuf_printf (oBuf, "%s", iComments2); dbuf_printf (oBuf, "; absolute symbol definitions\n"); dbuf_printf (oBuf, "%s", iComments2); for (addr=min; addr <= max; addr++) { size = 1; aliases = hTabItemWithKey (ht, addr); if (aliases && elementsInSet(aliases)) { /* Make sure there is no initialized value at this location! */ for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) { if (sym->ival) break; } // for if (sym) continue; dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n", moduleName, addr, addr); for (sym = setFirstItem (aliases); sym; sym = setNextItem (aliases)) { if (getSize(sym->type) > size) { size = getSize(sym->type); } /* initialized values are handled somewhere else */ if (sym->ival) continue; /* emit STATUS as well as _STATUS, required for SFRs only */ //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name); dbuf_printf (oBuf, "%s\n", sym->rname); if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) { //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name); emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname); } // if } // for dbuf_printf (oBuf, "\tres\t%d\n", size); } // if } // for i }
/*-----------------------------------------------------------------*/ void separateLiveRanges (iCode *sic, ebbIndex *ebbi) { iCode *ic; set *candidates = 0; symbol *sym; // printf("separateLiveRanges()\n"); for (ic = sic; ic; ic = ic->next) { if (ic->op == IFX || ic->op == GOTO || ic->op == JUMPTABLE || !IC_RESULT (ic) || !IS_ITEMP (IC_RESULT (ic)) || bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) <= 1 || isinSet (candidates, OP_SYMBOL (IC_RESULT (ic)))) continue; addSet (&candidates, OP_SYMBOL (IC_RESULT (ic))); } if (!candidates) return; for(sym = setFirstItem (candidates); sym; sym = setNextItem (candidates)) { // printf("Looking at %s, %d definitions\n", sym->name, bitVectnBitsOn (sym->defs)); int i; set *defs = 0; for (i = 0; i < sym->defs->size; i++) if (bitVectBitValue (sym->defs, i)) { iCode *dic; if(dic = hTabItemWithKey (iCodehTab, i)) addSet (&defs, hTabItemWithKey (iCodehTab, i)); else { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Definition not found"); return; } } do { set *visited = 0; set *newdefs = 0; int oldsize; wassert (defs); wassert (setFirstItem (defs)); // printf("Looking at def at %d now\n", ((iCode *)(setFirstItem (defs)))->key); if (!bitVectBitValue (((iCode *)(setFirstItem (defs)))->rlive, sym->key)) { werror (W_INTERNAL_ERROR, __FILE__, __LINE__, "Variable is not alive at one of its definitions"); break; } visit (&visited, setFirstItem (defs), sym->key); addSet (&newdefs, setFirstItem (defs)); do { oldsize = elementsInSet(visited); ic = setFirstItem (defs); for(ic = setNextItem (defs); ic; ic = setNextItem (defs)) { // printf("Looking at other def at %d now\n", ic->key); set *visited2 = 0; set *intersection = 0; visit (&visited2, ic, sym->key); intersection = intersectSets (visited, visited2, THROW_NONE); intersection = subtractFromSet (intersection, defs, THROW_DEST); if (intersection) { visited = unionSets (visited, visited2, THROW_DEST); addSet (&newdefs, ic); } deleteSet (&intersection); deleteSet (&visited2); } } while (oldsize < elementsInSet(visited)); defs = subtractFromSet (defs, newdefs, THROW_DEST); if (newdefs && defs) { operand *tmpop = newiTempOperand (operandType (IC_RESULT ((iCode *)(setFirstItem (newdefs)))), TRUE); // printf("Splitting %s from %s, using def at %d, op %d\n", OP_SYMBOL_CONST(tmpop)->name, sym->name, ((iCode *)(setFirstItem (newdefs)))->key, ((iCode *)(setFirstItem (newdefs)))->op); for (ic = setFirstItem (visited); ic; ic = setNextItem (visited)) { if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic)) == sym) IC_LEFT (ic) = operandFromOperand (tmpop); if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic)) == sym) IC_RIGHT (ic) = operandFromOperand (tmpop); if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym && !POINTER_SET(ic) && ic->next && !isinSet (visited, ic->next)) continue; if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) && OP_SYMBOL (IC_RESULT (ic)) == sym) { bool pset = POINTER_SET(ic); IC_RESULT (ic) = operandFromOperand (tmpop); if (pset) IC_RESULT(ic)->isaddr = TRUE; } bitVectUnSetBit (sym->uses, ic->key); } } deleteSet (&newdefs); deleteSet (&visited); } while (elementsInSet(defs) > 1); deleteSet (&defs); } deleteSet (&candidates); }
/*-----------------------------------------------------------------* * void pCodeOptime2pCodes(pCode *pc1, pCode *pc2) * * ADHOC pattern checking * Now look for specific sequences that are easy to optimize. * Many of these sequences are characteristic of the compiler * (i.e. it'd probably be a waste of time to apply these adhoc * checks to hand written assembly.) * * *-----------------------------------------------------------------*/ static int pCodeOptime2pCodes(pCode *pc1, pCode *pc2, pCode *pcfl_used, regs *reg, int can_free, int optimize_level) { pCode *pct1, *pct2; regs *reg1, *reg2; int t = total_registers_saved; if(reg->type == REG_SFR)return 0; if(pc2->seq < pc1->seq) { pct1 = pc2; pc2 = pc1; pc1 = pct1; } /* fprintf(stderr,"pCodeOptime2pCodes\n"); pc1->print(stderr,pc1); pc2->print(stderr,pc2); */ if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){ /* clrf reg stuff... movf reg,w can be replaced with stuff... movlw 0 */ pCode *newpc; //fprintf(stderr, " CLRF/MOVFW. instruction after MOVFW is:\n"); pct1 = pic16_findNextInstruction(pc2->next); if(PCI(pct1)->op == POC_MOVWF) { newpc = pic16_newpCode(POC_CLRF, PCI(pct1)->pcop); pct1->destruct(pct1); } else { newpc = pic16_newpCode(POC_MOVLW, pic16_newpCodeOpLit(0)); } pic16_pCodeInsertAfter(pc2, newpc); PCI(newpc)->pcflow = PCFL(pcfl_used); newpc->seq = pc2->seq; /* take care if register is used after pc2, if yes, then don't delete * clrf reg, because, reg should be initialized with zero */ { pCode *spc; int maxSeq=0; for(spc=setFirstItem(reg->reglives.usedpCodes);spc;spc=setNextItem(reg->reglives.usedpCodes)) { if(maxSeq < spc->seq)maxSeq = spc->seq; } // fprintf(stderr, "pc1->seq = %d\tpc2->seq = %d\tspc->seq = %d\n", pc1->seq, pc2->seq, maxSeq); if(maxSeq > pc2->seq) { /* this means that a pCode uses register after pc2, then * we can't delete pc1 pCode */ Remove2pcodes(pcfl_used, NULL, pc2, reg, can_free); } else { /* we can remove both pCodes */ Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); } } total_registers_saved++; // debugging stats. } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){ //fprintf(stderr, " CLRF/IORFW.\n"); pct2 = pic16_findNextInstruction(pc2->next); if(pic16_pCodeSearchCondition(pct2, PCC_Z) > 0) { pct2 = pic16_newpCode(POC_IORLW, pic16_newpCodeOpLit(0)); pct2->seq = pc2->seq; PCI(pct2)->pcflow = PCFL(pcfl_used); pic16_pCodeInsertAfter(pc1,pct2); } Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); total_registers_saved++; // debugging stats. } else if(PCI(pc1)->op == POC_MOVWF) { reg1 = pic16_getRegFromInstruction(pc1); if(reg1->type == REG_SFR)return (total_registers_saved != t); pct2 = pic16_findNextInstruction(pc2->next); if(PCI(pc2)->op == POC_MOVFW) { #if 0 fprintf(stderr, " MOVWF/MOVFW. instruction after MOVFW is:\n"); pct2->print(stderr,pct2); #endif if(PCI(pct2)->op == POC_MOVWF) { /* Change: movwf reg stuff... movf reg,w movwf reg2 To: */ reg2 = pic16_getRegFromInstruction(pct2); if(reg2 && !regUsedinRange(pc1,pc2,reg2) && (reg2->type != REG_SFR)) { // if(reg2 && !regUsedinRange(pc1,pc2,reg2)) if(pic16_pCodeSearchCondition(pct2, PCC_Z) < 1) { pCode *pct3 = pic16_findNextInstruction(pct2->next); pct2->seq = pc1->seq; pic16_unlinkpCode(pct2); pic16_pCodeInsertAfter(pic16_findPrevInstruction(pc1->prev),pct2); #define usesW(x) ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0)) if(usesW(pct3)) ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free); else { Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); total_registers_saved++; // debugging stats. return 1; } } else { // fprintf(stderr,"didn't optimize because Z bit is used\n"); } } #if 0 fprintf(stderr, " couldn't optimize\n"); if(reg2) fprintf(stderr, " %s is used in range\n", reg2->name); else fprintf(stderr, " reg2 is NULL\n"); #endif } } pct1 = pic16_findPrevInstruction(pc1->prev); if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) { if ( (PCI(pct1)->op == POC_MOVFW) && (PCI(pc2)->op == POC_MOVFW)) { reg1 = pic16_getRegFromInstruction(pct1); if(reg1 && !regUsedinRange(pc1,pc2,reg1)) { #if 0 fprintf(stderr, " MOVF/MOVFW. \n"); fprintf(stderr, " ...optimizing\n"); #endif /* Change: movf reg1,w movwf reg stuff... movf reg,w To: stuff... movf reg1,w Or, if we're not deleting the register then the "To" is: stuff... movf reg1,w movwf reg */ pct2 = pic16_newpCode(PCI(pc2)->op, PCI(pct1)->pcop); pic16_pCodeInsertAfter(pc2, pct2); PCI(pct2)->pcflow = PCFL(pcfl_used); pct2->seq = pc2->seq; if(can_free) { Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free); } else { /* If we're not freeing the register then that means (probably) * the register is needed somewhere else.*/ pic16_unlinkpCode(pc1); pic16_pCodeInsertAfter(pct2, pc1); Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free); } Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0); total_registers_saved++; // debugging stats. } } else if ( (PCI(pct1)->op == POC_MOVWF) && (PCI(pc2)->op == POC_MOVFW)) { // fprintf(stderr,"movwf MOVWF/MOVFW\n"); if(optimize_level > 1 && can_free) { pct2 = pic16_newpCode(POC_MOVFW, PCI(pc1)->pcop); pic16_pCodeInsertAfter(pc2, pct2); Remove2pcodes(pcfl_used, pc1, pc2, reg, 1); total_registers_saved++; // debugging stats. } } } } return (total_registers_saved != t); }
/*-----------------------------------------------------------------*/ static void pic14emitOverlay (struct dbuf_s * aBuf) { set *ovrset; /* if (!elementsInSet (ovrSetSets))*/ /* the hack below, fixes translates for devices which * only have udata_shr memory */ dbuf_printf (aBuf, "%s\t%s\n", (elementsInSet(ovrSetSets)?"":";"), port->mem.overlay_name); /* for each of the sets in the overlay segment do */ for (ovrset = setFirstItem (ovrSetSets); ovrset; ovrset = setNextItem (ovrSetSets)) { symbol *sym; if (elementsInSet (ovrset)) { /* this dummy area is used to fool the assembler otherwise the assembler will append each of these declarations into one chunk and will not overlay sad but true */ /* I don't think this applies to us. We are using gpasm. CRF */ dbuf_printf (aBuf, ";\t.area _DUMMY\n"); /* output the area informtion */ dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */ } for (sym = setFirstItem (ovrset); sym; sym = setNextItem (ovrset)) { /* if extern then do nothing */ if (IS_EXTERN (sym->etype)) continue; /* if allocation required check is needed then check if the symbol really requires allocation only for local variables */ if (!IS_AGGREGATE (sym->type) && !(sym->_isparm && !IS_REGPARM (sym->etype)) && !sym->allocreq && sym->level) continue; /* if global variable & not static or extern and addPublics allowed then add it to the public set */ if ((sym->_isparm && !IS_REGPARM (sym->etype)) && !IS_STATIC (sym->etype)) addSetHead (&publics, sym); /* if extern then do nothing or is a function then do nothing */ if (IS_FUNC (sym->type)) continue; /* print extra debug info if required */ if (options.debug || sym->level == 0) { if (!sym->level) { /* global */ if (IS_STATIC (sym->etype)) dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */ else dbuf_printf (aBuf, "G_"); /* scope is global */ } else /* symbol is local */ dbuf_printf (aBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-")); dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block); } /* if is has an absolute address then generate an equate for this no need to allocate space */ if (SPEC_ABSA (sym->etype)) { if (options.debug || sym->level == 0) dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype)); dbuf_printf (aBuf, "%s\t=\t0x%04x\n", sym->rname, SPEC_ADDR (sym->etype)); } else { if (options.debug || sym->level == 0) dbuf_printf (aBuf, "==.\n"); /* allocate space */ dbuf_printf (aBuf, "%s:\n", sym->rname); dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff); } } } }
/*-----------------------------------------------------------------* * void pCodeRegOptimeRegUsage(pBlock *pb) *-----------------------------------------------------------------*/ static void OptimizeRegUsage(set *fregs, int optimize_multi_uses, int optimize_level) { regs *reg; int used; pCode *pc1=NULL, *pc2=NULL; while(fregs) { pCode *pcfl_used, *pcfl_assigned; /* Step through the set by directly accessing the 'next' pointer. * We could also step through by using the set API, but the * the (debug) calls to print instructions affect the state * of the set pointers */ reg = fregs->item; fregs = fregs->next; if(reg->type == REG_SFR) { // fprintf(stderr,"skipping SFR: %s\n",reg->name); continue; } pcfl_used = setFirstItem(reg->reglives.usedpFlows); pcfl_assigned = setFirstItem(reg->reglives.assignedpFlows); used = elementsInSet(reg->reglives.usedpCodes); // fprintf(stderr, "%s:%d register %s used %d times in pCode\n", __FILE__, __LINE__, reg->name, used); if(used == 2) { /* * In this section, all registers that are used in only in two * instructions are examined. If possible, they're optimized out. */ #if 0 fprintf (stderr, "OptimizeRegUsage: %s addr=0x%03x rIdx=0x%03x type=%d used=%d\n", reg->name, reg->address, reg->rIdx, reg->type, used); #endif pc1 = setFirstItem(reg->reglives.usedpCodes); pc2 = setNextItem(reg->reglives.usedpCodes); if(pcfl_used && pcfl_assigned) { /* expected case - the register has been assigned a value and is subsequently used */ //fprintf(stderr," used only twice\n"); if(pcfl_used->seq == pcfl_assigned->seq && !(setNextItem(reg->reglives.usedpFlows)) && !(setNextItem(reg->reglives.assignedpFlows))) { //fprintf(stderr, " and used in same flow\n"); pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 1,optimize_level); } else { // fprintf(stderr, " and used in different flows\n"); } } else if(pcfl_used) { /* register has been used twice without ever being assigned */ //fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name); } else { // fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1); total_registers_saved++; // debugging stats. } } else { /* register has been used either once, or more than twice */ if(used && !pcfl_used && pcfl_assigned) { pCode *pc; fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name); pc = setFirstItem(reg->reglives.usedpCodes); while(pc) { pcfl_assigned = PCODE(PCI(pc)->pcflow); Remove1pcode(pc, reg); deleteSetItem (&(PCFL(pcfl_assigned)->registers), reg); /* deleteSetItem (&(reg->reglives.usedpCodes),pc); pc->destruct(pc); */ pc = setNextItem(reg->reglives.usedpCodes); } reg->isFree = 1; reg->wasUsed = 0; total_registers_saved++; // debugging stats. } else if( (used > 2) && optimize_multi_uses) { set *rset1=NULL; set *rset2=NULL; int searching=1; pCodeFlow *pcfl1=NULL, *pcfl2=NULL; /* examine the number of times this register is used */ rset1 = reg->reglives.usedpCodes; while(rset1 && searching) { pc1 = rset1->item; rset2 = rset1->next; if(pc1 && isPCI(pc1) && ( (pcfl1 = PCI(pc1)->pcflow) != NULL) ) { //while(rset2 && searching) { if(rset2) { pc2 = rset2->item; if(pc2 && isPCI(pc2) && ( (pcfl2 = PCI(pc2)->pcflow) != NULL) ) { if(pcfl2 == pcfl1) { if(pCodeOptime2pCodes(pc1, pc2, pcfl_used, reg, 0,optimize_level)) searching = 0; } } //rset2 = rset2->next; } } rset1 = rset1->next; } } } } }
void outputDebugSymbols(void) { if(getenv("SDCC_DEBUG_VAR_STORAGE")) { dumpSymInfo("Code", code); dumpSymInfo("Data", data); dumpSymInfo("PData", pdata); dumpSymInfo("XData", xdata); dumpSymInfo("XIData", xidata); dumpSymInfo("XInit", xinit); dumpSymInfo("IData", idata); dumpSymInfo("Bit", bit); dumpSymInfo("Statics", statsg); dumpSymInfo("SFR", sfr); dumpSymInfo("SFRBits", sfrbit); dumpSymInfo("Reg", reg); dumpSymInfo("Generic", generic); dumpSymInfo("Overlay", overlay); dumpSymInfo("EEProm", eeprom); dumpSymInfo("Home", home); } if(options.debug && debugFile) { symbol *sym; if (data) { for (sym = setFirstItem (data->syms); sym; sym = setNextItem (data->syms)) debugFile->writeSymbol(sym); } if (idata) { for (sym = setFirstItem (idata->syms); sym; sym = setNextItem (idata->syms)) debugFile->writeSymbol(sym); } if (bit) { for (sym = setFirstItem (bit->syms); sym; sym = setNextItem (bit->syms)) debugFile->writeSymbol(sym); } if (pdata) { for (sym = setFirstItem (pdata->syms); sym; sym = setNextItem (pdata->syms)) debugFile->writeSymbol(sym); } if (xdata) { for (sym = setFirstItem (xdata->syms); sym; sym = setNextItem (xdata->syms)) debugFile->writeSymbol(sym); } if(port->genXINIT && xidata) { for (sym = setFirstItem (xidata->syms); sym; sym = setNextItem (xidata->syms)) debugFile->writeSymbol(sym); } if (sfr) { for (sym = setFirstItem (sfr->syms); sym; sym = setNextItem (sfr->syms)) debugFile->writeSymbol(sym); } if (sfrbit) { for (sym = setFirstItem (sfrbit->syms); sym; sym = setNextItem (sfrbit->syms)) debugFile->writeSymbol(sym); } if (home) { for (sym = setFirstItem (home->syms); sym; sym = setNextItem (home->syms)) debugFile->writeSymbol(sym); } if (code) { for (sym = setFirstItem (code->syms); sym; sym = setNextItem (code->syms)) debugFile->writeSymbol(sym); } if (statsg) { for (sym = setFirstItem (statsg->syms); sym; sym = setNextItem (statsg->syms)) debugFile->writeSymbol(sym); } if(port->genXINIT && xinit) { for (sym = setFirstItem (xinit->syms); sym; sym = setNextItem (xinit->syms)) debugFile->writeSymbol(sym); } } return; }
/* * Emit a set of symbols. * type - 0: have symbol tell whether it is local, extern or global * 1: assume all symbols in set to be global * 2: assume all symbols in set to be extern */ static void emitSymbolSet(set *s, int type) { symbol *sym; initList *list; unsigned sectionNr = 0; for (sym = setFirstItem(s); sym; sym = setNextItem(s)) { #if 0 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n", sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used); #endif if (sym->etype && SPEC_ABSA(sym->etype) && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)) && sym->ival) { // handle config words pic14_assignConfigWordValue(SPEC_ADDR(sym->etype), (int)list2int(sym->ival)); pic14_stringInSet(sym->rname, &emitted, 1); continue; } if (sym->isstrlit) { // special case: string literals emitInitVal(ivalBuf, sym, sym->type, NULL); continue; } if (type != 0 || sym->cdef || (!IS_STATIC(sym->etype) && IS_GLOBAL(sym))) { // bail out for ___fsadd and friends if (sym->cdef && !sym->used) continue; /* export or import non-static globals */ if (!pic14_stringInSet(sym->rname, &emitted, 0)) { if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef) { /* do not add to emitted set, it might occur again! */ //if (!sym->used) continue; // declare symbol emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname); } else { // declare symbol emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname); if (!sym->ival && !IS_FUNC(sym->type)) { // also define symbol if (IS_ABSOLUTE(sym->etype)) { // absolute location? //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype)); // deferred to pic14_constructAbsMap } else { dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++); dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type)); } } // if } // if pic14_stringInSet(sym->rname, &emitted, 1); } // if } // if list = sym->ival; //if (list) showInitList(list, 0); if (list) { resolveIvalSym( list, sym->type ); emitInitVal(ivalBuf, sym, sym->type, sym->ival); dbuf_printf (ivalBuf, "\n"); } } // for sym }