📄 cgen.c
字号:
/****************************************************/
/* File: cgen.c */
/* The code generator implementation */
/* for the TINY compiler */
/* (generates code for the TM machine) */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/
#include "Globals.h"
#include "SymTab.h"
#include "Code.h"
#include "CGen.h"
#include <math.h>
#include "TmStack.h"
#include "Util.h"
int iloc = 0 ;
int dloc = 0 ;
int traceflag = TRUE;
int icountflag = TRUE;
BYTE dMem [DADDR_SIZE];
WORD reg [NO_REGS];
DWORD dreg [NO_REGS];
static char in_Line[LINESIZE] ;
int base[MAXLEVEL];
map<int,int> mIndex;
TmStack mStack;
int lineLen ;
int inCol ;
int num ;
static int fun_offset = 0;
static int label_num = 0;
int vari_offset;
int para_offset;
/* tmpOffset is the memory offset for temps
It is decremented each time a temp is
stored, and incremeted when loaded again
*/
static int tmpOffset = 0;
static int pLevel = 0;
static int pSaveLevel = 0;
static int IsInFunction = 0;
static int nFuncTop = 0;
static int nGlobalTop = 0;
const char * opCodeTab[] = {
"START","HALT","IN","OUT","ADD","SUB","MUL","DIV","LT","LE","GT","GE","EQ","NEQ",
"AND","OR","NOT","UJP","FJP","LAB","PUSH","POP","COPY","SYSCALL","????",
/* RR opcodes */
"LD","ST","????", /* RM opcodes */
"LDA","LDC",
"ENT","RET","MST","CUP","CSP","????"
/* RA opcodes */
};
void genLabel(int &label)
{
static int i=1;
label = i;
i++;
}
/********************************************/
void writeInstruction ( int loc )
{
printf( "%5d: ", loc) ;
if ( (loc >= 0) && (loc < IADDR_SIZE) )
{
printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
switch ( opClass(iMem[loc].iop) )
{
case opclRR:
printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
break;
case opclRM:
case opclRA:
if((iMem[loc].iop == opLDC)&&(iMem[loc].isize == sizeofdouble))
printf("%3f(%1d)", iMem[loc].darg2, iMem[loc].iarg3);
else
printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
break;
}
printf(" %3d", iMem[loc].isize);
printf ("\n") ;
}
} /* writeInstruction */
/********************************************/
void getInput ()
{
memset(in_Line, 0, sizeof(in_Line));
gets(in_Line);
//printf("in_Line: %s\n", in_Line);
return;
}
void lab(int label)
{
emitRO(opLAB, label, 0, 0, " label");
}
void ujp(int label)
{
emitRO(opUJP, label, 0, 0, " ujp label");
}
void fjp(int label)
{
emitRO(opFJP, label, 0, 0, " fjp label");
}
static ExpType getType(TreeNode * t){
if(t->kind.exp == StructIdK){
return getType(t->child[0]);
}
return t->type.type;
}
void ret(int r,char * name)
{
int addr = 0;
FunEntry * pEntry = (FunEntry*)malloc(sizeof(FunEntry));
if(r){//if the function has a return value
pEntry = Lookup_Fun(name);
addr = pEntry ->ret_val;
}
//恢复旧的sp,tp
emitRM(opLD,tp,callFO,sp,"load old tp");
//恢复寄存器
//emitRM(opPOP,ac,0,0,"call: pop function ret");
//emitRM(opPOP,ac1,0,0,"call: pop ac");
//恢复返回地址
if(strcmp(name, "main"))
emitRM(opLD,bp,retFO,sp,"pre load old pc");
emitRM(opLD,sp,ospFO,sp,"load old sp");
if(strcmp(name, "main"))
emitRM(opLDA,pc,0,bp,"load old pc");
}
/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree, int addrFlag = 0);
static void genDec(TreeNode *tree, int addrFlag = 0){
TreeNode * p1, * p2, * p3;
int savedLoc1,savedLoc2,currentLoc;
ValEntry * pEntry = (ValEntry *)malloc(sizeof(ValEntry));
FunEntry * pFunEntry = (FunEntry *)malloc(sizeof(FunEntry));
int i, level,loc,size,flag;
ExpType type;
switch (tree->kind.dec){
case FunDecK:
break;
case FunDefK:
//主函数要设特殊标志
emitRM(opENT,0,0,0,tree->attr.name);
//传入参数
pLevel = 0;
for(i=0;i<MAXLEVEL;i++)
base[i] = 0;
base[0] = -4;
pFunEntry = Lookup_Fun(tree->attr.name);
size = pFunEntry->ret_val;
//保存寄存器
//emitRM(opPUSH,ac,0,0,"FunDefK: push ac");
//emitRM(opPUSH,ac1,0,0,"FunDefK: push ac1");
//保存旧的sp,tp
emitRM(opST,tp,-size+callFO,tp,"FunDefK: store current tp");
emitRM(opST,sp,-size+ospFO,tp,"FunDefK: store current sp");
//保存返回地址 ---???,ac已经变化
emitRM(opST,ac,-size+retFO,tp,"FunDefK: store current sp");
//置新的sp,tp
emitRM(opLDA,sp,-size,tp,"FunDefK: set new sp");
emitRM(opLDA,tp,-size,tp,"FunDefK: set new tp");
p2 = tree->child[1]; // comp_dec
cGen(p2);
//返回值
//ret(FALSE,tree ->attr.name);
if(strcmp(tree->attr.name,"main") == 0)
emitRM(opRET,0,0,0,tree->attr.name);
else
emitRM(opRET,1,0,0,tree->attr.name);
break;
case VarK:
p1 = tree->child[0];
if((tree->kind.exp == NumK)||(tree->kind.exp == CharK)||(tree->kind.exp == DNumK))
while(p1){
if(p1->nodekind == StmtK) //AssignK
{
p2 = p1->child[0];
//用于数组的情况
//if(p2->child[0])
// cGen(p2->child[0]);
/* now store value */
level = Lookup_Var(pTable, pTable ->funEntry, p2->attr.name, pEntry);
loc = pEntry ->offset;
//printf("tree->attr.name: %s pTable ->nestlevel: %d\n ", p2->attr.name, level);
p3 = p1->child[1];
cGen(p3);
if(level == 0){
if(p2->type.type == Double){
emitRM(opPOP,ac,0,0,"assign: pop double value",sizeofdouble);
emitRM(opST,ac,loc,gp,"assign: store double value",sizeofdouble);
}else if(p2->type.type == Integer){
emitRM(opPOP,ac,0,0,"assign: pop integer value",sizeofint);
emitRM(opST,ac,loc,gp,"assign: store integer value",sizeofint);
}else if(p2->type.type == Char){
emitRM(opPOP,ac,0,0,"assign: pop char value",sizeofchar);
emitRM(opST,ac,loc,gp,"assign: store char value",sizeofchar);
}
} else {
emitRM(opLD,bp,base[level-1],sp,"set location bp");
if(p2->type.type == Double){
emitRM(opPOP,ac,0,0,"assign: pop double value",sizeofdouble);
emitRM(opST,ac,loc,bp,"assign: store double value",sizeofdouble);
} else if(p2->type.type == Integer){
emitRM(opPOP,ac,0,0,"assign: pop integer value",sizeofint);
emitRM(opST,ac,loc,bp,"assign: store integer value",sizeofint);
} else if(p2->type.type == Char){
emitRM(opPOP,ac,0,0,"assign: pop char value",sizeofchar);
emitRM(opST,ac,loc,bp,"assign: store char value",sizeofchar);
}
}
}
else
{
}
p1 = p1->sibling;
}
break;
case CompK:
pTable = tree->attr.table;
size = pTable->memloc;
base[pLevel+1] = base[pLevel] - size - 4;
printf("pLevel: %d size: %d base[pLevel]: %d\n", pLevel, size, base[pLevel]);
//保存top
emitRM(opLDA,tp,-4-size,tp,"add CompK tp");
emitRM(opST,tp,0,sp,"store CompK top");
pLevel++;
p1 = tree->child[0];
if(p1) // Dec
cGen(p1);
p2 = tree->child[1];
if(p2) //stmt
cGen(p2);
pTable = pTable->parent;
pLevel--;
break;
case ParamK:
break;
default:
break;
}
}
/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * tree, int addrFlag = 0)
{
TreeNode * p1, * p2, * p3;
ValEntry * pEntry = (ValEntry *)malloc(sizeof(ValEntry));
FunEntry * pFunEntry = (FunEntry *)malloc(sizeof(FunEntry));
int savedLoc1,savedLoc2,currentLoc;
int loc, level, size, i, index, result, refFlag, nSize;
ExpType type,type2;
switch (tree->kind.stmt) {
case IfK :
if (TraceCode)
emitComment("-> if") ;
genLabel(pTable ->lab1);
genLabel(pTable ->lab2);
//printf("lab1: %d\n", pTable ->lab1);
//printf("lab2: %d\n", pTable ->lab2);
p1 = tree->child[0] ;
p2 = tree->child[1] ;
p3 = tree->child[2] ;
if(p1->kind.exp == NumK) // optimize
{
if(p1->attr.val.i == 0)
ujp(pTable ->lab1);
}
else
{
cGen(p1);
emitRM(opPOP, ac, 0, 0, "if pop condition");
fjp(pTable ->lab1);
}
/* recurse on then part */
//pTable = p2->attr.table;
cGen(p2);
//有else的情况
if(p3) {
ujp(pTable ->lab2);
}
lab(pTable ->lab1);
if(p3)
{
//pTable = p3->attr.table;
cGen(p3);
lab(pTable ->lab2);
}
if (TraceCode)
emitComment("<- if") ;
break; /* if_k */
case WhileK:
if (TraceCode)
emitComment("-> while") ;
genLabel(pTable ->lab1);
genLabel(pTable ->lab2);
lab(pTable ->lab1);
p1 = tree->child[0];
if(p1 ->kind.exp == NumK) // optimize
{
if(p1->attr.val.i == 0)
ujp(pTable ->lab2);
}
else
{
cGen(p1);
emitRM(opPOP, ac, 0, 0, "while pop condition");
fjp(pTable ->lab2);
}
if(tree->child[1])
cGen(tree->child[1]);
ujp(pTable ->lab1);
lab(pTable ->lab2);
if (TraceCode)
emitComment("<- while") ;
break; /* if_k */
case CallK:
emitRM(opMST,0,0,0,"begin-args ");
pFunEntry = Lookup_Fun(tree->attr.name);
if(pFunEntry){
if (TraceCode)
emitComment("-> CallK") ;
p1 = tree->child[0];
i = 0;
size = pFunEntry->ret_val;
while(p1 != NULL){
result = Lookup_Param(pFunEntry, i, pEntry);
if(result < 0){
printf("CallK Param Index Error\n");
exit(-1);
}
refFlag = pEntry->refFlag;
loc = pEntry->offset;
nSize = pEntry->size;
//传地址,参数是结构时也用地址,处理时以地址加大小进行copy
if((refFlag == 1)||(pEntry->type.type == Struct))
cGen(p1,1);
else
cGen(p1);
printf("-size+loc: %d\n", -size+loc);
type = getType(p1);
//传地址
emitRM(opPOP,ac,0,0,"call: pop para");
if(refFlag == 1)
emitRM(opST,ac,-size+loc,tp,"call: push param addr" );
else if(p1->type.type == Struct){
emitRM(opLDA,ac1,-size+loc,tp,"call: load param record addr" );
emitRM(opCOPY,ac1,ac,nSize,"call: copy param record value" );
}
else if(type == Double)
emitRM(opST,ac,-size+loc,tp,"call: push param double",sizeofdouble);
else if(type == Integer)
emitRM(opST,ac,-size+loc,tp,"call: push param integer",sizeofint);
else if(type == Char)
emitRM(opST,ac,-size+loc,tp,"call: push param char",sizeofchar);
i++;
p1 = p1->sibling;
}
emitRM(opCUP,0,0,0,tree->attr.name);
emitRM(opLDA,0,1,pc,"call: backup call next");
emitRM(opLDC,pc,mStart[tree->attr.name],0,"call: load function begin");
if (TraceCode)
emitComment("<- CallK") ;
//处理返回值
}
else {
if (TraceCode)
emitComment("-> SysCallK") ;
p1 = tree->child[0];
p2 = p1->sibling;
pFunEntry = Lookup_SysFun(tree->attr.name);
index = pFunEntry->ret_val;
if(strcmp(tree->attr.name,"read") == 0){
cGen(p1,1);
type = getType(p1);
if(type == Double)
emitRM(opSYSCALL,0,index,0,"call read function double",sizeofdouble);
else if(type == Integer)
emitRM(opSYSCALL,0,index,0,"call read function");
else if(type == Char)
emitRM(opSYSCALL,0,index,0,"call read function char",sizeofchar);
emitRM(opPOP, ac, 0, 0, "read pop addr");
//read后值存入ac1
if(type == Double){
emitRM(opST,ac1, 0, ac, "read store double",sizeofdouble);
} else if(type == Integer){
emitRM(opST,ac1, 0, ac, "read store ",sizeofint);
} else if(type == Char){
emitRM(opST,ac1, 0, ac, "read store ",sizeofchar);
} else if(type == String){
}
} else if(strcmp(tree->attr.name,"write") == 0){
type = getType(p1);
if(type == String)
cGen(p1,1);
else
cGen(p1);
if(type == Double){
emitRM(opPOP, ac, 0, 0, "write pop double value",sizeofdouble);
emitRM(opSYSCALL,0,index,0,"call write function double",sizeofdouble);
}else if(type == Integer){
emitRM(opPOP, ac, 0, 0, "write pop value",sizeofint);
emitRM(opSYSCALL,0,index,0,"call write function",sizeofint);
} else if(type == Char){
emitRM(opPOP, ac, 0, 0, "write pop char value", sizeofchar);
emitRM(opSYSCALL,0,index,0,"call write function", sizeofchar);
} else if(type == String){
emitRM(opPOP, ac, 0, 0, "write pop string addr", sizeofint);
emitRM(opSYSCALL,0,index,0,"call write function", typestring);
}
} else if(strcmp(tree->attr.name,"abs") == 0){
cGen(p1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -