📄 midtodemi.cpp
字号:
// 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 + -