codegen.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- init_codegen
- gen_verb
- gen_make_frame
- gen_exp
- gen_add_grp
- gen_cmp_grp
- gen_label
- gen_goto
- gen_jz
- gen_set
1 /*
2
3 Tiny ZiNC Compiler --- code generater
4
5
6 Copyright (C) 2000 KISHIMOTO, Makoto
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22
23 KISHIMOTO, Makoto <cs96068@cs.tuat.ac.jp>
24
25 */
26
27 /*
28
29 コードジェネレータ
30
31 */
32
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36
37 #include "confdef.h"
38
39 #include "express.h"
40 #include "name.h"
41 #include "labelgen.h"
42
43 #include "codegen.h"
44
45 static void gen_add_grp(exp_node *p, char const op[]);
46 static void gen_cmp_grp(exp_node *p, char const op[]);
47
48 static FILE *out_file;
49
50 void
51 init_codegen(FILE *fp)
/* [<][>][^][v][top][bottom][index][help] */
52 {
53 out_file = fp;
54 }
55
56 void
57 gen_verb(char s[])
/* [<][>][^][v][top][bottom][index][help] */
58 {
59 fprintf(out_file, "%s", s);
60 }
61
62 void
63 gen_make_frame(int size)
/* [<][>][^][v][top][bottom][index][help] */
64 {
65 fprintf(out_file, "\tsubl $%d, %%esp\n", size);
66 }
67
68 void
69 gen_exp(exp_node *p)
/* [<][>][^][v][top][bottom][index][help] */
70 {
71 switch (p->type)
72 {
73 case EXP_ISEQ:
74 gen_cmp_grp(p, "jne"); /* 条件の反転に注意 */
75 break;
76 case EXP_ISNOTEQ:
77 gen_cmp_grp(p, "je"); /* 条件の反転に注意 */
78 break;
79 case EXP_ISLT:
80 gen_cmp_grp(p, "jnl"); /* 条件の反転に注意 */
81 break;
82 case EXP_ISGT:
83 gen_cmp_grp(p, "jng"); /* 条件の反転に注意 */
84 break;
85 case EXP_ISLTEQ:
86 gen_cmp_grp(p, "jnle"); /* 条件の反転に注意 */
87 break;
88 case EXP_ISGTEQ:
89 gen_cmp_grp(p, "jnge"); /* 条件の反転に注意 */
90 break;
91
92 case EXP_ADD:
93 gen_add_grp(p, "addl");
94 break;
95 case EXP_SUB:
96 gen_add_grp(p, "subl");
97 break;
98 case EXP_OR:
99 gen_add_grp(p, "orl");
100 break;
101
102 case EXP_MUL:
103 gen_exp(p->val._2._1);
104 fprintf(out_file, "\tpushl %%eax\n");
105 gen_exp(p->val._2._0);
106 fprintf(out_file, "\tpopl %%ecx\n");
107 fprintf(out_file, "\timull %%ecx, %%eax\n");
108 break;
109 case EXP_DIV:
110 gen_exp(p->val._2._1);
111 fprintf(out_file, "\tpushl %%eax\n");
112 gen_exp(p->val._2._0);
113 fprintf(out_file, "\tpopl %%ecx\n");
114 fprintf(out_file, "\tcltd\n");
115 fprintf(out_file, "\tidivl %%ecx, %%eax\n");
116 break;
117 case EXP_MOD:
118 gen_exp(p->val._2._1);
119 fprintf(out_file, "\tpushl %%eax\n");
120 gen_exp(p->val._2._0);
121 fprintf(out_file, "\tpopl %%ecx\n");
122 fprintf(out_file, "\tcltd\n");
123 fprintf(out_file, "\tidivl %%ecx, %%eax\n");
124 fprintf(out_file, "\tmovl %%edx, %%eax\n");
125 break;
126 case EXP_LSL:
127 gen_exp(p->val._2._1);
128 fprintf(out_file, "\tpushl %%eax\n");
129 gen_exp(p->val._2._0);
130 fprintf(out_file, "\tpopl %%ecx\n");
131 fprintf(out_file, "\tshll %%cl, %%eax\n");
132 break;
133 case EXP_ASR:
134 gen_exp(p->val._2._1);
135 fprintf(out_file, "\tpushl %%eax\n");
136 gen_exp(p->val._2._0);
137 fprintf(out_file, "\tpopl %%ecx\n");
138 fprintf(out_file, "\tsarl %%cl, %%eax\n");
139 break;
140 case EXP_LSR:
141 gen_exp(p->val._2._1);
142 fprintf(out_file, "\tpushl %%eax\n");
143 gen_exp(p->val._2._0);
144 fprintf(out_file, "\tpopl %%ecx\n");
145 fprintf(out_file, "\tshrl %%cl, %%eax\n");
146 break;
147
148 case EXP_AND:
149 gen_add_grp(p, "andl");
150 break;
151 case EXP_NOT:
152 gen_exp(p->val._1._0);
153 fprintf(out_file, "\tnotl %%eax\n");
154 break;
155 case EXP_PLUS:
156 gen_exp(p->val._1._0);
157 break;
158 case EXP_MINUS:
159 gen_exp(p->val._1._0);
160 fprintf(out_file, "\tnegl %%eax\n");
161 break;
162
163 case EXP_CONST:
164 fprintf(out_file, "\tmovl $%d, %%eax\n", p->val.constval);
165 break;
166 case EXP_VAR:
167 {
168 name_type var_scope;
169 var_scope = name_get_type(p->val.var);
170 if (var_scope == NAME_GLO_VAR)
171 {
172 fprintf(out_file, "\tmovl %s, %%eax\n", name_get_str(p->val.var));
173 }
174 else if (var_scope == NAME_LOC_VAR)
175 {
176 fprintf(out_file, "\tmovl -%d(%%ebp), %%eax\n", name_get_id(p->val.var));
177 }
178 else
179 {
180 EMSTOP("internal conflict", 0);
181 exit(1);
182 }
183 break;
184 }
185 }
186 }
187
188 static void
189 gen_add_grp(exp_node *p, char const op[])
/* [<][>][^][v][top][bottom][index][help] */
190 {
191 gen_exp(p->val._2._1);
192 fprintf(out_file, "\tpushl %%eax\n");
193 gen_exp(p->val._2._0);
194 fprintf(out_file, "\tpopl %%ecx\n");
195 fprintf(out_file, "\t%s %%ecx, %%eax\n", op);
196 }
197
198 static void
199 gen_cmp_grp(exp_node *p, char const op[])
/* [<][>][^][v][top][bottom][index][help] */
200 {
201 int label;
202
203 gen_add_grp(p, "cmpl");
204 fprintf(out_file, "\tmovl $0, %%eax\n"); /* 注 : ←ここを xorl %eax, %eax に */
205 label = getnewnum(); /* しては **いけない** */
206 fprintf(out_file, "\t%s L.%d\n", op, label); /* なぜなら←ここで見ている */
207 fprintf(out_file, "\tnotl %%eax\n"); /* フラグを破壊してしまうからである */
208 gen_label(label);
209 }
210
211 void
212 gen_label(int n)
/* [<][>][^][v][top][bottom][index][help] */
213 {
214 fprintf(out_file, "L.%d:\n", n);
215 }
216
217 void
218 gen_goto(int n)
/* [<][>][^][v][top][bottom][index][help] */
219 {
220 fprintf(out_file, "\tjmp L.%d\n", n);
221 }
222
223 void
224 gen_jz(int n)
/* [<][>][^][v][top][bottom][index][help] */
225 {
226 fprintf(out_file, "\tjz L.%d\n", n);
227 }
228
229 void
230 gen_set(name_info *store_to)
/* [<][>][^][v][top][bottom][index][help] */
231 {
232 name_type var_scope;
233
234 var_scope = name_get_type(store_to);
235 if (var_scope == NAME_GLO_VAR)
236 {
237 fprintf(out_file, "\tmovl %%eax, %s\n", name_get_str(store_to));
238 }
239 else if (var_scope == NAME_LOC_VAR)
240 {
241 fprintf(out_file, "\tmovl %%eax, -%d(%%ebp)\n", name_get_id(store_to));
242 }
243 else
244 {
245 EMSTOP("internal conflict", 0);
246 exit(1);
247 }
248 }