⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 target.java

📁 这是编译原理的目标代码生成器java代码
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
        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 + -