📄 cgen.c
字号:
#include "globals.h"
#include "symtab.h"
#include "code.h"
#include "cgen.h"
/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree, int isAddr, char * label);
/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * t, char * label)
{
char codestr[CODESIZE];
char * lab1, * lab2;
TreeNode * temp;
switch(t->kind.stmt){
case ExK:
cGen(t->child[0],0,label);
break;
case IfK:
cGen(t->child[0],0,label);
lab1 = genLabel();
sprintf(codestr,"%s %s","fjp",lab1);
emitCode(codestr);
cGen(t->child[1],0,label);
if(t->child[2] != NULL)
{
lab2 = genLabel();
sprintf(codestr,"%s %s" ,"ujp" ,lab2);
emitCode(codestr);
}
sprintf(codestr,"%s %s", "lab",lab1);
emitCode(codestr);
if(t->child[2]!=NULL)
{
cGen(t->child[2],0,label);
sprintf(codestr,"%s %s","lab",lab2);
emitCode(codestr);
}
break;
case WhileK:
lab1 = genLabel();
sprintf(codestr,"%s %s", "lab",lab1);
emitCode(codestr);
cGen(t->child[0],0,label);
lab2 = genLabel();
sprintf(codestr,"%s %s","fjp",lab2);
emitCode(codestr);
cGen(t->child[1],0,lab2);
sprintf(codestr,"%s %s" ,"ujp" ,lab1);
emitCode(codestr);
sprintf(codestr,"%s %s","lab",lab2);
emitCode(codestr);
break;
case BreakK:
sprintf(codestr,"%s %s","ujp",label);
emitCode(codestr);
break;
case DeclK:
temp=t->child[1];
while(temp!=NULL){
if(temp->type==Integer){
if(temp->kind.exp==IdK){
emitComment("define integer");
sprintf(codestr,"%s di ?",temp->attr.name);
emitCode(codestr);
}
else{
emitComment("define integer array");
sprintf(codestr,"%s di %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i);
emitCode(codestr);
}
}
else if(temp->type==Float) {
if(temp->kind.exp==IdK){
emitComment("define float");
sprintf(codestr,"%s df ?",temp->attr.name);
emitCode(codestr);
}
else{
emitComment("define float array");
sprintf(codestr,"%s df %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i);
emitCode(codestr);
}
}
else {
if(temp->kind.exp==IdK){
emitComment("define char");
sprintf(codestr,"%s dc ?",temp->attr.name);
emitCode(codestr);
}
else{
emitComment("define char array");
sprintf(codestr,"%s dc %d dup(?)",temp->attr.name,temp->child[0]->attr.val.i);
emitCode(codestr);
}
}
temp=temp->sibling;
}
break;
default:
emitCode("Error");
break;
}
} /* genStmt */
/* Procedure genExp generates code at an expression node */
static void genExp( TreeNode * t, int isAddr)
{
char codestr[CODESIZE];
switch(t->kind.exp){
case OpK:
switch(t->attr.op){
case PLUS:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
if(t->type==Integer)
emitCode("addi");
else
emitCode("addf");
}
break;
case MINUS:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
if(t->type==Integer)
emitCode("subi");
else
emitCode("subf");
}
break;
case TIMES:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
if(t->type==Integer)
emitCode("muli");
else
emitCode("mulf");
}
break;
case OVER:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
if(t->type==Integer)
emitCode("divi");
else
emitCode("divf");
}
break;
case AND:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("and");
}
break;
case OR:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("or");
}
break;
case EQ:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("eq");
}
break;
case NE:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("ne");
}
break;
case LT:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("lt");
}
break;
case MT:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("mt");
}
break;
case LE:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("le");
}
break;
case ME:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("me");
}
break;
case NOT:
if(isAddr) emitCode("Error");
else{
cGen(t->child[0],FALSE,NULL);
emitCode("not");
}
break;
default:
emitCode("error");
break;
}
break;
case IK:
if(isAddr) emitCode("error");
else{
sprintf(codestr,"%s %d","ldci",t->attr.val.i);
emitCode(codestr);
}
break;
case FK:
if(isAddr) emitCode("error");
else{
sprintf(codestr,"%s %f","ldcf",t->attr.val.f);
emitCode(codestr);
}
break;
case CK:
if(isAddr) emitCode("error");
else{
sprintf(codestr,"%s %c","ldcc",t->attr.val.c);
emitCode(codestr);
}
break;
case IdK:
if(isAddr)
sprintf(codestr,"%s %s","lda",t->attr.name);
else{
if(t->type==Integer)
sprintf(codestr,"%s %s","lodi",t->attr.name);
else if(t->type==Float)
sprintf(codestr,"%s %s","lodf",t->attr.name);
else
sprintf(codestr,"%s %s","lodc",t->attr.name);
}
emitCode(codestr);
break;
case ArrK:
sprintf(codestr,"%s %s","lda",t->attr.name);
emitCode(codestr);
cGen(t->child[0],FALSE,NULL);
if(t->type==Integer)
sprintf(codestr,"%s %d","ixa",sizeof(int));
else if(t->type==Float)
sprintf(codestr,"%s %d","ixa",sizeof(float));
else
sprintf(codestr,"%s %d","ixa",sizeof(char));
emitCode(codestr);
if(!isAddr) emitCode("ind 0");
break;
case AssignK:
cGen(t->child[0],TRUE,NULL);
cGen(t->child[1],FALSE,NULL);
emitCode("stn");
break;
default:
emitCode("error");
break;
}
} /* gen*/
/* Procedure cGen recursively generates code by
* tree traversal
*/
static void cGen( TreeNode * tree, int isAddr, char * label)
{ if (tree != NULL)
{ switch (tree->nodekind) {
case StmtK:
genStmt(tree,label);
break;
case ExpK:
genExp(tree,isAddr);
break;
default:
break;
}
cGen(tree->sibling,isAddr,label);
}
}
/**********************************************/
/* 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 = malloc(strlen(codefile)+7);
strcpy(s,"File: ");
strcat(s,codefile);
emitComment("C Compilation to P-Code");
emitComment(s);
/* generate standard prelude */
/* generate code for TINY program */
cGen(syntaxTree, FALSE, NULL);
/* finish */
emitComment("End of execution.");
emitCode("ret");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -