+ return idx;
+}
+
+/*------------------------------------------------------------------*/
+/* ReuseReg were call tree permits */
+/* */
+/* Re-allocate the GPR for optimum reuse for a given pblock */
+/* eg if a function m() calls function f1() and f2(), where f1 */
+/* allocates a local variable vf1 and f2 allocates a local */
+/* variable vf2. Then providing f1 and f2 do not call each other */
+/* they may share the same general purpose registers for vf1 and */
+/* vf2. */
+/* This is done by first setting the the regs rIdx to start after */
+/* all the global variables, then walking through the call tree */
+/* renaming the registers to match their new idx and incrementng */
+/* it as it goes. If a function has already been called it will */
+/* only rename the registers if it has already used up those */
+/* registers ie rIdx of the function's registers is lower than the */
+/* current rIdx. That way the register will not be reused while */
+/* still being used by an eariler function call. */
+/* */
+/* Note for this to work the functions need to be declared static. */
+/* */
+/*------------------------------------------------------------------*/
+void ReuseReg(void)
+{
+ pBlock *pb;
+ if (!the_pFile) return;
+ InitReuseReg();
+ for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+ /* Non static functions can be called from other modules so their registers must reassign */
+ if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
+ register_reassign(pb,peakIdx,0);
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* buildCallTree - look at the flow and extract all of the calls */
+/* */
+/*-----------------------------------------------------------------*/
+
+void buildCallTree(void )
+{
+ pBranch *pbr;
+ pBlock *pb;
+ pCode *pc;
+
+ if(!the_pFile)
+ return;
+
+ /* Now build the call tree.
+ First we examine all of the pCodes for functions.
+ Keep in mind that the function boundaries coincide
+ with pBlock boundaries.
+
+ The algorithm goes something like this:
+ We have two nested loops. The outer loop iterates
+ through all of the pBlocks/functions. The inner
+ loop iterates through all of the pCodes for
+ a given pBlock. When we begin iterating through
+ a pBlock, the variable pc_fstart, pCode of the start
+ of a function, is cleared. We then search for pCodes
+ of type PC_FUNCTION. When one is encountered, we
+ initialize pc_fstart to this and at the same time
+ associate a new pBranch object that signifies a
+ branch entry. If a return is found, then this signifies
+ a function exit point. We'll link the pCodes of these
+ returns to the matching pc_fstart.
+
+ When we're done, a doubly linked list of pBranches
+ will exist. The head of this list is stored in
+ `the_pFile', which is the meta structure for all
+ of the pCode. Look at the printCallTree function
+ on how the pBranches are linked together.
+
+ */
+ for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+ pCode *pc_fstart=NULL;
+ for(pc = pb->pcHead; pc; pc = pc->next) {
+ if(isPCF(pc)) {
+ pCodeFunction *pcf = PCF(pc);
+ if (pcf->fname) {
+
+ if(STRCASECMP(pcf->fname, "_main") == 0) {
+ //fprintf(stderr," found main \n");
+ pb->cmemmap = NULL; /* FIXME do we need to free ? */
+ pb->dbName = 'M';
+ }
+
+ pbr = Safe_calloc(1,sizeof(pBranch));
+ pbr->pc = pc_fstart = pc;
+ pbr->next = NULL;
+
+ the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
+
+ // Here's a better way of doing the same:
+ addSet(&pb->function_entries, pc);
+
+ } else {
+ // Found an exit point in a function, e.g. return
+ // (Note, there may be more than one return per function)
+ if(pc_fstart)
+ pBranchLink(PCF(pc_fstart), pcf);
+
+ addSet(&pb->function_exits, pc);
+ }
+ } else if(isCALL(pc)) {
+ addSet(&pb->function_calls,pc);
+ }
+ }
+ }