/***************************************************************************** * Project: dcc * File: backend.c * Purpose: Back-end module. Generates C code for each procedure. * (C) Cristina Cifuentes ****************************************************************************/ #include #include #include "dcc.h" #include "disassem.h" #include #include #include #include #include #include "project.h" bundle cCode; /* Procedure declaration and code */ using namespace std; /* Returns a unique index to the next label */ int getNextLabel() { static int labelIdx = 1; /* index of the next label */ return (labelIdx++); } /* displays statistics on the subroutine */ void Function::displayStats () { printf("\nStatistics - Subroutine %s\n", name.c_str()); printf ("Number of Icode instructions:\n"); printf (" Low-level : %4d\n", stats.numLLIcode); if (! (flg & PROC_ASM)) { printf (" High-level: %4d\n", stats.numHLIcode); printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode * 100.0) / stats.numLLIcode); } } /**** this proc is not required any more?? ****/ #if 0 static void fixupLabels (PPROC pProc) /* Checks the graph (pProc->cfg) for any nodes that have labels, and gives * a unique label number for it. This label is placed in the associated * icode for the node (pProc->Icode). The procedure is done in sequential * order of dsfLast numbering. */ { int i; /* index into the dfsLast array */ PBB *dfsLast; /* pointer to the dfsLast array */ dfsLast = pProc->dfsLast; for (i = 0; i < pProc->numBBs; i++) if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) { pProc->Icode.icode[dfsLast[i]->start].ll()->flg |= HLL_LABEL; pProc->Icode.icode[dfsLast[i]->start].ll()->hllLabNum = getNextLabel(); } } #endif /* Returns the corresponding C string for the given character c. Character * constants such as carriage return and line feed, require 2 C characters. */ char *cChar (uint8_t c) { static char res[3]; switch (c) { case 0x8: /* backspace */ sprintf (res, "\\b"); break; case 0x9: /* horizontal tab */ sprintf (res, "\\t"); break; case 0x0A: /* new line */ sprintf (res, "\\n"); break; case 0x0C: /* form feed */ sprintf (res, "\\f"); break; case 0x0D: /* carriage return */ sprintf (res, "\\r"); break; default: /* any other character*/ sprintf (res, "%c", c); } return (res); } /* Prints the variable's name and initial contents on the file. * Note: to get to the value of the variable: * com file: prog.Image[operand] * exe file: prog.Image[operand+0x100] */ static void printGlobVar (std::ostream &ostr,SYM * psym) { int j; PROG &prog(Project::get()->prog); uint32_t relocOp = prog.fCOM ? psym->label : psym->label + 0x100; switch (psym->size) { case 1: ostr << "uint8_t\t"<name<<" = "<name<<" = "<type == TYPE_PTR) /* pointer */ ostr << "uint16_t *\t"<name<<" = "<name<<"[4] = \""<< prog.Image[relocOp]<size; j++) strContents << cChar(prog.Image[relocOp + j]); ostr << "char\t*"<name<<" = \""<prog); /* Write header information */ cCode.init(); cCode.appendDecl( "/*\n"); cCode.appendDecl( " * Input file\t: %s\n", fileName); cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE"); cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n"); /* Write global symbol table */ /** writeGlobSymTable(); *** need to change them into locident fmt ***/ writeBundle (_ios, cCode); freeBundle (&cCode); } // Note: Not currently called! /** Checks the given icode to determine whether it has a label associated * to it. If so, a goto is emitted to this label; otherwise, a new label * is created and a goto is also emitted. * Note: this procedure is to be used when the label is to be forward on * the code; that is, the target code has not been traversed yet. */ #if 0 static void emitFwdGotoLabel (ICODE * pt, int indLevel) { if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */ { /* Generate new label */ pt->ll()->hllLabNum = getNextLabel(); pt->ll()->setFlags(HLL_LABEL); } cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum); } #endif /* Writes the procedure's declaration (including arguments), local variables, * and invokes the procedure that writes the code of the given record *hli */ void Function::codeGen (std::ostream &fs) { int numLoc; ostringstream ostr; //STKFRAME * args; /* Procedure arguments */ //char buf[200], /* Procedure's definition */ // arg[30]; /* One argument */ BB *pBB; /* Pointer to basic block */ /* Write procedure/function header */ cCode.init(); if (flg & PROC_IS_FUNC) /* Function */ ostr<< "\n"<writeCode (1, this, &numLoc, MAX, UN_INIT); } cCode.appendCode( "}\n\n"); writeBundle (fs, cCode); freeBundle (&cCode); /* Write Live register analysis information */ if (option.verbose) for (size_t i = 0; i < numBBs; i++) { pBB = m_dfsLast[i]; if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */ cout << "BB "<proc->flg & PROC_OUTPUT) || (pcallGraph->proc->flg & PROC_ISLIB)) return; pcallGraph->proc->flg |= PROC_OUTPUT; /* Dfs if this procedure has any successors */ for (size_t i = 0; i < pcallGraph->outEdges.size(); i++) { backBackEnd (filename, pcallGraph->outEdges[i], _ios); } /* Generate code for this procedure */ stats.numLLIcode = pcallGraph->proc->Icode.size(); stats.numHLIcode = 0; pcallGraph->proc->codeGen (_ios); /* Generate statistics */ if (option.Stats) pcallGraph->proc->displayStats (); if (! (pcallGraph->proc->flg & PROC_ASM)) { stats.totalLL += stats.numLLIcode; stats.totalHL += stats.numHLIcode; } } /* Invokes the necessary routines to produce code one procedure at a time. */ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph) { std::ofstream fs; /* Output C file */ /* Get output file name */ std::string outNam(fileName); outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */ /* Open output file */ fs.open(outNam); if(!fs.is_open()) fatalError (CANNOT_OPEN, outNam.c_str()); printf ("dcc: Writing C beta file %s\n", outNam.c_str()); /* Header information */ writeHeader (fs, fileName); /* Initialize total Icode instructions statistics */ stats.totalLL = 0; stats.totalHL = 0; /* Process each procedure at a time */ backBackEnd (fileName, pcallGraph, fs); /* Close output file */ fs.close(); printf ("dcc: Finished writing C beta file\n"); }