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

📄 gen.c

📁 unix环境下实现的cmm语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "cmm.h"#include <limits.h>static void docall(Node p);static void prelabel(Node p);static void mark_instruction(Node forest);static void free_node_reg(Node p);static void set_spill_protector(Node p);static void reset_spill_protector(Node p);static Symbol sel_over_reg(Symbol s);static void overflow(Symbol s);static Symbol ask_reg(Symbol rs);static Symbol get_reg(Symbol s);static void reg_alloc(Node p);static char *get_code_templates(Node p);static void emit_asm(Node p);static void emit_code(Node forest);static Symbol askfixedreg(Symbol rs);static char NeedsReg[] = { /*值为1的结点需要分配寄存器*/ 	0,		/*unuse*/	0,		/*CNST*/	0,		/*ARG*/	0,		/*ASGN*/	1,		/*INDIR*/	1,		/*CVC*/	1,		/*CVI*/	1,		/*CVP*/	1,		/*CALL*/	0,		/*RET*/	0,		/*ADDRG*/	1,		/*ADDRL*/	1,		/*ADD*/	1,		/*SUB*/	1,		/*MOD*/	1,		/*DIV*/	1,		/*MUL*/	0,		/*EQ*/	0,		/*GE*/	0,		/*GT*/	0,		/*LE*/	0,		/*LT*/	0,		/*NE*/	0,		/*JUMP*/	0,		/*LABEL*/	0,		/*NOT*/	1,		/*NEG*/	1,		/*CVU*/	1,		/*LOAD*/	0,		/*VREG*/};int offset;			/*记录栈的偏移量*/int maxoffset;		/*栈的最大偏移量*/int argoffset;		/*参数区的长度*/int maxargoffset;unsigned freemask;	/*记录寄存器的空闲状态*/static unsigned non_spill_mask;	/*为寄存器设置溢出保护*/Symbol rmap[16];/*mkreg:生成寄存器fmt为寄存器的名字,n为寄存器的编号*/Symbol mkreg(char *fmt, int n){	Symbol p;	NEW0(p, PERM);	p->x.name = stringf(fmt, n);	NEW0(p->x.regnode, PERM);	p->x.regnode->number = n;	p->x.regnode->mask = 1<<n;	return p;}/*mkwildcard:生成通用寄存器组*/Symbol mkwildcard(Symbol *syms){	Symbol p;	NEW0(p, PERM);	p->x.name = "wildcard";	p->x.wildcard = syms;	return p;}/*blockbeg:在块的开始保存当前的栈的偏移并为局部变量分配存储空间*/void blockbeg(Env *e){	e->offset = offset;	if (offset > maxoffset) { /*为局部变量在栈中分配存储空间*/		print("sub esp, %d\n", offset - maxoffset);		maxoffset = offset;	}	}/*mkauto:为变量在栈中分配空间*/void mkauto(Symbol p){	assert(AUTO == p->sclass);	offset = roundup(offset + p->type->size, p->type->align);	p->x.offset = -offset;	p->x.name = stringd(-offset);}/*blockend:在块的结束处恢复之前在块的开始处保存的值*/void blockend(Env *e){	offset = e->offset;}/*mkactual:返回参数区按align字节对齐后的长度, 并由size计算加入参数后参数区的长度*/int mkactual(int align, int size) {	int n = roundup(argoffset, align);	argoffset = n + size;	return n;}/*docall:为CALL结点保存参数区的总的长度,以便在函数调用完成后释放该区域*/static void docall(Node p){	p->syms[1] = p->syms[0];	p->syms[0] = intconst(argoffset);	if (argoffset > maxargoffset) 		maxargoffset = argoffset;	argoffset = 0;}/*rtarget:为p的第n个子结点重定位寄存器r*/void rtarget(Node p, int n, Symbol r){	Node q = p->kids[n];		assert(q);	assert(r->sclass == REGISTER || !r->x.wildcard);	if (NULL == q->syms[RX] 	|| (r != q->syms[RX] && !q->syms[RX]->x.wildcard)){/*LOAD实现将值装入特定的寄存器*/		q->count--;	/*因为LOAD会增加q结点的引用计数*/		q = newnode(LOAD + optype(q->op),			q, NULL, q->syms[0]);		p->kids[n] = q;	}	setreg(q, r);	}/*setreg:为p结点设置寄存器r*/void setreg(Node p, Symbol r){	p->syms[RX] = r;}/*prelabel:为forest预先设置待分配的寄存器*/static void prelabel(Node forest){	Node p = forest;	if (NULL == p || p->x.emitted)		return ;	prelabel(p->kids[0]);	prelabel(p->kids[1]);	if (NeedsReg[index(p->op)]) /*为需要寄存器的结点设置合适的寄存器组*/		setreg(p,rmap[optype(p->op)]);	switch (generic(p->op)) {	case ADDRL:		if (REGISTER == p->syms[0]->sclass) 			p->op = VREG+P; 		break;	case INDIR:		if (VREG+P == p->kids[0]->op) 			setreg(p, p->kids[0]->syms[0]);		break;	}	if (CALL == generic(p->op))		docall(p);	else if (ARG == generic(p->op))		(*IR->x.doarg)(p);	(IR->x.target)(p);}/*mark_instruction:对dag森林中需要产生指令的结点进行标记*/static void mark_instruction(Node forest){	Node p = forest;	if (NULL == p || p->x.marked)		return ;	mark_instruction(p->kids[0]);	mark_instruction(p->kids[1]);	switch(generic(p->op)) {	case ARG: 	case CVC: case CALL: case ADD:	case SUB: case MOD:  case DIV:	case MUL: case EQ:	 case GE:	case GT:  case LE:	 case LT:	case NE:  case JUMP: case LABEL:	case NEG: case LOAD: case ADDRL:		p->x.isinstruction = 1;		break;	case CVI: case CVU: case CVP:	/*对于像CVIU类的结点在子结点己产生指令的情况下可以不产生指令*/		if (C == optype(p->op) || !p->kids[0]->x.isinstruction) 			p->x.isinstruction = 1;		break;	case ASGN:			if (A == optype(p->op)) {			p->x.isinstruction = 1;			break;		}	case INDIR:		/*从局部变量中取右值,或者使用其左值都可以用[ebp+i]。	 不需要生成计算地址的代码*/		if (ADDRLP == p->kids[0]->op) 			p->kids[0]->x.isinstruction = 0;		p->x.isinstruction = 1;		break;	default:		p->x.isinstruction = 0;		break;	}	p->x.marked = 1; }/*free_temp_stack:释放为溢出的寄存器而分配的临时栈*/static void free_temp_stack(int boffset){	if (offset > boffset)		print("add esp, %d\n", offset - boffset);	maxoffset =  offset = boffset;	}/*gen:为dag森林进行代码生成*/void gen(Node forest){	Node p = forest;	int boffset;	DEBUG(fprint(2, "gen begin:%d\n", p->op));	for (p = forest; p; p = p->link) {		prelabel(p);		mark_instruction(p);		boffset = offset;	/*保存当前栈的偏移*/		emit_code(p);		/*释放临时栈是为防止计算函数的参数时		 *因寄存器溢出而破坏原来压栈的参数区*/		free_temp_stack(boffset);		if (NeedsReg[index(p->op)] && 0 == p->count)			free_node_reg(p);	/*释放根结点的寄存器*/	}	DEBUG(fprint(2, "gen end:\n"));}/*free_node_reg:释放p的寄存器*/static void free_node_reg(Node p){	Symbol r;	/*在结点发生了溢出时不能释放之前的寄存器*/	if ( !p || !p->x.isinstruction || !NeedsReg[index(p->op)] || p->x.spills)		return ;	r = p->syms[RX];	assert(r);	if (r->sclass != REGISTER && --p->count <= 0)             putreg(r); /*释放不是为公共结点或寄存器变量分配的寄存器*/}/*set_spill_protector:设置寄存器溢出保护器,保护为p结点分配的寄存器被溢出*/static void set_spill_protector(Node p){	assert(p);	if (NeedsReg[index(p->op)] && p->x.isinstruction)		non_spill_mask |= p->syms[RX]->x.regnode->mask;}/*reset_spill_protector复位p结点的寄存器溢出保护器*/static void reset_spill_protector(Node p){	assert(p);	if (NeedsReg[index(p->op)] && p->x.isinstruction)		non_spill_mask &= ~p->syms[RX]->x.regnode->mask;}/*sel_over_reg选择溢出的寄存器*/static Symbol sel_over_reg(Symbol rs){	int i, min;	Node p;	if (!rs->x.wildcard)		return rs;	for (i = 7, min = INT_MAX; i >= 0; i--) {		Symbol ri = rs->x.wildcard[i];		if (ri != NULL && ri->x.lastuse) {			Node q = ri->x.lastuse;			if (q->count < min 			/*查找引用次数最小的结点*/			&& (!ri->x.regnode->vbl)	/*不溢出寄存器变量*/			&& (ri->x.regnode->mask & ~non_spill_mask)){				min = q->count;				p = q;			}		}	}	return p->syms[RX];}/*overflow:保存溢出寄存器rs中的值,并将重新产生为引用rs的值的结点*/static void overflow(Symbol rs){	int ty;	assert(rs);	Node p = rs->x.lastuse;	assert(p);	DEBUG(fprint(2, "overflow register:%s,%d\n", rs->x.name, p->op));	Symbol temp = newtemp(AUTO,optype(p->op));	if (offset > maxoffset)  {	/*为临时变量在栈中分配存储空间*/		print("sub esp, %d\n", offset - maxoffset);		maxoffset = offset;	}	ty = optype(p->op);	/*将寄存器中的值保存到临时变量中*/	if (C == ty) 		print("mov byte [ebp + %s], %s\n", temp->x.name, p->syms[RX]->x.name);	else 		print("mov dword [ebp + %s], %s\n", temp->x.name, p->syms[RX]->x.name);	/*重新产生引用寄存器的结点*/	p->kids[0] = newnode(ADDRL+P, NULL, NULL, temp);	p->op = INDIR+optype(p->op);	p->syms[RX] = NULL;	p->kids[1] = NULL;	p->x.isinstruction = 0;		p->x.emitted = 0;		/*需要重新生成取值代码*/	p->x.spills = 1;			p->x.marked = 0;	putreg(rs);}/*askfixedreg:申请固定的寄存器rs*/static Symbol askfixedreg(Symbol rs){	Regnode r = rs->x.regnode;	assert(rs && !rs->x.wildcard);	if (r->mask &~freemask) /*freemask中相应的位置位时,表示对应的寄存器空闲*/		return NULL;	else {		freemask &= ~r->mask;		return rs;	}	return NULL;}/*ask_reg:申请寄存器*/static Symbol ask_reg(Symbol rs){	int i;	if (NULL == rs->x.wildcard) /*rs为固定的寄存器*/		return askfixedreg(rs);	for (i = 7; i >= 0; i--) {		Symbol r = rs->x.wildcard[i];		if (r != NULL && askfixedreg(r))			return r;	}	return NULL;}/*askregvar:为p申请寄存器regs*/int askregvar(Symbol p, Symbol regs){	Symbol r;	assert(p);	if (p->sclass != REGISTER)		return 0;	else if (!isscalar(p->type)) {		p->sclass = AUTO;		return 0;	}else if ((r = ask_reg(regs)) != NULL) {		p->x.regnode = r->x.regnode;		p->x.regnode->vbl = p;		p->x.name = r->x.name;		return 1;	}else {		p->sclass = AUTO;		return 0;	}}/*get_reg:为结点获得寄存器rs*/static Symbol get_reg(Symbol rs){	assert(rs);	Symbol r = ask_reg(rs);	if (NULL == r) {	/*需要溢出寄存器*/		r = sel_over_reg(rs);		overflow(r);		r = ask_reg(r);	}	return r;}/*get_node_reg: 为p分配寄存器*/static void get_node_reg(Node p, int t){	Symbol rs = NULL;	if (!p->syms[RX]->x.wildcard) { /*需要固定的寄存器*/		if ((DIV == generic(p->op) || MOD == generic(p->op)) && t) {			rs = p->syms[RX];	/*保存原来的寄存器*/			set_eax(p);			/*设置为eax寄存器*/			get_node_reg(p, 0);			set_edx(p);			/*设置为edx寄存器*/			get_node_reg(p, 0);			p->syms[RX] = rs;	/*恢复原来的寄存器*/			rs->x.lastuse = p;			return ;		}		rs = askfixedreg(p->syms[RX]);		if (!rs && p->syms[RX]->x.lastuse->kids[0] == p) 		/*如果是它的父结点占用了寄存器则不必溢出寄存器

⌨️ 快捷键说明

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