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

📄 cgen.c

📁 SIP软件开发记录 由于通信网的封闭性
💻 C
字号:
/* cgen.c
 * The code generator implementation to the TINY compiler
 * (generates code for TM machine)
 *
 * Compiler Construction: Principles and Practice
 * Kenneth C. Louden
 * 编译原理及实践
 * (美) Kenneth C. Louden 著
 * 冯博琴 冯岚 等译
 * 机械工业出版社 IBSN 7-111-07703-2
 * 源代码:zwf编辑并修订
 * Code Modify: 
 */
#include "globals.h"
#include "symtab.h"
#include "code.h"
#include "cgen.h"

/* tmpOffset is the memory offset for temps
 * It is decremented each time a temp is
 * store, and incremented when loaded again
 */
static int tmpOffset = 0;

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

/* Procedure genStmt generates code at a statment node */
static void genStmt(TreeNode * tree)
{
	TreeNode *p1, *p2, *p3;
	int sLoc1, sLoc2, cLoc;
	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);
		sLoc1 = emitSkip(1);
		emitComment("if: jump to else belongs here");
		/* recurse on then part */
		cGen(p2);
		sLoc2 = emitSkip(1);
		emitComment("if: jump to end belongs here");
		cLoc = emitSkip(0);
		emitBackup(sLoc1);
		emitRM_Abs("JEQ", ac, cLoc, "if: jmp tp else");
		emitRestore();
		/* recurse on else part */
		cGen(p3);
		cLoc = emitSkip(0);
		emitBackup(sLoc2);
		emitRM_Abs("LDA", pc, cLoc, "jmp to end");
		emitRestore();
		if (TraceCode)
			emitComment("<- if");
		break;
	case RepeatK:
		if (TraceCode)
			emitComment("-> repeat");
		p1 = tree->child[0];
		p2 = tree->child[1];
		sLoc1 = emitSkip(0);
		emitComment("repeat: jump after body comes back here");
		/* generate code for body */
		cGen(p1);
		/* generate code for test */
		cGen(p2);
		emitRM_Abs("JEQ", ac, sLoc1, "repeat: jmp back to body");
		if (TraceCode)
			emitComment("<- repeat");
		break;
	case AssignK:
		if (TraceCode)
			emitComment("-> assign");
		/* generate code for rhs */
		cGen(tree->child[0]);
		/* now store value */
		loc = st_lookup(tree->attr.name);
		emitRM("ST", ac, loc, gp, "assign: store value");
		if (TraceCode)
			emitComment("<- assign");
		break;
	case ReadK:
		emitRO("IN", ac, 0, 0, "read integer value");
		loc = st_lookup(tree->attr.name);
		emitRM("ST", ac, loc, gp, "read: store value");
		break;
	case WriteK:
		/* generate code for expression to write */
		cGen(tree->child[0]);
		/* now output it */
		emitRO("OUT", ac, 0, 0, "write ac");
		break;
	default:
		break;
	}
}

/* Procedure genExp generate 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("LDC", ac, tree->attr.val, 0, "load const");
		if (TraceCode)
			emitComment("<- Const");
		break;
	case IdK:
		if (TraceCode)
			emitComment("-> Id");
		loc = st_lookup(tree->attr.name);
		emitRM("LD", ac, loc, gp, "load id value");
		if (TraceCode)
			emitComment("<- Id");
		break;
	case OpK:
		if (TraceCode)
			emitComment("-> Op");
		p1 = tree->child[0];
		p2 = tree->child[1];
		/* gen code for ac = left arg */
		cGen(p1);
		/* gen code tp push left operand */
		emitRM("ST", ac, tmpOffset--, mp, "op: push left");
		/* gen code for ac = right operand */
		cGen(p2);
		/* now load left operand */
		emitRM("LD", ac1, ++tmpOffset, mp, "op: load left");
		switch (tree->attr.op) {
		case PLUS:
			emitRO("ADD", ac, ac1, ac, "op +");
			break;
		case MINUS:
			emitRO("SUB", ac, ac1, ac, "op -");
			break;
		case TIMES:
			emitRO("MUL", ac, ac1, ac, "op *");
			break;
		case OVER:
			emitRO("DIV", ac, ac1, ac, "op /");
			break;
//      case '%':
//          emitRO("%",ac,ac1,ac,"op %");
//          break;
		case LT:
			emitRO("SUB", ac, ac1, ac, "op <");
			emitRM("JLT", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		case GT:				/* Larry */
			emitRO("SUB", ac, ac1, ac, "op >");
			emitRM("JGT", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		case LE:				/* Larry */
			emitRO("SUB", ac, ac1, ac, "op <=");
			emitRM("JLE", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		case GE:				/* Larry */
			emitRO("SUB", ac, ac1, ac, "op >=");
			emitRM("JGE", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		case NE:				/* Larry */
			emitRO("SUB", ac, ac1, ac, "op <>");
			emitRM("JNE", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		case EQ:
			emitRO("SUB", ac, ac1, ac, "op ==");
			emitRM("JEQ", ac, 2, pc, "br if true");
			emitRM("LDC", ac, 0, ac, "false case");
			emitRM("LDA", pc, 1, pc, "unconditional jmp");
			emitRM("LDC", ac, 1, ac, "true case");
			break;
		default:
			emitComment("BUG: Unknown operator");
			break;
		}
		if (TraceCode)
			emitComment("<- Op");
		break;
	default:
		break;
	}
}

/* Procedure cGen recursively generate 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 generate code to a code
 * file by traversal of the syntax tree. the
 * second paramater (codefile) is the file name
 * of the code file, and is used tp print the
 * file name as a comment in the code file
 */
void codeGen(TreeNode * syntaxTree, char *codefile)
{
	char *s = malloc(strlen(codefile) + 7);

	strcpy(s, "File: ");
	strcat(s, codefile);
	emitComment("TINY Compilation to TM Code");
	emitComment(s);
	/* generate standard prelude */
	emitComment("Standard prelund:");
	emitRM("LD", mp, 0, ac, "load maxaddress from location 0");
	emitRM("ST", ac, 0, ac, "clear location 0");
	emitComment("End of standard prelude.");
	/* generate code for TINY program */
	cGen(syntaxTree);
	/* finish */
	emitComment("End of execution.");
	emitRO("HALT", 0, 0, 0, "");
}

⌨️ 快捷键说明

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