changed printf format for size_t printing
[cparser] / driver / gen_firm_asm.c
1 /*
2  * Generate Firm assembler from Firm graphs.
3  *
4  * (C) 2005-2006  Michael Beck   beck@ipd.info.uni-karlsruhe.de
5  */
6 #include <stdio.h>
7 #include <string.h>
8 #include <libfirm/firm.h>
9 #include "firm_opt.h"
10
11 /**
12  * The variable context. Contains information
13  * about needed variables.
14  */
15 typedef struct var_ctx {
16   FILE *f;              /**< File handle for output. */
17   int max_arity;        /**< Maximum arity of in array. */
18   int need_tv;          /**< If set, need a tv variable. */
19   int need_unknown_X;   /**< If set, need an unknown_X variable. */
20   int need_unknown;     /**< If set, need an unknown variable. */
21 } var_ctx;
22
23 /**
24  * A context for backedge fixes.
25  */
26 typedef struct fix_ctx {
27   FILE *f;              /**< File handle for output. */
28   ir_node *start_block; /**< The start block of the current graph. */
29   int has_backedges;    /**< If set the current graph contains backedges. */
30 } fix_ctx;
31
32 /**
33  * Print the name of an IR-node as <prefix><op>_<idx><suffix>.
34  *
35  * @param f       the output file handle
36  * @param prefix  a prefix to print before the node name
37  * @param n       the IR-node
38  * @param suffix  a suffix to print after the node name
39  */
40 static void name(FILE *f, const char *prefix, ir_node *n, const char *suffix)
41 {
42   const char *op_name = get_op_name(get_irn_op(n));
43   unsigned    index   = get_irn_idx(n);
44   if(prefix == NULL)
45     prefix = "";
46   if(suffix == NULL)
47     suffix = "";
48
49   fprintf(f, "%s%s_%u%s", prefix, op_name, index, suffix);
50 }
51
52 /**
53  * Generate the header of the function.
54  *
55  * @param f    the output file handle
56  * @param irg  the graph
57  */
58 static void generate_header(FILE *f, ir_graph *irg)
59 {
60   int i, n;
61   ir_entity *ent = get_irg_entity(irg);
62   ir_type *tp = get_entity_type(ent);
63   const char *s = get_entity_name(ent);
64   fprintf(f,
65     "/**\n"
66     " * Generates the Firm code for\n"
67     " * ");
68
69   if (get_method_n_ress(tp) == 0)
70     fprintf(f, "void");
71   else
72     fprintf(f, get_type_name(get_method_res_type(tp, 0)));
73   fprintf(f, " %s(", s);
74   n = get_method_n_params(tp);
75   if (n == 0)
76     fprintf(f, get_method_variadicity(tp) == variadicity_variadic ? "" : "void");
77   else {
78     for (i = 0; i < n; ++i) {
79       if (i > 0)
80         fprintf(f, ", ");
81       fprintf(f, get_type_name(get_method_param_type(tp, i)));
82     }
83     if (get_method_variadicity(tp) == variadicity_variadic)
84       fprintf(f, ", ...");
85   }
86   fprintf(f, ")\n");
87
88   fprintf(f,
89     " *\n"
90     " * @param func  the entity for the generated graph\n"
91     " */\n"
92     "void gen_firm_%s(ir_entity *func)\n"
93     "{\n", s);
94   fprintf(f,
95     "  ir_graph *rem = current_ir_graph;\n");
96 }
97
98 /**
99  * Generate the function prolog.
100  *
101  * @param env   a variable context
102  * @param irg   the graph
103  */
104 static void generate_prolog(var_ctx *env, ir_graph *irg)
105 {
106   FILE *f = env->f;
107   (void) irg;
108   fprintf(f,
109     "  irg = new_ir_graph(func, 0);\n"
110     "  /* kill the current block */\n"
111     "  tmp = get_cur_block();\n"
112     "  mature_immBlock(tmp);\n"
113     "  set_Block_dead(tmp);\n");
114   if (env->need_unknown_X)
115     fprintf(f, "  unknownX = new_r_Unknown(irg, mode_X);\n");
116 }
117
118 /**
119  * Walker: Fix Block and Phi nodes containing backedges.
120  */
121 static void fix_block_and_phi(ir_node *n, void *ctx)
122 {
123   fix_ctx *env = ctx;
124   int i, arity;
125   FILE *f;
126
127   if (is_Block(n) || is_Phi(n)) {
128     arity = get_irn_arity(n);
129
130     /* ignore the start block */
131     if (n == env->start_block)
132       return;
133
134     f = env->f;
135     for (i = 0; i < arity; ++i) {
136       if (is_backedge(n, i)) {
137         name(f, "  set_irn_n(", n, NULL);
138         fprintf(f, ", %d, ", i);
139         name(f, NULL, get_irn_n(n, i), ");\n");
140       }
141     }
142   }
143 }
144
145 /**
146  * Generate the function epilog.
147  *
148  * @param env   the backedge fix context
149  * @param irg   the graph
150  */
151 static void generate_epilog(fix_ctx *env, ir_graph *irg)
152 {
153   FILE *f = env->f;
154   ir_node *end;
155   int i, n;
156
157   /* Fix backedges if there was any */
158   if (env->has_backedges) {
159     fprintf(f, "  /* fix Blocks and Phis */\n");
160     env->start_block = get_irg_start_block(irg);
161     irg_walk_graph(irg, NULL, fix_block_and_phi, env);
162   }
163
164   /* create the keep-alives */
165   end = get_irg_end(irg);
166   n = get_End_n_keepalives(end);
167   for (i = 0; i < n; ++i) {
168     name(f, "  add_End_keepalive(", end, NULL);
169     name(f, ", ", get_End_keepalive(end, i), ");\n");
170   }
171   name(f, "  mature_immBlock(", get_irg_end_block(irg), ");\n");
172   fprintf(f, "  current_ir_graph = rem;\n");
173   fprintf(f, "}  /* gen_firm_%s */\n\n", get_entity_name(get_irg_entity(irg)));
174 }
175
176 /**
177  * Walker: Create a variable declaration for a given node.
178  * The variable name is <op>_<node idx>, see name().
179  *
180  * @param n    the current IR-node
181  * @param ctx  a variable context
182  */
183 static void dump_var_def(ir_node *n, void *ctx)
184 {
185   var_ctx *env = ctx;
186   int arity = get_irn_arity(n);
187
188   name(env->f, "  ir_node *", n, " = NULL;\n");
189   if (arity > env->max_arity)
190      env->max_arity = arity;
191   if (get_irn_op(n) == op_Const)
192     env->need_tv = 1;
193   if (has_backedges(n)) {
194     if (is_Block(n))
195       env->need_unknown_X = 1;
196     else
197       env->need_unknown = 1;
198   }
199 }
200
201 /**
202  * Generate all needed variable declarations for a graph.
203  *
204  * @param env  a variable context
205  * @param irg  the graph
206  */
207 static void generate_var_decls(var_ctx *env, ir_graph *irg)
208 {
209   FILE *f = env->f;
210
211   irg_walk_graph(irg, NULL, dump_var_def, env);
212   fprintf(f, "  ir_node *in[%d];\n", env->max_arity);
213   if (env->need_tv)
214     fprintf(f, "  tarval *tv = NULL;\n");
215   fprintf(f, "  const char *s = NULL;\n");
216   fprintf(f, "  ir_entity *ent = NULL;\n");
217   fprintf(f, "  ir_mode *mode = NULL;\n");
218   fprintf(f, "  ir_graph *irg = NULL;\n");
219   fprintf(f, "  ir_node *tmp = NULL;\n");
220   fprintf(f, "  symconst_symbol sym;\n");
221   if (env->need_unknown_X)
222     fprintf(f, "  ir_node *unknownX = NULL;\n");
223   if (env->need_unknown)
224     fprintf(f, "  ir_node *unknown = NULL;\n");
225   fprintf(f, "\n");
226 }
227
228 /**
229  * Generate code for a predefined node.
230  *
231  * @param f   file handle for output
232  * @param n   the node
233  *
234  * @return non-zero if n was a predefined node, 0 else
235  */
236 static int generate_predef_node(FILE *f, ir_node *n)
237 {
238   ir_graph *irg = current_ir_graph;
239
240 #define X(code)                         \
241   else if (n == code)                   \
242     name(f, "  ", n, " = " #code ";\n");
243
244   if (0);
245   X(get_irg_start(irg))
246   X(get_irg_start_block(irg))
247   X(get_irg_end(irg))
248   X(get_irg_end_block(irg))
249   X(get_irg_frame(irg))
250   X(get_irg_globals(irg))
251   X(get_irg_tls(irg))
252   X(get_irg_value_param_base(irg))
253   X(get_irg_initial_mem(irg))
254   X(get_irg_no_mem(irg))
255   else
256     return 0;
257   return 1;
258
259 #undef X
260 }
261
262 /**
263  * Generate code for a Binop node.
264  *
265  * @param f   file handle for output
266  * @param n   the node
267  */
268 static void generate_code_Binop(FILE *f, ir_node *n)
269 {
270   ir_op *op = get_irn_op(n);
271   ir_node *right = get_binop_right(n);
272
273   name(f, "  ", n, " = ");
274   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
275   name(f, NULL, get_nodes_block(n), ", ");
276   name(f, NULL, right, ", ");
277   name(f, NULL, get_binop_left(n), ", get_irn_mode(");
278   name(f, NULL, right, "));\n");
279 }
280
281 /**
282  * Generate code for a Divop node.
283  *
284  * @param f   file handle for output
285  * @param n   the node
286  */
287 static void generate_code_Divop(FILE *f, ir_node *n)
288 {
289   ir_op *op = get_irn_op(n);
290   ir_node *right = get_binop_right(n);
291   ir_mode *mode = get_divop_resmod(n);
292
293   name(f, "  ", n, " = ");
294   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
295   name(f, NULL, get_nodes_block(n), ", ");
296   name(f, NULL, get_fragile_op_mem(n), ", ");
297   name(f, NULL, get_binop_left(n), ", ");
298   name(f, NULL, right, ", ");
299
300   /* avoid to print the mode name if possible */
301   if (mode == get_irn_mode(right)) {
302     name(f, "get_irn_mode(", right, ");\n");
303   } else {
304     fprintf(f, "mode_%s);\n", get_mode_name(mode));
305   }
306 }
307
308 /**
309  * Generate code for an Unop node.
310  *
311  * @param f   file handle for output
312  * @param n   the node
313  */
314 static void generate_code_Unop(FILE *f, ir_node *n)
315 {
316   ir_op *op = get_irn_op(n);
317   ir_node *irn = get_unop_op(n);
318
319   name(f, "  ", n, " = ");
320   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
321   name(f, NULL, get_nodes_block(n), ", ");
322   name(f, NULL, irn, ", get_irn_mode(");
323   name(f, NULL, irn, "));\n");
324 }
325
326 /**
327  * Generate code for a Load.
328  *
329  * @param f   file handle for output
330  * @param n   the node
331  */
332 static void generate_code_Load(FILE *f, ir_node *n)
333 {
334   ir_node       *ptr = get_Load_ptr(n);
335   ir_op         *op = get_irn_op(ptr);
336   ir_volatility vol;
337
338   /* try to detect the mode */
339   if (op == op_Sel) {
340     name(f, "  ent = get_Sel_entity(", ptr, ");\n");
341     fprintf(f, "  mode = get_type_mode(get_entity_type(ent));\n");
342   }
343   else if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
344     name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
345     fprintf(f, "  mode = get_type_mode(get_entity_type(ent));\n");
346   }
347   else
348     fprintf(f, "  mode = mode_%s;\n", get_mode_name(get_Load_mode(n)));
349
350   name(f, "  ", n, " = ");
351   fprintf(f, "new_r_Load(irg, ");
352   name(f, NULL, get_nodes_block(n), ", ");
353   name(f, NULL, get_Load_mem(n), ", ");
354   name(f, NULL, ptr, ", mode);\n");
355   vol = get_Load_volatility(n);
356   if (vol != volatility_non_volatile) {
357     name(f, "  set_Load_volatility(", n, ", ");
358     fprintf(f, "%s);\n", get_volatility_name(vol));
359   }
360 }
361
362 /**
363  * Generate code for a Store.
364  *
365  * @param f   file handle for output
366  * @param n   the node
367  */
368 static void generate_code_Store(FILE *f, ir_node *n)
369 {
370   ir_volatility vol;
371
372   name(f, "  ", n, " = ");
373   fprintf(f, "new_r_Store(irg, ");
374   name(f, NULL, get_nodes_block(n), ", ");
375   name(f, NULL, get_Store_mem(n), ", ");
376   name(f, NULL, get_Store_ptr(n), ", ");
377   name(f, NULL, get_Store_value(n), ")\n");
378   vol = get_Store_volatility(n);
379   if (vol != volatility_non_volatile) {
380     name(f, "  set_Store_volatility(", n, ", ");
381     fprintf(f, "%s);\n", get_volatility_name(vol));
382   }
383 }
384
385 /**
386  * Generate code for a Return.
387  */
388 static void generate_code_Return(FILE *f, ir_node *n)
389 {
390   int i, n_res = get_Return_n_ress(n);
391
392   if (n_res > 1)
393     for (i = 0; i < n_res; ++i) {
394       fprintf(f, "  in[%d] = ", i);
395       name(f, NULL, get_Return_res(n, i), ";\n");
396     }
397   name(f, "  ", n, " = ");
398   fprintf(f, "new_r_Return(irg, ");
399   name(f, NULL, get_nodes_block(n), ", ");
400   name(f, NULL, get_Return_mem(n), ", ");
401   if (n_res > 1)
402     fprintf(f, "%d, in);\n", n_res);
403   else if (n_res == 1)
404     name(f, "1, &", get_Return_res(n, 0), ");\n");
405   else
406     fprintf(f, "0, NULL);\n");
407 }
408
409 /**
410  * Generate code for a Raise.
411  *
412  * @param f   file handle for output
413  * @param n   the node
414  */
415 static void generate_code_Raise(FILE *f, ir_node *n)
416 {
417   name(f, "  ", n, " = new_r_Return(irg, ");
418   name(f, NULL, get_nodes_block(n), ", ");
419   name(f, NULL, get_Raise_mem(n), ", ");
420   name(f, NULL, get_Raise_exo_ptr(n), ");\n");
421 }
422
423 /**
424  * Generate code for a Bound.
425  *
426  * @param f   file handle for output
427  * @param n   the node
428  */
429 static void generate_code_Bound(FILE *f, ir_node *n)
430 {
431   name(f, NULL, get_nodes_block(n), ", ");
432   name(f, NULL, get_Bound_mem(n), ", ");
433   name(f, NULL, get_Bound_index(n), ", ");
434   name(f, NULL, get_Bound_lower(n), ", ");
435   name(f, NULL, get_Bound_upper(n), ");\n");
436 }
437
438 /**
439  * Generate code for an Unknown.
440  *
441  * @param f   file handle for output
442  * @param n   the node
443  */
444 static void generate_code_Unknown(FILE *f, ir_node *n)
445 {
446   name(f, "  ", n, " = new_r_Unknown(irg, ");
447   fprintf(f, "mode_%s);\n", get_mode_name(get_irn_mode(n)));
448 }
449
450 /**
451  * Generate code for a Bad.
452  *
453  * @param f   file handle for output
454  * @param n   the node
455  */
456 static void generate_code_Bad(FILE *f, ir_node *n)
457 {
458   name(f, "  ", n, " = new_r_Bad(irg);\n");
459 }
460
461 /**
462  * Generate code for a Const.
463  *
464  * @param f   file handle for output
465  * @param n   the node
466  */
467 static void generate_code_Const(FILE *f, ir_node *n)
468 {
469   ir_type *tp = get_Const_type(n);
470   tarval *tv = get_Const_tarval(n);
471   ir_mode *mode = get_irn_mode(n);
472   char buf[256];
473
474   if (tp == get_unknown_type()) {
475     name(f, "  ", n, " = new_r_Const(irg, ");
476   }
477   else {
478     name(f, "  ", n, " = new_r_Const_type(irg, ");
479   }
480   name(f, NULL, get_nodes_block(n), ", ");
481   fprintf(f, "mode_%s, ", get_mode_name(mode));
482
483   if (! mode_is_reference(mode)) {
484     if (tv == get_tarval_null(mode))
485       fprintf(f, "get_tarval_null(mode)");
486     else if (tv == get_tarval_one(mode))
487       fprintf(f, "get_tarval_one(mode)");
488     else if (tv == get_tarval_b_false())
489       fprintf(f, "get_tarval_b_false()");
490     else if (tv == get_tarval_b_true())
491       fprintf(f, "get_tarval_b_true()");
492         else if (tv == get_tarval_minus_one(mode))
493           fprintf(f, "get_tarval_minus_one(mode)");
494     else if (mode_is_float(mode)) {
495                 if (tv == get_tarval_nan(mode))
496                   fprintf(f, "get_tarval_nan(mode)");
497                 else if (tv == get_tarval_minus_inf(mode))
498                   fprintf(f, "get_tarval_minus_inf(mode)");
499                 else if (tv == get_tarval_plus_inf(mode))
500                   fprintf(f, "get_tarval_plus_inf(mode)");
501                 else
502                   goto def_mode;
503         }
504     else
505       goto def_mode;
506   }
507   else {
508     if (tv == get_tarval_null(mode))
509       fprintf(f, "get_tarval_null(mode)");
510     else {
511 def_mode:
512       tarval_snprintf(buf, sizeof(buf), tv);
513       fprintf(f, "new_tarval_from_str(\"%s\", %zd, ", buf, strlen(buf));
514       fprintf(f, "mode_%s)", get_mode_name(mode));
515     }
516   }
517
518   if (tp != get_unknown_type())
519     fprintf(f, ", %s", get_type_name(tp));
520   fprintf(f, ");\n");
521 }
522
523 /**
524  * Generate code for a SymConst.
525  *
526  * @param f   file handle for output
527  * @param n   the node
528  */
529 static void generate_code_SymConst(FILE *f, ir_node *n)
530 {
531   ident *id;
532   ir_type *tp;
533   ir_entity *ent;
534   ir_label_t label;
535   symconst_kind kind = get_SymConst_kind(n);
536   const char *k_name = "NULL";
537   const char *str;
538
539   switch (kind) {
540   case symconst_addr_ent:
541     fprintf(f, "  sym.entity_p = ENTITY(%s);\n", get_entity_name(get_SymConst_entity(n)));
542     k_name = "symconst_addr_ent";
543     break;
544   case symconst_addr_name:
545     id = get_SymConst_name(n);
546     str = get_id_str(id);
547     fprintf(f, "  sym.ident_p = new_id_from_chars(\"%s\", %d);\n", str, get_id_strlen(id));
548     k_name = "symconst_addr_name";
549     break;
550   case symconst_type_size:
551     tp = get_SymConst_type(n);
552     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
553     k_name = "symconst_type_size";
554     break;
555   case symconst_type_align:
556     tp = get_SymConst_type(n);
557     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
558     k_name = "symconst_type_align";
559     break;
560   case symconst_type_tag:
561     tp = get_SymConst_type(n);
562     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
563     k_name = "symconst_type_tag";
564     break;
565   case symconst_ofs_ent:
566     ent = get_SymConst_entity(n);
567     fprintf(f, "  sym.entity_p = %s;\n", get_entity_name(ent));
568     k_name = "symconst_ofs_ent";
569     break;
570   case symconst_enum_const:
571     id = get_SymConst_name(n);
572     str = get_id_str(id);
573     fprintf(f, "  sym.ident_p = new_id_from_chars(\"%s\", %d);\n", str, get_id_strlen(id));
574     k_name = "symconst_enum_const";
575     break;
576   case symconst_label:
577     label = get_SymConst_label(n);
578     fprintf(f, "  sym.label = %lu;\n", label);
579     k_name = "symconst_label";
580     break;
581   }
582   name(f, "  ", n, " = new_r_SymConst(irg, ");
583   name(f, NULL, get_nodes_block(n), ", sym, ");
584   fprintf(f, "%s);\n", k_name);
585 }
586
587 /**
588  * Generate code for a Sel.
589  *
590  * @param f   file handle for output
591  * @param n   the node
592  */
593 static void generate_code_Sel(FILE *f, ir_node *n)
594 {
595   int n_index = get_Sel_n_indexs(n);
596   int i;
597   ir_op *op;
598   ir_node *ptr = get_Sel_ptr(n);
599   ir_entity *ent = get_Sel_entity(n);
600   int have_ent = 0;
601
602   if (n_index > 0) {
603     ir_type *tp;
604     ir_entity *up_ent;
605
606     /* try to detect the array entity */
607     op = get_irn_op(ptr);
608     if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
609       up_ent = get_SymConst_entity(ptr);
610       tp = get_entity_type(up_ent);
611       if (is_Array_type(tp) && get_array_element_entity(tp) == ent) {
612         name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
613         fprintf(f, "  ent = get_array_element_entity(get_entity_type(ent));\n");
614         have_ent = 1;
615       }
616     }
617     else if (op == op_Sel) {
618       up_ent = get_Sel_entity(ptr);
619       tp = get_entity_type(up_ent);
620       if (is_Array_type(tp) && get_array_element_entity(tp) == ent) {
621         name(f, "  ent = get_Sel_entity(", ptr, ");\n");
622         fprintf(f, "  ent = get_array_element_entity(get_entity_type(ent));\n");
623         have_ent = 1;
624       }
625     }
626   }
627   if (n_index > 1)
628     for (i = 0; i < n_index; ++i) {
629       fprintf(f, "  in[%d] = ", i);
630       name(f, NULL, get_Sel_index(n, i), ";\n");
631     }
632
633   if (n_index == 0)
634     name(f, "  ", n, " = new_r_simpleSel(irg, ");
635   else
636     name(f, "  ", n, " = new_r_Sel(irg, ");
637   name(f, NULL, get_nodes_block(n), ", ");
638   name(f, NULL, get_Sel_mem(n), ", ");
639   name(f, NULL, ptr, ", ");
640   if (n_index == 1)
641     name(f, "1, &", get_Sel_index(n, 0), ", ");
642   else if (n_index > 0)
643     fprintf(f, "%d, in, ", n_index);
644
645   ent = get_Sel_entity(n);
646   if (have_ent)
647     fprintf(f, "ent);\n");
648   else
649     fprintf(f, "ENTITY(%s));\n", get_entity_name(get_Sel_entity(n)));
650 }
651
652 /**
653  * Generate code for a Block. Break loops here.
654  *
655  * @param f   file handle for output
656  * @param n   the node
657  */
658 static void generate_code_Block(fix_ctx *env, ir_node *n)
659 {
660   FILE *f = env->f;
661   int i, arity = get_irn_arity(n);
662   for (i = 0; i < arity; ++i) {
663     fprintf(f, "  in[%d] = ", i);
664     if (is_backedge(n, i)) {
665       fprintf(f, "unknownX;\n");
666       env->has_backedges = 1;
667     }
668     else
669       name(f, NULL, get_irn_n(n, i), ";\n");
670   }
671
672   name(f, "  ", n, " = new_r_Block(irg, ");
673   fprintf(f, "%d, in);\n", arity);
674 }
675
676 /**
677  * Generate code for a Phi. Break loops here.
678  *
679  * @param f   file handle for output
680  * @param n   the node
681  */
682 static void generate_code_Phi(fix_ctx *env, ir_node *n)
683 {
684   FILE *f = env->f;
685   int i, arity = get_irn_arity(n);
686   ir_mode *mode = get_irn_mode(n);
687
688   if (has_backedges(n)) {
689     fprintf(f, "  unknown = new_r_Unknown(irg, mode_%s);\n", get_mode_name(mode));
690     env->has_backedges = 1;
691   }
692   for (i = 0; i < arity; ++i) {
693     fprintf(f, "  in[%d] = ", i);
694     if (is_backedge(n, i))
695       fprintf(f, "unknown;\n");
696     else
697       name(f, NULL, get_irn_n(n, i), ";\n");
698   }
699
700   name(f, "  ", n, " = new_r_Phi(irg, ");
701   fprintf(f, "%d, in, mode_%s);\n", arity, get_mode_name(mode));
702 }
703
704 /**
705  * Generate code for a Proj(Load).
706  *
707  * @param f   file handle for output
708  * @param n   the node
709  */
710 static void generate_code_Proj_Load(FILE *f, ir_node *n)
711 {
712   ir_node *pred = get_Proj_pred(n);
713   ir_node *block = get_nodes_block(n);
714   long proj_nr = get_Proj_proj(n);
715   const char *mode = "NULL";
716   const char *proj= "-1";
717
718   switch(proj_nr) {
719   case pn_Load_M:
720     mode = "mode_M";
721     proj = "pn_Load_M";
722     break;
723   case pn_Load_X_regular:
724     mode = "mode_X";
725     proj = "pn_Load_X_regular";
726     break;
727   case pn_Load_X_except:
728     mode = "mode_X";
729     proj = "pn_Load_X_except";
730     break;
731   case pn_Load_res:
732     mode = "mode";
733     proj = "pn_Load_res";
734     name(f, "  mode = get_Load_mode(", pred, ");\n");
735     break;
736   }
737   name(f, "  ", n, " = new_r_Proj(irg, ");
738   name(f, NULL, block, ", ");
739   name(f, NULL, pred, ", ");
740   fprintf(f, "%s, %s);\n", mode, proj);
741 }
742
743 /**
744  * Generate code for a Proj(Store).
745  *
746  * @param f   file handle for output
747  * @param n   the node
748  */
749 static void generate_code_Proj_Store(FILE *f, ir_node *n)
750 {
751   ir_node *pred = get_Proj_pred(n);
752   ir_node *block = get_nodes_block(n);
753   long proj_nr = get_Proj_proj(n);
754   const char *mode = "NULL";
755   const char *proj= "-1";
756
757   switch(proj_nr) {
758   case pn_Store_M:
759     mode = "mode_M";
760     proj = "pn_Store_M";
761     break;
762   case pn_Store_X_regular:
763     mode = "mode_X";
764     proj = "pn_Store_X_regular";
765     break;
766   case pn_Store_X_except:
767     mode = "mode_X";
768     proj = "pn_Store_X_except";
769     break;
770   }
771   name(f, "  ", n, " = new_r_Proj(irg, ");
772   name(f, NULL, block, ", ");
773   name(f, NULL, pred, ", ");
774   fprintf(f, "%s, %s);\n", mode, proj);
775 }
776
777 /**
778  * Generate code for a Proj(Div).
779  *
780  * @param f   file handle for output
781  * @param n   the node
782  */
783 static void generate_code_Proj_Div(FILE *f, ir_node *n)
784 {
785   ir_node *pred = get_Proj_pred(n);
786   ir_node *block = get_nodes_block(n);
787   long proj_nr = get_Proj_proj(n);
788   const char *mode = "NULL";
789   const char *proj= "-1";
790
791   switch(proj_nr) {
792   case pn_Div_M:
793     mode = "mode_M";
794     proj = "pn_Div_M";
795     break;
796   case pn_Div_X_regular:
797     mode = "mode_X";
798     proj = "pn_Div_X_regular";
799     break;
800   case pn_Div_X_except:
801     mode = "mode_X";
802     proj = "pn_Div_X_except";
803     break;
804   case pn_Div_res:
805     mode = "mode";
806     proj = "pn_Div_res";
807     name(f, "  mode = get_Div_resmode(", pred, ");\n");
808     break;
809   }
810   name(f, "  ", n, " = new_r_Proj(irg, ");
811   name(f, NULL, block, ", ");
812   name(f, NULL, pred, ", ");
813   fprintf(f, "%s, %s);\n", mode, proj);
814 }
815
816 /**
817  * Generate code for a Proj(Mod).
818  *
819  * @param f   file handle for output
820  * @param n   the node
821  */
822 static void generate_code_Proj_Mod(FILE *f, ir_node *n)
823 {
824   ir_node *pred = get_Proj_pred(n);
825   ir_node *block = get_nodes_block(n);
826   long proj_nr = get_Proj_proj(n);
827   const char *mode = "NULL";
828   const char *proj= "-1";
829
830   switch(proj_nr) {
831   case pn_Mod_M:
832     mode = "mode_M";
833     proj = "pn_Mod_M";
834     break;
835   case pn_Mod_X_regular:
836     mode = "mode_X";
837     proj = "pn_Mod_X_regular";
838     break;
839   case pn_Mod_X_except:
840     mode = "mode_X";
841     proj = "pn_Mod_X_except";
842     break;
843   case pn_Mod_res:
844     mode = "mode";
845     proj = "pn_Mod_res";
846     name(f, "  mode = get_Mod_resmode(", pred, ");\n");
847     break;
848   }
849   name(f, "  ", n, " = new_r_Proj(irg, ");
850   name(f, NULL, block, ", ");
851   name(f, NULL, pred, ", ");
852   fprintf(f, "%s, %s);\n", mode, proj);
853 }
854
855 /**
856  * Generate code for a Proj(DivMod).
857  *
858  * @param f   file handle for output
859  * @param n   the node
860  */
861 static void generate_code_Proj_DivMod(FILE *f, ir_node *n)
862 {
863   ir_node *pred = get_Proj_pred(n);
864   ir_node *block = get_nodes_block(n);
865   long proj_nr = get_Proj_proj(n);
866   const char *mode = "NULL";
867   const char *proj= "-1";
868
869   switch(proj_nr) {
870   case pn_DivMod_M:
871     mode = "mode_M";
872     proj = "pn_DivMod_M";
873     break;
874   case pn_DivMod_X_except:
875     mode = "mode_X";
876     proj = "pn_DivMod_X_except";
877     break;
878   case pn_DivMod_res_div:
879     mode = "mode";
880     proj = "pn_DivMod_res_div";
881     name(f, "  mode = get_DivMod_resmode(", pred, ");\n");
882     break;
883   case pn_DivMod_res_mod:
884     mode = "mode";
885     proj = "pn_DivMod_res_mod";
886     name(f, "  mode = get_DivMod_resmode(", pred, ");\n");
887     break;
888   }
889   name(f, "  ", n, " = new_r_Proj(irg, ");
890   name(f, NULL, block, ", ");
891   name(f, NULL, pred, ", ");
892   fprintf(f, "%s, %s);\n", mode, proj);
893 }
894
895 /**
896  * Generate code for a Proj(Cmp).
897  *
898  * @param f   file handle for output
899  * @param n   the node
900  */
901 static void generate_code_Proj_Cmp(FILE *f, ir_node *n)
902 {
903   long proj_nr = get_Proj_proj(n);
904
905   name(f, "  ", n, " = new_r_Proj(irg, ");
906   name(f, NULL, get_nodes_block(n), ", ");
907   name(f, NULL, get_Proj_pred(n), ", ");
908   fprintf(f, "mode_b, %s);\n", get_pnc_string(proj_nr));
909 }
910
911 /**
912  * Generate code for a Proj(Cond).
913  *
914  * @param f   file handle for output
915  * @param n   the node
916  */
917 static void generate_code_Proj_Cond(FILE *f, ir_node *n)
918 {
919   ir_node *cond = get_Proj_pred(n);
920   ir_node *sel = get_Cond_selector(cond);
921   ir_node *block = get_nodes_block(n);
922   long proj_nr = get_Proj_proj(n);
923
924   if (get_irn_mode(sel) == mode_b) {
925     name(f, "  ", n, " = new_r_Proj(irg, ");
926     name(f, NULL, block, ", ");
927     name(f, NULL, cond, ", ");
928     fprintf(f, "mode_b, %s);\n", proj_nr ? "pn_Cond_true" : "pn_Cond_false");
929   }
930   else {
931     if (proj_nr == get_Cond_defaultProj(cond))
932       name(f, "  ", n, " = new_r_defaultProj(irg, ");
933     else
934       name(f, "  ", n, " = new_r_Proj(irg, ");
935
936     name(f, NULL, block, ", ");
937     name(f, NULL, cond, ", ");
938     fprintf(f, "mode_%s, %ld);\n", get_mode_name(get_irn_mode(n)), proj_nr);
939   }
940 }
941
942 /**
943  * Generate code for a Proj.
944  *
945  * @param f   file handle for output
946  * @param n   the node
947  */
948 static void generate_code_Proj(FILE *f, ir_node *n)
949 {
950   ir_node *pred = get_Proj_pred(n);
951
952   switch (get_irn_opcode(pred)) {
953   case iro_Load:
954     generate_code_Proj_Load(f, n);
955     break;
956   case iro_Store:
957     generate_code_Proj_Store(f, n);
958     break;
959   case iro_Div:
960     generate_code_Proj_Div(f, n);
961     break;
962   case iro_Mod:
963     generate_code_Proj_Mod(f, n);
964     break;
965   case iro_DivMod:
966     generate_code_Proj_DivMod(f, n);
967     break;
968   case iro_Cmp:
969     generate_code_Proj_Cmp(f, n);
970     break;
971   case iro_Cond:
972     generate_code_Proj_Cond(f, n);
973     break;
974   default: {
975     const char *mode_name = get_mode_name(get_irn_mode(n));
976     name(f, "  ", n, " = new_r_Proj(irg, ");
977     name(f, NULL, get_nodes_block(n), ", ");
978     name(f, NULL, get_Proj_pred(n), ", ");
979     fprintf(f, "mode_%s, %ld);\n", mode_name, get_Proj_proj(n));
980   }
981   }
982 }
983
984 /**
985  * Generate code for a Jmp.
986  *
987  * @param f   file handle for output
988  * @param n   the node
989  */
990 static void generate_code_Jmp(FILE *f, ir_node *n)
991 {
992   name(f, "  ", n, " = new_r_Jmp(irg, ");
993   name(f, NULL, get_nodes_block(n), ");\n");
994 }
995
996 /**
997  * Generate code for a Cond.
998  *
999  * @param f   file handle for output
1000  * @param n   the node
1001  */
1002 static void generate_code_Cond(FILE *f, ir_node *n)
1003 {
1004   name(f, "  ", n, " = new_r_Cond(irg, ");
1005   name(f, NULL, get_nodes_block(n), ", ");
1006   name(f, NULL, get_Cond_selector(n), ");\n");
1007 }
1008
1009 /**
1010  * Generate code for a Call.
1011  *
1012  * @param f   file handle for output
1013  * @param n   the node
1014  */
1015 static void generate_code_Call(FILE *f, ir_node *n)
1016 {
1017   int i, n_param = get_Call_n_params(n);
1018   ir_node *ptr = get_Call_ptr(n);
1019   ir_op *op = get_irn_op(ptr);
1020   ir_entity *ent;
1021   ir_type *tp = get_Call_type(n);
1022   int have_tp = 0;
1023
1024   /* try to detect the type */
1025   if (op == op_Sel) {
1026     ent = get_Sel_entity(ptr);
1027     if (tp == get_entity_type(ent)) {
1028       name(f, "  ent = get_Sel_entity(", ptr, ");\n");
1029       fprintf(f, "  tp = get_entity_type(ent);\n");
1030       have_tp = 1;
1031     }
1032   }
1033   else if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
1034     ent = get_SymConst_entity(ptr);
1035     if (tp == get_entity_type(ent)) {
1036       name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
1037       fprintf(f, "  tp = get_entity_type(ent);\n");
1038       have_tp = 1;
1039     }
1040   }
1041   if (! have_tp)
1042     fprintf(f, "  tp = TYPE(%s);\n", get_type_name(tp));
1043
1044   for (i = 0; i < n_param; ++i) {
1045     fprintf(f, "  in[%d] = ", i);
1046     name(f, NULL, get_Call_param(n, i), ";\n");
1047   }
1048   name(f, "  ", n, " = ");
1049   fprintf(f, "new_r_Call(irg, ");
1050   name(f, NULL, get_nodes_block(n), ", ");
1051   name(f, NULL, get_Call_mem(n), ", ");
1052   if (n_param > 0)
1053     fprintf(f, "%d, in, tp);\n", n_param);
1054   else
1055     fprintf(f, "0, NULL, tp);\n");
1056 }
1057
1058 /**
1059  * Create code for the given Alloc node
1060  *
1061  * @param f   file handle for output
1062  * @param n   the node
1063  */
1064 static void generate_code_Alloc(FILE *f, ir_node *n)
1065 {
1066   name(f, "  ", n, " = new_r_Alloc(irg, ");
1067   name(f, NULL, get_nodes_block(n), ", ");
1068   name(f, NULL, get_Alloc_mem(n), ", ");
1069   name(f, NULL, get_Alloc_size(n), ", tp, ");
1070   fprintf(f, get_Alloc_where(n) == stack_alloc ? "stack_alloc);\n" : "heap_alloc);\n");
1071 }
1072
1073 /**
1074  * Create code for the given Free node
1075  *
1076  * @param f   file handle for output
1077  * @param n   the node
1078  */
1079 static void generate_code_Free(FILE *f, ir_node *n)
1080 {
1081   fprintf(f, "  tp = TYPE(%s);\n", get_type_name(get_Free_type(n)));
1082   name(f, "  ", n, " = new_r_Alloc(irg, ");
1083   name(f, NULL, get_nodes_block(n), ", ");
1084   name(f, NULL, get_Free_ptr(n), ", ");
1085   name(f, NULL, get_Free_size(n), ", tp, ");
1086   fprintf(f, get_Free_where(n) == stack_alloc ? "stack_alloc);\n" : "heap_alloc);\n");
1087 }
1088
1089 /**
1090  * Create code for the given node constructor.
1091  *
1092  * @param f   file handle for output
1093  * @param n   the node
1094  */
1095 static void generate_node(fix_ctx *env, ir_node *n)
1096 {
1097   FILE *f = env->f;
1098   ir_op *op = get_irn_op(n);
1099
1100   if (op == op_Div || op == op_Mod || op == op_DivMod || op == op_Quot)
1101     generate_code_Divop(f, n);
1102   else if (op == op_Load)
1103     generate_code_Load(f, n);
1104   else if (op == op_Store)
1105     generate_code_Store(f, n);
1106   else if (op == op_Return)
1107     generate_code_Return(f, n);
1108   else if (op == op_Raise)
1109     generate_code_Raise(f, n);
1110   else if (op == op_Bound)
1111     generate_code_Bound(f, n);
1112   else if (op == op_Unknown)
1113     generate_code_Unknown(f, n);
1114   else if (op == op_Bad)
1115     generate_code_Bad(f, n);
1116   else if (op == op_Const)
1117     generate_code_Const(f, n);
1118   else if (op == op_SymConst)
1119     generate_code_SymConst(f, n);
1120   else if (op == op_Sel)
1121     generate_code_Sel(f, n);
1122   else if (op == op_Block)
1123     generate_code_Block(env, n);
1124   else if (op == op_Phi)
1125     generate_code_Phi(env, n);
1126   else if (op == op_Proj)
1127     generate_code_Proj(f, n);
1128   else if (op == op_Jmp)
1129     generate_code_Jmp(f, n);
1130   else if (op == op_Cond)
1131     generate_code_Cond(f, n);
1132   else if (op == op_Call)
1133     generate_code_Call(f, n);
1134   else if (op == op_Alloc)
1135     generate_code_Alloc(f, n);
1136   else if (op == op_Free)
1137     generate_code_Free(f, n);
1138   else if (is_binop(n))
1139     generate_code_Binop(f, n);
1140   else if (is_unop(n))
1141     generate_code_Unop(f, n);
1142   else
1143     name(f, "  ", n, " = NULL;\n");
1144 }
1145
1146 /**
1147  * Walker: Create code for the given node.
1148  */
1149 static void dump_code(ir_node *n, void *ctx)
1150 {
1151   fix_ctx *env = ctx;
1152
1153   if (! generate_predef_node(env->f, n))
1154     generate_node(env, n);
1155 }
1156
1157 /**
1158  * Generate Firm code.
1159  *
1160  * @param env  a fix environment
1161  * @param irg  the graph
1162  */
1163 static void generate_code(fix_ctx *env, ir_graph *irg)
1164 {
1165   irg_walk_graph(irg, NULL, dump_code, env);
1166 }
1167
1168 /**
1169  * Generate Firm assembler for a given graph
1170  *
1171  * @param f    the output file handle
1172  * @param irg  the graph
1173  */
1174 static void gen_Firm_assembler_irg(FILE *f, ir_graph *irg)
1175 {
1176   fix_ctx fenv;
1177   var_ctx venv;
1178
1179   venv.f              = f;
1180   venv.max_arity      = 0;
1181   venv.need_tv        = 0;
1182   venv.need_unknown_X = 0;
1183   venv.need_unknown   = 0;
1184
1185   fenv.f              = f;
1186   fenv.start_block    = get_irg_start_block(irg);
1187   fenv.has_backedges  = 0;
1188
1189   /* needed to detect loops */
1190   construct_backedges(irg);
1191
1192   generate_header(f, irg);
1193   generate_var_decls(&venv, irg);
1194   generate_prolog(&venv, irg);
1195   generate_code(&fenv, irg);
1196   generate_epilog(&fenv, irg);
1197 }
1198
1199 void gen_Firm_assembler(const char *input_filename)
1200 {
1201   FILE     *f;
1202   ir_graph *irg;
1203   int      i, n;
1204   (void) input_filename;
1205
1206   f = fopen("firm_output.c", "w");
1207   if (f) {
1208     for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
1209       irg = get_irp_irg(i);
1210       gen_Firm_assembler_irg(f, irg);
1211     }
1212   }
1213   else {
1214     /* report some error here */
1215   }
1216   fclose(f);
1217 }