📄 midcode.cpp
字号:
/****************************************************/
/* 文件 midcode.cpp */
/* 说明 TINY编译器中间代码生成实现 */
/****************************************************/
#include "globals.h" /* 该头文件定义全局类型和变量 */
#include "util.h" /*该头文件定义了一些实用函数*/
#include "symbTable.h"
#include "midcode.h" /* 该头文件声明了中间代码生成文件的界面函数*/
/*临时变量编号,全局变量,每个过程开始都对TempOffset进行
初始化,注:所以,不同过程中,可能有编号相同的临时变量,但是
由于他们互不相干,所以不会有问题;而且优化部分是对基本块进行优化,
每个基本块最大是一个过程,也不会有问题*/
int TempOffset ;
/*标号值,全局变量*/
int Label = 0;
/*指向第一条中间代码*/
CodeFile *firstCode = NULL ;
/*指向当前最后一条中间代码*/
CodeFile *lastCode = NULL ;
/***********函数声明******************/
CodeFile *GenMidCode(TreeNode *t);
void GenProcDec(TreeNode *t);
void GenBody(TreeNode *t);
void GenStatement(TreeNode *t);
void GenAssignS(TreeNode *t);
ArgRecord *GenVar(TreeNode *t);
ArgRecord *GenArray(ArgRecord *V1arg,TreeNode *t,int low ,int size);
ArgRecord *GenField(ArgRecord *V1arg,TreeNode *t ,fieldChain *head );
ArgRecord *GenExpr(TreeNode *t);
void GenCallS(TreeNode *t );
void GenReadS (TreeNode *t );
void GenWriteS(TreeNode *t );
void GenIfS(TreeNode *t );
void GenWhileS(TreeNode *t);
/********************************************************/
/* 函数名 GenMidCode */
/* 功 能 中间代码生成主函数 */
/* 说 明 若有过程声明,调用过程声明的代码声明函数; */
/* 调用程序体的代码生成函数 */
/********************************************************/
CodeFile * GenMidCode(TreeNode *t)
{
/*若有过程声明,调用相应函数,产生过程声明的中间代码*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*display表相对于sp的偏移*/
ArgRecord *Noff = ARGValue(StoreNoff);
/*生成主程序入口声明代码*/
CodeFile *code = GenCode(MENTRY,NULL,NULL,Noff);
/*初始化临时变量的开始编号,为临时变量区的第一个地址*/
TempOffset = StoreNoff + 1;
/*调用语句序列的代码生成函数*/
GenBody(t->child[2]);
/*回填主程序的AR的大小到主程序入口中间代码*/
int size = TempOffset;
ArgRecord *sizeArg = ARGValue(size);
code->codeR.arg2= sizeArg;
return (firstCode) ;
}
/****************************************************/
/* 函数名 GenProcDec */
/* 功 能 过程声明中间代码生成函数 */
/* 说 明 生成过程入口中间代码,生成过程体的中间 */
/* 代码,生成过程出口的中间代码 */
/****************************************************/
void GenProcDec(TreeNode *t)
{
/*得到过程的入口标号*/
int ProcEntry = NewLabel( );
/*过程名在符号表中的地址*/
SymbTable *Entry = t->table[0];
/*过程入口标号,回填入节点中*/
Entry->attrIR.More.ProcAttr.codeEntry = ProcEntry;
/*过程的display表的偏移量*/
int noff = Entry->attrIR.More.ProcAttr.nOff;
/*得到过程的层数及其ARG结构*/
int procLevel = Entry->attrIR.More.ProcAttr.level;
ArgRecord *levelArg = ARGValue(procLevel);
/*若过程内部仍有过程声明,调用相应函数,产生过程声明的中间代码*/
TreeNode *t1=t->child[1];
while (t1!=NULL)
{ if (t1->nodekind==ProcDecK)
GenProcDec(t1);
t1=t1->sibling;
}
/*产生过程入口中间代码*/
ArgRecord *arg1=ARGLabel(ProcEntry);
CodeFile *code = GenCode(PENTRY,arg1,NULL,levelArg);
/*初始化临时变量的开始编号,为过程临时变量区的第一个地址*/
TempOffset = noff + procLevel+1;
/*调用语句序列的代码生成函数处理过程体*/
GenBody(t->child[2]);
/*得到过程的AR的大小,回填入过程入口中间代码*/
int size = TempOffset;
ArgRecord *sizeArg = ARGValue(size);
code->codeR.arg2 = sizeArg;
/*产生过程出口中间代码*/
GenCode(ENDPROC,NULL,NULL,NULL);
}
/****************************************************/
/* 函数名 GenBody */
/* 功 能 语句序列中间代码生成函数 */
/* 说 明 用于处理过程体或者程序体, */
/* 循环处理各个语句 */
/****************************************************/
void GenBody(TreeNode *t)
{
TreeNode *t1 = t;
/*令指针指向第一条语句*/
if (t1->nodekind==StmLK)
t1=t1->child[0];
while (t1!=NULL)
{ /*调用语句处理函数*/
GenStatement(t1);
t1= t1->sibling;
}
}
/****************************************************/
/* 函数名 GenStatement */
/* 功 能 语句处理函数 */
/* 说 明 根据语句的具体类型,分别调用相应的 */
/* 语句处理函数 */
/****************************************************/
void GenStatement(TreeNode *t)
{
switch(t->kind.stmt)
{ case AssignK : GenAssignS(t); break;
case CallK: GenCallS(t); break;
case ReadK: GenReadS(t); break;
case WriteK: GenWriteS(t); break;
case IfK : GenIfS (t); break;
case WhileK: GenWhileS(t); break;
case ReturnK: /*直接生成中间代码*/
GenCode(RETURNC,NULL,NULL,NULL);
break;
default : break;
}
}
/****************************************************/
/* 函数名 GenAssignS */
/* 功 能 赋值语句处理函数 */
/* 说 明 处理左部变量,处理右部表达式,生成 */
/* 赋值语句中间代码 */
/****************************************************/
void GenAssignS(TreeNode *t)
{ /*调用赋值左部变量的处理函数*/
ArgRecord *Larg = GenVar(t->child[0]);
/*调用赋值右部表达式的处理函数*/
ArgRecord *Rarg = GenExpr(t->child[1]);
/*生成赋值语句中间代码*/
GenCode(ASSIG,Rarg,Larg,NULL);
}
/****************************************************/
/* 函数名 GenVar */
/* 功 能 变量处理 函数 */
/* 说 明 */
/****************************************************/
ArgRecord *GenVar(TreeNode *t)
{
int low ,size;
fieldChain *head = NULL ;
/*生成变量名的ARG结构, Entry为标识符在符号表中的地址*/
SymbTable *Entry = t->table[0];
ArgRecord *V1arg = ARGAddr(t->name[0],
Entry->attrIR.More.VarAttr.level,
Entry->attrIR.More.VarAttr.off,
Entry->attrIR.More.VarAttr.access);
/*返回的ARG结构*/
ArgRecord * Varg = NULL;
switch(t->attr.ExpAttr.varkind)
{ /*标识符变量情形*/
case IdV: Varg = V1arg; break;
/*数组成员变量情形*/
case ArrayMembV:
/*构造数组下届和数组大小的ARG结构*/
low = Entry->attrIR.idtype->More.ArrayAttr.low;
size = Entry->attrIR.idtype->More.ArrayAttr.elemTy->size;
Varg = GenArray(V1arg, t , low, size);
break;
/*域变量情形*/
case FieldMembV:
head = Entry->attrIR.idtype->More.body;
Varg = GenField(V1arg,t ,head);
break;
default : break;
}
return (Varg);
}
/****************************************************/
/* 函数名 GenArray */
/* 功 能 数组成员变量处理函数 */
/* 说 明 由函数GenVar或函数GenField调用 */
/****************************************************/
ArgRecord *GenArray(ArgRecord *V1arg,TreeNode *t,int low ,int size)
{ /*处理下标表达式*/
ArgRecord *Earg= GenExpr(t->child[0]);
ArgRecord *lowArg = ARGValue(low);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -