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