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