3816942364161f3d5fbeeedc03fa0a6b15d19637
[libfirm] / ir / be / ia32 / ia32_emitter.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <limits.h>
6
7 #include "tv.h"
8 #include "iredges.h"
9 #include "debug.h"
10 #include "irgwalk.h"
11 #include "irprintf.h"
12 #include "irop_t.h"
13 #include "irargs_t.h"
14
15 #include "../besched.h"
16
17 #include "ia32_emitter.h"
18 #include "gen_ia32_emitter.h"
19 #include "ia32_nodes_attr.h"
20 #include "ia32_new_nodes.h"
21 #include "ia32_map_regs.h"
22
23 #define SNPRINTF_BUF_LEN 128
24
25 static const arch_env_t *arch_env = NULL;
26
27
28 /*************************************************************
29  *             _       _    __   _          _
30  *            (_)     | |  / _| | |        | |
31  *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
32  * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
33  * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
34  * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
35  * | |                                       | |
36  * |_|                                       |_|
37  *************************************************************/
38
39 /**
40  * Return node's tarval as string.
41  */
42 const char *node_const_to_str(ir_node *n) {
43         char   *buf;
44         tarval *tv = get_ia32_Immop_tarval(n);
45
46         if (tv) {
47                 buf = malloc(SNPRINTF_BUF_LEN);
48                 tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
49                 return buf;
50         }
51         else if (get_ia32_old_ir(n)) {
52                 return get_sc_name(get_ia32_old_ir(n));
53         }
54         else
55                 return "0";
56 }
57
58 /**
59  * Returns node's offset as string.
60  */
61 char *node_offset_to_str(ir_node *n) {
62         char   *buf;
63         tarval *tv = get_ia32_am_offs(n);
64
65         if (tv) {
66                 buf = malloc(SNPRINTF_BUF_LEN);
67                 tarval_snprintf(buf, SNPRINTF_BUF_LEN, tv);
68                 return buf;
69         }
70         else
71                 return "";
72 }
73
74 /* We always pass the ir_node which is a pointer. */
75 static int ia32_get_arg_type(const lc_arg_occ_t *occ) {
76         return lc_arg_type_ptr;
77 }
78
79
80 /**
81  * Returns the register at in position pos.
82  */
83 static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
84         ir_node                *op;
85         const arch_register_t  *reg = NULL;
86
87         assert(get_irn_arity(irn) > pos && "Invalid IN position");
88
89         /* The out register of the operator at position pos is the
90            in register we need. */
91         op = get_irn_n(irn, pos);
92
93         reg = arch_get_irn_register(arch_env, op);
94
95         assert(reg && "no in register found");
96         return reg;
97 }
98
99 /**
100  * Returns the register at out position pos.
101  */
102 static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
103         ir_node                *proj;
104         const arch_register_t  *reg = NULL;
105
106         assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
107
108         /* 1st case: irn is not of mode_T, so it has only                 */
109         /*           one OUT register -> good                             */
110         /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
111         /*           Proj with the corresponding projnum for the register */
112
113         if (get_irn_mode(irn) != mode_T) {
114                 reg = arch_get_irn_register(arch_env, irn);
115         }
116         else if (is_ia32_irn(irn)) {
117                 reg = get_ia32_out_reg(irn, pos);
118         }
119         else {
120                 const ir_edge_t *edge;
121
122                 foreach_out_edge(irn, edge) {
123                         proj = get_edge_src_irn(edge);
124                         assert(is_Proj(proj) && "non-Proj from mode_T node");
125                         if (get_Proj_proj(proj) == pos) {
126                                 reg = arch_get_irn_register(arch_env, proj);
127                                 break;
128                         }
129                 }
130         }
131
132         assert(reg && "no out register found");
133         return reg;
134 }
135
136 /**
137  * Returns the number of the in register at position pos.
138  */
139 int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) {
140         const arch_register_t *reg;
141         ir_node               *op;
142
143         if (in_out == 1) {
144                 reg = get_in_reg(irn, pos);
145         }
146         else {
147                 reg = get_out_reg(irn, pos);
148         }
149
150         return arch_register_get_index(reg);
151 }
152
153 /**
154  * Returns the name of the in register at position pos.
155  */
156 const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) {
157         const arch_register_t *reg;
158         ir_node               *op;
159
160         if (in_out == 1) {
161                 reg = get_in_reg(irn, pos);
162         }
163         else {
164                 reg = get_out_reg(irn, pos);
165         }
166
167         return arch_register_get_name(reg);
168 }
169
170 /**
171  * Get the register name for a node.
172  */
173 static int ia32_get_reg_name(lc_appendable_t *app,
174     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
175 {
176         const char *buf;
177         ir_node    *X  = arg->v_ptr;
178         int         nr = occ->width - 1;
179
180         if (!X)
181                 return lc_arg_append(app, occ, "(null)", 6);
182
183         if (occ->conversion == 'S') {
184                 buf = get_ia32_reg_name(X, nr, 1);
185         }
186         else { /* 'D' */
187                 buf = get_ia32_reg_name(X, nr, 0);
188         }
189
190         lc_appendable_chadd(app, '%');
191         return lc_arg_append(app, occ, buf, strlen(buf));
192 }
193
194 /**
195  * Returns the tarval or offset of an ia32 as a string.
196  */
197 static int ia32_const_to_str(lc_appendable_t *app,
198     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
199 {
200         const char *buf;
201         ir_node    *X = arg->v_ptr;
202
203         if (!X)
204                 return lc_arg_append(app, occ, "(null)", 6);
205
206         if (occ->conversion == 'C') {
207                 buf = node_const_to_str(X);
208         }
209         else { /* 'O' */
210                 buf = node_offset_to_str(X);
211         }
212
213         return lc_arg_append(app, occ, buf, strlen(buf));
214 }
215
216 /**
217  * Determines the SSE suffix depending on the mode.
218  */
219 static int ia32_get_mode_suffix(lc_appendable_t *app,
220     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
221 {
222         ir_node *X = arg->v_ptr;
223
224         if (!X)
225                 return lc_arg_append(app, occ, "(null)", 6);
226
227         if (get_mode_size_bits(get_irn_mode(X)) == 32)
228                 return lc_appendable_chadd(app, 's');
229         else
230                 return lc_appendable_chadd(app, 'd');
231 }
232
233 /**
234  * Return the ia32 printf arg environment.
235  * We use the firm environment with some additional handlers.
236  */
237 const lc_arg_env_t *ia32_get_arg_env(void) {
238         static lc_arg_env_t *env = NULL;
239
240         static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
241         static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
242         static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
243
244         if(env == NULL) {
245                 /* extend the firm printer */
246                 env = firm_get_arg_env();
247                         //lc_arg_new_env();
248
249                 lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
250                 lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
251                 lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
252                 lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
253                 lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
254         }
255
256         return env;
257 }
258
259 /**
260  * For 2-address code we need to make sure the first src reg is equal to dest reg.
261  */
262 void equalize_dest_src(FILE *F, ir_node *n) {
263         if (get_ia32_reg_nr(n, 0, 1) != get_ia32_reg_nr(n, 0, 0)) {
264                 if (get_irn_arity(n) > 1 && get_ia32_reg_nr(n, 1, 1) == get_ia32_reg_nr(n, 0, 0)) {
265                         if (! is_op_commutative(get_irn_op(n))) {
266                                 /* we only need to exchange for non-commutative ops */
267                                 lc_efprintf(ia32_get_arg_env(), F, "\txchg %1S, %2S\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
268                         }
269                 }
270                 else {
271                         lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1S, %1D\t\t\t/* src -> dest for 2 address code */\n", n, n);
272                 }
273         }
274 }
275
276 /*
277  * Add a number to a prefix. This number will not be used a second time.
278  */
279 char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
280         static unsigned long id = 0;
281         snprintf(buf, buflen, "%s%lu", prefix, ++id);
282         return buf;
283 }
284
285
286 /*************************************************
287  *                 _ _                         _
288  *                (_) |                       | |
289  *   ___ _ __ ___  _| |_    ___ ___  _ __   __| |
290  *  / _ \ '_ ` _ \| | __|  / __/ _ \| '_ \ / _` |
291  * |  __/ | | | | | | |_  | (_| (_) | | | | (_| |
292  *  \___|_| |_| |_|_|\__|  \___\___/|_| |_|\__,_|
293  *
294  *************************************************/
295
296 /*
297  * coding of conditions
298  */
299 struct cmp2conditon_t {
300         const char *name;
301         pn_Cmp      num;
302 };
303
304 /*
305  * positive conditions for signed compares
306  */
307 static const struct cmp2conditon_t cmp2condition_s[] = {
308   { NULL,              pn_Cmp_False },  /* always false */
309   { "e",               pn_Cmp_Eq },     /* == */
310   { "l",               pn_Cmp_Lt },     /* < */
311   { "le",              pn_Cmp_Le },     /* <= */
312   { "g",               pn_Cmp_Gt },     /* > */
313   { "ge",              pn_Cmp_Ge },     /* >= */
314   { "ne",              pn_Cmp_Lg },     /* != */
315   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
316   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
317   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
318   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
319   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
320   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
321   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
322   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
323   { NULL,              pn_Cmp_True },   /* always true */
324 };
325
326 /*
327  * positive conditions for unsigned compares
328  */
329 static const struct cmp2conditon_t cmp2condition_u[] = {
330   { NULL,              pn_Cmp_False },  /* always false */
331   { "e",               pn_Cmp_Eq },     /* == */
332   { "b",               pn_Cmp_Lt },     /* < */
333   { "be",              pn_Cmp_Le },     /* <= */
334   { "a",               pn_Cmp_Gt },     /* > */
335   { "ae",              pn_Cmp_Ge },     /* >= */
336   { "ne",              pn_Cmp_Lg },     /* != */
337   { "ordered",         pn_Cmp_Leg },    /* Floating point: ordered */
338   { "unordered",       pn_Cmp_Uo },     /* FLoting point: unordered */
339   { "unordered or ==", pn_Cmp_Ue },     /* Floating point: unordered or == */
340   { "unordered or <",  pn_Cmp_Ul },     /* Floating point: unordered or < */
341   { "unordered or <=", pn_Cmp_Ule },    /* Floating point: unordered or <= */
342   { "unordered or >",  pn_Cmp_Ug },     /* Floating point: unordered or > */
343   { "unordered or >=", pn_Cmp_Uge },    /* Floating point: unordered or >= */
344   { "unordered or !=", pn_Cmp_Ne },     /* Floating point: unordered or != */
345   { NULL,              pn_Cmp_True },   /* always true */
346 };
347
348 /*
349  * returns the condition code
350  */
351 static const char *get_cmp_suffix(int cmp_code, int unsigned_cmp)
352 {
353         assert(cmp2condition_s[cmp_code].num == cmp_code);
354         assert(cmp2condition_u[cmp_code].num == cmp_code);
355
356         return unsigned_cmp ? cmp2condition_u[cmp_code & 7].name : cmp2condition_s[cmp_code & 7].name;
357 }
358
359 /**
360  * Returns the target label for a control flow node.
361  */
362 static char *get_cfop_target(const ir_node *irn, char *buf) {
363         ir_node *bl = get_irn_link(irn);
364
365         snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
366         return buf;
367 }
368
369 /**
370  * Emits the jump sequence for a conditional jump (cmp + jmp_true + jmp_false)
371  */
372 static void finish_CondJmp(FILE *F, ir_node *irn) {
373         const ir_node   *proj;
374         const ir_edge_t *edge;
375         char buf[SNPRINTF_BUF_LEN];
376
377         edge = get_irn_out_edge_first(irn);
378         proj = get_edge_src_irn(edge);
379         assert(is_Proj(proj) && "CondJmp with a non-Proj");
380
381         if (get_Proj_proj(proj) == 1) {
382                 fprintf(F, "\tj%s %s\t\t\t/* cmp(a, b) == TRUE */\n",
383                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
384                                         get_cfop_target(proj, buf));
385         }
386         else  {
387                 fprintf(F, "\tjn%s %s\t\t\t/* cmp(a, b) == FALSE */\n",
388                                         get_cmp_suffix(get_ia32_pncode(irn), !mode_is_signed(get_irn_mode(get_irn_n(irn, 0)))),
389                                         get_cfop_target(proj, buf));
390         }
391
392         edge = get_irn_out_edge_next(irn, edge);
393         if (edge) {
394                 proj = get_edge_src_irn(edge);
395                 assert(is_Proj(proj) && "CondJmp with a non-Proj");
396                 fprintf(F, "\tjmp %s\t\t\t/* otherwise */\n", get_cfop_target(proj, buf));
397         }
398 }
399
400 /**
401  * Emits code for conditional jump with two variables.
402  */
403 static void emit_ia32_CondJmp(ir_node *irn, emit_env_t *env) {
404         FILE *F = env->out;
405
406         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %2S, %1S\t\t\t/* CondJmp(%+F, %+F) */\n", irn, irn,
407                                                                                                                                         get_irn_n(irn, 0), get_irn_n(irn, 1));
408         finish_CondJmp(F, irn);
409 }
410
411 /**
412  * Emits code for conditional jump with immediate.
413  */
414 void emit_ia32_CondJmp_i(ir_node *irn, emit_env_t *env) {
415         FILE *F = env->out;
416
417         lc_efprintf(ia32_get_arg_env(), F, "\tcmp %C, %1S\t\t\t/* CondJmp_i(%+F) */\n", irn, irn, get_irn_n(irn, 0));
418         finish_CondJmp(F, irn);
419 }
420
421
422
423 /*********************************************************
424  *                 _ _       _
425  *                (_) |     (_)
426  *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
427  *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
428  * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
429  *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
430  *                         _/ |               | |
431  *                        |__/                |_|
432  *********************************************************/
433
434 /* jump table entry (target and corresponding number) */
435 typedef struct _branch_t {
436         ir_node *target;
437         int      value;
438 } branch_t;
439
440 /* jump table for switch generation */
441 typedef struct _jmp_tbl_t {
442         ir_node  *defProj;         /**< default target */
443         int       min_value;       /**< smallest switch case */
444         int       max_value;       /**< largest switch case */
445         int       num_branches;    /**< number of jumps */
446         char     *label;           /**< label of the jump table */
447         branch_t *branches;        /**< jump array */
448 } jmp_tbl_t;
449
450 /**
451  * Compare two variables of type branch_t. Used to sort all switch cases
452  */
453 static int ia32_cmp_branch_t(const void *a, const void *b) {
454         branch_t *b1 = (branch_t *)a;
455         branch_t *b2 = (branch_t *)b;
456
457         if (b1->value <= b2->value)
458                 return -1;
459         else
460                 return 1;
461 }
462
463 /**
464  * Emits code for a SwitchJmp (creates a jump table if
465  * possible otherwise a cmp-jmp cascade). Port from
466  * cggg ia32 backend
467  */
468 void emit_ia32_SwitchJmp(const ir_node *irn, emit_env_t *emit_env) {
469         unsigned long       interval;
470         char                buf[SNPRINTF_BUF_LEN];
471         int                 last_value, i, pn, do_jmp_tbl = 1;
472         jmp_tbl_t           tbl;
473         ir_node            *proj;
474         const ir_edge_t    *edge;
475         const lc_arg_env_t *env = ia32_get_arg_env();
476         FILE               *F   = emit_env->out;
477
478         /* fill the table structure */
479         tbl.label        = malloc(SNPRINTF_BUF_LEN);
480         tbl.label        = get_unique_label(tbl.label, SNPRINTF_BUF_LEN, "JMPTBL_");
481         tbl.defProj      = NULL;
482         tbl.num_branches = get_irn_n_edges(irn);
483         tbl.branches     = calloc(tbl.num_branches, sizeof(tbl.branches[0]));
484         tbl.min_value    = INT_MAX;
485         tbl.max_value    = INT_MIN;
486
487         i = 0;
488         /* go over all proj's and collect them */
489         foreach_out_edge(irn, edge) {
490                 proj = get_edge_src_irn(edge);
491                 assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
492
493                 pn = get_Proj_proj(proj);
494
495                 /* create branch entry */
496                 tbl.branches[i].target = proj;
497                 tbl.branches[i].value  = pn;
498
499                 tbl.min_value = pn < tbl.min_value ? pn : tbl.min_value;
500                 tbl.max_value = pn > tbl.max_value ? pn : tbl.max_value;
501
502                 /* check for default proj */
503                 if (pn == get_ia32_pncode(irn)) {
504                         assert(tbl.defProj == NULL && "found two defProjs at SwitchJmp");
505                         tbl.defProj = proj;
506                 }
507
508                 i++;
509         }
510
511         /* sort the branches by their number */
512         qsort(tbl.branches, tbl.num_branches, sizeof(tbl.branches[0]), ia32_cmp_branch_t);
513
514         /* two-complement's magic make this work without overflow */
515         interval = tbl.max_value - tbl.min_value;
516
517         /* check value interval */
518         if (interval > 16 * 1024) {
519                 do_jmp_tbl = 0;
520         }
521
522         /* check ratio of value interval to number of branches */
523         if ((float)(interval + 1) / (float)tbl.num_branches > 8.0) {
524                 do_jmp_tbl = 0;
525         }
526
527         if (do_jmp_tbl) {
528                 /* emit the table */
529                 if (tbl.min_value != 0) {
530                         fprintf(F, "\tcmpl %lu, -%d", interval, tbl.min_value);
531                         lc_efprintf(env, F, "(%1S)\t\t/* first switch value is not 0 */\n", irn);
532                 }
533                 else {
534                         fprintf(F, "\tcmpl %lu, ", interval);
535                         lc_efprintf(env, F, "%1S\t\t\t/* compare for switch */\n", irn);
536                 }
537
538                 fprintf(F, "\tja %s\t\t\t/* default jump if out of range  */\n", get_cfop_target(tbl.defProj, buf));
539
540                 if (tbl.num_branches > 1) {
541                         /* create table */
542
543                         //fprintf(F, "\tjmp *%s", tbl.label);
544                         lc_efprintf(env, F, "\tjmp *%s(,%1S,4)\t\t/* get jump table entry as target */\n", tbl.label, irn);
545
546                         fprintf(F, "\t.section\t.rodata\t\t/* start jump table */\n");
547                         fprintf(F, "\t.align 4\n");
548
549                         fprintf(F, "%s:\n", tbl.label);
550                         fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[0].target, buf), tbl.branches[0].value);
551
552                         last_value = tbl.branches[0].value;
553                         for (i = 1; i < tbl.num_branches; ++i) {
554                                 while (++last_value < tbl.branches[i].value) {
555                                         fprintf(F, "\t.long %s\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
556                                 }
557                                 fprintf(F, "\t.long %s\t\t\t/* case %d */\n", get_cfop_target(tbl.branches[i].target, buf), last_value);
558                         }
559
560                         fprintf(F, "\t.text\t\t\t\t/* end of jump table */\n");
561                 }
562                 else {
563                         /* one jump is enough */
564                         fprintf(F, "\tjmp %s\t\t/* only one case given */\n", get_cfop_target(tbl.branches[0].target, buf));
565                 }
566         }
567         else { // no jump table
568                 for (i = 0; i < tbl.num_branches; ++i) {
569                         fprintf(F, "\tcmpl %d, ", tbl.branches[i].value);
570                         lc_efprintf(env, F, "%1S", irn);
571                         fprintf(F, "\t\t\t/* case %d */\n", tbl.branches[i].value);
572                         fprintf(F, "\tje %s\n", get_cfop_target(tbl.branches[i].target, buf));
573                 }
574
575                 fprintf(F, "\tjmp %s\t\t\t/* default case */\n", get_cfop_target(tbl.defProj, buf));
576         }
577
578         if (tbl.label)
579                 free(tbl.label);
580         if (tbl.branches)
581                 free(tbl.branches);
582 }
583
584 /**
585  * Emits code for a unconditional jump.
586  */
587 void emit_Jmp(ir_node *irn, emit_env_t *env) {
588         FILE *F = env->out;
589
590         char buf[SNPRINTF_BUF_LEN];
591         ir_fprintf(F, "\tjmp %s\t\t\t/* Jmp(%+F) */\n", get_cfop_target(irn, buf), get_irn_link(irn));
592 }
593
594
595
596 /****************************
597  *                  _
598  *                 (_)
599  *  _ __  _ __ ___  _  ___
600  * | '_ \| '__/ _ \| |/ __|
601  * | |_) | | | (_) | |\__ \
602  * | .__/|_|  \___/| ||___/
603  * | |            _/ |
604  * |_|           |__/
605  ****************************/
606
607 /**
608  * Emits code for a proj -> node
609  */
610 void emit_Proj(ir_node *irn, emit_env_t *env) {
611         ir_node *pred = get_Proj_pred(irn);
612
613         if (get_irn_opcode(pred) == iro_Start) {
614                 switch(get_Proj_proj(irn)) {
615                         case pn_Start_X_initial_exec:
616                                 emit_Jmp(irn, env);
617                                 break;
618                         default:
619                                 break;
620                 }
621         }
622 }
623
624
625
626 /***********************************************************************************
627  *                  _          __                                             _
628  *                 (_)        / _|                                           | |
629  *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
630  * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
631  * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
632  * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
633  *
634  ***********************************************************************************/
635
636 /**
637  * Emits code for a node.
638  */
639 void ia32_emit_node(ir_node *irn, void *env) {
640         emit_env_t *emit_env   = env;
641         firm_dbg_module_t *mod = emit_env->mod;
642         FILE              *F   = emit_env->out;
643
644         DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
645
646 #define IA32_EMIT(a) if (is_ia32_##a(irn))               { emit_ia32_##a(irn, emit_env); return; }
647 #define EMIT(a)      if (get_irn_opcode(irn) == iro_##a) { emit_##a(irn, emit_env); return; }
648
649         /* generated int emitter functions */
650         IA32_EMIT(Copy);
651         IA32_EMIT(Perm);
652
653         IA32_EMIT(Const);
654
655         IA32_EMIT(Add);
656         IA32_EMIT(Add_i);
657         IA32_EMIT(Sub);
658         IA32_EMIT(Sub_i);
659         IA32_EMIT(Minus);
660         IA32_EMIT(Inc);
661         IA32_EMIT(Dec);
662
663         IA32_EMIT(Max);
664         IA32_EMIT(Min);
665
666         IA32_EMIT(And);
667         IA32_EMIT(And_i);
668         IA32_EMIT(Or);
669         IA32_EMIT(Or_i);
670         IA32_EMIT(Eor);
671         IA32_EMIT(Eor_i);
672         IA32_EMIT(Not);
673
674         IA32_EMIT(Shl);
675         IA32_EMIT(Shl_i);
676         IA32_EMIT(Shr);
677         IA32_EMIT(Shr_i);
678         IA32_EMIT(Shrs);
679         IA32_EMIT(Shrs_i);
680         IA32_EMIT(RotL);
681         IA32_EMIT(RotL_i);
682         IA32_EMIT(RotR);
683
684         IA32_EMIT(Lea);
685         IA32_EMIT(Lea_i);
686
687         IA32_EMIT(Mul);
688         IA32_EMIT(Mul_i);
689
690         IA32_EMIT(Cltd);
691         IA32_EMIT(DivMod);
692
693         IA32_EMIT(Store);
694         IA32_EMIT(Load);
695
696         /* generated floating point emitter */
697         IA32_EMIT(fConst);
698
699         IA32_EMIT(fAdd);
700         IA32_EMIT(fSub);
701         IA32_EMIT(fMinus);
702
703         IA32_EMIT(fMul);
704         IA32_EMIT(fDiv);
705
706         IA32_EMIT(fMin);
707         IA32_EMIT(fMax);
708
709         IA32_EMIT(fLoad);
710         IA32_EMIT(fStore);
711
712         /* other emitter functions */
713         IA32_EMIT(CondJmp);
714         IA32_EMIT(CondJmp_i);
715         IA32_EMIT(SwitchJmp);
716
717         EMIT(Jmp);
718         EMIT(Proj);
719
720         ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
721 }
722
723 /**
724  * Walks over the nodes in a block connected by scheduling edges
725  * and emits code for each node.
726  */
727 void ia32_gen_block(ir_node *block, void *env) {
728         ir_node *irn;
729
730         if (! is_Block(block))
731                 return;
732
733         fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
734         sched_foreach(block, irn) {
735                 ia32_emit_node(irn, env);
736         }
737 }
738
739
740 /**
741  * Emits code for function start.
742  */
743 void ia32_emit_start(FILE *F, ir_graph *irg) {
744         const char *irg_name = get_entity_name(get_irg_entity(irg));
745
746         fprintf(F, "\t.text\n");
747         fprintf(F, ".globl %s\n", irg_name);
748         fprintf(F, "\t.type\t%s, @function\n", irg_name);
749         fprintf(F, "%s:\n", irg_name);
750 }
751
752 /**
753  * Emits code for function end
754  */
755 void ia32_emit_end(FILE *F, ir_graph *irg) {
756         const char *irg_name = get_entity_name(get_irg_entity(irg));
757
758         fprintf(F, "\tret\n");
759         fprintf(F, "\t.size\t%s, .-%s\n\n", irg_name, irg_name);
760 }
761
762 /**
763  * Sets labels for control flow nodes (jump target)
764  * TODO: Jump optimization
765  */
766 void ia32_gen_labels(ir_node *block, void *env) {
767         ir_node *pred;
768         int n = get_Block_n_cfgpreds(block);
769
770         for (n--; n >= 0; n--) {
771                 pred = get_Block_cfgpred(block, n);
772                 set_irn_link(pred, block);
773         }
774 }
775
776 /**
777  * Main driver
778  */
779 void ia32_gen_routine(FILE *F, ir_graph *irg, const arch_env_t *env) {
780         emit_env_t emit_env;
781
782         emit_env.mod      = firm_dbg_register("ir.be.codegen.ia32");
783         emit_env.out      = F;
784         emit_env.arch_env = env;
785
786         arch_env = env;
787
788         ia32_emit_start(F, irg);
789         irg_block_walk_graph(irg, ia32_gen_labels, NULL, &emit_env);
790         irg_walk_blkwise_graph(irg, NULL, ia32_gen_block, &emit_env);
791         ia32_emit_end(F, irg);
792 }