📄 treetodemi.cpp
字号:
if(TraceCode) emitComment("<-procedure");
}
/*************************************************************/
/* 函数名 genStmt */
/* 功 能 该函数生成一个语句节点的代码 */
/* 说 明 根据不同的语法树节点产生不同的语句代码 */
/*************************************************************/
void Ctreetodemi::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;
}/*while循环结束*/
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
/*@@@@@@@@@@ 进入子程序入口 @@@@@@@@@@@@@*/
/*保存当前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("ST",displayOff,6,top," save nOff");
/*新的displayOff的值*/
emitRM("LDC",displayOff,pp->table[0]->attrIR.More.ProcAttr.nOff,0," new displayOff");
/*返回值*/
//emitRM("LDC",ac,0,0,"");
//emitRM("ST",ac,7,top,"return value");
/*保存返回地址*/
savedLoc1 = emitSkip(2);
/*过程层数*/
emitRM("LDC",ac1,pp->table[0]->attrIR.More.ProcAttr.level,0," save procedure level");
emitRM("ST",ac1,2,top,"");
/*移display表*/
for(ss = 0;ss<(pp->table[0]->attrIR.More.ProcAttr.level);ss++)
{
/*取原displayOff,存入ac2中*/
emitRM("LD",ac2,6,top," fetch old display Off");
/*ss要加上当前nOff才是对于sp的偏移*/
emitRM("LDA",ac2,ss,ac2," old display item");
/*ac2中为绝对地址*/
emitRO("ADD",ac2,ac2,sp,"");
/*取当前AR中display表的的第ss项,存入ac1中*/
emitRM("LD",ac1,0,ac2," fetch display table item");
/*当前AR的displayOff*/
emitRM("LDA",ac2,ss,displayOff," current display item");
/*ac2中为绝对地址*/
emitRO("ADD",ac2,ac2,top,"");
/*将ac1中的内容送入ac2所指地址中*/
emitRM("ST",ac1,0,ac2," send display table item");
}
/*在display表中的最上层填写本层的sp*/
/*ac2中存储的为display表最上层的相对off*/
emitRM("LDA",ac2,pp->table[0]->attrIR.More.ProcAttr.level,displayOff," current sp in display");
emitRO("ADD",ac2,top,ac2," absolute off");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -