?? cgen.cpp
字號:
#include "globals.h"
#include "symtab.h"
#include "code.h"
#include "cgen.h"
/* loc is the memory offset for temps
It is incremented each time a temp is
stored
*/
static int loc = 0;
static char funExitLab[10];
/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree);
static void genExp( TreeNode * tree, int isAddr);
void genLabel(char lab1[])
{
static int nLabel = 1;
sprintf(lab1, "@Label%d", nLabel);
nLabel++;
}
/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * tree)
{
TreeNode * p1, * p2, * p3, * p4;
int temploc;
char lab1[10], lab2[10];
char codestr[CODESIZE];
if (tree != 0) switch (tree->kind.stmt)
{
case IfK :
if (TraceCode)
emitComment("-> if") ;
p1 = tree->child[0] ;
p2 = tree->child[1] ;
p3 = tree->child[2] ;
/* generate code for test expression */
cGen(p1);
genLabel(lab1);
sprintf(codestr, "%s %s", "fjp", lab1);
emitCode(codestr);
emitComment("if: jump to else belongs here");
/* recurse on then part */
cGen(p2);
if (p3 != 0)
{
genLabel(lab2);
sprintf(codestr, "%s %s", "ujp", lab2);
emitCode(codestr);
}
sprintf(codestr, "%s %s", "lab", lab1);
emitCode(codestr);
if (p3 != 0)
{
cGen(p3);
sprintf(codestr, "%s %s", "lab", lab2);
emitCode(codestr);
}
if (TraceCode)
emitComment("-> if") ;
break;
case WhileK:
if (TraceCode)
emitComment("-> while");
p1 = tree->child[0] ;
p2 = tree->child[1] ;
genLabel(lab1);
sprintf(codestr, "%s %s", "lab", lab1);
emitCode(codestr);
cGen(p1);
genLabel(lab2);
sprintf(codestr, "%s %s", "fjp", lab2);
emitCode(codestr);
cGen(p2);
sprintf(codestr, "%s %s", "ujp", lab1);
emitCode(codestr);
sprintf(codestr, "%s %s", "lab", lab2);
emitCode(codestr);
if (TraceCode)
emitComment("<- while");
break;
case ForK:
if (TraceCode)
emitComment("-> for");
p1 = tree->child[0] ;
p2 = tree->child[1] ;
p3 = tree->child[2] ;
p4 = tree->child[3] ;
cGen(p1);
genLabel(lab1);
sprintf(codestr, "%s %s", "lab", lab1);
emitCode(codestr);
cGen(p2);
genLabel(lab2);
sprintf(codestr, "%s %s", "fjp", lab2);
emitCode(codestr);
cGen(p4);
cGen(p3);
sprintf(codestr, "%s %s", "ujp", lab1);
emitCode(codestr);
sprintf(codestr, "%s %s", "lab", lab2);
emitCode(codestr);
if (TraceCode)
emitComment("<- for");
break;
case ReturnK:
if (TraceCode)
emitComment("-> return");
p1 = tree->child[0];
if (p1 != 0)
genExp(p1, FALSE);
else
emitCode("ldc 0");
sprintf(codestr, "%s %s", "ujp", funExitLab);
emitCode(codestr);
if (TraceCode)
emitComment("<- return");
break;
case CompoundK:
if (TraceCode)
emitComment("-> compound");
p1 = tree->child[0];
temploc = loc;
st_newBuck();
cGen(p1);
if (TraceCode)
emitComment("<- compound");
st_delBuck();
loc = temploc;
break;
default:
break;
}
} /* genStmt */
/* Procedure genExp generates code at an expression node */
static void genExp( TreeNode * tree, int isAddr)
{
TreeNode * p1, * p2;
char lab1[10], lab2[10];
char codestr[CODESIZE];
switch (tree->kind.exp)
{
case ConstK :
if (TraceCode) emitComment("-> Const") ;
switch (tree->attr.vartype)
{
case Integer:
sprintf(codestr, "%s %d", "ldci", tree->attr.vali);
break;
case Float:
sprintf(codestr, "%s %f", "ldcf", tree->attr.valf);
break;
case Char:
sprintf(codestr, "%s %c", "ldcc", tree->attr.valch);
break;
}
emitCode(codestr);
if (TraceCode) emitComment("<- Const") ;
break; /* ConstK */
case NotK:
if (TraceCode)
emitComment("-> Not") ;
cGen(tree->child[0]);
emitCode("not");
if (TraceCode) emitComment("<- Not") ;
break; /* NotK */
case ArrayK:
if (TraceCode)
emitComment("-> Array") ;
sprintf(codestr, "%s %s", "lod", tree->attr.name);
emitCode(codestr);
cGen(tree->child[0]);
sprintf(codestr, "%s elem_size(%s)", "ixa", tree->attr.name);
emitCode(codestr);
if (isAddr == FALSE)
emitCode("ind 0");
if (TraceCode)
emitComment("<- Array") ;
break;
case IdK:
if (TraceCode) emitComment("-> Id") ;
if (isAddr == TRUE)
sprintf(codestr, "%s %s", "lda", tree->attr.name);
else
sprintf(codestr, "%s %s", "lod", tree->attr.name);
emitCode(codestr);
if (TraceCode) emitComment("<- Id") ;
break; /* IdK */
case OpK :
if (TraceCode)
emitComment("-> Op");
p1 = tree->child[0];
p2 = tree->child[1];
switch (tree->attr.op)
{
case ASSIGN:
genExp(p1, TRUE);
genExp(p2, FALSE);
if(isAddr == FALSE)
emitCode("stn");
else
emitCode("sto");
break;
case PLUS:
genExp(p1, FALSE);
genExp(p2, FALSE);
switch (tree->attr.vartype)
{
case Integer: emitCode("adi"); break;
case Float: emitCode("adf"); break;
}
break;
case MINUS:
genExp(p1, FALSE);
genExp(p2, FALSE);
switch (tree->attr.vartype)
{
case Integer: emitCode("subi"); break;
case Float: emitCode("subf"); break;
}
break;
case TIMES:
genExp(p1, FALSE);
genExp(p2, FALSE);
switch (tree->attr.vartype)
{
case Integer: emitCode("multi"); break;
case Float: emitCode("multf"); break;
}
break;
case OVER:
genExp(p1, FALSE);
genExp(p2, FALSE);
switch (tree->attr.vartype)
{
case Integer: emitCode("divi"); break;
case Float: emitCode("divf"); break;
}
break;
case LT:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("les");
break;
case GT:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("grt");
break;
case LE:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("leq");
break;
case GE:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("geq");
break;
case EQ:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("equ");
break;
case NE:
genExp(p1, FALSE);
genExp(p2, FALSE);
emitCode("neq");
break;
case OR:
genExp(p1, FALSE);
emitCode("ldc 1");
emitCode("neq");
genLabel(lab1);
sprintf(codestr, "%s %s", "fjp", lab1);
emitCode("lod TRUE");
genLabel(lab2);
sprintf(codestr, "%s %s", "ujp", lab2);
emitCode(codestr);
sprintf(codestr, "%s %s", "lab", lab1);
emitCode(codestr);
genExp(p2, FALSE);
sprintf(codestr, "%s %s", "lab", lab2);
emitCode(codestr);
break;
case AND:
genExp(p1, FALSE);
emitCode("ldc 0");
emitCode("neq");
genLabel(lab1);
sprintf(codestr, "%s %s", "fjp", lab1);
genExp(p2, FALSE);
genLabel(lab2);
sprintf(codestr, "%s %s", "ujp", lab2);
emitCode(codestr);
sprintf(codestr, "%s %s", "lab", lab1);
emitCode(codestr);
emitCode("lod FALSE");
sprintf(codestr, "%s %s", "lab", lab2);
emitCode(codestr);
break;
default:
emitComment("BUG: Unknown operator");
break;
} /* case op */
if (TraceCode)
emitComment("<- Op");
break; /* OpK */
case CallK:
if (TraceCode)
emitComment("-> Call");
p1 = tree->child[0];
p2 = tree->child[1];
emitCode("mst");
while(p2 != 0)
{
genExp(p2, FALSE);
p2 = p2 -> sibling;
}
sprintf(codestr, "%s %s", "cup", p1->attr.name);
emitCode(codestr);
if (TraceCode)
emitComment("<- Call");
break;
default:
break;
}
} /* genExp */
static void genDecl(TreeNode * tree)
{
TreeNode *p1, *p2, *p3, *p4;
char codestr[CODESIZE];
switch (tree->kind.decl)
{
case VarDeclK:
if (TraceCode)
emitComment("-> VarDecl");
for(p2 = tree->child[1]; p2 != 0; p2 = p2->sibling)
{
switch (p2->attr.vartype)
{
case Integer:
st_setLoc(p2->attr.name, loc);
loc += 4;
if(p2->kind.exp == ArrayK)
{
loc += 4 * (p2->child[0]->attr.vali - 1);
}
break;
case Float:
st_setLoc(p2->attr.name, loc);
loc += 4;
if(p2->kind.exp == ArrayK)
{
loc += 4 * (p2->child[0]->attr.vali - 1);
}
break;
case Char:
st_setLoc(p2->attr.name, loc);
loc += 1;
if(p2->kind.exp == ArrayK)
{
loc += 4 * (p2->child[0]->attr.vali - 1);
}
break;
}
}
if (TraceCode)
emitComment("<- VarDecl");
break; /* VarDeclK */
case FuncDefK:
p2 = tree->child[1];
p3 = tree->child[2];
p4 = tree->child[3];
loc = 0;
if (TraceCode)
emitComment("-> FuncDef");
genLabel(funExitLab);
sprintf(codestr, "%s %s", "ent", p2->attr.name);
emitCode(codestr);
st_setLoc(p2->attr.name, emitLoc);
st_newBuck();
cGen(p3);
cGen(p4);
st_delBuck();
sprintf(codestr, "%s %s", "lab", funExitLab);
emitCode(codestr);
emitCode("ret");
if (TraceCode)
emitComment("<- FuncDef");
break; /* FuncDefK */
case ParamK:
st_setLoc(tree->child[1]->attr.name, loc);
switch (tree->child[0]->attr.vartype)
{
case Integer: loc += 4; break;
case Float: loc += 4; break;
case Char: loc += 1; break;
}
break;
default:
break;
}
}
/* Procedure cGen recursively generates code by
* tree traversal
*/
static void cGen( TreeNode * tree)
{
if (tree != NULL)
{ switch (tree->nodekind) {
case StmtK:
genStmt(tree);
break;
case ExpK:
genExp(tree, TRUE); //set to TRUE for destructive store
break;
case DeclK:
genDecl(tree);
default:
break;
}
cGen(tree->sibling);
}
}
/**********************************************/
/* the primary function of the code generator */
/**********************************************/
/* Procedure codeGen generates code to a code
* file by traversal of the syntax tree. The
* second parameter (codefile) is the file name
* of the code file, and is used to print the
* file name as a comment in the code file
*/
void codeGen(TreeNode * syntaxTree, char * codefile)
{
char* s = (char*) malloc(strlen(codefile)+7);
strcpy(s,"File: ");
strcat(s,codefile);
emitComment("C- Compilation to P-Code");
emitComment(s);
/* generate code for C- program */
cGen(syntaxTree);
/* finish */
emitComment("End of execution.");
//emitCode("stp");
if (TraceAnalyze)
{
fprintf(listing,"\nSymbol table:\n\n");
printSymTab(listing);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -