📄 target.java
字号:
/*根据操作符,生成运算的目标代码,ac中为计算结果*/
if (midcode.codeR.codekind.equals("ADD"))
/*相加*/
emitRO("ADD",ac,ac1,ac,"op +");
else if (midcode.codeR.codekind.equals("SUB"))
/*相减*/
emitRO("SUB",ac,ac1,ac,"op -");
else if (midcode.codeR.codekind.equals("MULT"))
/*相乘*/
emitRO("MUL",ac,ac1,ac,"op *");
else if (midcode.codeR.codekind.equals("DIV"))
/*相除*/
emitRO("DIV",ac,ac1,ac,"op /");
else if (midcode.codeR.codekind.equals("LTC"))
{
/*小于*/
/* 写入减指令,将(左-右)操作数相减,结果送累加器ac */
emitRO("SUB",ac,ac1,ac,"op <");
/* 写入判断跳转指令,如果累加器ac的值小于0,则代码指令指示器跳过两条指令*/
emitRM("JLT",ac,2,pc,"br if true");
/* 写入载入常量指令,将累加器ac赋值为0 */
emitRM("LDC",ac,0,0,"false case");
/* 写入数值载入指令,代码指令指示器pc跳过下一条指令 */
emitRM("LDA",pc,1,pc,"unconditional jmp") ;
/* 写入载入常量指令,将累加器ac赋值为1 */
emitRM("LDC",ac,1,0,"true case");
}
else if (midcode.codeR.codekind.equals("EQC"))
{
/*等于*/
/* 写入减法指令,将左,右操作数相减,结果送累加器ac */
emitRO("SUB",ac,ac1,ac,"op ==");
/* 写入判断跳转指令,如果累加器ac等于0,代码指令指示器pc跳过两条指令*/
emitRM("JEQ",ac,2,pc,"br if true");
/* 写入载入常量指令,将累加器ac赋值为0 */
emitRM("LDC",ac,0,0,"false case");
/* 写入数值载入指令,代码指令指示器pc跳过一条指令 */
emitRM("LDA",pc,1,pc,"unconditional jmp") ;
/* 写入载入常量指令,将累加器ac赋值为1 */
emitRM("LDC",ac,1,0,"true case");
}
/*后面要用ac,故保存ac*/
emitRM("LDA",ac2,0,ac,"op: store result ");
/*计算目的操作数的地址,存在ac中*/
FindAddr(midcode.codeR.arg3);
/*取出暂存的计算结果,存入ac1*/
emitRM("LDA",ac1,0,ac2,"op: load result");
/*计算结果存入目的操作数*/
emitRM("ST",ac1,0,ac, "");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释信息,标注操作结束 */
if (TraceCode)
emitComment("<- Op");
}
/************************************************/
/* 函数名 operandGen */
/* 功 能 生成操作数的目标代码 */
/* 说 明 分操作数为常数或者变量两种情况处理 */
/* 注意不能用ac2 */
/************************************************/
void operandGen(ArgRecord arg)
{
if (arg.form.equals("ValueForm"))
{
/*操作数为常数*/
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,常数部分开始 */
if (TraceCode)
emitComment("-> Const");
/* 生成载入常量指令,载入常量到累加器ac */
emitRM("LDC",ac,arg.midAttr.value,0,"load const");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,常数部分结束 */
if (TraceCode)
emitComment("<- Const");
}
else if (arg.form.equals("LabelForm"))
{
/*分量为标号*/
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标号部分开始 */
if (TraceCode)
emitComment("-> Label");
/* 生成载入标号指令,载入标号值到累加器ac */
emitRM("LDC",ac,arg.midAttr.label,0,"load label");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标号部分结束 */
if (TraceCode)
emitComment("<- Label");
}
else if (arg.form.equals("AddrForm"))
{
/*操作数为变量,有可能是临时变量*/
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标注标识符开始 */
if (TraceCode)
emitComment("-> var");
FindAddr(arg);
/*其中ac返回的是源变量或临时变量的绝对偏移*/
if(arg.midAttr.addr.access.equals("indir"))
{
/*取内容作为地址,再取内容*/
emitRM("LD",ac1,0,ac,"indir load id value");
emitRM("LD",ac,0,ac1,"");
}
else
{
/*存的是值*/
/* 写入数值载入指令,载入变量标识符的值*/
emitRM("LD",ac,0,ac,"load id value");
}
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,标注标识符结束 */
if (TraceCode)
emitComment("<- var");
}
}
/************************************************/
/* 函数名 aaddGen */
/* 功 能 生成地址加操作的目标代码 */
/* 说 明 */
/************************************************/
void aaddGen(CodeFile midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,aadd语句开始 */
if (TraceCode)
emitComment("->address add");
if (midcode.codeR.arg1.midAttr.addr.access.equals("dir"))
{
/*ac中的地址即为基地址*/
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAddr(midcode.codeR.arg1);
}
else
{
/*ac中的地址存放的内容为基地址*/
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAddr(midcode.codeR.arg1);
emitRM("LD",ac,0,ac,"");
}
/*基地址转存到ac2*/
emitRM("LDA",ac2,0,ac,"op: store baseaddr ");
/*求地址相加运算的偏移量,存在ac中*/
operandGen(midcode.codeR.arg2);
/*地址相加,结果在ac2中*/
emitRO("ADD",ac2,ac2,ac,"op +");
/*求目的变量的地址,存入ac*/
FindAddr(midcode.codeR.arg3);
/*地址相加结果写入目的变量*/
emitRM("ST",ac2,0,ac,"");
}
/************************************************/
/* 函数名 readGen */
/* 功 能 生成读操作的目标代码 */
/* 说 明 根据变量是直接变量还是间接变量进行 */
/* 不同的处理 */
/************************************************/
void readGen(CodeFile midcode)
{
/*生成读指令,该指令完成读入外部数值到累加器ac2的动作*/
emitRO("IN",ac2,0,0,"read integer value");
/*计算变量的绝对偏移,ac中存为变量的绝对偏移*/
FindAddr(midcode.codeR.arg1);
if(midcode.codeR.arg1.midAttr.addr.access.equals("dir"))
{
/*直接存*/
/*最后生成存储指令*/
emitRM("ST",ac2,0,ac," var read : store value");
}
else
{
/*以ac内容作为地址找变量单元,再存*/
emitRM("LD",ac1,0,ac,"");
emitRM("ST",ac2,0,ac1," indir var read : store value");
}
}
/************************************************/
/* 函数名 writeGen */
/* 功 能 生成写操作的目标代码 */
/* 说 明 调用函数得到值,并产生输出代码 */
/************************************************/
void writeGen(CodeFile midcode)
{
/*调用函数,得到输出的值,存在ac中*/
operandGen(midcode.codeR.arg1);
/*生成写指令,该指令完成将累加器ac中的值输出的动作*/
emitRO("OUT",ac,0,0,"write ac");
}
/************************************************/
/* 函数名 returnGen */
/* 功 能 生成返回语句的目标代码 */
/* 说 明 返回过程调用的下一条语句,注意return */
/* 语句只在过程中出现 */
/************************************************/
void returnGen(CodeFile midcode)
{
/*从过程里跳出,所做的工作与过程结束相同*/
endprocGen(midcode);
}
/************************************************/
/* 函数名 assigGen */
/* 功 能 生成赋值语句的目标代码 */
/* 说 明 */
/************************************************/
void assigGen(CodeFile midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,assign语句开始 */
if (TraceCode)
emitComment("->assign");
/*赋值左部变量的地址,存在ac中*/
FindAddr(midcode.codeR.arg2);
/*转放在ac2中*/
emitRM("LDA",ac2,0,ac,"op: store addr ");
/*生成赋值右部的目标代码,值存在ac中*/
operandGen(midcode.codeR.arg1);
if(midcode.codeR.arg2.midAttr.addr.access.equals("dir"))
/*赋值,ac2中为地址*/
emitRM("ST",ac,0,ac2,"var assign : store value");
else
{
/*从ac2中取出内容,作为地址*/
emitRM("LD",ac1,0,ac2," indir var assign");
emitRM("ST",ac,0,ac1," store value");
}
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,assign语句结束 */
if (TraceCode)
emitComment("<- assign") ;
}
/************************************************/
/* 函数名 labelGen */
/* 功 能 处理标号的目标代码生成 */
/* 说 明 若表中没有此标号对应得项,填标号地址表 */
/* 若表中有此标号对应项,则回填目标代码 */
/************************************************/
void labelGen(CodeFile midcode)
{
/*取得标号值*/
int label = midcode.codeR.arg1.midAttr.label;
/*取得当前目标代码编号*/
int currentLoc = emitSkip(0) ;
/*查找标号地址表*/
LabelAddr item = labelAddrT;
LabelAddr last = item;
while (item!=null)
{
if (item.label == label)
break;
last = item;
item = item.next;
}
if (item==null) /*表中没有此标号对应得项,填表 */
{
/*新建一项*/
LabelAddr newItem = new LabelAddr();
newItem.label = label;
newItem.destNum = currentLoc;
/*加入标号地址表中*/
if (labelAddrT == null)
labelAddrT = newItem;
else
last.next = newItem;
}
else /*表中有此标号对应项,则回填目标代码*/
{
/*退回到指令回填地址*/
emitBackup(item.destNum);
/*写入跳转到此标号所在目标代码位置的代码*/
emitRM("LDC",pc,currentLoc,0,"jump to label");
/*恢复当前目标代码*/
emitRestore();
}
}
/************************************************/
/* 函数名 jumpGen */
/* 功 能 生成跳转的目标代码 */
/* 说 明 参数i是为了复用此函数而设,根据i */
/* 决定从中间代码中哪个分量取标号值 */
/************************************************/
void jumpGen(CodeFile midcode,int i)
{
int label;
/*取得标号值*/
if (i == 1)
label = midcode.codeR.arg1.midAttr.label;
else
label = midcode.codeR.arg2.midAttr.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 = new LabelAddr();
newItem.label = label;
newItem.destNum = currentLoc;
/*加入标号地址表中*/
if (last == null)
labelAddrT = newItem;
else
last.next = newItem;
}
else
/*表中有此标号对应项,则可以生成目标代码*/
emitRM("LDC",pc,item.destNum,0,"jump to label");
}
/************************************************/
/* 函数名 jump0Gen */
/* 功 能 条件跳转语句的目标代码生成 */
/* 说 明 */
/************************************************/
void 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 valactGen(CodeFile midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合开始*/
if (TraceCode)
emitComment("->param combine ");
/*取得形参的偏移*/
int paramoff = midcode.codeR.arg2.midAttr.value;
/*调用函数,得到实参的值,存在ac中*/
operandGen(midcode.codeR.arg1);
/*进行形实参结合,在新的AR的对应形参位置写入实参值*/
emitRM("ST",ac,paramoff,top,"store param value");
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合结束*/
if (TraceCode)
emitComment("<-param combine ");
}
/************************************************/
/* 函数名 varactGen */
/* 功 能 形参为变参时的代码生成 */
/* 说 明 */
/************************************************/
void varactGen(CodeFile midcode)
{
/* 如果代码生成追踪标志TraceCode为TRUE,写入注释,形实参结合开始*/
if (TraceCode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -