initial checkin for TEMPLATE backend
[libfirm] / ir / be / TEMPLATE / TEMPLATE_emitter.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <limits.h>
6
7 #include "xmalloc.h"
8 #include "tv.h"
9 #include "iredges.h"
10 #include "debug.h"
11 #include "irgwalk.h"
12 #include "irprintf.h"
13 #include "irop_t.h"
14 #include "irargs_t.h"
15
16 #include "../besched.h"
17
18 #include "TEMPLATE_emitter.h"
19 #include "gen_TEMPLATE_emitter.h"
20 #include "TEMPLATE_nodes_attr.h"
21 #include "TEMPLATE_new_nodes.h"
22 #include "TEMPLATE_map_regs.h"
23
24 #define SNPRINTF_BUF_LEN 128
25
26 static const arch_env_t *arch_env = NULL;
27
28
29 /*************************************************************
30  *             _       _    __   _          _
31  *            (_)     | |  / _| | |        | |
32  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
33  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
34  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
35  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
36  * | |                                       | |
37  * |_|                                       |_|
38  *************************************************************/
39
40 /**
41  * Return a const or symconst as string.
42  */
43 static const char *node_const_to_str(ir_node *n) {
44         /* TODO */
45 }
46
47 /**
48  * Returns node's offset as string.
49  */
50 static char *node_offset_to_str(ir_node *n) {
51         /* TODO */
52 }
53
54 /* We always pass the ir_node which is a pointer. */
55 static int TEMPLATE_get_arg_type(const lc_arg_occ_t *occ) {
56         return lc_arg_type_ptr;
57 }
58
59
60 /**
61  * Returns the register at in position pos.
62  */
63 static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
64         ir_node                *op;
65         const arch_register_t  *reg = NULL;
66
67         assert(get_irn_arity(irn) > pos && "Invalid IN position");
68
69         /* The out register of the operator at position pos is the
70            in register we need. */
71         op = get_irn_n(irn, pos);
72
73         reg = arch_get_irn_register(arch_env, op);
74
75         assert(reg && "no in register found");
76         return reg;
77 }
78
79 /**
80  * Returns the register at out position pos.
81  */
82 static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
83         ir_node                *proj;
84         const arch_register_t  *reg = NULL;
85
86         assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
87
88         /* 1st case: irn is not of mode_T, so it has only                 */
89         /*           one OUT register -> good                             */
90         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
91         /*           Proj with the corresponding projnum for the register */
92
93         if (get_irn_mode(irn) != mode_T) {
94                 reg = arch_get_irn_register(arch_env, irn);
95         }
96         else if (is_TEMPLATE_irn(irn)) {
97                 reg = get_TEMPLATE_out_reg(irn, pos);
98         }
99         else {
100                 const ir_edge_t *edge;
101
102                 foreach_out_edge(irn, edge) {
103                         proj = get_edge_src_irn(edge);
104                         assert(is_Proj(proj) && "non-Proj from mode_T node");
105                         if (get_Proj_proj(proj) == pos) {
106                                 reg = arch_get_irn_register(arch_env, proj);
107                                 break;
108                         }
109                 }
110         }
111
112         assert(reg && "no out register found");
113         return reg;
114 }
115
116 /**
117  * Returns the number of the in register at position pos.
118  */
119 int get_TEMPLATE_reg_nr(ir_node *irn, int pos, int in_out) {
120         const arch_register_t *reg;
121
122         if (in_out == 1) {
123                 reg = get_in_reg(irn, pos);
124         }
125         else {
126                 reg = get_out_reg(irn, pos);
127         }
128
129         return arch_register_get_index(reg);
130 }
131
132 /**
133  * Returns the name of the in register at position pos.
134  */
135 const char *get_TEMPLATE_reg_name(ir_node *irn, int pos, int in_out) {
136         const arch_register_t *reg;
137
138         if (in_out == 1) {
139                 reg = get_in_reg(irn, pos);
140         }
141         else {
142                 reg = get_out_reg(irn, pos);
143         }
144
145         return arch_register_get_name(reg);
146 }
147
148 /**
149  * Get the register name for a node.
150  */
151 static int TEMPLATE_get_reg_name(lc_appendable_t *app,
152     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
153 {
154         const char *buf;
155         ir_node    *X  = arg->v_ptr;
156         int         nr = occ->width - 1;
157
158         if (!X)
159                 return lc_arg_append(app, occ, "(null)", 6);
160
161         if (occ->conversion == 'S') {
162                 buf = get_TEMPLATE_reg_name(X, nr, 1);
163         }
164         else { /* 'D' */
165                 buf = get_TEMPLATE_reg_name(X, nr, 0);
166         }
167
168         lc_appendable_chadd(app, '%');
169         return lc_arg_append(app, occ, buf, strlen(buf));
170 }
171
172 /**
173  * Returns the tarval or offset of an ia32 as a string.
174  */
175 static int TEMPLATE_const_to_str(lc_appendable_t *app,
176     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
177 {
178         const char *buf;
179         ir_node    *X = arg->v_ptr;
180
181         if (!X)
182                 return lc_arg_append(app, occ, "(null)", 6);
183
184         if (occ->conversion == 'C') {
185                 buf = node_const_to_str(X);
186         }
187         else { /* 'O' */
188                 buf = node_offset_to_str(X);
189         }
190
191         return lc_arg_append(app, occ, buf, strlen(buf));
192 }
193
194 /**
195  * Determines the SSE suffix depending on the mode.
196  */
197 static int TEMPLATE_get_mode_suffix(lc_appendable_t *app,
198     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
199 {
200         ir_node *X = arg->v_ptr;
201
202         if (!X)
203                 return lc_arg_append(app, occ, "(null)", 6);
204
205         if (get_mode_size_bits(get_irn_mode(X)) == 32)
206                 return lc_appendable_chadd(app, 's');
207         else
208                 return lc_appendable_chadd(app, 'd');
209 }
210
211 /**
212  * Return the ia32 printf arg environment.
213  * We use the firm environment with some additional handlers.
214  */
215 const lc_arg_env_t *TEMPLATE_get_arg_env(void) {
216         static lc_arg_env_t *env = NULL;
217
218         static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
219         static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
220         static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
221
222         if(env == NULL) {
223                 /* extend the firm printer */
224                 env = firm_get_arg_env();
225                         //lc_arg_new_env();
226
227                 lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
228                 lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
229                 lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
230                 lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
231                 lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
232         }
233
234         return env;
235 }
236
237 /**
238  * For 2-address code we need to make sure the first src reg is equal to dest reg.
239  */
240 void equalize_dest_src(FILE *F, ir_node *n) {
241         if (get_ia32_reg_nr(n, 0, 1) != get_ia32_reg_nr(n, 0, 0)) {
242                 if (get_irn_arity(n) > 1 && get_ia32_reg_nr(n, 1, 1) == get_ia32_reg_nr(n, 0, 0)) {
243                         if (! is_op_commutative(get_irn_op(n))) {
244                                 /* we only need to exchange for non-commutative ops */
245                                 lc_efprintf(ia32_get_arg_env(), F, "\txchg %1S, %2S\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
246                         }
247                 }
248                 else {
249                         lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1S, %1D\t\t\t/* src -> dest for 2 address code */\n", n, n);
250                 }
251         }
252 }
253
254 /*
255  * Add a number to a prefix. This number will not be used a second time.
256  */
257 char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
258         static unsigned long id = 0;
259         snprintf(buf, buflen, "%s%lu", prefix, ++id);
260         return buf;
261 }
262
263
264 /**
265  * Returns the target label for a control flow node.
266  */
267 static char *get_cfop_target(const ir_node *irn, char *buf) {
268         ir_node *bl = get_irn_link(irn);
269
270         snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
271         return buf;
272 }
273
274 /*********************************************************
275  *                 _ _       _
276  *                (_) |     (_)
277  *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
278  *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
279  * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
280  *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
281  *                         _/ |               | |
282  *                        |__/                |_|
283  *********************************************************/
284
285 /**
286  * Emits code for a Switch (creates a jump table if
287  * possible otherwise a cmp-jmp cascade).
288  */
289 void emit_TEMPLATE_Switch(const ir_node *irn, emit_env_t *emit_env) {
290         unsigned long       interval;
291         jmp_tbl_t          *tbl;
292         ir_node           **cases;
293         int                 def_projnum;
294         int                 do_jmp_tbl = 1;
295         const lc_arg_env_t *env        = ia32_get_arg_env();
296         FILE               *F          = emit_env->out;
297
298         /* TODO:                                                         */
299         /* - create list of projs, each corresponding to one switch case */
300         /* - determine the projnumber of the default case                */
301
302         tbl = create_jump_table(cases, def_projnum, "JMPTBL_");
303
304         /* two-complement's magic make this work without overflow */
305         interval = tbl.max_value - tbl.min_value;
306
307         /* check value interval: do not create jump table if interval is too large */
308         if (interval > 16 * 1024) {
309                 do_jmp_tbl = 0;
310         }
311
312         /* check ratio of value interval to number of branches */
313         if (((float)(interval + 1) / (float)tbl.num_branches) > 8.0) {
314                 do_jmp_tbl = 0;
315         }
316
317         if (do_jmp_tbl) {
318                 /* TODO: emit table code */
319         }
320         else {
321                 /* TODO: emit cmp - jmp cascade */
322         }
323
324         if (tbl.label)
325                 free(tbl.label);
326         if (tbl.branches)
327                 free(tbl.branches);
328 }
329
330
331
332 /***********************************************************************************
333  *                  _          __                                             _
334  *                 (_)        / _|                                           | |
335  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
336  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
337  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
338  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
339  *
340  ***********************************************************************************/
341
342 /**
343  * Emits code for a node.
344  */
345 void TEMPLATE_emit_node(ir_node *irn, void *env) {
346         emit_env_t *emit_env   = env;
347         firm_dbg_module_t *mod = emit_env->mod;
348         FILE              *F   = emit_env->out;
349
350         DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
351
352 #define BE_EMIT(a) if (is_TEMPLATE_##a(irn)) { emit_TEMPLATE_##a(irn, emit_env); return; }
353
354         /* generated int emitter functions */
355         BE_EMIT(Copy);
356         BE_EMIT(Perm);
357
358         BE_EMIT(Const);
359
360         BE_EMIT(Add);
361         BE_EMIT(Add_i);
362         BE_EMIT(Sub);
363         BE_EMIT(Sub_i);
364         BE_EMIT(Minus);
365         BE_EMIT(Inc);
366         BE_EMIT(Dec);
367
368         BE_EMIT(And);
369         BE_EMIT(And_i);
370         BE_EMIT(Or);
371         BE_EMIT(Or_i);
372         BE_EMIT(Eor);
373         BE_EMIT(Eor_i);
374         BE_EMIT(Not);
375
376         BE_EMIT(Shl);
377         BE_EMIT(Shl_i);
378         BE_EMIT(Shr);
379         BE_EMIT(Shr_i);
380         BE_EMIT(RotL);
381         BE_EMIT(RotL_i);
382         BE_EMIT(RotR);
383
384         BE_EMIT(Mul);
385         BE_EMIT(Mul_i);
386
387         BE_EMIT(Store);
388         BE_EMIT(Load);
389
390         /* generated floating point emitter */
391         BE_EMIT(fConst);
392
393         BE_EMIT(fAdd);
394         BE_EMIT(fSub);
395         BE_EMIT(fMinus);
396
397         BE_EMIT(fMul);
398         BE_EMIT(fDiv);
399
400         BE_EMIT(fMin);
401         BE_EMIT(fMax);
402
403         BE_EMIT(fLoad);
404         BE_EMIT(fStore);
405
406         /* other emitter functions */
407 //      BE_EMIT(Switch);
408
409         ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
410 }
411
412 /**
413  * Walks over the nodes in a block connected by scheduling edges
414  * and emits code for each node.
415  */
416 void TEMPLATE_gen_block(ir_node *block, void *env) {
417         ir_node *irn;
418
419         if (! is_Block(block))
420                 return;
421
422         fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
423         sched_foreach(block, irn) {
424                 TEMPLATE_emit_node(irn, env);
425         }
426 }
427
428
429 /**
430  * Emits code for function start.
431  */
432 void TEMPLATE_emit_start(FILE *F, ir_graph *irg) {
433         const char *irg_name = get_entity_name(get_irg_entity(irg));
434
435         /* TODO: emit function header */
436 }
437
438 /**
439  * Emits code for function end
440  */
441 void TEMPLATE_emit_end(FILE *F, ir_graph *irg) {
442         const char *irg_name = get_entity_name(get_irg_entity(irg));
443
444         /* TODO: emit function end */
445 }
446
447 /**
448  * Sets labels for control flow nodes (jump target)
449  * TODO: Jump optimization
450  */
451 void TEMPLATE_gen_labels(ir_node *block, void *env) {
452         ir_node *pred;
453         int n = get_Block_n_cfgpreds(block);
454
455         for (n--; n >= 0; n--) {
456                 pred = get_Block_cfgpred(block, n);
457                 set_irn_link(pred, block);
458         }
459 }
460
461 /**
462  * Main driver
463  */
464 void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
465         emit_env_t emit_env;
466
467         emit_env.mod      = firm_dbg_register("firm.be.TEMPLATE.emit");
468         emit_env.out      = F;
469         emit_env.arch_env = cg->arch_env;
470         emit_env.cg       = cg;
471
472         /* set the global arch_env (needed by print hooks) */
473         arch_env = cg->arch_env;
474
475         TEMPLATE_emit_start(F, irg);
476         irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, &emit_env);
477         irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, &emit_env);
478         TEMPLATE_emit_end(F, irg);
479 }