📄 cgen.cpp
字号:
/****************************************************/
/* 文件 cgen.cpp */
/* 说明 类PASCAL语言编译器代码生成程序 */
/* 主题 编译器结构:原理和实例 */
/****************************************************/
/*********** 该文件所包含的头文件 ****************/
#include "globals.h"
#include "util.h"
#include "symbTable.h"
#include "scanner.h"
#include "parse.h"
#include "analyze.h"
#include "string.h"
#include "cgen.h"
#include "code.h"
static int tmpOffset = 0; /*临时变量区的偏移*/
static void genStmt(TreeNode * t);
/*************************************************************/
/* 函数名 genProc */
/* 功 能 该函数生成过程节点的代码 */
/* 说 明 该函数处理过程声明部分的代码生成,在过程信息表中填 */
/* 写过程入口地址,结束是在pc中存入返回地址 */
/*************************************************************/
void genProc(TreeNode * t)
{
int savedLoc1; /*处理过程入口时所需的代码地址*/
/*处理过程体部分*/
int currentLoc = emitSkip(0);
/*在过程信息表中填写过程入口地址*/
t->table[0]->attrIR.More.ProcAttr.procEntry = currentLoc;
/*初始化寄存器displayOff*/
emitRM("LDC",displayOff,t->table[0]->attrIR.More.ProcAttr.nOff,0,"noff value");
/*提示信息,过程处理部分开始*/
if(TraceCode) emitComment("->procedure");
TreeNode * p1 = t->child[1];
TreeNode * p2 = t->child[2];
while(p1!=NULL)
{
/*处理过程声明部分*/
if(p1->nodekind==ProcDecK)
{
savedLoc1 = emitSkip(1);
genProc(p1);
/*待过程处理完成,回填指令执行地址*/
currentLoc = emitSkip(0);
emitBackup(savedLoc1);
emitRM("LDC",pc,currentLoc,0," procedure entry");
//emitRM_Abs("JEQ",ac,currentLoc," jump to outside procedure");
emitRestore();
}
p1 = p1->sibling;
}
if(p2!=NULL)
p2 = p2->child[0];
/*处理语句部分*/
while (p2!=NULL)
{
genStmt(p2);
p2 = p2->sibling;
}
/*指令寄存器pc的值置为返回地址*/
emitRM("LD",ac2,1,sp," fetch return address");
/*******注:此处的数字应该为0,而不是1*******/
emitRM("LDA",pc,0,ac2," return old procedure");
/*提示信息,当前过程处理部分结束*/
if(TraceCode) emitComment("<-procedure");
}
/*************************************************************/
/* 函数名 genStmt */
/* 功 能 该函数生成一个语句节点的代码 */
/* 说 明 根据不同的语法树节点产生不同的语句代码 */
/*************************************************************/
void genStmt(TreeNode * t)
{
/*用于控制转移display表的各项sp值*/
int ss;
/*用于存储语法树的各个节点*/
TreeNode * p0 = NULL;
TreeNode * p1 = NULL;
TreeNode * pp = NULL;
TreeNode * p2 = NULL;
SymbTable * entry = NULL;
/*用于记录形参地址*/
int FormParam;
/*用于记录跳转回填时的地址*/
int savedLoc1,savedLoc2,currentLoc;
/*指向域变量的指针*/
fieldChain * fieldMem = NULL;
/*指向实参的指针*/
ParamTable * curParam = NULL;
switch(t->kind.stmt)
{
/*处理if语句*/
case IfK:
if(TraceCode) emitComment("->if");
p0 = t->child[0]; /*条件表达式部分*/
p1 = t->child[1]; /*then语句序列部分*/
p2 = t->child[2]; /*else语句序列部分*/
cGen(p0); /*产生测试表达式的代码*/
/* savedLoc1赋值为当前指令的tm地址号(emitLoc),emitLoc加1, *
/* 为if条件表达式为假时,产生跳转地址回填所留一代码空位 */
savedLoc1 = emitSkip(1);
/* 指令回填地址savedLoc1记录当前生成代码写入地址, *
* 再将当前生成代码写入地址emitLoc加1 *
* 为条件表达式为假的跳转指令留一条指令写入空位,用于代码回填 *
* 将注释写入目标代码文件code,此处为向else跳转指令位置 */
emitComment("if: jump to else belongs here");
/*产生then语句部分的代码*/
cGen(p1);
/* 指令回填地址savedLoc2记录当前生成代码写入地址, *
* 再将当前生成代码写入地址emitLoc加1 *
* 为跳转到判断语句结束位置的指令留一条代码空位,用于代码回填 *
* 将注释写入目标代码文件code,此处为向end跳转指令位置 */
savedLoc2 = emitSkip(1);
emitComment("if: jump to end belongs here");
/* 指令回填地址currentLoc为当前生成代码写入地址 *
* 当前地址为条件为假的处理指令开始地址 */
currentLoc = emitSkip(0);
/*退回到指令回填地址savedLoc1,此处已经预留了一个指令空位*/
emitBackup(savedLoc1);
/* 写入跳转到else的指令,此时跳转位置currentLoc已经得到 *
* 指令的跳转地址为相对地址 */
emitRM_Abs("JEQ",ac,currentLoc,"if : jmp to else");
/* 恢复当前生成代码写入地址emitLoc为指令回填地址currentLoc, *
* 恢复后地址为条件为假处理指令开始地址,即else开始位置 */
emitRestore();
/* 处理else语句部分的代码 */
cGen(p2);
/* 指令回填地址currentLoc作为当前生成代码写入地址 *
* 当前地址为判断语句结束位置 */
currentLoc = emitSkip(0);
/* 回退到指令回填地址savedLoc2,此处已经预留了一个指令空间 */
emitBackup(savedLoc2);
/* 写入跳转到end的指令,此时跳转位置currentLoc已经得到地址 */
emitRM_Abs("LDA",pc,currentLoc,"jmp to end");
/* 恢复当前生成代码写入地址emitLoc为指令回填地址currentLoc, *
* 恢复后地址为判断语句结束地址,即end位置 */
emitRestore();
if (TraceCode) emitComment("<- if"); /*if语句结束*/
break;
/*处理while语句*/
case WhileK:
if ( TraceCode ) emitComment("->while");
p0 = t->child[0]; /*p0为while语句的条件表达式部分*/
p1 = t->child[1]; /*p1为while语句的语句序列部分*/
currentLoc = emitSkip(0);
cGen(p0); /*生成条件表达式部分代码*/
/* 如果条件表达式为假,则跳转至while语句结束 *
/* 此处为地址回填预留一个指令空间 */
savedLoc1 = emitSkip(1);
emitComment(" while : jump out while ");
cGen(p1); /*生成语句序列部分代码*/
/*跳到条件表达式处,进入下一次循环*/
emitRM("LDC",pc,currentLoc,0," jump to start ");
emitComment(" return to condition exp");
/*条件为假时,跳出while循环*/
currentLoc = emitSkip(0);
emitBackup(savedLoc1);
emitRM_Abs("JEQ",ac,currentLoc," jump out while ");
emitRestore();
if(TraceCode) emitComment("<-while");
break;
/*处理赋值语句*/
case AssignK:
if(TraceCode) emitComment("->assign");
p0 = t->child[0]; /*赋值号左侧的部分*/
p1 = t->child[1]; /*赋值号右侧的部分*/
FindAdd(p0);
/*ac中存为赋值号左侧变量的绝对偏移*/
/*先把ac存到ac2中*/
emitRM("LDA",ac2,0,ac,"save ac");
cGen(p1); /*处理赋值号右侧的表达式部分*/
/*结果存入ac中*/
if(p0->table[0]->attrIR.More.VarAttr.access==dir)
/*赋值*/
emitRM("ST",ac,0,ac2,"var assign : store value");
else
{
/*ac2中为该变量的实际存储位置*/
emitRM("LD",ac2,0,ac2," indir var assign");
emitRM("ST",ac,0,ac2," store value");
}
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,assign语句结束 */
if (TraceCode) emitComment("<- assign") ;
break;
/*处理输入语句*/
case ReadK:
/*生成读指令,该指令完成读入外部数值到累加器ac的动作*/
emitRO("IN",ac,0,0,"read integer value");
emitRM("LDA",ac2,0,ac,"save ac");
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAdd(t);
if(t->table[0]->attrIR.More.VarAttr.access==dir)
{
/*直接存*/
/*最后生成存储指令*/
emitRM("ST",ac2,0,ac," var read : store value");
}
else
{
/*以ac内容作为地址找变量单元,再存*/
/*ac内容放入ac1中*/
emitRM("LD",ac1,0,ac,"");
emitRM("ST",ac2,0,ac1," var read : store value");
}
break;
/* 处理write语句类型 */
case WriteK:
p0 = t->child[0];
cGen(p0); /*处理write语句部分的表达式部分*/
emitRO("OUT",ac,0,0,"write ac");
break;
/* 处理过程调用语句 */
case CallK:
p0 = t->child[0]; /*过程名*/
p1 = t->child[1]; /*过程的实参*/
pp = p0;
if(TraceCode) emitComment("->procedure call");
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*@@@@@@ 参数传递 @@@@@@@@*/
/*curParam是指向该过程形参表的指针*/
curParam = p0->table[0]->attrIR.More.ProcAttr.param;
while ((curParam!=NULL)&&(p1!=NULL))/*p1是实参*/
{
/*该形参的偏移*/
FormParam = curParam->entry->attrIR.More.VarAttr.off;
/*形参是变参时有三种情况*/
if(curParam->entry->attrIR.More.VarAttr.access==indir)
//{
/*实参是非形参,第一种*/
//if(!p1->table[0]->attrIR.More.VarAttr.isParam)
//{
/*计算该实参的绝对地址*/
// FindAdd(p1);
/*ac中现在存放的是实参的绝对地址*/
/*将实参地址送入currentAR的行参单元中*/
/*参数传递*/
// emitRM("ST",ac,FormParam,top," store actParam");
//}
/*实参是形参,分为两种情况:dir,indir处理*/
//else
//{
/*实参是值参*/
if(p1->table[0]->attrIR.More.VarAttr.access==dir)
{
FindAdd(p1);
/*ac中为实参的绝对地址*/
/*将实参地址入currentAR的行参单元中*/
/*参数传递*/
emitRM("ST",ac,FormParam,top," store actParam");
}
/*实参是变参*/
else
{
/*此时将实参的单元内容传送入currentAR的行参单元中*/
FindAdd(p1);
/*ac中为p1的绝对偏移*/
/******ac中存的是实参单元地址******/
emitRM("LD",ac,0,ac," ActParam value");
/******ac中存的是实参单元内容******/
/*参数传递*/
emitRM("ST",ac,FormParam,top," formal and act link ");
}
//}
//}
/*形参是值参时有四种情况*/
else
{
switch(p1->kind.exp)
{
/*第一种,数值或表达式,直接送值*/
case OpK:
case ConstK:
/*ac中存有表达式的值*/
genExp(p1);
emitRM("ST",ac,FormParam,top," formal and act link");
break;
case VariK:
/*该函数使ac中存储为实参的绝对地址*/
FindAdd(p1);
/*该形参的偏移*/
FormParam = curParam->entry->attrIR.More.VarAttr.off;
/*该实参是形参,不能是a.b或a[b]的形式*/
//if(p1->table[0]->attrIR.More.VarAttr.isParam)
//{
/*第二种,值参,送值*/
if(p1->table[0]->attrIR.More.VarAttr.access==dir)
{
/*以ac中的值作为绝对地址,找出其对应的存储单元,*
*取出其内容,作为实参 */
emitRM("LD",ac2,0,ac,"");
/*ac2中存放的是该变量内容*/
emitRM("ST",ac2,FormParam,top," Act and Formal link");
}
/*第三种,变参,取内容作为地址,再取内容送入*/
else
{
/*以ac中的内容作为绝对地址*/
emitRM("LD",ac2,0,ac,"");
/*以ac2中的内容作为绝对地址*/
emitRM("LD",ac2,0,ac2,"");
/*以ac2中的内容作为实参*/
emitRM("ST",ac2,FormParam,top," Act and Formal link");
}
//}
/*该实参是普通变量*/
//else
//{
/*以ac中的值作为绝对地址*/
// emitRM("LD",ac2,0,ac,"");
/*以ac2的内容作为实参*/
// emitRM("ST",ac2,FormParam,top," Act and Formal link");
//}
break;
}
}
curParam = curParam->next;
p1 = p1->sibling;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -