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

📄 genexp.c

📁 用C++编写的一个编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include "genasm.h"

AddrMode *gen_exp(ExpNode *exp, int flag, int size)
{
	AddrMode *res=NULL;
	int lab0, lab1;
begin:
	switch(exp->exptype)
	{
	case exp_void:
		return NULL;
	case exp_const:
		if(exp->datatype->basic_type == bt_pointer
			||exp->datatype->basic_type == bt_funcptr)
			res = newImme(exp->val.addr.base, exp->val.addr.offset);
		else
			res = newImme(NULL, exp->val.i);
		break;

	case exp_label:
//function name and named label
		res = newImme(exp->val.addr.base, exp->val.addr.offset);
		
		if(flag&F_ADDR)
			res ->mode = am_label;
		return res;

	case exp_aref:
		if(exp->val.addr.base)
		{
			if(flag&F_ADDR)
				return newDirect(exp->val.addr.base, exp->val.addr.offset);
			else 
				res = newImme(exp->val.addr.base, exp->val.addr.offset);
		}
		else 
		{
			AddrMode *tmp ;
			res = newRelative(EBP, exp->val.addr.offset);
			if(flag&F_ADDR)
				return res;
			tmp = temp_data();
			gen_code(op_lea, 4, tmp, res);
			res = tmp;	
		}
		break;
	case exp_vref:
		if(exp->val.addr.base)
			res = newDirect(exp->val.addr.base, exp->val.addr.offset);
		else 
			res = newRelative(EBP, exp->val.addr.offset);
		if(is_real(exp->datatype->basic_type))
			res->size = exp->datatype->size;
		break;
	case exp_call:
		res = gen_call(exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_assign:
		res = gen_assign(exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_ptomem:
	case exp_ntomem:
	case exp_array:
		res = gen_index(exp);
		break;
	case exp_ptr:
		res = gen_ptr(exp->val.opd[1]);
		break;
	case exp_val:
		res = gen_val(exp->val.opd[1]);
		break;
	case exp_uminus:
		res = gen_unary(op_neg, exp->val.opd[1]);
		break;
	case exp_rvs:
		res = gen_unary(op_not, exp->val.opd[1]);
		break;
	case exp_lnot:
	case exp_land:
	case exp_lor:
	case exp_eq:
	case exp_ueq:
	case exp_gtr:
	case exp_geq:
	case exp_les:
	case exp_leq:
		lab0 = newlabelno++;
		lab1 = newlabelno++;
		falsejp(exp,lab0);
		res = temp_data();
		gen_code(op_mov, 4, res, newImme(NULL, 1));
		gen_code(op_jmp, 4, newLabel(lab1), NULL);
		gen_label(lab0);
		gen_code(op_sub, 4, res, res);
		gen_label(lab1);
		break;
	case exp_incr:
	case exp_decr:
		if(exp->val.opd[1])
			res = gen_indecr(exp->exptype, exp->val.opd[1]);
		else if(flag&F_NOVALUE)//opt
			res = gen_indecr(exp->exptype, exp->val.opd[0]);
		else 
			res = gen_indecr(-exp->exptype, exp->val.opd[0]);
		break;
	case exp_lsh:
		res = gen_shift(op_sal, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_rsh:
		res = gen_shift(op_sar, exp->val.opd[0], exp->val.opd[1]);
		break;//????????????
	case exp_mul:
		res = gen_mul(op_imul, exp->val.opd[0], exp->val.opd[1], 0);
		break;
	case exp_div:
		res = gen_mul(op_idiv, exp->val.opd[0], exp->val.opd[1], 0);
		break;
	case exp_mod:
		res = gen_mul(op_idiv, exp->val.opd[0], exp->val.opd[1], 1);
		break;
	case exp_umul:
		res = gen_mul(op_mul, exp->val.opd[0], exp->val.opd[1], 0);
		break;
	case exp_udiv:
		res = gen_mul(op_div, exp->val.opd[0], exp->val.opd[1], 0);
		break;
	case exp_umod:
		res = gen_mul(op_div, exp->val.opd[0], exp->val.opd[1], 1);
		break;
	case exp_and: 
		res = gen_binary(op_and, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_xor:
		res = gen_binary(op_xor, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_or:
		res = gen_binary(op_or, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_add:
		res = gen_binary(op_add, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_sub:
		res = gen_binary(op_sub, exp->val.opd[0], exp->val.opd[1]);
		break;
	case exp_trinary:
		res = gen_trinary(exp);
		break;
	}

	if(exp->next) //just for comma expression, 
		//the first few have no need to make_legal
	{
		exp=exp->next;
		goto begin; 
	}

	return	make_legal(res, flag, size, is_unsigned(exp->datatype->basic_type));
}
//return the size of sp changed
int push_exp(struct _expnode *exp)
{
	AddrMode *res;
	int size,depth;

	if(exp->datatype->array_vol)
		size=depth=4;
	else 
	{
		size=exp->datatype->size;
		depth=(size+3)&~3;
	}

	res= gen_exp(exp, F_ALL, exp->datatype->size);
 
	if(size<=4)
	{
		res = make_legal(res, F_ALL, 4, is_unsigned(exp->datatype->basic_type));
		gen_code(op_push, 4, res, NULL);
	}
	else 
	{
		AddrMode *esp=newDreg(ESP);
		gen_code(op_sub, 4, esp, newImme(0, depth));
		esp->mode = am_relative;
		block_move(esp, res, size);
	}
	freeregs(res);
	return depth;
}
AddrMode *gen_call(
	struct _expnode *func,
	struct _expnode *arglist)
{
	int depth=0;
	AddrMode *funcaddr, *res=newDreg(EAX);
	ExpNode *exp = arglist, *next;

	funcaddr = gen_exp(func, F_ALL|F_ADDR, 4);
	if(exp->exptype == exp_void)
		goto call;
	for(;exp;exp=next)
	{
		mark();
		next = exp->next;
		exp->next = NULL;
		depth += push_exp(exp);
		release();
	}
call:
	reserve();
	gen_code(op_call, 4, funcaddr, NULL);
	if(depth>0)
		gen_code(op_add, 4, newDreg(ESP), newImme(NULL, depth));

	res->size = func->datatype->subtype->size;
	if(func->datatype->subtype->basic_type == bt_struct
		|| func->datatype->subtype->basic_type == bt_union)
		res->mode = am_relative;

	return res;//???????
}
void block_move(AddrMode *dst, AddrMode *src, int size)
{
	AddrMode *edi=newDreg(EDI), *esi=newDreg(ESI), *ecx=newDreg(ECX);
	if(regs[EDI])  
		push_reg(EDI);
	gen_code(op_lea, 4, edi, dst);
	//leave some bugs, so troublesome
	if(regs[ESI])
	{
		if(src->base_reg != ESI
			&&src->index_reg !=ESI)
			push_reg(ESI);
		else 
			regs[ESI] = false;
	}
	gen_code(op_lea, 4, esi, src);


	if(regs[ECX])
	{
		push_reg(ECX);
	}
	gen_code(op_mov, 4, ecx, newImme(NULL, size));
	gen_code(op_cld, 4, NULL, NULL);
	gen_code(op_rep, 4, NULL, NULL);
	gen_code(op_movsb, 4, NULL, NULL);

	if(regs[ECX])
		pop_reg(ECX);
	if(regs[ESI])
		pop_reg(ESI);
	if(regs[EDI])
		pop_reg(EDI);
	return;
}
AddrMode *gen_assign(
	struct _expnode *opd1,
	struct _expnode *opd2)
{
	AddrMode *left, *right;
	int size;
	if(opd1->datatype->array_vol)
		size=4;
	else
		size= opd1->datatype->size;
	left = gen_exp(opd1, F_MEM, size);
	mark();
	right = gen_exp(opd2, F_DREG|F_IMME, size);
	
	if(opd1->datatype->basic_type != bt_struct
		&&opd1->datatype->basic_type != bt_union)
	{
		//no struct assign here
		make_legal(right, F_DREG | F_IMME, size, is_unsigned(opd2->datatype->basic_type));
		gen_code(op_mov, size, left, right);
	}
	else 
		block_move(left, right, size);
	freeregs(right);
	release();
	return left;
}
//ap1 is dreg and size 4
//ap2 is all and size 4
//multiply, divide or mode

AddrMode *make_legal(AddrMode *ap, int flag, int size, int unsign)
{
	AddrMode *res;
	if(flag & F_NOVALUE)
	{
		freeregs(ap);
		return ap;
	}
/*	if(flag & F_ADDR)
	{
		res = temp_data();
		if(ap->mode == am_direct ||ap->mode == am_label)
		{
			ap->mode = am_imme;
			gen_code(op_mov, 4, res, ap); 
		}
		else if(ap->mode == am_relative 
			|| ap->mode == am_scale)
		{
			gen_code(op_lea, 4, res, ap);
			freeregs(ap);
		}
		return res;
	}
*/	if(size>ap->size&&size<=4)
	{
		freeregs(ap);
		res = temp_data();
		if(unsign)
			gen_code2(op_movzx, size, res, ap->size, ap);
		else 
			gen_code2(op_movsx, size, res, ap->size, ap);
		ap = res;
	}

	switch(ap->mode)
	{
	case am_label:
		return ap;
	case am_imme:
		if(flag&F_IMME)
			return ap;
		break;			
	case am_dreg:
		if(flag&F_DREG)
			return ap;
		break;
	case am_freg:
		if(flag&F_FREG)
			return ap;
		break;//????
	case am_direct:
	case am_relative:
	case am_scale:
		if(flag&F_MEM)
			return ap;
		break;
	}

	if(flag&F_DREG)
	{
		freeregs(ap);
		res = temp_data();
		res->size = ap->size;
		gen_code(op_mov, size, res, ap);
		ap = res;
	}
	else
	{
		debug("need to tackle specially\n");
	}
	return ap;
}
AddrMode *gen_binary(
	int op,
	struct _expnode *opd1,
	struct _expnode *opd2)
{
	AddrMode *left, *right;
	left = gen_exp(opd1, F_DREG, 4);
	mark();
	right = gen_exp(opd2, F_ALL, 4);

	gen_code(op, 4, left, right);

	freeregs(right);
	release();
	return left;
}

AddrMode *gen_mul(int op, struct _expnode *opd1, struct _expnode *opd2, int mod)
{
	AddrMode *left, *right;
	AddrMode *eax = newDreg(EAX), *ecx=newDreg(ECX), *edx = newDreg(EDX);
	AddrMode *div;
	int tmp, topush;

	left = gen_exp(opd1, F_DREG, 4);
	mark();
	right = gen_exp(opd2, F_ALT, 4);
	
	if(left->base_reg != EAX)
	{
		gen_code(op_xchg, 4, eax, left);
		tmp = regs[EAX];
		regs[EAX] = regs[left->base_reg];
		regs[left->base_reg] = tmp;
/*		if(right->base_reg == EAX)
			right->base_reg = left->base_reg;
		else if(ap2->index_reg == EAX)
			right->index_reg = left->base_reg; 
*/	}
	if(right->base_reg == EDX ||right->index_reg == EDX)
	{
		topush = ECX;
		div = ecx;
	}
	else
	{
		topush = EDX;
		div = right;
	}
	if(regs[topush])
		push_reg(topush);

⌨️ 快捷键说明

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