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

📄 cgen.c

📁 1.小型编译器 2。支持整数
💻 C
字号:
/****************************************************/
/* 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"

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

int dMem [DADDR_SIZE];
int reg [NO_REGS];
char in_Line[LINESIZE] ;

int lineLen ;
int inCol  ;
int num  ;

/* 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;

const char * opCodeTab[] = {
	"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
    /* RR opcodes */
   	"LD","ST","????", /* RM opcodes */
   	"LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
   	/* RA opcodes */
};

/********************************************/
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: 
				printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
	            break;
	    }
    	printf ("\n") ;
  	}
} /* writeInstruction */


/* prototype for internal recursive code generator */
static void cGen (TreeNode * tree);

/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * tree)
{ 
	TreeNode * p1, * p2, * p3;
	int savedLoc1,savedLoc2,currentLoc;
	int loc;
  	switch (tree->kind.stmt) {
    	case IfK :
         	if (TraceCode) 
				emitComment("-> if") ;
         	p1 = tree->child[0] ;
         	p2 = tree->child[1] ;
         	p3 = tree->child[2] ;
         	/* generate code for test expression */
         	cGen(p1);
         	savedLoc1 = emitSkip(1) ;
         	emitComment("if: jump to else belongs here");
         	/* recurse on then part */
         	cGen(p2);
         	savedLoc2 = emitSkip(1) ;
         	emitComment("if: jump to end belongs here");
         	currentLoc = emitSkip(0) ;
         	emitBackup(savedLoc1) ;
         	emitRM_Abs(opJEQ,ac,currentLoc,"if: jmp to else");
         	emitRestore() ;
         	/* recurse on else part */
         	cGen(p3);
         	currentLoc = emitSkip(0) ;
         	emitBackup(savedLoc2) ;
         	emitRM_Abs(opLDA,pc,currentLoc,"jmp to end") ;
         	emitRestore() ;
         	if (TraceCode)  
				emitComment("<- if") ;
         	break; /* if_k */

      	case RepeatK:
         	if (TraceCode) 
				emitComment("-> repeat") ;
         	p1 = tree->child[0] ;
         	p2 = tree->child[1] ;
         	savedLoc1 = emitSkip(0);
         	emitComment("repeat: jump after body comes back here");
         	/* generate code for body */
         	cGen(p1);
         	/* generate code for test */
         	cGen(p2);
         	emitRM_Abs(opJEQ,ac,savedLoc1,"repeat: jmp back to body");
         	if (TraceCode)  
				emitComment("<- repeat") ;
         	break; /* repeat */

      	case AssignK:
         	if (TraceCode) 
				emitComment("-> assign") ;
         	/* generate code for rhs */
         	cGen(tree->child[0]);
         	/* now store value */
         	loc = st_lookup(tree->attr.name);
         	emitRM(opST,ac,loc,gp,"assign: store value");
         	if (TraceCode)  
				emitComment("<- assign") ;
         	break; /* assign_k */

      	case ReadK:
         	emitRO(opIN,ac,0,0,"read integer value");
         	loc = st_lookup(tree->attr.name);
         	emitRM(opST,ac,loc,gp,"read: store value");
         	break;
      	case WriteK:
         	/* generate code for expression to write */
         	cGen(tree->child[0]);
         	/* now output it */
         	emitRO(opOUT,ac,0,0,"write ac");
         	break;
      	default:
         	break;
    }
} /* genStmt */

/* Procedure genExp generates code at an expression node */
static void genExp( TreeNode * tree)
{ 
	int loc;
  	TreeNode * p1, * p2;
  	switch (tree->kind.exp) {

    	case ConstK :
      		if (TraceCode) 
				emitComment("-> Const") ;
      		/* gen code to load integer constant using LDC */
      		emitRM(opLDC,ac,tree->attr.val,0,"load const");
      		if (TraceCode)  
				emitComment("<- Const") ;
      	break; /* ConstK */
    
    	case IdK :
      		if (TraceCode) 
				emitComment("-> Id") ;
      		loc = st_lookup(tree->attr.name);
      		emitRM(opLD,ac,loc,gp,"load id value");
      		if (TraceCode)  
				emitComment("<- Id") ;
      	break; /* IdK */

    	case OpK :
         	if (TraceCode) 
				emitComment("-> Op") ;
         	p1 = tree->child[0];
         	p2 = tree->child[1];
         	/* gen code for ac = left arg */
        	cGen(p1);
         	/* gen code to push left operand */
         	emitRM(opST,ac,tmpOffset--,mp,"op: push left");
         	/* gen code for ac = right operand */
         	cGen(p2);
         	/* now load left operand */
         	emitRM(opLD,ac1,++tmpOffset,mp,"op: load left");
         	switch (tree->attr.op) {
            	case PLUS :
               		emitRO(opADD,ac,ac1,ac,"op +");
               		break;
            	case MINUS :
               		emitRO(opSUB,ac,ac1,ac,"op -");
               		break;
            	case TIMES :
               		emitRO(opMUL,ac,ac1,ac,"op *");
              		break;
            	case OVER :
               		emitRO(opDIV,ac,ac1,ac,"op /");
               		break;
            	case LT :
               		emitRO(opSUB,ac,ac1,ac,"op <") ;
               		emitRM(opJLT,ac,2,pc,"br if true") ;
               		emitRM(opLDC,ac,0,ac,"false case") ;
               		emitRM(opLDA,pc,1,pc,"unconditional jmp") ;
               		emitRM(opLDC,ac,1,ac,"true case") ;
               		break;
            	case EQ :
               		emitRO(opSUB,ac,ac1,ac,"op ==") ;
               		emitRM(opJEQ,ac,2,pc,"br if true");
               		emitRM(opLDC,ac,0,ac,"false case") ;
               		emitRM(opLDA,pc,1,pc,"unconditional jmp") ;
               		emitRM(opLDC,ac,1,ac,"true case") ;
               		break;
            	default:
               		emitComment("BUG: Unknown operator");
               		break;
         	} /* case op */
         	if (TraceCode)  
				emitComment("<- Op") ;
         	break; /* OpK */

    	default:
      		break;
	}
} /* genExp */

/* Procedure cGen recursively generates code by
 * tree traversal
 */
static void cGen( TreeNode * tree)
{ 
	if (tree != NULL)
  	{ 
  		switch (tree->nodekind) {
      	case StmtK:
        	genStmt(tree);
        	break;
      	case ExpK:
        	genExp(tree);
        	break;
      	default:
        	break;
    	}
   	 	cGen(tree->sibling);
  	}
}

/**********************************************/
/* the primary function of the code generator */
/**********************************************/
/* Procedure codeGen generates code to a code
 * file by traversal of the syntax tree. The
 * second parameter (codefile) is the file name
 * of the code file, and is used to print the
 * file name as a comment in the code file
 */
void codeGen(TreeNode * syntaxTree, char * codefile)
{  
	emitLoc = 0;
	char *s = (char*)malloc(strlen(codefile)+7);
   	strcpy(s,"File: ");
   	strcat(s,codefile);
  	emitComment("TINY Compilation to TM Code");
   	emitComment(s);
   	/* generate standard prelude */
   	emitComment("Standard prelude:");
   	emitRM(opLD,mp,0,ac,"load maxaddress from location 0");
   	emitRM(opST,ac,0,ac,"clear location 0");
   	emitComment("End of standard prelude.");
   	/* generate code for TINY program */
   	cGen(syntaxTree);
   	/* finish */
   	emitComment("End of execution.");
   	emitRO(opHALT,0,0,0,"");
};

/********************************************/
static STEPRESULT stepTM ()
{ 
	INSTRUCTION currentinstruction;
  	int pcindex;
  	int r,s,t,m;
  	int ok ;

  	pcindex = reg[PC_REG] ;
  	if ( (pcindex < 0) || (pcindex > IADDR_SIZE)  )
    	return srIMEM_ERR ;
  	reg[PC_REG] = pcindex + 1 ;
  	currentinstruction = iMem[ pcindex ] ;
  	switch (opClass(currentinstruction.iop) )
  	{ 
  		case opclRR :
    		/***********************************/
      		r = currentinstruction.iarg1 ;
      		s = currentinstruction.iarg2 ;
      		t = currentinstruction.iarg3 ;
      		break;

    	case opclRM :
    		/***********************************/
      		r = currentinstruction.iarg1 ;
      		s = currentinstruction.iarg3 ;
      		m = currentinstruction.iarg2 + reg[s] ;
      		if ( (m < 0) || (m > DADDR_SIZE))
         		return srDMEM_ERR ;
      		break;

    	case opclRA :
    		/***********************************/
      		r = currentinstruction.iarg1 ;
      		s = currentinstruction.iarg3 ;
      		m = currentinstruction.iarg2 + reg[s] ;
      		break;
  	} /* case */

  	switch ( currentinstruction.iop)
  	{ 
  		/* RR instructions */
    	case opHALT :
    		/***********************************/
      		printf("HALT: %1d,%1d,%1d\n",r,s,t);
      		return srHALT ;
      		/* break; */

    	case opIN :
    		/***********************************/
			ok = 0;
      		do
      		{ 
      			printf("Enter value for IN instruction: ") ;
        		fflush (stdin);
        		fflush (stdout);
        		gets(in_Line);
        		lineLen = strlen(in_Line) ;
        		inCol = 0;
        		//ok = getNum();
        		//if ( ! ok ) 
				//	printf ("Illegal value\n");
				num = atoi(in_Line);
				printf("Num is: %d\n", num);
				if(num > 0)
					ok = 1;
				
        		//else reg[r] = num;
        		reg[r] = num;
      		}
      		while (! ok);
      		break;

    	case opOUT :  
      		printf ("OUT instruction prints: %d\n", reg[r] ) ;
      		break;
    	case opADD :  
			reg[r] = reg[s] + reg[t] ;  
			break;
    	case opSUB :  
			reg[r] = reg[s] - reg[t] ;  
			break;
    	case opMUL :  
			reg[r] = reg[s] * reg[t] ;  
			break;

   		case opDIV :
    		/***********************************/
      		if ( reg[t] != 0 ) 
				reg[r] = reg[s] / reg[t];
      		else 
				return srZERODIVIDE ;
      		break;

    	/*************** RM instructions ********************/
    	case opLD :    
			reg[r] = dMem[m] ;  
			break;
    	case opST :    
			dMem[m] = reg[r] ;  
			break;

    	/*************** RA instructions ********************/
    	case opLDA :    
			reg[r] = m ; 
			break;
    	case opLDC :    
			reg[r] = currentinstruction.iarg2 ;   
			break;
    	case opJLT :    
			if ( reg[r] <  0 ) 
				reg[PC_REG] = m ; 
			break;
    	case opJLE :    
			if ( reg[r] <=  0 ) 
				reg[PC_REG] = m ; 
			break;
    	case opJGT :    
			if ( reg[r] >  0 ) 
				reg[PC_REG] = m ; 
			break;
    	case opJGE :    
			if ( reg[r] >=  0 ) 
				reg[PC_REG] = m ; 
			break;
    	case opJEQ :    
			if ( reg[r] == 0 ) 
				reg[PC_REG] = m ; 
			break;
    	case opJNE :    
			if ( reg[r] != 0 ) 
				reg[PC_REG] = m ; 
			break;

    /* end of legal instructions */
  	} /* case */
  	return srOKAY ;
} /* stepTM */

int	doRun(){
	//初始化
	int stepResult, regNo, loc;
	int stepcnt=0;
	
	iloc = 0;
  	dloc = 0;
  	for (regNo = 0;  regNo < NO_REGS ; regNo++)
    	reg[regNo] = 0 ;
  	dMem[0] = DADDR_SIZE - 1 ;
  	for (loc = 1 ; loc < DADDR_SIZE ; loc++)
    	dMem[loc] = 0 ;

	printf("\nInstucation Begin: \n");
	for(loc = 0; loc < emitLoc; loc++)
		writeInstruction( loc ) ;
	printf("Instucation End: \n\n");

	stepResult = srOKAY;
	while (stepResult == srOKAY)
    { 
    	iloc = reg[PC_REG] ;
        if ( traceflag ) 
			writeInstruction( iloc ) ;
		stepcnt++;
        stepResult = stepTM ();
    }
	if(!stepResult)
		printf("Run Error !\n");
    if ( icountflag )
    	printf("Number of instructions executed = %d\n",stepcnt);

	return 0;
}

⌨️ 快捷键说明

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