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

📄 gen.c

📁 unix环境下实现的cmm语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
		 *这主要是为了处理在子结点出现寄存器溢出时,为它生成		 *重新取值代码,而分配寄存器时可能会溢出它的父结点寄存器的情况		 */			return ; 			}	if (NULL == rs)		rs = get_reg(p->syms[RX]); 	rs->x.lastuse = p;/*lastuse指向使用它的结点*/	p->syms[RX] = rs;}/*reg_alloc:为p申请寄存器*/static void reg_alloc(Node p){	assert(p);	if (p->kids[1]) /*为p的右子结点分配的寄存器不能被溢出*/		set_spill_protector(p->kids[1]);	if (NeedsReg[index(p->op)] && p->x.isinstruction 	&&(INDIR != generic(p->op) || p->kids[0]->op != VREG+P)) 	/*不需要为引用寄存器变量的结点分配寄存器*/		get_node_reg(p, 1);	if (p->kids[1])		reset_spill_protector(p->kids[1]);}static char *templates[] = { /*汇编代码生成模板*//* 0 */	0,/* 1 */ 0,/* 2 */ 0,/* 3 */ 0,/* 4 */ 0,/* 5 */ 0,/* 6 */ 0,/* 7 */ 0,/* 8 */ 0,		/*CNST*//* 9 */ "%a", 	/*CNSTC*//* 10 */ "%a", 	/*CNSTI*//* 11 */ 0,	/* 12 */ "%a", 	/*CNSTP*//* 13 */ "%a",	/*CNSTA*/	/* 14 */ "%a",	/*CNSTU*//* 15 */ 0,/* 16 */ 0,				/*ARG*//* 17 */ "push %0\n",	/*ARGC*//* 18 */ "push %0\n", 	/*ARGI*//* 19 */ 0,/* 20 */ "push %0\n",	/*ARGP*//* 21 */ 0,/* 22 */ 0,/* 23 */ 0,/* 24 */ 0,							/*ASGN*//* 25 */ "mov byte  [%0], %1\n" ,	/*ASGNC*//* 26 */ "mov dword  [%0], %1\n", 	/*ASGNI*//* 27 */ 0,/* 28 */ "mov dword  [%0], %1\n", 	/*ASGNP*//* 29 */ "mov ecx, %a\nrep movsb\n",/*ASGNA*//* 30 */ 0,/* 31 */ 0,/* 32 */ 0,						/*INDIR*//* 33 */ "mov %c,byte  [%0]\n",	/*INDIRC*//* 34 */ "mov %c, dword [%0]\n",/*INDIRI*//* 35 */ 0,/* 36 */ "mov %c, dword [%0]\n",/*INDIRP*//* 37 */ "mov %c, %0\n",		/*INDIR+A*//* 38 */ 0,/* 39 */ 0,/* 40 */ 0,				/*CVC*//* 41 */ 0,/* 42 */ "# extend\n",	/*CVCI*//* 43 */ 0,/* 44 */ 0,/* 45 */ 0,/* 46 */ 0,/* 47 */ 0,/* 48 */ 0,				/*CVI*//* 49 */ "# truncate\n",/*CVIC*//* 50 */ 0,/* 51 */ 0,/* 52 */ 0,		/* 53 */ 0,/* 54 */ "mov %c,%0\n", /*CVIU*//* 55 */ 0,/* 56 */ 0,				/*CVP*//* 57 */ 0,/* 58 */ 0,/* 59 */ 0,/* 60 */ 0,/* 61 */ 0,/* 62 */ "mov %c, %0\n", /*CVPU*/ /* 63 */ 0,/* 64 */ 0,							/*CALL*//* 65 */ 0,/* 66 */ "call %1\nadd esp, %a\n",	/*CALLI*//* 67 */ "call %1\nadd esp, %a\n",	/*CALLV*//* 68 */ "call %1\nadd esp, %a\n",	/*CALLP*//* 69 */ 0,/* 70 */ 0,/* 71 */ 0,/* 72 */ 0,			/*RET*//* 73 */ 0,/* 74 */ "# ret\n", /*RETI*//* 75 */ 0,/* 76 */ 0,/* 77 */ 0,/* 78 */ 0,/* 79 */ 0,/* 80 */ 0,		/*ADDRG*//* 81 */ 0,/* 82 */ 0,/* 83 */ 0,/* 84 */ "%a",	/*ADDRGP*//* 85 */ 0,/* 86 */ 0,/* 87 */ 0,/* 88 */ 0,		/*ADDRL*//* 89 */ 0,/* 90 */ 0,/* 91 */ 0,/* 92 */ "ebp+%a", /*ADDRLP*//* 93 */ 0,/* 94 */ 0,/* 95 */ 0,/* 96 */ 0,								/*ADD*//* 97 */ 0,/* 98 */ "?mov %c, %0\nadd %c, %1\n",	/*ADDI*//* 99 */ 0,/* 100 */ "?mov %c, %0\nadd %c, %1\n",	/*ADDP*//* 101 */ 0,/* 102 */ 0,/* 103 */ 0,/* 104 */ 0,							/*SUB*//* 105 */ 0,/* 106 */ "?mov %c, %0\nsub %c, %1\n",	/*SUBI*//* 107 */ 0,/* 108 */ "?mov %c, %0\nsub %c, %1\n", /*SUBP*//* 109 */ 0,/* 110 */ 0,/* 111 */ 0,/* 112 */ 0,				/*MOD*//* 113 */ 0,/* 114 */ "cdq\nidiv %1\n",	/*MODI*//* 115 */ 0,/* 116 */ 0,/* 117 */ 0,/* 118 */ 0,/* 119 */ 0,/* 120 */ 0,				/*DIV*//* 121 */ 0,/* 122 */ "cdq\nidiv %1\n", /*DIVI*//* 123 */ 0,/* 124 */ 0,/* 125 */ 0,/* 126 */ 0,/* 127 */ 0,/* 128 */ 0,							/*MUL*//* 129 */ 0,/* 130 */ "?mov %c, %0\nimul %c, %1\n",	/*MULI*//* 131 */ 0,/* 132 */ 0,/* 133 */ 0,/* 134 */ 0,/* 135 */ 0,/* 136 */ 0,						/*EQ*//* 137 */ 0,/* 138 */ "cmp %0, %1\nje near %a\n",	/*EQI*//* 139 */ 0, /* 140 */ 0, /* 141 */ 0,/* 142 */ "cmp %0,%1\n je near %a\n", /*EQU*/ /* 143 */ 0,/* 144 */ 0,						/*GE*//* 145 */ 0,/* 146 */ "cmp %0,%1\njge near %a\n",	/*GEI*//* 147 */ 0,/* 148 */ 0,/* 149 */ 0,/* 150 */ "cmp %0,%1\njae near %a\n", /*GEU*//* 151 */ 0,/* 152 */ 0,					/*GT*//* 153 */ 0,/* 154 */ "cmp %0,%1\njg near %a\n", /*GTI*//* 155 */ 0,/* 156 */ 0,/* 157 */ 0,/* 158 */ "cmp %0,%1\nja  near %a\n", /*GTU*//* 159 */ 0,/* 160 */ 0,						/*LE*//* 161 */ 0,/* 162 */ "cmp %0,%1\njle near %a\n",	/*LEI*/	/* 163 */ 0,/* 164 */ 0,/* 165 */ 0,/* 166 */ "cmp %0,%1\njbe near %a\n",/*LEU*//* 167 */ 0,/* 168 */ 0,					/*LT*//* 169 */ 0,/* 170 */ "cmp %0,%1\njl near %a\n",	/*LTI*//* 171 */ 0,/* 172 */ 0,/* 173 */ 0,/* 174 */ "cmp %0,%1\njb near %a\n",	/*LTU*//* 175 */ 0,/* 176 */ 0,					/*NE*//* 177 */ 0,/* 178 */ "cmp %0,%1\njne near %a\n",/*NEI*/	/* 179 */ 0,/* 180 */ 0,/* 181 */ 0,/* 182 */ "cmp %0,%1\njne near %a\n",/*NEU*//* 183 */ 0,/* 184 */ 0,			/*JUMP*//* 185 */ 0,/* 186 */ 0,/* 187 */ "jmp %0\n",	/*JUMPV*/	/* 188*/ 0,/* 189 */ 0,/* 190 */ 0,/* 191 */ 0,/* 192 */ 0,		/*LABEL*//* 193 */ 0,/* 194 */ 0,/* 195 */ "%a:\n", /*LABELV*//* 196 */ 0,/* 197 */ 0,/* 198 */ 0,/* 199 */ 0,/* 200 */ 0,/* 201 */ 0,/* 202 */ 0,/* 203 */ 0,/* 204 */ 0,/* 205 */ 0,/* 206 */ 0,/* 207 */ 0,/* 208 */ 0,						/*NEG*//* 209 */ 0,/* 210 */ "?mov %c,%0\nneg %c\n",	/*NEGI*//* 211 */ 0,/* 212 */ 0,/* 213 */ 0,/* 214 */ 0,/* 215 */ 0,/* 216 */ 0,			/*CVU*//* 217 */ 0,/* 218 */ "mov %c,%0\n",/*CVUI*//* 219 */ 0,/* 220 */ "mov %c,%0\n",/*CVUP*//* 221 */ 0,/* 222 */ 0,/* 223 */ 0,/* 224 */ 0,			/*LOAD*//* 225 */ "mov %c,%0\n",/*LOADC*//* 226 */ "mov %c,%0\n",/*LOADI*//* 227 */ 0,/* 228 */ "mov %c,%0\n",/*LOADP*//* 229 */ 0,/* 230 */ "mov %c,%0\n",/*LOADU*//* 231 */ 0,/* 232 */ 0,	/*VREG*//* 233 */ 0,/* 234 */ 0,/* 235 */ 0,/* 236 */ "%a",	/*VREG+P*//* 237 */ 0,/* 238 */ 0,/* 239 */ 0,};/*gen_re_load:为溢出的结点重新生成取值代码*/static void gen_re_load(Node p, int n){	int f;	DEBUG(fprint(2, "gen_re_load\n"));	p->kids[n]->x.spills = 0;	f = NeedsReg[index(p->op)];		NeedsReg[index(p->op)] = 0;	/*为了防止prelabel为p结点重新设置寄存器*/	prelabel(p);	NeedsReg[index(p->op)] = f;		p->x.marked = 0;	/*对p进行重新的标记*/	mark_instruction(p);	/*由于已经为p分配了寄存器,这里是为了防止在其子结点进行寄存器	 分配时再次溢出p的寄存器*/		set_spill_protector(p); 	emit_code(p->kids[n]);	/*如果是左子结点溢出,则需要释放为它分配的寄存器。	 *右结点的寄存器可以在emit_code中释放。	 *由于之前在emit_code中没有释放左结点的寄存器,	 *所以现在必需释放在左结点的寄存器,前提是它不能与当前结点的寄存器相同。	 *这是避免把当前结点的寄存器也释放*/	if ((0 == n) || (1 == n && !equal_reg(p, p->kids[0])))		free_node_reg(p->kids[0]);	reset_spill_protector(p);}/*get_code_templates:为p选择汇编代码模板*/static char *get_code_templates(Node p){	assert(p);	DEBUG(fprint(2, "get_code_templates begin:%d\n", p->op));	if (p->kids[0] && p->kids[0]->x.spills)		gen_re_load(p, 0);	if (p->kids[1] && p->kids[1]->x.spills)		gen_re_load(p, 1);	switch (generic(p->op)){		case CVI: case CVP: 	case CVU: 		if (CVIU == p->op || CVUI == p->op		|| CVUP == p->op || CVPU == p->op)			if (!p->x.isinstruction)				return "%0";		break;	case ASGN:		if (A == optype(p->op)) /*为初始局部数组选择指令*/			get_reg(p->syms[RX]);	/*设置寄存器ecx*/			if (VREG == generic(p->kids[0]->op))			return "mov %0, %1\n";		break;	case INDIR:		if (VREG == generic(p->kids[0]->op))			return "#read register\n";		break;	case ADDRL:		if (p->x.isinstruction)	/*计算局部变量的地址*/			return "mov %c, ebp\nadd %c, %a\n";		break;	}	DEBUG(fprint(2, "get_code_templates end:%d\n", p->op));	return templates[p->op];	}/*emit_asm:为p产生汇编代码*/static void emit_asm(Node p){	DEBUG(fprint(2, "emit_asm begin:\n"));	char *fmt;	if (p->x.isinstruction && p->x.emitted) {		outs(p->syms[RX]->x.name);			return ;	}	fmt = get_code_templates(p);	assert(fmt);	if (*fmt == '#')		(*IR->x.emit2)(p);	else {		if (*fmt == '?') {			fmt++;			assert(p->kids[0]);			if (equal_reg(p, p->kids[0]))				while (*fmt++ != '\n')					;		}		for (; *fmt; fmt++)			if (*fmt != '%')				*bp++ = *fmt;			else if (*++fmt >= '0' && *fmt <= '2') 				emit_asm(p->kids[*fmt - '0']);			else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms)){					outs(p->syms[*fmt - 'a']->x.name);			}else				*bp++ = *fmt;	}	if (ASGN+A == p->op)		putreg(p->syms[RX]);	DEBUG(fprint(2, "emit_asm end:\n"));}static void emit_code(Node forest){	Node p = forest;	/*对于溢出结点的重新取值是在get_code_template中进行的*/	if (NULL == p || p->x.emitted || p->x.spills)		return ;	DEBUG(fprint(2, "emit_code begin:%d\n",p->op));	if (CALL == generic(p->op)) { 		Symbol rs = get_reg(p->syms[RX]);		putreg(rs);	}		emit_code(p->kids[0]);	if (ARG == generic(p->op))		emit_asm(p);	emit_code(p->kids[1]);	/*NEG不能改变原寄存器的值,所以不能释放左结点的寄存器。	 *当右结点发生寄存器溢出时,为了防止为它生成重新取值代码而	 *占用左结点的寄存器而不释放左结点的寄存器,但如果父结点的	 *寄存器与左结点的寄存器相同,可以释放在左结点的寄存器,因为	 *在释放左结点的寄存器之后,在为父结点分配寄存器时,会分配该寄存器。	 */ 	if (generic(p->op) != NEG	&& (!p->kids[1] || !p->kids[1]->x.spills	|| equal_reg(p,p->kids[0])))		free_node_reg(p->kids[0]);	reg_alloc(p);	if (p->x.isinstruction && generic(p->op) != ARG)		emit_asm(p);	p->x.emitted = 1;	free_node_reg(p->kids[1]);	if (DIV == generic(p->op))	/*DIV结点中的edx可以提前释放,以节约寄存器*/		put_edx();	if (MOD == generic(p->op))	/*MOD结点中的eax可以提前释放*/		put_eax();	DEBUG(fprint(2, "emit_code end:%d\n", p->op));}/*getregnum:从结点p中取得为它分配的寄存器的编号*/int getregnum(Node p){	assert(p && p->syms[RX] && p->syms[RX]->x.regnode);	return p->syms[RX]->x.regnode->number;}

⌨️ 快捷键说明

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