📄 midtodemi.cpp
字号:
/*取得标号值*/
if (i == 1)
label = midcode->codeR.arg1->Attr.label;
else label = midcode->codeR.arg2->Attr.label;
/*查找标号地址表*/
LabelAddr *item = labelAddrT;
LabelAddr *last = item;
while (item!=NULL)
{ if (item->label == label)
break;
last = item;
item = item->next;
}
if (item==NULL) /*表中没有此标号对应得项,填表 */
{
/*预留回填地址*/
int currentLoc = emitSkip(1);
/*新建一项*/
LabelAddr *newItem = (LabelAddr *)malloc(sizeof(LabelAddr));
newItem->label = label;
newItem->destNum = currentLoc;
newItem->next = NULL;
/*加入标号地址表中*/
if (last == NULL)
labelAddrT = newItem;
else last->next = newItem;
}
else
/*表中有此标号对应项,则可以生成目标代码*/
emitRM("LDC",pc,item->destNum,0,"jump to label");
}
/************************************************/
/* 函数名 jump0Gen */
/* 功 能 生成条件跳转语句的目标代码 */
/* 说 明 根据arg1的值判断是否跳转,arg2给出要*/
/* 跳转到的标号值,调用函数jumpGen处理 */
/* 跳转部分 */
/************************************************/
void Cmidtodemi::jump0Gen(CodeFile *midcode)
{
/*取得决定是否跳转的值,存在ac中*/
operandGen(midcode->codeR.arg1);
/*转存到ac2中*/
emitRM("LDA",ac2,0,ac,"op: store addr ");
/* 此处为地址回填预留一个指令空间,生成不跳转时的代码*/
int savedLoc = emitSkip(1);
/*生成跳转代码,通过调用*/
jumpGen(midcode,2);
/*指令回填*/
int currentLoc = emitSkip(0);
emitBackup(savedLoc);
emitRM_Abs("JNE",ac2,currentLoc,"not jump");
emitRestore();
}
/************************************************/
/* 函数名 valactGen */
/* 功 能 形参为值参时的形实参结合代码生成 */
/* 说 明 */
/************************************************/
void Cmidtodemi::valactGen(CodeFile *midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合开始*/
if(TraceCode) emitComment("->param combine ");
/*取得形参的偏移*/
int paramoff = midcode->codeR.arg2->Attr.value;
/*调用函数,得到实参的值,存在ac中*/
operandGen(midcode->codeR.arg1);
/*进行形实参结合,在新的AR的对应形参位置写入实参值*/
emitRM("ST",ac, paramoff, top,"store param value");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合结束*/
if(TraceCode) emitComment("<-param combine ");
}
/************************************************/
/* 函数名 varactGen */
/* 功 能 形参为变参时的代码生成 */
/* 说 明 */
/************************************************/
void Cmidtodemi::varactGen(CodeFile *midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合开始*/
if(TraceCode) emitComment("->param combine ");
/*记录参数的偏移*/
int paramoff = midcode->codeR.arg2->Attr.value;
/*形参是变参*/
/*1.实参是直接变量*/
if(midcode->codeR.arg1->Attr.addr.access == dir)
{ /*ac中的地址即为实参地址*/
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAddr(midcode->codeR.arg1);
}
/*2.实参是间接变量*/
else
{ /*ac中的地址存放的内容为实参地址*/
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAddr(midcode->codeR.arg1);
emitRM("LD",ac,0,ac,"");
}
/*进行形实参结合,在新的AR的对应形参位置写入实参变量的地址*/
emitRM("ST",ac, paramoff, top,"store param var");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合结束*/
if(TraceCode) emitComment("<-param combine ");
}
/************************************************/
/* 函数名 callGen */
/* 功 能 过程调用处的处理工作 */
/* 说 明 为了节约目标代码,将过程调用中的整体*/
/* 工作分配到三部分,过程调用处,过程入*/
/* 口处,过程出口处 */
/************************************************/
void Cmidtodemi::callGen(CodeFile *midcode)
{
/*保存旧的display表的偏移*/
emitRM("ST",displayOff,6,top," save nOff");
/*新的displayOff的值*/
int Noff = midcode->codeR.arg3->Attr.value;
emitRM("LDC",displayOff,Noff,0," new displayOff");
/*记录下返回地址,注:返回地址只能在这里求得,而且是跳过保存返回
地址得两条指令,和跳转得一条指令的下一条指令,故加3*/
int currentLoc = emitSkip(0)+3;
/*保存返回地址*/
emitRM("LDC",ac,currentLoc,0,"save return address");
emitRM("ST",ac,1,top,"");
/*与跳转指令处理相同,注意:跳转写在最后*/
jumpGen(midcode,1);
}
/************************************************/
/* 函数名 pentryGen */
/* 功 能 过程体入口处的处理 */
/* 说 明 过程入口中间代码中,ARG1是过程入口 */
/* 标号,ARG2是diplay表的偏移量,ARG3 */
/* 是过程的层数 */
/************************************************/
void Cmidtodemi::pentryGen(CodeFile *midcode)
{
/*首先处理标号,调用标号处理函数*/
labelGen(midcode);
/*取出AR大小信息*/
int ARsize = midcode->codeR.arg2->Attr.value;
/*取出过程层数信息*/
int procLevel = midcode->codeR.arg3->Attr.value;
/*保存当前sp*/
emitRM("ST",sp,0,top,"save old sp");
/*保存寄存器0,1,2,4*/
emitRM("ST",ac,3,top,"save ac");
emitRM("ST",ac1,4,top,"save ac1");
emitRM("ST",ac2,5,top," save ac2");
/*保存过程层数*/
emitRM("LDC",ac,procLevel,0,"save procedure level");
emitRM("ST",ac,2,top,"");
/*移display表*/
for(int ss = 0;ss<procLevel;ss++)
{
/*取原displayOff,存入ac1中*/
emitRM("LD",ac1,6,top," fetch old display Off");
/*ss要加上当前nOff才是对于sp的偏移*/
emitRM("LDA",ac1,ss,ac1," old display item");
/*ac1中为绝对地址*/
emitRO("ADD",ac1,ac1,sp,"");
/*取当前AR中display表的第ss项,存入ac中*/
emitRM("LD",ac,0,ac1," fetch display table item");
/*当前AR的displayOff*/
emitRM("LDA",ac1,ss,displayOff," current display item");
/*ac1中为绝对地址*/
emitRO("ADD",ac1,ac1,top,"");
/*将ac中的内容送入ac1所指地址中*/
emitRM("ST",ac,0,ac1," send display table item");
}
/*在display表中的最上层填写本层的sp*/
/*ac中存储的为display表最上层的相对off*/
emitRM("LDA",ac,procLevel,displayOff," current sp in display");
emitRO("ADD",ac,top,ac," absolute off");
emitRM("ST",top,0,ac," store address" );
/*修改sp和top*/
emitRM("LDA",sp,0,top," new sp value");
emitRM("LDA",top,ARsize,top,"new top value");
}
/************************************************/
/* 函数名 endprocGen */
/* 功 能 过程出口处的处理 */
/* 说 明 */
/************************************************/
void Cmidtodemi::endprocGen(CodeFile *midcode)
{
/*恢复寄存器值*/
emitRM("LD",ac,3,sp,"resume ac");
emitRM("LD",ac1,4,sp,"resume ac1");
emitRM("LD",ac2,5,sp,"resume ac2");
emitRM("LD",displayOff,6,sp,"resume nOff");
/*恢复sp和top值*/
emitRM("LDA",top,0,sp,"resume top");
emitRM("LD",sp,0,sp,"resume sp");
/*取出返回地址,返回*/
emitRM("LD",pc,1,top," load return address");
}
/***********************************************************/
/* 函数名 mentryGen */
/* 功 能 主程序入口的处理部分 */
/* 说 明 主程序入口中间代码的ARG2记录了主程序AR的display */
/* 表的偏移;参数savedLoc记录跳转改变pc的指令应在的*/
/* 位置 */
/***********************************************************/
void Cmidtodemi::mentryGen(CodeFile *midcode ,int savedLoc)
{
/*主程序入口*/
int currentLoc = emitSkip(0);
/*回退到目标代码第一条空语句处*/
emitBackup(savedLoc);
/*添加指令,将主程序入口地址传至指令寄存器pc*/
emitRM("LDC",pc,currentLoc,0,"main entry");
/*恢复当前地址*/
emitRestore();
emitComment("-> main procedure");
/*处理主程序的过程活动记录,需要填写的内容有:
全局变量、display表*/
/*初始化寄存器*/
emitRM("LDC",ac,0,0,"initialize ac");
emitRM("LDC",ac1,0,0,"initialize ac1");
emitRM("LDC",ac2,0,0,"initialize ac2");
/*确定sp*/
emitRM("ST",ac,0,sp," main sp");
/*确定displayOff*/
int Noff = midcode->codeR.arg3->Attr.value;
emitRM("LDC",displayOff,Noff,0," new displayOff");
/*填写display表,只有主程序本层的sp(0)*/
emitRM("ST",ac,0,displayOff," main display ");
/*填写top,根据AR的大小*/
int size = midcode->codeR.arg2->Attr.value;
emitRM("LDA",top, size, sp," main top");
}
/***********************************************************/
/* 函数名 FindAddr */
/* 功 能 计算变量的绝对地址 */
/* 说 明 将绝对地址存入ac中,注意要保证不用到ac2 */
/***********************************************************/
void Cmidtodemi::FindAddr( ArgRecord *arg )
{
/*源变量和临时变量处理方式不同*/
/*记录该变量所在层*/
int varLevel = arg->Attr.addr.dataLevel;
/*记录该变量的相对偏移*/
int varOff = arg->Attr.addr.dataOff;
/*源变量*/
if (varLevel != -1)
{
/*计算该变量的sp,存入ac中*/
FindSp(varLevel);
/*该变量相对于sp的偏移,存入ac1中*/
emitRM("LDC",ac1,varOff,0," ");
/* 计算绝对偏移 */
emitRO("ADD",ac,ac,ac1," var absolute off");
}
/*临时变量*/
else
{ /*临时变量是局部的,只在本AR中有效*/
/*该变量相对于sp的偏移,存入ac1中*/
emitRM("LDC",ac1,varOff,0," ");
/* 计算绝对偏移 */
emitRO("ADD",ac,sp,ac1," temp absolute off");
}
}
/***********************************************************/
/* 函数名 FindSp */
/* 功 能 找到该变量所在AR的sp,存入ac中 */
/* 说 明 */
/***********************************************************/
void Cmidtodemi::FindSp(int varlevel)
{
/*先求该变量层数在AR中的位置,其中varLevel表示变量所在层*/
emitRM("LDA",ac,varlevel,displayOff," var process");
/*绝对地址*/
emitRO("ADD",ac,ac,sp," var sp relative address");
/*该变量所在AR的sp地址存在ac1中*/
emitRM("LD",ac,0,ac," var sp");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -