improved dump of node attributes
[libfirm] / ir / be / ia32 / transform.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include "irnode_t.h"
6 #include "irgraph_t.h"
7 #include "irmode_t.h"
8 #include "irgmod.h"
9 #include "dbginfo.h"
10 #include "irop_t.h"
11 #include "debug.h"
12
13 #include "../firm2arch_nodes_attr.h"
14 #include "../bearch_firm.h"
15 #include "transform.h"
16 #include "new_nodes.h"
17
18 /* determine if one operator is an Imm */
19 ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
20   if (op1)
21     return is_Imm(op1) ? op1 : (is_Imm(op2) ? op2 : NULL);
22   else return is_Imm(op2) ? op2 : NULL;
23 }
24
25 /* determine if one operator is not an Imm */
26 ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
27   return !is_Imm(op1) ? op1 : (!is_Imm(op2) ? op2 : NULL);
28 }
29
30
31
32 /**
33  * Creates an ia32 Add with immediate.
34  *
35  * @param dbg       firm dbg
36  * @param block     the block the new node should belong to
37  * @param expr_op   operator
38  * @param mode      node mode
39  * @return the created ia23 Add_i node
40  */
41 ir_node *gen_imm_Add(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
42   return new_rd_ia32_Add_i(dbg, current_ir_graph, block, expr_op, mode);
43 }
44
45 /**
46  * Creates an ia32 Add.
47  *
48  * @param dbg       firm node dbg
49  * @param block     the block the new node should belong to
50  * @param op1       first operator
51  * @param op2       second operator
52  * @param mode      node mode
53  * @return the created ia32 Add node
54  */
55 ir_node *gen_Add(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
56   return new_rd_ia32_Add(dbg, current_ir_graph, block, op1, op2, mode);
57 }
58
59
60
61 /**
62  * Creates an ia32 Mul with immediate.
63  *
64  * @param dbg       firm dbg
65  * @param block     the block the new node should belong to
66  * @param expr_op   operator
67  * @param mode      node mode
68  * @return the created ia23 Mul_i node
69  */
70 ir_node *gen_imm_Mul(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
71   return new_rd_ia32_Mul_i(dbg, current_ir_graph, block, expr_op, mode);
72 }
73
74 /**
75  * Creates an ia32 Mul.
76  *
77  * @param dbg       firm node dbg
78  * @param block     the block the new node should belong to
79  * @param op1       first operator
80  * @param op2       second operator
81  * @param mode      node mode
82  * @return the created ia32 Mul node
83  */
84 ir_node *gen_Mul(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
85   return new_rd_ia32_Mul(dbg, current_ir_graph, block, op1, op2, mode);
86 }
87
88
89
90 /**
91  * Creates an ia32 And with immediate.
92  *
93  * @param dbg       firm dbg
94  * @param block     the block the new node should belong to
95  * @param expr_op   operator
96  * @param mode      node mode
97  * @return the created ia23 And_i node
98  */
99 ir_node *gen_imm_And(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
100   return new_rd_ia32_And_i(dbg, current_ir_graph, block, expr_op, mode);
101 }
102
103 /**
104  * Creates an ia32 And.
105  *
106  * @param dbg       firm node dbg
107  * @param block     the block the new node should belong to
108  * @param op1       first operator
109  * @param op2       second operator
110  * @param mode      node mode
111  * @return the created ia32 And node
112  */
113 ir_node *gen_And(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
114   return new_rd_ia32_And(dbg, current_ir_graph, block, op1, op2, mode);
115 }
116
117
118
119 /**
120  * Creates an ia32 Or with immediate.
121  *
122  * @param dbg       firm dbg
123  * @param block     the block the new node should belong to
124  * @param expr_op   operator
125  * @param mode      node mode
126  * @return the created ia23 Or_i node
127  */
128 ir_node *gen_imm_Or(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
129   return new_rd_ia32_Or_i(dbg, current_ir_graph, block, expr_op, mode);
130 }
131
132 /**
133  * Creates an ia32 Or.
134  *
135  * @param dbg       firm node dbg
136  * @param block     the block the new node should belong to
137  * @param op1       first operator
138  * @param op2       second operator
139  * @param mode      node mode
140  * @return the created ia32 Or node
141  */
142 ir_node *gen_Or(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
143   return new_rd_ia32_Or(dbg, current_ir_graph, block, op1, op2, mode);
144 }
145
146
147
148 /**
149  * Creates an ia32 Eor with immediate.
150  *
151  * @param dbg       firm dbg
152  * @param block     the block the new node should belong to
153  * @param expr_op   operator
154  * @param mode      node mode
155  * @return the created ia23 Eor_i node
156  */
157 ir_node *gen_imm_Eor(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
158   return new_rd_ia32_Eor_i(dbg, current_ir_graph, block, expr_op, mode);
159 }
160
161 /**
162  * Creates an ia32 Eor.
163  *
164  * @param dbg       firm node dbg
165  * @param block     the block the new node should belong to
166  * @param op1       first operator
167  * @param op2       second operator
168  * @param mode      node mode
169  * @return the created ia32 Eor node
170  */
171 ir_node *gen_Eor(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
172   return new_rd_ia32_Eor(dbg, current_ir_graph, block, op1, op2, mode);
173 }
174
175
176
177 /**
178  * Creates an ia32 Cmp with immediate.
179  *
180  * @param dbg       firm dbg
181  * @param block     the block the new node should belong to
182  * @param expr_op   operator
183  * @param mode      node mode
184  * @return the created ia23 Cmp_i node
185  */
186 ir_node *gen_imm_Cmp(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
187   return new_rd_ia32_Cmp_i(dbg, current_ir_graph, block, expr_op, mode);
188 }
189
190 /**
191  * Creates an ia32 Cmp.
192  *
193  * @param dbg       firm node dbg
194  * @param block     the block the new node should belong to
195  * @param op1       first operator
196  * @param op2       second operator
197  * @param mode      node mode
198  * @return the created ia32 Cmp node
199  */
200 ir_node *gen_Cmp(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
201   return new_rd_ia32_Cmp(dbg, current_ir_graph, block, op1, op2, mode);
202 }
203
204
205
206 /**
207  * Creates an ia32 Sub with immediate.
208  *
209  * @param dbg       firm dbg
210  * @param block     the block the new node should belong to
211  * @param expr_op   operator
212  * @param mode      node mode
213  * @return the created ia23 Sub_i node
214  */
215 ir_node *gen_imm_Sub(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
216   return new_rd_ia32_Sub_i(dbg, current_ir_graph, block, expr_op, mode);
217 }
218
219 /**
220  * Creates an ia32 Sub.
221  *
222  * @param dbg       firm node dbg
223  * @param block     the block the new node should belong to
224  * @param op1       first operator
225  * @param op2       second operator
226  * @param mode      node mode
227  * @return the created ia32 Sub node
228  */
229 ir_node *gen_Sub(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
230   ir_node *sub = NULL;
231
232   /* transform "Const -- Sub -- Expr" into "Minus -- (Expr -- Sub -- Const)" */
233   if (is_Imm(op1) && !is_Imm(op2)) {
234     imm_attr_t *attr_imm = (imm_attr_t *)get_irn_generic_attr(op1);
235
236     DBG((mod, LEVEL_1, "optimizing c-e into -(e-c) ... "));
237
238     /* make sure that Imm is a Const and no SymConst */
239     if (attr_imm->tp == imm_Const) {
240       sub = gen_imm_Sub(dbg, block, op2, mode);
241
242       /* make the Const an attribute */
243       asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(sub);
244       attr->tv = attr_imm->data.tv;
245     }
246     else
247       goto gen_normal_sub;
248
249     /* negate result */
250     sub = new_rd_ia32_Minus(dbg, current_ir_graph, block, sub, mode);
251   }
252   else {
253 gen_normal_sub:
254     sub = new_rd_ia32_Sub(dbg, current_ir_graph, block, op1, op2, mode);
255   }
256
257   return sub;
258 }
259
260
261
262 /**
263  * Creates an ia32 Mod with immediate.
264  *
265  * @param dbg       firm dbg
266  * @param block     the block the new node should belong to
267  * @param expr_op   operator
268  * @param mode      node mode
269  * @return the created ia23 Mod_i node
270  */
271 ir_node *gen_imm_Mod(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
272   return new_rd_ia32_Mod_i(dbg, current_ir_graph, block, expr_op, mode);
273 }
274
275 /**
276  * Creates an ia32 Mod.
277  *
278  * @param dbg       firm node dbg
279  * @param block     the block the new node should belong to
280  * @param op1       first operator
281  * @param op2       second operator
282  * @param mode      node mode
283  * @return the created ia32 Mod node
284  */
285 ir_node *gen_Mod(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
286   return new_rd_ia32_Mod(dbg, current_ir_graph, block, op1, op2, mode);
287 }
288
289
290
291 /**
292  * Creates an ia32 Shl with immediate.
293  *
294  * @param dbg       firm dbg
295  * @param block     the block the new node should belong to
296  * @param expr_op   operator
297  * @param mode      node mode
298  * @return the created ia23 Shl_i node
299  */
300 ir_node *gen_imm_Shl(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
301   return new_rd_ia32_Shl_i(dbg, current_ir_graph, block, expr_op, mode);
302 }
303
304 /**
305  * Creates an ia32 Shl.
306  *
307  * @param dbg       firm node dbg
308  * @param block     the block the new node should belong to
309  * @param op1       first operator
310  * @param op2       second operator
311  * @param mode      node mode
312  * @return the created ia32 Shl node
313  */
314 ir_node *gen_Shl(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
315   return new_rd_ia32_Shl(dbg, current_ir_graph, block, op1, op2, mode);
316 }
317
318
319
320 /**
321  * Creates an ia32 Shr with immediate.
322  *
323  * @param dbg       firm dbg
324  * @param block     the block the new node should belong to
325  * @param expr_op   operator
326  * @param mode      node mode
327  * @return the created ia23 Shr_i node
328  */
329 ir_node *gen_imm_Shr(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
330   return new_rd_ia32_Shr_i(dbg, current_ir_graph, block, expr_op, mode);
331 }
332
333 /**
334  * Creates an ia32 Shr.
335  *
336  * @param dbg       firm node dbg
337  * @param block     the block the new node should belong to
338  * @param op1       first operator
339  * @param op2       second operator
340  * @param mode      node mode
341  * @return the created ia32 Shr node
342  */
343 ir_node *gen_Shr(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
344   return new_rd_ia32_Shr(dbg, current_ir_graph, block, op1, op2, mode);
345 }
346
347
348
349 /**
350  * Creates an ia32 Shrs with immediate.
351  *
352  * @param dbg       firm dbg
353  * @param block     the block the new node should belong to
354  * @param expr_op   operator
355  * @param mode      node mode
356  * @return the created ia23 Shrs_i node
357  */
358 ir_node *gen_imm_Shrs(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
359   return new_rd_ia32_Shrs_i(dbg, current_ir_graph, block, expr_op, mode);
360 }
361
362 /**
363  * Creates an ia32 Shrs.
364  *
365  * @param dbg       firm node dbg
366  * @param block     the block the new node should belong to
367  * @param op1       first operator
368  * @param op2       second operator
369  * @param mode      node mode
370  * @return the created ia32 Shrs node
371  */
372 ir_node *gen_Shrs(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
373   return new_rd_ia32_Shrs(dbg, current_ir_graph, block, op1, op2, mode);
374 }
375
376
377
378 /**
379  * Creates an ia32 Rot with immediate.
380  *
381  * @param dbg       firm dbg
382  * @param block     the block the new node should belong to
383  * @param expr_op   operator
384  * @param mode      node mode
385  * @return the created ia23 Rot_i node
386  */
387 ir_node *gen_imm_Rot(dbg_info *dbg, ir_node *block, ir_node *expr_op, ir_mode *mode) {
388   return new_rd_ia32_Rot_i(dbg, current_ir_graph, block, expr_op, mode);
389 }
390
391 /**
392  * Creates an ia32 Rot.
393  *
394  * @param dbg       firm node dbg
395  * @param block     the block the new node should belong to
396  * @param op1       first operator
397  * @param op2       second operator
398  * @param mode      node mode
399  * @return the created ia32 Rot node
400  */
401 ir_node *gen_Rot(firm_dbg_module_t *mod, dbg_info *dbg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) {
402   return new_rd_ia32_Rot(dbg, current_ir_graph, block, op1, op2, mode);
403 }
404
405
406
407 /**
408  * Transforms a Minus node.
409  *
410  * @param mod     the debug module
411  * @param block   the block the new node should belong to
412  * @param node    the ir Minus node
413  * @param op      operator
414  * @param mode    node mode
415  * @return the created ia32 Minus node
416  */
417 ir_node *gen_Minus(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
418   if (is_ia32_Minus(op)) {
419     DBG((mod, LEVEL_1, "optimizing --(e) to e ..."));
420     return get_irn_n(op, 0);
421   }
422   else
423     return new_rd_ia32_Minus(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
424 }
425
426
427
428 /**
429  * Transforms a Conv node.
430  *
431  * @param mod     the debug module
432  * @param block   the block the new node should belong to
433  * @param node    the ir Conv node
434  * @param op      operator
435  * @param mode    node mode
436  * @return the created ia32 Conv node
437  */
438 ir_node *gen_Conv(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op, ir_mode *mode) {
439   return new_rd_ia32_Conv(get_irn_dbg_info(node), current_ir_graph, block, op, mode);
440 }
441
442
443
444 /**
445  * Transforms commutative operations (op_Add, op_Mul, op_And, op_Or, op_Eor, op_Cmp)
446  * and non-commutative operations with com == 0 (op_Sub, op_Mod, op_Shl, op_Shr, op_Shrs, op_Rot)
447  *
448  * @param mod       the debug module
449  * @param block     the block node belongs to
450  * @param node      the node to transform
451  * @param op1       first operator
452  * @param op2       second operator
453  * @param mode      node mode
454  * @param com       flag if op is commutative
455  * @return the created assembler node
456  */
457 ir_node *gen_arith_Op(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_node *op1, ir_node *op2, ir_mode *mode, int com) {
458   dbg_info *dbg     = get_irn_dbg_info(node);
459   ir_node *imm_op   = NULL;
460   ir_node *expr_op  = NULL;
461   ir_node *asm_node = NULL;
462
463 #define GENOP(a)  case iro_##a: asm_node = gen_##a(mod, dbg, block, op1, op2, mode); break
464 #define GENOPI(a) case iro_##a: asm_node = gen_imm_##a(dbg, block, expr_op, mode); break
465
466   if (com)
467     imm_op  = get_immediate_op(op1, op2);
468   else
469     imm_op  = get_immediate_op(NULL, op2);
470
471   expr_op = get_expr_op(op1, op2);
472
473   /* TODO: Op(Imm, Imm) support */
474   if (is_Imm(op1) && is_Imm(op2)) {
475     DBG((mod, LEVEL_1, "found unexpected %s(Imm, Imm), creating binop ... ", get_irn_opname(node)));
476     imm_op = NULL;
477   }
478
479   DBG((mod, LEVEL_1, "(op1: %s -- op2: %s) ... ", get_irn_opname(op1), get_irn_opname(op2)));
480
481   if (imm_op) {
482     imm_attr_t *attr_imm = (imm_attr_t *)get_irn_generic_attr(imm_op);
483
484     DBG((mod, LEVEL_1, "%s with imm ... ", get_irn_opname(node)));
485
486     /* make sure that Imm is a Const and no SymConst */
487     if (attr_imm->tp == imm_Const) {
488       switch(get_irn_opcode(node)) {
489         GENOPI(Add);
490         GENOPI(Mul);
491         GENOPI(And);
492         GENOPI(Or);
493         GENOPI(Eor);
494         GENOPI(Cmp);
495
496         GENOPI(Sub);
497         GENOPI(Mod);
498         GENOPI(Shl);
499         GENOPI(Shr);
500         GENOPI(Shrs);
501         GENOPI(Rot);
502         default:
503           assert("binop_i: THIS SHOULD NOT HAPPEN");
504       }
505
506       /* make the Const an attribute */
507       asmop_attr *attr = (asmop_attr *)get_irn_generic_attr(asm_node);
508       attr->tv = attr_imm->data.tv;
509     } /* TODO: SymConst support */
510     else
511       goto do_binop;
512   }
513   else {
514 do_binop:
515     DBG((mod, LEVEL_1, "%s as binop ... ", get_irn_opname(node)));
516
517     switch(get_irn_opcode(node)) {
518       GENOP(Add);
519       GENOP(Mul);
520       GENOP(And);
521       GENOP(Or);
522       GENOP(Eor);
523       GENOP(Cmp);
524
525       GENOP(Sub);
526       GENOP(Mod);
527       GENOP(Shl);
528       GENOP(Shr);
529       GENOP(Shrs);
530       GENOP(Rot);
531       default:
532         assert("binop: THIS SHOULD NOT HAPPEN");
533     }
534   }
535
536   return asm_node;
537 }
538
539
540
541 /**
542  * Transforms a Load.
543  *
544  * @param mod     the debug module
545  * @param block   the block the new node should belong to
546  * @param node    the ir Load node
547  * @param mode    node mode
548  * @return the created ia32 Load node
549  */
550 ir_node *gen_Load(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
551   return new_rd_ia32_Load(get_irn_dbg_info(node), current_ir_graph, block, get_Load_mem(node), get_Load_ptr(node), mode);
552 }
553
554
555
556 /**
557  * Transforms a Store.
558  *
559  * @param mod     the debug module
560  * @param block   the block the new node should belong to
561  * @param node    the ir Store node
562  * @param mode    node mode
563  * @return the created ia32 Store node
564  */
565 ir_node *gen_Store(firm_dbg_module_t *mod, ir_node *block, ir_node *node, ir_mode *mode) {
566   return new_rd_ia32_Store(get_irn_dbg_info(node), current_ir_graph, block, get_Store_mem(node), get_Store_ptr(node), get_Store_value(node), mode);
567 }
568
569
570
571 /**
572  * Transforms the given firm node (and maybe some other related nodes)
573  * into one or more assembler nodes.
574  *
575  * @param node    the firm node
576  * @param env     the debug module
577  */
578 void transform_node(ir_node *node, void *env) {
579   firm_dbg_module_t *mod = (firm_dbg_module_t *)env;
580   opcode  code           = get_irn_opcode(node);
581   ir_node *asm_node      = NULL;
582   ir_node *block;
583   ir_mode *mode;
584
585   if (is_Block(node))
586     return;
587
588   block = get_nodes_block(node);
589   mode  = get_irn_mode(node);
590
591 #define BINOP_COM(a)   case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 1); break
592 #define BINOP_NCOM(a)  case iro_##a: asm_node = gen_arith_Op(mod, block, node, get_irn_n(node, 0), get_irn_n(node, 1), mode, 0); break
593 #define UNOP(a)        case iro_##a: asm_node = gen_##a(mod, block, node, get_irn_n(node, 0), mode); break
594 #define GEN(a)         case iro_##a: asm_node = gen_##a(mod, block, node, mode); break
595 #define IGN(a)         case iro_##a: break
596
597   DBG((mod, LEVEL_1, "transforming node %s (%ld) ... ", get_irn_opname(node), get_irn_node_nr(node)));
598
599   switch (code) {
600     BINOP_COM(Add);
601     BINOP_COM(Mul);
602     BINOP_COM(And);
603     BINOP_COM(Or);
604     BINOP_COM(Eor);
605     BINOP_COM(Cmp);
606
607     BINOP_NCOM(Sub);
608     BINOP_NCOM(Mod);
609     BINOP_NCOM(Shl);
610     BINOP_NCOM(Shr);
611     BINOP_NCOM(Shrs);
612     BINOP_NCOM(Rot);
613 //    BINOP_ARITH_NCOM(DivMod);
614
615     UNOP(Minus);
616     UNOP(Conv);
617     GEN(Load);
618     GEN(Store);
619   }
620
621   if (asm_node) {
622     exchange(node, asm_node);
623     DBG((mod, LEVEL_1, "created node %u\n", get_irn_node_nr(asm_node)));
624   }
625   else {
626     DBG((mod, LEVEL_1, "ignored\n"));
627   }
628 }