📄 target.java
字号:
emitComment("->param combine ");
/*记录参数的偏移*/
int paramoff = midcode.codeR.arg2.midAttr.value;
/*形参是变参*/
/*1.实参是直接变量*/
if (midcode.codeR.arg1.midAttr.addr.access.equals("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 callGen(CodeFile midcode)
{
/*保存旧的display表的偏移*/
emitRM("ST",displayOff,6,top," save nOff");
/*新的displayOff的值*/
int Noff = midcode.codeR.arg3.midAttr.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 pentryGen(CodeFile midcode)
{
/*首先处理标号,调用标号处理函数*/
labelGen(midcode);
/*取出AR大小信息*/
int ARsize = midcode.codeR.arg2.midAttr.value;
/*取出过程层数信息*/
int procLevel = midcode.codeR.arg3.midAttr.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 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 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.midAttr.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.midAttr.value;
emitRM("LDA",top, size, sp," main top");
}
/***********************************************************/
/* 函数名 FindAddr */
/* 功 能 计算变量的绝对地址 */
/* 说 明 将绝对地址存入ac中,注意要保证不用到ac2 */
/***********************************************************/
void FindAddr( ArgRecord arg)
{
/*源变量和临时变量处理方式不同*/
/*记录该变量所在层*/
int varLevel = arg.midAttr.addr.dataLevel;
/*记录该变量的相对偏移*/
int varOff = arg.midAttr.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 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");
}
/****************************************************************/
/* 函数名 emitComment */
/* 功 能 注释生成函数 */
/* 说 明 该函数将函数参数c指定的注释内容写入代码文件code */
/****************************************************************/
void emitComment(String c)
/* 如果代码生成追踪标志TraceCode为TRUE,将注释写入目标代码文件 */
{
if (TraceCode)
mbcode=mbcode+"* "+c+"\n";
}
/********************************************************/
/* 函数名 emitRO */
/* 功 能 寄存器地址模式指令生成函数 */
/* 说 明 该函数产生一条只用寄存器操作数的TM指令 */
/* op 为操作码; */
/* r 为目标寄存器; */
/* s 第一源寄存器; */
/* t 第二源寄存器; */
/* c 为将写入代码文件code的注释内容 */
/********************************************************/
void emitRO(String op,int r,int s,int t,String c)
{
/* 将TM指令格式化写入代码文件,当前生成代码写入地址emitLoc加1 */
mbcode=mbcode+String.valueOf(emitLoc++)+":"+op+" "+String.valueOf(r)+","+String.valueOf(s)+","+String.valueOf(t);
/* 如果代码生成追踪标志TraceCode为TRUE,将注释c写入代码文件 */
if (TraceCode)
mbcode=mbcode+"\t"+"*"+c;
/* 一条代码指令写完,加入代码行结束标志 */
mbcode=mbcode+"\n";
/* 当前生成代码写入地址若超出最高生成代码写入地址 改变最高生成代码写入地址highEmitLoc为当前生成代码写入地址emitLoc */
if (highEmitLoc<emitLoc)
highEmitLoc = emitLoc ;
}
/********************************************************/
/* 函数名 emitRM */
/* 功 能 变址地址模式指令生成函数 */
/* 说 明 该函数产生一条寄存器-内存操作数TM指令 */
/* op 操作码; */
/* r 目标寄存器; */
/* d 为偏移值; */
/* s 为基地址寄存器; */
/* c 为将写入代码文件code的注释内容 */
/********************************************************/
void emitRM(String op,int r,int d,int s,String c)
{
/* 将TM指令格式化写入代码文件,当前生成代码写入地址emitLoc加1 */
mbcode=mbcode+String.valueOf(emitLoc++)+":"+op+" "+String.valueOf(r)+","+String.valueOf(d)+"("+String.valueOf(s)+")";
/* 如果代码生成追踪标志TraceCode为TRUE,将注释c写入代码文件 */
if (TraceCode)
mbcode=mbcode+"\t"+"*"+c;
/* 一条代码指令写完,加入代码行结束标志 */
mbcode=mbcode+"\n";
/* 当前生成代码写入地址若超出最高生成代码写入地址 改变最高生成代码写入地址highEmitLoc为当前生成代码写入地址emitLoc */
if (highEmitLoc<emitLoc)
highEmitLoc = emitLoc ;
}
/****************************************************/
/* 函数名 emitSkip */
/* 功 能 空过生成函数 */
/* 说 明 该函数空过howMany指定数量的写入代码位置, */
/* 返回当前生成代码写入地址 */
/****************************************************/
int emitSkip(int howMany)
{
/* 当前生成代码写入地址emitLoc赋给变量i */
int i = emitLoc;
/* 新的当前生成代码写入地址emitLoc略过howMany指定数量的写入指令位置 */
emitLoc = emitLoc+howMany ;
/* 若当前生成代码写入地址emitLoc超过最高生成代码写入地址highEmitLoc
更新最高生成代码写入地址highEmitLoc */
if (highEmitLoc < emitLoc)
highEmitLoc = emitLoc ;
/* 函数返回旧的当前生成代码写入地址i */
return i;
}
/********************************************************/
/* 函数名 emitBackup */
/* 功 能 地址回退函数 */
/* 说 明 该函数退回到以前被空过的生成代码写入地址loc */
/********************************************************/
void emitBackup(int loc)
{
/* 如果要退回的地址loc比当前最高地址highEmitLoc还高
报退回错误,将错误信息作为注释写入代码文件code */
if (loc > highEmitLoc)
emitComment("BUG in emitBackup");
/* 更新当前生成代码写入地址emitLoc为函数参数loc,完成退回动作 */
emitLoc = loc ;
}
/********************************************************/
/* 函数名 emitRestore */
/* 功 能 地址恢复函数 */
/* 说 明 该函数将当前生成代码写入地址emitLoc恢复为 */
/* 当前未写入指令的最高地址highEmitLoc */
/********************************************************/
void emitRestore()
{
emitLoc = highEmitLoc;
}
/************************************************/
/* 函数名 emitRM_Abs */
/* 功 能 地址转换函数 */
/* 说 明 该函数在产生一条寄存器-内存TM指令时, */
/* 将绝对地址参数转换成pc相对地址参数 */
/* op 为操作码; */
/* r 为目标寄存器; */
/* a 为存储器绝对地址; */
/* c 为将写入代码文件code的注释 */
/************************************************/
void emitRM_Abs(String op,int r,int a,String c)
{
/* 将TM指令格式化写入代码文件,将函数参数a给定的绝对地址
转换为相对于指令指示器pc的相对地址a-(emitLoc+1) */
mbcode=mbcode+String.valueOf(emitLoc)+":"+op+" "+String.valueOf(r)+","+String.valueOf(a-(emitLoc+1))+"("+String.valueOf(pc)+")";
/* 如果代码生成追踪标志TraceCode为TRUE,将注释c写入代码文件 */
if (TraceCode)
mbcode=mbcode+"\t"+"*"+c;
/* 一条代码指令写完,加入代码行结束标志 */
mbcode=mbcode+"\n";
/* 当前生成代码写入地址若超出最高生成代码写入地址 改变最高生成代码写入地址highEmitLoc为当前生成代码写入地址emitLoc */
if (highEmitLoc<emitLoc)
highEmitLoc = emitLoc;
}
}
/********************************************************************/
/* 类 名 Opt */
/* 功 能 总程序的处理 */
/* 说 明 建立一个类,处理总程序 */
/********************************************************************/
class Opt
{
CodeFile baseBlock[]=new CodeFile[100];
int blocknum;
/*临时变量编号,全局变量,每个过程开始都对TempOffset进行
初始化,注:所以,不同过程中,可能有编号相同的临时变量,但是
由于他们互不相干,所以不会有问题;而且优化部分是对基本块进行优化,
每个基本块最大是一个过程,也不会有问题 */
int TempOffset=0;
/*标号值,全局变量*/
int Label=0;
/*指向第一条中间代码*/
CodeFile firstCode;
/*指向当前最后一条中间代码*/
CodeFile lastCode;
/*记录主程序display表的偏移量*/
int StoreNoff;
/*常量定值表*/
ConstDefT table;
ValuNum valuNumT;
UsableExpr usableExprT;
TempEqua tempEquaT;
/*记录值编码*/
int Vnumber=0;
/*变量定值表,用变量的arg结构表示变量*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -