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