static pFile *the_pFile = NULL;
-static int peepOptimizing = 0;
+static int peepOptimizing = 1;
static int GpCodeSequenceNumber = 1;
static int GpcFlowSeq = 1;
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,1, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,1, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,1, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,1, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
1,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
0, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
1,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
1,1, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
0, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
0, // num ops
0,0, // dest, bit instruction
1,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
1,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
0, // num ops
0,0, // dest, bit instruction
1,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
1,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
2, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
NULL, // label
NULL, // operand
NULL, // flow block
+ NULL, // C source
1, // num ops
0,0, // dest, bit instruction
0,0, // branch, skip
void pCodeInitRegisters(void)
{
- initStack(0x38, 8);
+ initStack(0xfff, 8);
init_pic(port->processor);
pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
pcf->pc.destruct = genericDestruct;
pcf->pc.print = pCodePrintFunction;
+ pcf->ncalled = 0;
+
if(mod) {
//_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
pcf->modname = Safe_calloc(1,strlen(mod)+1);
}
+/*-----------------------------------------------------------------*/
+/* newpCodeCSource - create a new pCode Source Symbol */
+/*-----------------------------------------------------------------*/
+
+pCode *newpCodeCSource(int ln, char *f, char *l)
+{
+
+ pCodeCSource *pccs;
+
+ pccs = Safe_calloc(1,sizeof(pCodeCSource));
+
+ pccs->pc.type = PC_CSOURCE;
+ pccs->pc.prev = pccs->pc.next = NULL;
+ pccs->pc.pb = NULL;
+
+ pccs->pc.destruct = genericDestruct;
+ pccs->pc.print = genericPrint;
+
+ pccs->line_number = ln;
+ if(l)
+ pccs->line = Safe_strdup(l);
+ else
+ pccs->line = NULL;
+
+ if(f)
+ pccs->file_name = Safe_strdup(f);
+ else
+ pccs->file_name = NULL;
+
+ return ( (pCode *)pccs);
+
+}
/*-----------------------------------------------------------------*/
/* pCodeLabelDestruct - free memory used by a label. */
/*-----------------------------------------------------------------*/
the_pFile->pbTail = pb;
}
+/*-----------------------------------------------------------------*/
+/* removepBlock - remove a pBlock from the pFile */
+/*-----------------------------------------------------------------*/
+void removepBlock(pBlock *pb)
+{
+ pBlock *pbs;
+
+ if(!the_pFile)
+ return;
+
+
+ //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
+
+ for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
+ if(pbs == pb) {
+
+ if(pbs == the_pFile->pbHead)
+ the_pFile->pbHead = pbs->next;
+
+ if (pbs == the_pFile->pbTail)
+ the_pFile->pbTail = pbs->prev;
+
+ if(pbs->next)
+ pbs->next->prev = pbs->prev;
+
+ if(pbs->prev)
+ pbs->prev->next = pbs->next;
+
+ return;
+
+ }
+ }
+
+ fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
+
+}
+
/*-----------------------------------------------------------------*/
/* printpCode - write the contents of a pCode to a file */
/*-----------------------------------------------------------------*/
if(pc) {
+#ifdef PCODE_DEBUG
+ fprintf(stderr,"Unlinking: ");
+ printpCode(stderr, pc);
+#endif
if(pc->prev)
pc->prev->next = pc->next;
if(pc->next)
static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
{
- fprintf(of,"pcodeopprint\n");
+ fprintf(of,"pcodeopprint- not implemented\n");
}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
char *pCode2str(char *str, int size, pCode *pc)
{
char *s = str;
case PC_FLOW:
SAFE_snprintf(&s,&size,";\t--FLOW change\n");
break;
+ case PC_CSOURCE:
+ SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+ break;
+
}
return str;
}
}
+ if(PCI(pc)->cline)
+ genericPrint(of,PCODE(PCI(pc)->cline));
{
char str[256];
fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
break;
+ case PC_CSOURCE:
+ fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
+ break;
case PC_LABEL:
default:
fprintf(of,"unknown pCode type %d\n",pc->type);
/* findNextInstruction - given a pCode, find the next instruction */
/* in the linked list */
/*-----------------------------------------------------------------*/
-pCode * findNextInstruction(pCode *pc)
+pCode * findNextInstruction(pCode *pci)
{
+ pCode *pc = pci;
while(pc) {
if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
return pc;
+
#ifdef PCODE_DEBUG
fprintf(stderr,"findNextInstruction: ");
printpCode(stderr, pc);
return NULL;
}
+/*-----------------------------------------------------------------*/
+/* findNextInstruction - given a pCode, find the next instruction */
+/* in the linked list */
+/*-----------------------------------------------------------------*/
+pCode * findPrevInstruction(pCode *pci)
+{
+ return findPrevpCode(pci, PC_OPCODE);
+}
+
/*-----------------------------------------------------------------*/
/* findFunctionEnd - given a pCode find the end of the function */
-/* that contains it t */
+/* that contains it */
/*-----------------------------------------------------------------*/
pCode * findFunctionEnd(pCode *pc)
{
/*-----------------------------------------------------------------*/
int OptimizepBlock(pBlock *pb)
{
- pCode *pc;
+ pCode *pc, *pcprev;
int matches =0;
if(!pb || !peepOptimizing)
return 0;
DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
+/*
for(pc = pb->pcHead; pc; pc = pc->next)
matches += pCodePeepMatchRule(pc);
+*/
+
+ pc = findNextInstruction(pb->pcHead);
+ pcprev = pc->prev;
+ do {
+
+
+ if(pCodePeepMatchRule(pc)) {
+
+ matches++;
+
+ if(pcprev)
+ pc = findNextInstruction(pcprev->next);
+ else
+ pc = findNextInstruction(pb->pcHead);
+ } else
+ pc = findNextInstruction(pc->next);
+ } while(pc);
+
if(matches)
DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
return matches;
* So, unlink the pCode label from it's pCode chain
* and destroy the label */
- DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
-
+ DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
if(pc->type == PC_LABEL) {
unlinkPC(pc);
pCodeLabelDestruct(pc);
for(pc = pb->pcHead; pc; pc = pc->next) {
if(pc->type == PC_LABEL) {
+
+ //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
//fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
- if( !(pcnext = findNextInstruction(pc)) )
- return; // Couldn't find an instruction associated with this label
-
- // Unlink the pCode label from it's pCode chain
- unlinkPC(pc);
-
- //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
- // And link it into the instruction's pBranch labels. (Note, since
- // it's possible to have multiple labels associated with one instruction
- // we must provide a means to accomodate the additional labels. Thus
- // the labels are placed into the singly-linked list "label" as
- // opposed to being a single member of the pCodeInstruction.)
-
- //_ALLOC(pbr,sizeof(pBranch));
- pbr = Safe_calloc(1,sizeof(pBranch));
- pbr->pc = pc;
- pbr->next = NULL;
-
- PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
- if(pcnext->prev)
- pc = pcnext->prev;
- else
- pc = pcnext;
+ if((pcnext = findNextInstruction(pc) )) {
+
+ pCode *pcn = pc->next;
+
+ // Unlink the pCode label from it's pCode chain
+ unlinkPC(pc);
+
+ //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
+ // And link it into the instruction's pBranch labels. (Note, since
+ // it's possible to have multiple labels associated with one instruction
+ // we must provide a means to accomodate the additional labels. Thus
+ // the labels are placed into the singly-linked list "label" as
+ // opposed to being a single member of the pCodeInstruction.)
+
+ //_ALLOC(pbr,sizeof(pBranch));
+ pbr = Safe_calloc(1,sizeof(pBranch));
+ pbr->pc = pc;
+ pbr->next = NULL;
+
+
+ PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
+
+ pc = pcn;
+
+ } else {
+ fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
+ }
+ } else if(pc->type == PC_CSOURCE) {
+
+ /* merge the source line symbolic info into the next instruction */
+ if((pcnext = findNextInstruction(pc) )) {
+
+ pCode *pcn = pc->next;
+
+ // Unlink the pCode label from it's pCode chain
+ unlinkPC(pc);
+ PCI(pcnext)->cline = PCCS(pc);
+ //fprintf(stderr, "merging CSRC\n");
+ //genericPrint(stderr,pcnext);
+ pc = pcn;
+ }
+
}
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
-void OptimizepCode(char dbName)
+int OptimizepCode(char dbName)
{
#define MAX_PASSES 4
pBlock *pb;
if(!the_pFile)
- return;
+ return 0;
DFPRINTF((stderr," Optimizing pCode\n"));
do {
+ matches = 0;
for(pb = the_pFile->pbHead; pb; pb = pb->next) {
if('*' == dbName || getpBlock_dbName(pb) == dbName)
matches += OptimizepBlock(pb);
}
while(matches && ++passes < MAX_PASSES);
+ return matches;
}
/*-----------------------------------------------------------------*/
for(pb = the_pFile->pbHead; pb; pb = pb->next) {
pCode *pc_fstart=NULL;
for(pc = pb->pcHead; pc; pc = pc->next) {
- if(isPCF(pc)) { //pc->type == PC_FUNCTION) {
+ if(isPCF(pc)) {
if (PCF(pc)->fname) {
if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
pb->dbName = 'M';
}
- //_ALLOC(pbr,sizeof(pBranch));
pbr = Safe_calloc(1,sizeof(pBranch));
pbr->pc = pc_fstart = pc;
pbr->next = NULL;
addSet(&pb->function_exits, pc);
}
- } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+ } else if(isCALL(pc)) {
addSet(&pb->function_calls,pc);
}
}
if('*' == dbName || getpBlock_dbName(pb) == dbName) {
DFPRINTF((stderr," analyze and merging block %c\n",dbName));
- //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
pBlockMergeLabels(pb);
AnalyzepBlock(pb);
+ } else {
+ DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
}
}
- changes = 0;
+ changes = OptimizepCode(dbName);
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- if('*' == dbName || getpBlock_dbName(pb) == dbName)
- changes += OptimizepBlock(pb);
- }
-
} while(changes && (i++ < MAX_PASSES));
buildCallTree();
// set *registersInCallPath = NULL;
if(!of)
- return;// registers;
+ return;
if(indent > 10)
- return; // registers; //recursion ?
+ return; //recursion ?
pc = setFirstItem(pb->function_entries);
}
-#if 0
- fprintf(stderr,"pBlock before register optim.\n");
- pBlockStats(stderr,pb); // debug
-
- if(registersInCallPath) {
- /* registers were used in the functions this pBlock has called */
- /* so now, we need to see if these collide with the ones we are using here */
-
- regs *r1,*r2, *newreg;
-
- fprintf(stderr,"comparing registers\n");
-
- r1 = setFirstItem(registersInCallPath);
- while(r1) {
-
- r2 = setFirstItem(pb->registers);
-
- while(r2) {
-
- if(r2->rIdx == r1->rIdx) {
- newreg = pic14_findFreeReg();
-
-
- if(!newreg) {
- fprintf(stderr,"Bummer, no more registers.\n");
- exit(1);
- }
-
- fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
- r1->rIdx, newreg->rIdx);
- r2->rIdx = newreg->rIdx;
- //if(r2->name) free(r2->name);
- if(newreg->name)
- r2->name = Safe_strdup(newreg->name);
- else
- r2->name = NULL;
- newreg->isFree = 0;
- newreg->wasUsed = 1;
- }
- r2 = setNextItem(pb->registers);
- }
-
- r1 = setNextItem(registersInCallPath);
- }
-
- /* Collisions have been resolved. Now free the registers in the call path */
- r1 = setFirstItem(registersInCallPath);
- while(r1) {
- newreg = pic14_regWithIdx(r1->rIdx);
- newreg->isFree = 1;
- r1 = setNextItem(registersInCallPath);
- }
-
- } else
- MarkUsedRegisters(pb->registers);
-
- registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
-
- if(registers)
- fprintf(stderr,"returning regs\n");
- else
- fprintf(stderr,"not returning regs\n");
-
- fprintf(stderr,"pBlock after register optim.\n");
- pBlockStats(stderr,pb); // debug
-
-
- return registers;
-
-#endif
-
/*-----------------------------------------------------------------*/
/* printCallTree - writes the call tree to a file */
}
- /* Re-allocate the registers so that there are no collisions
- * between local variables when one function call another */
-#if 0
- pic14_deallocateAllRegs();
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- if(!pb->visited)
- register_usage(pb);
- }
-#endif
-
fprintf(of,"\n**************\n\na better call tree\n");
for(pb = the_pFile->pbHead; pb; pb = pb->next) {
if(pb->visited)
fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
}
}
+
+
+
+/*-----------------------------------------------------------------*/
+/* */
+/*-----------------------------------------------------------------*/
+
+void InlineFunction(pBlock *pb)
+{
+ pCode *pc;
+ pCode *pc_call;
+
+ if(!pb)
+ return;
+
+ pc = setFirstItem(pb->function_calls);
+
+ for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+ if(isCALL(pc)) {
+ pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
+ pCode *pct;
+ pCode *pce;
+
+ pBranch *pbr;
+
+ if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
+
+ //fprintf(stderr,"Cool can inline:\n");
+ //pcn->print(stderr,pcn);
+
+ //fprintf(stderr,"recursive call Inline\n");
+ InlineFunction(pcn->pb);
+ //fprintf(stderr,"return from recursive call Inline\n");
+
+ /*
+ At this point, *pc points to a CALL mnemonic, and
+ *pcn points to the function that is being called.
+
+ To in-line this call, we need to remove the CALL
+ and RETURN(s), and link the function pCode in with
+ the CALLee pCode.
+
+ */
+
+
+ /* Remove the CALL */
+ pc_call = pc;
+ pc = pc->prev;
+
+ /* remove callee pBlock from the pBlock linked list */
+ removepBlock(pcn->pb);
+
+ pce = pcn;
+ while(pce) {
+ pce->pb = pb;
+ pce = pce->next;
+ }
+
+ /* Remove the Function pCode */
+ pct = findNextInstruction(pcn->next);
+
+ /* Link the function with the callee */
+ pc->next = pcn->next;
+ pcn->next->prev = pc;
+
+ /* Convert the function name into a label */
+
+ pbr = Safe_calloc(1,sizeof(pBranch));
+ pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
+ pbr->next = NULL;
+ PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
+ PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
+
+ /* turn all of the return's except the last into goto's */
+ /* check case for 2 instruction pBlocks */
+ pce = findNextInstruction(pcn->next);
+ while(pce) {
+ pCode *pce_next = findNextInstruction(pce->next);
+
+ if(pce_next == NULL) {
+ /* found the last return */
+ pCode *pc_call_next = findNextInstruction(pc_call->next);
+
+ //fprintf(stderr,"found last return\n");
+ //pce->print(stderr,pce);
+ pce->prev->next = pc_call->next;
+ pc_call->next->prev = pce->prev;
+ PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
+ PCI(pce)->label);
+ }
+
+ pce = pce_next;
+ }
+
+
+ }
+ } else
+ fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* */
+/*-----------------------------------------------------------------*/
+
+void InlinepCode(void)
+{
+
+ pBlock *pb;
+ pCode *pc;
+
+ if(!the_pFile)
+ return;
+
+
+ /* Loop through all of the function definitions and count the
+ * number of times each one is called */
+
+ for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+ pc = setFirstItem(pb->function_calls);
+
+ for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+ if(isCALL(pc)) {
+ pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
+ if(pcn && isPCF(pcn)) {
+ PCF(pcn)->ncalled++;
+ }
+ } else
+ fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+ }
+ }
+
+
+ /* Now, Loop through the function definitions again, but this
+ * time inline those functions that have only been called once. */
+
+ InlineFunction(the_pFile->pbHead);
+
+}