📄 gen.c
字号:
*这主要是为了处理在子结点出现寄存器溢出时,为它生成 *重新取值代码,而分配寄存器时可能会溢出它的父结点寄存器的情况 */ 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 + -