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

📄 cgen.cpp

📁 小型编译系统的源代码
💻 CPP
字号:
#include "globals.h"
#include "symtab.h"
#include "code.h"
#include "cgen.h"

/* loc is the memory offset for temps
   It is incremented each time a temp is
   stored
*/
static int loc = 0;
static char funExitLab[10];

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

void genLabel(char lab1[])
{
	static int nLabel = 1;

	sprintf(lab1, "@Label%d", nLabel);
	nLabel++;
}

/* Procedure genStmt generates code at a statement node */
static void genStmt( TreeNode * tree)
{ 
	TreeNode * p1, * p2, * p3, * p4;
  int temploc;
	char lab1[10], lab2[10];
	char codestr[CODESIZE];

	if (tree != 0) 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);
      genLabel(lab1);
			sprintf(codestr, "%s %s", "fjp", lab1);
			emitCode(codestr);
      emitComment("if: jump to else belongs here");
  
			/* recurse on then part */
      cGen(p2);
			if (p3 != 0)
			{
				genLabel(lab2);
				sprintf(codestr, "%s %s", "ujp", lab2);
				emitCode(codestr);
			}
			sprintf(codestr, "%s %s", "lab", lab1);
			emitCode(codestr);
			if (p3 != 0)
			{
				cGen(p3);
				sprintf(codestr, "%s %s", "lab", lab2);
				emitCode(codestr);
			}
      if (TraceCode)
				emitComment("-> if") ;
			break;

      case WhileK:
				if (TraceCode) 
					emitComment("-> while");
				p1 = tree->child[0] ;
        p2 = tree->child[1] ;

				genLabel(lab1);
				sprintf(codestr, "%s %s", "lab", lab1);
				emitCode(codestr);
				cGen(p1);
				genLabel(lab2);
				sprintf(codestr, "%s %s", "fjp", lab2);
				emitCode(codestr);
				cGen(p2);
				sprintf(codestr, "%s %s", "ujp", lab1);
				emitCode(codestr);
				sprintf(codestr, "%s %s", "lab", lab2);
				emitCode(codestr);
				if (TraceCode) 
					emitComment("<- while");
				break;

			case ForK:
				if (TraceCode)
					emitComment("-> for");
				p1 = tree->child[0] ;
        p2 = tree->child[1] ;
				p3 = tree->child[2] ;
        p4 = tree->child[3] ;

				cGen(p1);
				genLabel(lab1);
				sprintf(codestr, "%s %s", "lab", lab1);
				emitCode(codestr);
				cGen(p2);
				genLabel(lab2);
				sprintf(codestr, "%s %s", "fjp", lab2);
				emitCode(codestr);
				cGen(p4);
				cGen(p3);
				sprintf(codestr, "%s %s", "ujp", lab1);
				emitCode(codestr);
				sprintf(codestr, "%s %s", "lab", lab2);
				emitCode(codestr);
				if (TraceCode)
					emitComment("<- for");
				break;
			
			case ReturnK:
				if (TraceCode)
				  emitComment("-> return");
				
				p1 = tree->child[0];

				if (p1 != 0)
					genExp(p1, FALSE);
				else
					emitCode("ldc 0");

				sprintf(codestr, "%s %s", "ujp", funExitLab);
				emitCode(codestr);
				if (TraceCode)
				  emitComment("<- return");

				break;
			
			case CompoundK:
				if (TraceCode)
				  emitComment("-> compound");

				p1 = tree->child[0];
				temploc = loc;

				st_newBuck();
				cGen(p1);
				if (TraceCode)
					emitComment("<- compound");
				st_delBuck();
				loc = temploc;
				break;

			default:
         break;
    }
} /* genStmt */

/* Procedure genExp generates code at an expression node */
static void genExp( TreeNode * tree, int isAddr)
{
  TreeNode * p1, * p2;
	char lab1[10], lab2[10];
	char codestr[CODESIZE];

  switch (tree->kind.exp) 
	{
    case ConstK :
      if (TraceCode) emitComment("-> Const") ;
			switch (tree->attr.vartype)
			{
				case Integer:
					sprintf(codestr, "%s %d", "ldci", tree->attr.vali);
					break;
				case Float:
					sprintf(codestr, "%s %f", "ldcf", tree->attr.valf);
				  break;
				case Char:
					sprintf(codestr, "%s %c", "ldcc", tree->attr.valch);
					break;
			}
			emitCode(codestr);
      if (TraceCode)  emitComment("<- Const") ;
      break; /* ConstK */
    
		case NotK:
			if (TraceCode) 
				emitComment("-> Not") ;
			cGen(tree->child[0]);
			emitCode("not");
			if (TraceCode) emitComment("<- Not") ;
			break;	/* NotK */

		case ArrayK:
			if (TraceCode) 
				emitComment("-> Array") ;
			sprintf(codestr, "%s %s", "lod", tree->attr.name);
			emitCode(codestr);
			cGen(tree->child[0]);
			sprintf(codestr, "%s elem_size(%s)", "ixa", tree->attr.name);
			emitCode(codestr);

			if (isAddr == FALSE)
				emitCode("ind 0");
			if (TraceCode) 
				emitComment("<- Array") ;
			break;

    case IdK:
      if (TraceCode) emitComment("-> Id") ;
      if (isAddr == TRUE)
				sprintf(codestr, "%s %s", "lda", tree->attr.name);
			else
				sprintf(codestr, "%s %s", "lod", tree->attr.name);
			emitCode(codestr);
      if (TraceCode)  emitComment("<- Id") ;
      break; /* IdK */

    case OpK :
      if (TraceCode) 
				emitComment("-> Op");
      p1 = tree->child[0];
      p2 = tree->child[1];
    
      switch (tree->attr.op) 
			{
				case ASSIGN:
					genExp(p1, TRUE);
					genExp(p2, FALSE);
					if(isAddr == FALSE)
						emitCode("stn");
					else
						emitCode("sto");
					break;
        case PLUS:
          genExp(p1, FALSE);
					genExp(p2, FALSE);
					
					switch (tree->attr.vartype)
					{
						case Integer: emitCode("adi");	break;
						case Float:		emitCode("adf");	break;
					}
          break;
        case MINUS:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					switch (tree->attr.vartype)
					{
						case Integer: emitCode("subi");	break;
						case Float:		emitCode("subf");	break;
					}
					break;
        case TIMES:
          genExp(p1, FALSE);
					genExp(p2, FALSE);
					switch (tree->attr.vartype)
					{
						case Integer: emitCode("multi");	break;
						case Float:		emitCode("multf");	break;
					}
          break;
        case OVER:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					switch (tree->attr.vartype)
					{
						case Integer: emitCode("divi");	break;
						case Float:		emitCode("divf");	break;
					}
          break;       
				case LT:
          genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("les");
					break;
				case GT:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("grt");
					break;
				case LE:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("leq");
					break;
				case GE:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("geq");
					break;
				case EQ:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("equ");
					break;
				case NE:
					genExp(p1, FALSE);
					genExp(p2, FALSE);
					emitCode("neq");
					break;
				case OR:
					genExp(p1, FALSE);
					emitCode("ldc 1");
					emitCode("neq");
					genLabel(lab1);
					sprintf(codestr, "%s %s", "fjp", lab1);
					emitCode("lod TRUE");
					genLabel(lab2);
					sprintf(codestr, "%s %s", "ujp", lab2);
					emitCode(codestr);
					sprintf(codestr, "%s %s", "lab", lab1);
					emitCode(codestr);
					genExp(p2, FALSE);
					sprintf(codestr, "%s %s", "lab", lab2);
					emitCode(codestr);
				  break;
				case AND:
					genExp(p1, FALSE);
					emitCode("ldc 0");
					emitCode("neq");
					genLabel(lab1);
					sprintf(codestr, "%s %s", "fjp", lab1);
					genExp(p2, FALSE);
					genLabel(lab2);
					sprintf(codestr, "%s %s", "ujp", lab2);
					emitCode(codestr);
					sprintf(codestr, "%s %s", "lab", lab1);
					emitCode(codestr);
					emitCode("lod FALSE");
					sprintf(codestr, "%s %s", "lab", lab2);
					emitCode(codestr);
				  break;
        default:
          emitComment("BUG: Unknown operator");
          break;
      } /* case op */
      if (TraceCode)
				emitComment("<- Op");
        break; /* OpK */

		case CallK:
      if (TraceCode)
				emitComment("-> Call");
			p1 = tree->child[0];
			p2 = tree->child[1];

			emitCode("mst");
			while(p2 != 0)
			{
				genExp(p2, FALSE);
				p2 = p2 -> sibling;
			}
			sprintf(codestr, "%s %s", "cup", p1->attr.name);
			emitCode(codestr);
      if (TraceCode)
				emitComment("<- Call");
			break;

    default:
      break;
  }
} /* genExp */

static void genDecl(TreeNode * tree)
{
	TreeNode *p1, *p2, *p3, *p4;
	char codestr[CODESIZE];

	switch (tree->kind.decl)
	{
	case VarDeclK:
    if (TraceCode)
			emitComment("-> VarDecl");
	
		for(p2 = tree->child[1]; p2 != 0; p2 = p2->sibling)
		{
			switch (p2->attr.vartype)
			{
				case Integer:
					st_setLoc(p2->attr.name, loc);
					loc += 4;
					if(p2->kind.exp == ArrayK)
					{
						loc += 4 * (p2->child[0]->attr.vali - 1);
					}
					break;
				case Float:
					st_setLoc(p2->attr.name, loc);
					loc += 4;
					if(p2->kind.exp == ArrayK)
					{
						loc += 4 * (p2->child[0]->attr.vali - 1);
					}
					break;
				case Char:
					st_setLoc(p2->attr.name, loc);
					loc += 1;
					if(p2->kind.exp == ArrayK)
					{
						loc += 4 * (p2->child[0]->attr.vali - 1);
					}
					break;
			}
		}

    if (TraceCode)
			emitComment("<- VarDecl");
		break; /* VarDeclK */

	case FuncDefK:
		p2 = tree->child[1];
		p3 = tree->child[2];
		p4 = tree->child[3];

		loc = 0;

		if (TraceCode)
			emitComment("-> FuncDef");
		
		genLabel(funExitLab);
		sprintf(codestr, "%s %s", "ent", p2->attr.name);
		emitCode(codestr);
		st_setLoc(p2->attr.name, emitLoc);
		st_newBuck();
		cGen(p3);
		cGen(p4);
		st_delBuck();
		sprintf(codestr, "%s %s", "lab", funExitLab);
		emitCode(codestr);
		emitCode("ret");

    if (TraceCode)
			emitComment("<- FuncDef");
		break;	/* FuncDefK */

	case ParamK:
		st_setLoc(tree->child[1]->attr.name, loc);
		switch (tree->child[0]->attr.vartype)
		{
			case Integer:	loc += 4;	break;
			case Float:		loc += 4;	break;
			case Char:		loc += 1; break;
		}
		break;

	default:
		break;
	}
}
/* 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, TRUE);		//set to TRUE for destructive store
        break;
			case DeclK:
				genDecl(tree);
      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)
{
	char* s = (char*) malloc(strlen(codefile)+7);

  strcpy(s,"File: ");
  strcat(s,codefile);
  emitComment("C- Compilation to P-Code");
  emitComment(s);

  /* generate code for C- program */
  cGen(syntaxTree);

  /* finish */
  emitComment("End of execution.");
  //emitCode("stp");

	if (TraceAnalyze)
  { 
		fprintf(listing,"\nSymbol table:\n\n");
    printSymTab(listing);
  }
}

⌨️ 快捷键说明

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