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

📄 cgen.c

📁 1.小型编译器 2。支持整数
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************/
/* File: cgen.c                                     */
/* The code generator implementation                */
/* for the TINY compiler                            */
/* (generates code for the TM machine)              */
/* Compiler Construction: Principles and Practice   */
/* Kenneth C. Louden                                */
/****************************************************/

#include "Globals.h"
#include "SymTab.h"
#include "Code.h"
#include "CGen.h"
#include <math.h>
#include "TmStack.h"
#include "Util.h"

int 	iloc = 0 ;
int 	dloc = 0 ;
int 	traceflag = TRUE;
int 	icountflag = TRUE;

BYTE 	dMem [DADDR_SIZE];

WORD 	reg [NO_REGS];
DWORD 	dreg [NO_REGS];
static char 	in_Line[LINESIZE] ;
int		base[MAXLEVEL];
map<int,int>	mIndex;

TmStack	mStack;

int 	lineLen ;
int 	inCol  ;
int 	num  ;
static int		fun_offset = 0;

static int 	label_num = 0;
int 	vari_offset;
int 	para_offset;

/* tmpOffset is the memory offset for temps
   It is decremented each time a temp is
   stored, and incremeted when loaded again
*/
static int 	tmpOffset = 0;
static int	pLevel = 0;
static int  pSaveLevel = 0;
static int 	IsInFunction = 0;
static int 	nFuncTop = 0;
static int 	nGlobalTop = 0;

const char * opCodeTab[] = {
	"START","HALT","IN","OUT","ADD","SUB","MUL","DIV","LT","LE","GT","GE","EQ","NEQ",
	"AND","OR","NOT","UJP","FJP","LAB","PUSH","POP","COPY","SYSCALL","????",
    /* RR opcodes */
   	"LD","ST","????", /* RM opcodes */
   	"LDA","LDC",
   	"ENT","RET","MST","CUP","CSP","????"
   	/* RA opcodes */
};

void genLabel(int &label)
{
	static int i=1;
	label = i;
	i++;
}

/********************************************/
void writeInstruction ( int loc )
{ 
	printf( "%5d: ", loc) ;
  	if ( (loc >= 0) && (loc < IADDR_SIZE) )
  	{ 
  		printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
    	switch ( opClass(iMem[loc].iop) )
    	{ 
    		case opclRR: 
				printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
            	break;
      		case opclRM:
      		case opclRA: 
				if((iMem[loc].iop == opLDC)&&(iMem[loc].isize == sizeofdouble))
					printf("%3f(%1d)", iMem[loc].darg2, iMem[loc].iarg3);
				else
					printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
            	break;
    	}
		printf(" %3d", iMem[loc].isize);
		printf ("\n") ;
  	}
} /* writeInstruction */


/********************************************/
void getInput ()
{ 
	memset(in_Line, 0, sizeof(in_Line));
	gets(in_Line);
	//printf("in_Line: %s\n", in_Line);
	return;
} 

void lab(int label)
{
	emitRO(opLAB, label, 0, 0, " label");
}

void ujp(int label)
{
	emitRO(opUJP, label, 0, 0, " ujp label");
}

void fjp(int label)
{
	emitRO(opFJP, label, 0, 0, " fjp label");
}

static ExpType getType(TreeNode * t){
	if(t->kind.exp == StructIdK){
		return getType(t->child[0]);
	}
	return t->type.type;
}

void ret(int r,char * name)
{
	int addr = 0;
	FunEntry * pEntry = (FunEntry*)malloc(sizeof(FunEntry));
	if(r){//if the function has a return value
		pEntry = Lookup_Fun(name);
		addr = pEntry ->ret_val;
	}
	//恢复旧的sp,tp
	emitRM(opLD,tp,callFO,sp,"load old tp");
	//恢复寄存器
	//emitRM(opPOP,ac,0,0,"call: pop function ret");
	//emitRM(opPOP,ac1,0,0,"call: pop ac");
	//恢复返回地址
	if(strcmp(name, "main"))
		emitRM(opLD,bp,retFO,sp,"pre load old pc");
	emitRM(opLD,sp,ospFO,sp,"load old sp");
	if(strcmp(name, "main"))
		emitRM(opLDA,pc,0,bp,"load old pc");
	
}

/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree, int addrFlag = 0);

static void genDec(TreeNode *tree, int addrFlag = 0){
	TreeNode * p1, * p2, * p3;
	int savedLoc1,savedLoc2,currentLoc;
	ValEntry * pEntry = (ValEntry *)malloc(sizeof(ValEntry));
	FunEntry * pFunEntry = (FunEntry *)malloc(sizeof(FunEntry));
	int i, level,loc,size,flag;
	ExpType	type;
	switch (tree->kind.dec){
		case FunDecK:
			break;
		case FunDefK:
			//主函数要设特殊标志
			emitRM(opENT,0,0,0,tree->attr.name);
			//传入参数

			pLevel = 0;

			for(i=0;i<MAXLEVEL;i++)
				base[i] = 0;
			base[0] = -4;

			pFunEntry = Lookup_Fun(tree->attr.name);
			size = pFunEntry->ret_val;

			//保存寄存器
			//emitRM(opPUSH,ac,0,0,"FunDefK: push ac");
			//emitRM(opPUSH,ac1,0,0,"FunDefK: push ac1");
	
			//保存旧的sp,tp
			emitRM(opST,tp,-size+callFO,tp,"FunDefK: store current tp");
			emitRM(opST,sp,-size+ospFO,tp,"FunDefK: store current sp");
			
			//保存返回地址	---???,ac已经变化
			emitRM(opST,ac,-size+retFO,tp,"FunDefK: store current sp");
			
			//置新的sp,tp
			emitRM(opLDA,sp,-size,tp,"FunDefK: set new sp");
			emitRM(opLDA,tp,-size,tp,"FunDefK: set new tp");
						
			p2 = tree->child[1];	// comp_dec
			cGen(p2);
			//返回值

			//ret(FALSE,tree ->attr.name);
			
			if(strcmp(tree->attr.name,"main") == 0)
				emitRM(opRET,0,0,0,tree->attr.name);
			else
				emitRM(opRET,1,0,0,tree->attr.name);
			
			break;
		case VarK:
			p1 = tree->child[0];
			if((tree->kind.exp == NumK)||(tree->kind.exp == CharK)||(tree->kind.exp == DNumK))
			while(p1){
				if(p1->nodekind == StmtK)	//AssignK
				{
					p2 = p1->child[0];
					//用于数组的情况
					//if(p2->child[0])
			        // 	cGen(p2->child[0]);
					
			        /* now store value */
			       	level = Lookup_Var(pTable, pTable ->funEntry, p2->attr.name, pEntry);
					loc = pEntry ->offset;

					//printf("tree->attr.name: %s pTable ->nestlevel: %d\n ", p2->attr.name, level);

					p3 = p1->child[1];
					cGen(p3);
								
			  		if(level == 0){
						if(p2->type.type == Double){
							emitRM(opPOP,ac,0,0,"assign: pop double value",sizeofdouble);
			  				emitRM(opST,ac,loc,gp,"assign: store double value",sizeofdouble);
						}else if(p2->type.type == Integer){
							emitRM(opPOP,ac,0,0,"assign: pop integer value",sizeofint);
							emitRM(opST,ac,loc,gp,"assign: store integer value",sizeofint);
						}else if(p2->type.type == Char){
							emitRM(opPOP,ac,0,0,"assign: pop char value",sizeofchar);
							emitRM(opST,ac,loc,gp,"assign: store char value",sizeofchar);
						}
			  		} else {
						emitRM(opLD,bp,base[level-1],sp,"set location bp");
						if(p2->type.type == Double){
							emitRM(opPOP,ac,0,0,"assign: pop double value",sizeofdouble);
							emitRM(opST,ac,loc,bp,"assign: store double value",sizeofdouble);
						} else if(p2->type.type == Integer){
							emitRM(opPOP,ac,0,0,"assign: pop integer value",sizeofint);
							emitRM(opST,ac,loc,bp,"assign: store integer value",sizeofint);
						} else if(p2->type.type == Char){
							emitRM(opPOP,ac,0,0,"assign: pop char value",sizeofchar);
							emitRM(opST,ac,loc,bp,"assign: store char value",sizeofchar);
						}
			  		}
				}
				else
				{
				}
				p1 = p1->sibling;
			}
			break;
		case CompK:
			pTable = tree->attr.table;

			size = pTable->memloc;

			base[pLevel+1] = base[pLevel] - size - 4;
						
			printf("pLevel: %d size: %d base[pLevel]: %d\n", pLevel, size, base[pLevel]);
			
			//保存top
			emitRM(opLDA,tp,-4-size,tp,"add CompK tp");
			emitRM(opST,tp,0,sp,"store CompK top");

			pLevel++;
						
			p1 = tree->child[0];
			if(p1)	// Dec
				cGen(p1);
			p2 = tree->child[1];
			if(p2)	//stmt
				cGen(p2);
			pTable = pTable->parent;

			pLevel--;
			
			break;
		case ParamK:
			break;
		default:
			break;
	}
}

/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * tree, int addrFlag = 0)
{ 
	TreeNode * p1, * p2, * p3;
	ValEntry * pEntry = (ValEntry *)malloc(sizeof(ValEntry));
	FunEntry * pFunEntry = (FunEntry *)malloc(sizeof(FunEntry));
	int savedLoc1,savedLoc2,currentLoc;
	int loc, level, size, i, index, result, refFlag, nSize;
	ExpType	type,type2;
  	switch (tree->kind.stmt) {
    		case IfK :
         	if (TraceCode) 
				emitComment("-> if") ;

			genLabel(pTable ->lab1);
			genLabel(pTable ->lab2);

			//printf("lab1: %d\n", pTable ->lab1);
			//printf("lab2: %d\n", pTable ->lab2);
			
         	p1 = tree->child[0] ;
         	p2 = tree->child[1] ;
         	p3 = tree->child[2] ;

			if(p1->kind.exp == NumK)	// optimize
			{
				if(p1->attr.val.i == 0)
					ujp(pTable ->lab1);
			}
			else 
			{
				cGen(p1);
				emitRM(opPOP, ac, 0, 0, "if pop condition");
				fjp(pTable ->lab1);
			}
			
         	/* recurse on then part */
			//pTable = p2->attr.table;
         	cGen(p2);
			
			//有else的情况
         	if(p3) {
				ujp(pTable ->lab2);
         	}
			lab(pTable ->lab1);
			if(p3) 
			{
				//pTable = p3->attr.table;
				cGen(p3);
				lab(pTable ->lab2);
			}
			if (TraceCode) 
				emitComment("<- if") ;
			
         	break; /* if_k */

		case WhileK:
			if (TraceCode) 
				emitComment("-> while") ;
			
         	genLabel(pTable ->lab1);
			genLabel(pTable ->lab2);
			lab(pTable ->lab1);
			p1 = tree->child[0];
			if(p1 ->kind.exp == NumK)	// optimize
			{
				if(p1->attr.val.i == 0)
					ujp(pTable ->lab2);
			}
			else
			{
				cGen(p1);
				emitRM(opPOP, ac, 0, 0, "while pop condition");
				fjp(pTable ->lab2);
			}
			if(tree->child[1])
				cGen(tree->child[1]);
			ujp(pTable ->lab1);
			lab(pTable ->lab2);
			
			if (TraceCode)  
				emitComment("<- while") ;
         	break; /* if_k */

		case CallK:
			emitRM(opMST,0,0,0,"begin-args ");
			pFunEntry = Lookup_Fun(tree->attr.name);
			if(pFunEntry){
				if (TraceCode) 
					emitComment("-> CallK") ;
				
				p1 = tree->child[0];
				i = 0;
				size = pFunEntry->ret_val;
				while(p1 != NULL){
					result = Lookup_Param(pFunEntry, i, pEntry);
					if(result < 0){
						printf("CallK Param Index Error\n");
						exit(-1);
					}
					refFlag = pEntry->refFlag;
					loc = pEntry->offset;
					nSize = pEntry->size;
					
					//传地址,参数是结构时也用地址,处理时以地址加大小进行copy
					if((refFlag == 1)||(pEntry->type.type == Struct))
						cGen(p1,1);
					else
						cGen(p1);
					
					printf("-size+loc: %d\n", -size+loc);
					type = getType(p1);

					//传地址
					emitRM(opPOP,ac,0,0,"call: pop para");
					if(refFlag == 1)
						emitRM(opST,ac,-size+loc,tp,"call: push param addr" );
					else if(p1->type.type == Struct){
						emitRM(opLDA,ac1,-size+loc,tp,"call: load param record addr" );
						emitRM(opCOPY,ac1,ac,nSize,"call: copy param record value" );
					}
					else if(type == Double)
						emitRM(opST,ac,-size+loc,tp,"call: push param double",sizeofdouble);
					else if(type == Integer)
						emitRM(opST,ac,-size+loc,tp,"call: push param integer",sizeofint);	
					else if(type == Char)
						emitRM(opST,ac,-size+loc,tp,"call: push param char",sizeofchar);			
					
					i++;
					p1 = p1->sibling;
				}
				emitRM(opCUP,0,0,0,tree->attr.name);
				emitRM(opLDA,0,1,pc,"call: backup call next");
				emitRM(opLDC,pc,mStart[tree->attr.name],0,"call: load function begin");

				if (TraceCode) 
					emitComment("<- CallK") ;
				//处理返回值
			}
			else {
				if (TraceCode) 
					emitComment("-> SysCallK") ;
				
				p1 = tree->child[0];
				p2 = p1->sibling;
				
				pFunEntry = Lookup_SysFun(tree->attr.name);
				index = pFunEntry->ret_val;

				if(strcmp(tree->attr.name,"read") == 0){
					cGen(p1,1);
					type = getType(p1);
					if(type == Double)
						emitRM(opSYSCALL,0,index,0,"call read function double",sizeofdouble);
					else if(type == Integer)
						emitRM(opSYSCALL,0,index,0,"call read function");
					else if(type == Char)
						emitRM(opSYSCALL,0,index,0,"call read function char",sizeofchar);

					emitRM(opPOP, ac, 0, 0, "read pop addr");

					//read后值存入ac1					
					if(type == Double){
						emitRM(opST,ac1, 0, ac, "read store double",sizeofdouble);
					} else if(type == Integer){
						emitRM(opST,ac1, 0, ac, "read store ",sizeofint);
					} else if(type == Char){
						emitRM(opST,ac1, 0, ac, "read store ",sizeofchar);
					} else if(type == String){
						
					}
					
				} else if(strcmp(tree->attr.name,"write") == 0){

					type = getType(p1);
					if(type == String)
						cGen(p1,1);
					else
						cGen(p1);
					if(type == Double){
						emitRM(opPOP, ac, 0, 0, "write pop double value",sizeofdouble);
						emitRM(opSYSCALL,0,index,0,"call write function double",sizeofdouble);
					}else if(type == Integer){
						emitRM(opPOP, ac, 0, 0, "write pop value",sizeofint);
						emitRM(opSYSCALL,0,index,0,"call write function",sizeofint);
					} else if(type == Char){
						emitRM(opPOP, ac, 0, 0, "write pop char value", sizeofchar);
						emitRM(opSYSCALL,0,index,0,"call write function", sizeofchar);
					} else if(type == String){
						emitRM(opPOP, ac, 0, 0, "write pop string addr", sizeofint);
						emitRM(opSYSCALL,0,index,0,"call write function", typestring);
					}
				} else if(strcmp(tree->attr.name,"abs") == 0){
					cGen(p1);

⌨️ 快捷键说明

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