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

📄 midtodemi.cpp

📁 上课时老师用过的SNL编译器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// midtodemi.cpp: implementation of the Cmidtodemi class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "face.h"
#include "midtodemi.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Cmidtodemi::Cmidtodemi()
{
/*标号地址表*/
labelAddrT = NULL;


/* TM指令当前生成代码写入地址 */
 emitLoc = 0 ;

/* 用于在函数emitSkip,emitBackup,emitRestore	*
 * 中作为当前最高生成代码写入地址,初始为0		*/
 highEmitLoc = 0;

}

Cmidtodemi::~Cmidtodemi()
{

}


/*******************实用函数******************/

/****************************************************************/
/* 函数名 emitComment											*/
/* 功  能 注释生成函数											*/
/* 说  明 该函数将函数参数c指定的注释内容写入代码文件code		*/
/****************************************************************/
void Cmidtodemi::emitComment( char * c )

/* 如果代码生成追踪标志TraceCode为TRUE,将注释写入目标代码文件code */
{	
	if (TraceCode) 
	{
		fprintf(code,"* %s\n",c);
	}
}


/********************************************************/
/* 函数名 emitRO										*/
/* 功  能 寄存器地址模式指令生成函数					*/
/* 说  明 该函数产生一条只用寄存器操作数的TM指令		*/
/*		  op 为操作码;									*/
/*		  r  为目标寄存器;								*/
/*		  s  第一源寄存器;								*/
/*		  t  第二源寄存器;								*/
/*		  c  为将写入代码文件code的注释内容				*/
/********************************************************/
void Cmidtodemi::emitRO( char *op, int r, int s, int t, char *c)

{ 
  /* 将TM指令格式化写入代码文件code,当前生成代码写入地址emitLoc加1 */
  fprintf(code,"%3d:  %5s  %d,%d,%d ",emitLoc++,op,r,s,t);

  /* 如果代码生成追踪标志TraceCode为TRUE,将注释c写入代码文件code */
  if (TraceCode) 
  {
	  fprintf(code,"\t*%s",c);
  }

  /* 一条代码指令写完,加入代码行结束标志 */
  fprintf(code,"\n");

  /* 当前生成代码写入地址若超出最高生成代码写入地址						*
   * 改变最高生成代码写入地址highEmitLoc为当前生成代码写入地址emitLoc	*/
  if (highEmitLoc < emitLoc) highEmitLoc = emitLoc ;

} 



/********************************************************/
/* 函数名 emitRM										*/
/* 功  能 变址地址模式指令生成函数						*/
/* 说  明 该函数产生一条寄存器-内存操作数TM指令			*/
/*		  op 操作码;									*/
/*		  r  目标寄存器;								*/
/*		  d  为偏移值;									*/
/*		  s  为基地址寄存器;							*/
/*		  c  为将写入代码文件code的注释内容				*/
/********************************************************/
void Cmidtodemi::emitRM( char * op, int r, int d, int s, char *c)

{
  /* 将TM指令格式化写入代码文件code,当前生成代码写入地址emitLoc加1 */
  fprintf(code,"%3d:  %5s  %d,%d(%d) ",emitLoc++,op,r,d,s);

  /* 如果代码生成追踪标志TraceCode为TRUE,将注释c写入代码文件code */
  if (TraceCode) 
  {
	  fprintf(code,"\t*%s",c);
  }

  /* 写完一条代码指令,加入指令行结束标志 */
  fprintf(code,"\n");

  /* 若当前生成代码写入地址emitLoc超过最高生成代码写入地址highEmitLoc	*
   * 更新最高生成代码写入地址highEmitLoc								*/
  if (highEmitLoc < emitLoc)  highEmitLoc = emitLoc ;
} 



/****************************************************/
/* 函数名 emitSkip									*/	
/* 功  能 空过生成函数								*/
/* 说  明 该函数空过howMany指定数量的写入代码位置,	*/
/*		  返回当前生成代码写入地址					*/
/****************************************************/
int Cmidtodemi::emitSkip( int howMany)

{  
   /* 当前生成代码写入地址emitLoc赋给变量i */
   int i = emitLoc;

   /* 新的当前生成代码写入地址emitLoc略过howMany指定数量的写入指令位置 */
   emitLoc += howMany ;

   /* 若当前生成代码写入地址emitLoc超过最高生成代码写入地址highEmitLoc	*
    * 更新最高生成代码写入地址highEmitLoc								*/
   if (highEmitLoc < emitLoc)  highEmitLoc = emitLoc ;

   /* 函数返回旧的当前生成代码写入地址i */
   return i;
} 


/********************************************************/
/* 函数名 emitBackup									*/
/* 功  能 地址回退函数									*/	
/* 说  明 该函数退回到以前被空过的生成代码写入地址loc	*/
/********************************************************/
void Cmidtodemi::emitBackup( int loc)

{
  /* 如果要退回的地址loc比当前最高地址highEmitLoc还高	*
   * 报退回错误,将错误信息作为注释写入代码文件code		*/
  if (loc > highEmitLoc) emitComment("BUG in emitBackup");

  /* 更新当前生成代码写入地址emitLoc为函数参数loc,完成退回动作 */
  emitLoc = loc ;
} 


/********************************************************/
/* 函数名 emitRestore									*/
/* 功  能 地址恢复函数									*/
/* 说  明 该函数将当前生成代码写入地址emitLoc恢复为		*/
/*		  当前未写入指令的最高地址highEmitLoc			*/
/********************************************************/
void Cmidtodemi::emitRestore(void)

{ emitLoc = highEmitLoc;}


/************************************************/
/* 函数名 emitRM_Abs							*/
/* 功  能 地址转换函数							*/
/* 说  明 该函数在产生一条寄存器-内存TM指令时,	*/
/*		  将绝对地址参数转换成pc相对地址参数	*/
/*		  op 为操作码;							*/
/*		  r  为目标寄存器;						*/
/*		  a  为存储器绝对地址;					*/
/*		  c  为将写入代码文件code的注释			*/
/************************************************/
void Cmidtodemi::emitRM_Abs( char *op, int r, int a, char * c)

{ 
  /* 将TM指令格式化写入代码文件code,将函数参数a给定的绝对地址	*
   * 转换为相对于指令指示器pc的相对地址a-(emitLoc+1)			*/
  fprintf(code,"%3d:  %5s  %d,%d(%d) ",
               emitLoc,op,r,a-(emitLoc+1),pc);

  /* 更新当前生成代码写入地址emitLoc */
  ++emitLoc ;

  /* 如果代码生成追踪标志traceCode为TRUE,将注释c写入代码文件code */
  if (TraceCode) 
  {
	  fprintf(code,"\t*%s",c);
  }

  fprintf(code,"\n");

  /* 若当前生成代码写入地址emitLoc超出最高生成代码写入地址highEmitLoc	*
   * 更新最高生成代码写入地址highEmitLoc								*/
  if (highEmitLoc < emitLoc) highEmitLoc = emitLoc ;

} 

/*****************目标代码生成函数的实现*****************/


/************************************************/
/* 函数名 codeGen								*/ 
/* 功  能 目标代码生成主函数					*/		
/* 说  明 该函数通过扫描中间代码序列产生目标代码*/
/*        文件第二个参数codefile为目标代码文件名*/
/************************************************/
void Cmidtodemi::codeGen(CodeFile  *midcode, char * destcode)
{ 

/***********从构造函数拷贝,每次调用都要初始化***********/

	/*标号地址表*/
	labelAddrT = NULL;


	/* TM指令当前生成代码写入地址 */
	emitLoc = 0 ;

	/* 用于在函数emitSkip,emitBackup,emitRestore	*
	 * 中作为当前最高生成代码写入地址,初始为0		*/
	highEmitLoc = 0;

/********************************************************/

   /* 在内存中动态分配字串单元,返回单元指针s,	*
	* codefile为存储目标代码的代码文件名		*/
   char * s = (char *)malloc(strlen(destcode)+7);

   /* 将给定字串拷贝到s */
   strcpy(s,"File: ");

   /* 将目标代码文件名的字串拼接到s */
   strcat(s,destcode);
   fprintf(code,"\n\n");

   getchar();

   /* 生成代码文件说明注释,写入代码文件 */
   emitComment("TINY Compilation to TM Code");
   emitComment(s);
 
   /* 生成标准先驱指令 */
   emitComment("Standard prelude:");
   
   /* 写入单元设置指令,清空0地址单元中内容 */
   emitRM("ST",ac,0,ac,"clear location 0");
   
   /* 写入注释,先驱指令写完 */
   emitComment("End of standard prelude.");
   
   /*为主程序入口留一个跳转语句*/
   int  savedLoc = emitSkip(1);

   /*循环处理各条中间代码,调用相应得函数产生相应得目标代码*/
   while  (midcode!=NULL)
   {
	 switch(midcode->codeR.codekind)
	 {	/*运算处理,包括算术运算和关系运算*/
		case	ADD:
		case	SUB:
		case	MULT:
		case	DIV:	
		case	LTC:
		case	EQC:
					arithGen(midcode);		break;
		/*地址加运算*/
		case   AADD:
					aaddGen(midcode);		break;
		/*输入语句*/
		case   READC:
					readGen(midcode);		break;
		/*输出语句*/
		case   WRITEC:
					writeGen(midcode);		break;
		/*返回语句*/
		case   RETURNC:
					returnGen(midcode);		break;
		/*赋值语句*/
		case   ASSIG:
					assigGen(midcode);		break;
		/*标号声明语句*/
		case   LABEL:
		case   WHILESTART:
		case   ENDWHILE:
					labelGen(midcode);		break;
		/*跳转语句*/
		case   JUMP:
					jumpGen(midcode,1);		break;
		/*条件跳转语句*/
		case   JUMP0:
					jump0Gen(midcode);		break;
		/*形实参结合语句:形参是值参*/
		case   VALACT:
					valactGen(midcode);		break;
		/*形实参结合语句:形参是变参*/
		case   VARACT:
					varactGen(midcode);		break;
		/*过程调用语句*/
		case   CALL:
					callGen(midcode);		break;
		/*过程入口声明*/
		case   PENTRY:
					pentryGen(midcode);		break;
		/*过程出口声明*/
		case   ENDPROC:
					endprocGen(midcode);	break;
		/*主程序入口处理*/
		case   MENTRY:
				    mentryGen(midcode,savedLoc); break;

		default :  fprintf(code , " midcode  bug.\n");
	 }
   midcode = midcode->next;
   }

   /*处理完主程序,退出AR*/
   emitComment("<- end of main ");
   /* 写入注释,标志文件执行的结束 */
   emitComment("End of execution.");
   /* 写入停止指令,结束程序执行 */
   emitRO("HALT",0,0,0,"");

⌨️ 快捷键说明

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