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

📄 cgen.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************/
/* 文件 cgen.cpp				  					*/
/* 说明 类PASCAL语言编译器代码生成程序  			*/
/* 主题 编译器结构:原理和实例						*/	
/****************************************************/

/***********  该文件所包含的头文件  ****************/

#include "globals.h"	

#include "util.h"

#include "symbTable.h"		

#include "scanner.h"	

#include "parse.h"

#include "analyze.h"		

#include "string.h"

#include "cgen.h"

#include "code.h"



static int tmpOffset = 0;           /*临时变量区的偏移*/

static void genStmt(TreeNode * t);  


/*************************************************************/
/* 函数名  genProc                                           */
/* 功  能  该函数生成过程节点的代码                          */
/* 说  明  该函数处理过程声明部分的代码生成,在过程信息表中填 */
/*         写过程入口地址,结束是在pc中存入返回地址           */
/*************************************************************/
void genProc(TreeNode * t)
{
	int savedLoc1;         /*处理过程入口时所需的代码地址*/

	/*处理过程体部分*/

	int currentLoc = emitSkip(0);

	/*在过程信息表中填写过程入口地址*/
	t->table[0]->attrIR.More.ProcAttr.procEntry = currentLoc;

	/*初始化寄存器displayOff*/
	emitRM("LDC",displayOff,t->table[0]->attrIR.More.ProcAttr.nOff,0,"noff value");

	/*提示信息,过程处理部分开始*/
	if(TraceCode)  emitComment("->procedure");

	TreeNode * p1 = t->child[1];

	TreeNode * p2 = t->child[2];

	while(p1!=NULL)
	{
		/*处理过程声明部分*/
		if(p1->nodekind==ProcDecK)
		{
			savedLoc1 = emitSkip(1);
			genProc(p1);
			/*待过程处理完成,回填指令执行地址*/
			currentLoc = emitSkip(0);
			emitBackup(savedLoc1);
			emitRM("LDC",pc,currentLoc,0," procedure entry");
			//emitRM_Abs("JEQ",ac,currentLoc," jump to outside procedure");
			emitRestore();
		}
		p1 = p1->sibling;
	}

	if(p2!=NULL)
		p2 = p2->child[0];
	/*处理语句部分*/
	while (p2!=NULL)
	{
		genStmt(p2);
		p2 = p2->sibling;
	}
	
	/*指令寄存器pc的值置为返回地址*/
	emitRM("LD",ac2,1,sp," fetch return address");
	/*******注:此处的数字应该为0,而不是1*******/
	emitRM("LDA",pc,0,ac2," return old procedure");

	/*提示信息,当前过程处理部分结束*/
	if(TraceCode)  emitComment("<-procedure");
}



/*************************************************************/
/* 函数名  genStmt                                           */
/* 功  能  该函数生成一个语句节点的代码                      */
/* 说  明  根据不同的语法树节点产生不同的语句代码            */
/*************************************************************/
void 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;
			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -