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

📄 genstmt.c

📁 用C++编写的一个编译器
💻 C
字号:
#include <stdio.h>
#include "genasm.h"
#include "syntax.h"
#include "utility.h"

void gen_stmt(//the main routine of generate a stmt
	struct _stmtnode *stmt //auto tackle the next stmt
)
{
	Symbol *tmpsym;
	while( stmt != 0 )
	{
		if(stmt->labelno != UNKNOWN)
			gen_label(stmt->labelno);
		switch( stmt->stmtype )
		{
		case stmt_compound:
//		case stmt_label:
			gen_stmt(stmt->ss);
			break;

		case stmt_goto:
			tmpsym = stmt->exp->val.label;
			if(tmpsym->value.labelno==UNKNOWN)
				generror(ERR_NOT_FOUND, tmpsym->name);
			else 
				gen_code(op_jmp, 4, newLabel(tmpsym->value.labelno),0);
			break;
		case stmt_exp:
			initstack();
			gen_exp(stmt->exp, F_NOVALUE, stmt->exp->datatype->size);
			break;
		case stmt_return:
			gen_return(stmt);
			break;
		case stmt_if:
			gen_if(stmt);
			break;
		case stmt_while:
			gen_while(stmt);
			break;
		case stmt_do:
			gen_do(stmt);
			break;
		case stmt_for:
			gen_for(stmt);
			break;
		case stmt_continue:
			if(continuelabel != UNKNOWN)
				gen_code(op_jmp, 4, newLabel(continuelabel),0);
			else 
				genwarning(ERR_NOT_LOOP, "continue");
			break;
		case stmt_break:
			if(continuelabel != UNKNOWN)
				gen_code(op_jmp, 4, newLabel(breaklabel),0);
			else 
				genwarning(ERR_NOT_LOOP, "break");
			break;
		case stmt_switch:
			gen_switch(stmt);
			break;
//		case stmt_asm://no support this moment
			///????????
			break;
		default:
			debug("debug--unknown statement.\n");
			break;
		}
		stmt = stmt->next;
	}
}
void gen_funcbody(struct _stmtnode *stmt)
{
	if(error_count)
		return ;
	current_func->value.localdata = (current_func->value.localdata+3)&~3;
	asm_func_begin(current_func->name, current_func->value.localdata);
	returnlabel = newlabelno++;
	gen_stmt(stmt);
	gen_label(returnlabel);
	flush_queue();
	asm_func_end(current_func->name);
	returnlabel = UNKNOWN;
}
//map case to labelno;
/*typedef struct _casemap
{
	int key;
	int labelno;
}CaseMap;
*/
//so sorry, binary search optimization not ready
void gen_switch(struct _stmtnode *stmt)
{
	int defaultlabel=UNKNOWN;
	int oldbreak = breaklabel;
	
//	int casecount = 0; // for opt
	StmtNode *casestmt=stmt->s1, *defaultstmt = stmt->s2, *contentstmt = stmt->ss;
//	CaseMap *onecase;
//	List caselist = {0};
	AddrMode *key;
	breaklabel = newlabelno++;
	initstack();
	key = gen_exp(stmt->exp, F_DREG, 4);
	while(casestmt)
	{
		gen_code(op_cmp, 4, key, newImme(NULL, casestmt->exp->val.i));
		gen_code(op_jz, 4, newLabel(casestmt->labelno), NULL);
		casestmt= casestmt->next;
	}
	if(defaultstmt&&defaultstmt->labelno != stmt->ss->labelno)
		gen_code(op_jmp, 4, newLabel(defaultstmt->labelno), NULL);
	gen_stmt(stmt->ss);
	gen_label(breaklabel);
	breaklabel = oldbreak;
	return ;
}
void gen_for(struct _stmtnode *stmt)
{
	int  oldbreak, oldcont, enterlabel;

	oldbreak = breaklabel;
	oldcont = continuelabel;

	enterlabel = newlabelno++;
	breaklabel = newlabelno++;
	continuelabel = newlabelno++;
	initstack();
	if(stmt->s1 != NULL)
		gen_exp(stmt->s1->exp, F_NOVALUE, UNKNOWN);

	gen_label(enterlabel);
	if(stmt->exp->exptype != exp_void)
	{
		initstack();
		falsejp(stmt->exp, breaklabel);
	}
	if(stmt->ss->stmtype != stmt_exp || stmt->ss->exp->exptype != exp_void)
	{
		gen_stmt(stmt->ss);
		gen_label(continuelabel);
	}
	gen_stmt(stmt->s2);
	gen_code(op_jmp, 4, newLabel(enterlabel),0);
	
	gen_label(breaklabel);
	breaklabel = oldbreak;
	continuelabel = oldcont;
}
void gen_while(struct _stmtnode *stmt)
{
	int   oldcont, oldbreak;
	
	oldcont = continuelabel;         /* save old continue label */
	continuelabel = newlabelno++;		/* new continue label */
	gen_label(continuelabel);

	if( stmt->ss->stmtype == stmt_exp &&stmt->ss->exp->exptype ==exp_void )      /* no body*/
	{
		initstack();
		truejp(stmt->exp,continuelabel);
	}
	else
	{
		oldbreak = breaklabel;        /* save old break label */
		breaklabel = newlabelno++;
		initstack();
		falsejp(stmt->exp,breaklabel);

		gen_stmt(stmt->ss);
		
		gen_code(op_jmp, 4, newLabel(continuelabel),0);
		
		gen_label(breaklabel);
		breaklabel = oldbreak;        /* restore old break label */
	}
	continuelabel = oldcont;         /* restore old continue label */
}
//do-while routine
void gen_do(struct _stmtnode *stmt)
{
	int     oldcont, oldbreak;
	oldcont = continuelabel;//keep
	

	continuelabel = newlabelno++;
	gen_label(continuelabel);
	if( stmt->ss->stmtype == stmt_compound )
	{
		oldbreak = breaklabel;
		breaklabel = newlabelno++;
		gen_stmt(stmt->ss);      /* generate body */
		initstack();
		truejp(stmt->exp,continuelabel);
		gen_label(breaklabel);
		breaklabel = oldbreak;
	}
	else
	{
		gen_stmt(stmt->ss);
		initstack();
		truejp(stmt->exp,continuelabel);
	}
	continuelabel = oldcont;
}
void gen_if(struct _stmtnode *stmt)
{
	int  elselab, exitlab;
	elselab = newlabelno++;     
	
	initstack();
	falsejp(stmt->exp,elselab);
	gen_stmt(stmt->s1);
	if( stmt->s2 != 0 )
	{
		exitlab = newlabelno++;
		gen_code(op_jmp, 4, newLabel(exitlab),NULL);
		gen_label(elselab);
		gen_stmt(stmt->s2);
		gen_label(exitlab);
	}
	else
		gen_label(elselab);
}

void gen_return(struct _stmtnode *stmt)
{
	//now we don't support user defined type
	ExpNode *exp = stmt->exp;
	AddrMode *res ,*eax = newDreg(EAX);

	initstack();
	res = gen_exp(exp, F_ALL, exp->datatype->size);
	if(!res)
		return;
	if(res->mode == am_dreg&&EAX == res->base_reg)
		goto end;
	if(exp->datatype->basic_type == bt_struct
		||exp->datatype->basic_type == bt_union)
	{
		gen_code(op_lea, 4, eax, res);
	}
	else 
	{
		gen_code(op_mov, 4, eax, res);
	}
end:
	gen_code(op_jmp, 4, newLabel(returnlabel), NULL);
}

⌨️ 快捷键说明

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