- 2009 patch
[cparser] / driver / gen_firm_asm.c
1 /*
2  * Generate Firm assembler from Firm graphs.
3  *
4  * (C) 2005-2009  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     fputs(get_type_name(get_method_res_type(tp, 0)), f);
73   fprintf(f, " %s(", s);
74   n = get_method_n_params(tp);
75   if (n == 0)
76     fputs(get_method_variadicity(tp) == variadicity_variadic ? "" : "void", f);
77   else {
78     for (i = 0; i < n; ++i) {
79       if (i > 0)
80         fprintf(f, ", ");
81       fputs(get_type_name(get_method_param_type(tp, i)), f);
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_initial_exec(irg))
250   X(get_irg_frame(irg))
251   X(get_irg_tls(irg))
252   X(get_irg_initial_mem(irg))
253   X(get_irg_no_mem(irg))
254   else
255     return 0;
256   return 1;
257
258 #undef X
259 }
260
261 /**
262  * Generate code for a Binop node.
263  *
264  * @param f   file handle for output
265  * @param n   the node
266  */
267 static void generate_code_Binop(FILE *f, ir_node *n)
268 {
269   ir_op *op = get_irn_op(n);
270   ir_node *right = get_binop_right(n);
271
272   name(f, "  ", n, " = ");
273   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
274   name(f, NULL, get_nodes_block(n), ", ");
275   name(f, NULL, right, ", ");
276   name(f, NULL, get_binop_left(n), ", get_irn_mode(");
277   name(f, NULL, right, "));\n");
278 }
279
280 /**
281  * Generate code for a Divop node.
282  *
283  * @param f   file handle for output
284  * @param n   the node
285  */
286 static void generate_code_Divop(FILE *f, ir_node *n)
287 {
288   ir_op *op = get_irn_op(n);
289   ir_node *right = get_binop_right(n);
290   ir_mode *mode = get_divop_resmod(n);
291
292   name(f, "  ", n, " = ");
293   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
294   name(f, NULL, get_nodes_block(n), ", ");
295   name(f, NULL, get_fragile_op_mem(n), ", ");
296   name(f, NULL, get_binop_left(n), ", ");
297   name(f, NULL, right, ", ");
298
299   /* avoid to print the mode name if possible */
300   if (mode == get_irn_mode(right)) {
301     name(f, "get_irn_mode(", right, ");\n");
302   } else {
303     fprintf(f, "mode_%s);\n", get_mode_name(mode));
304   }
305 }
306
307 /**
308  * Generate code for an Unop node.
309  *
310  * @param f   file handle for output
311  * @param n   the node
312  */
313 static void generate_code_Unop(FILE *f, ir_node *n)
314 {
315   ir_op *op = get_irn_op(n);
316   ir_node *irn = get_unop_op(n);
317
318   name(f, "  ", n, " = ");
319   fprintf(f, "new_r_%s(irg, ", get_op_name(op));
320   name(f, NULL, get_nodes_block(n), ", ");
321   name(f, NULL, irn, ", get_irn_mode(");
322   name(f, NULL, irn, "));\n");
323 }
324
325 /**
326  * Generate code for a Load.
327  *
328  * @param f   file handle for output
329  * @param n   the node
330  */
331 static void generate_code_Load(FILE *f, ir_node *n)
332 {
333   ir_node       *ptr = get_Load_ptr(n);
334   ir_op         *op = get_irn_op(ptr);
335   ir_volatility vol;
336
337   /* try to detect the mode */
338   if (op == op_Sel) {
339     name(f, "  ent = get_Sel_entity(", ptr, ");\n");
340     fprintf(f, "  mode = get_type_mode(get_entity_type(ent));\n");
341   }
342   else if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
343     name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
344     fprintf(f, "  mode = get_type_mode(get_entity_type(ent));\n");
345   }
346   else
347     fprintf(f, "  mode = mode_%s;\n", get_mode_name(get_Load_mode(n)));
348
349   name(f, "  ", n, " = ");
350   fprintf(f, "new_r_Load(irg, ");
351   name(f, NULL, get_nodes_block(n), ", ");
352   name(f, NULL, get_Load_mem(n), ", ");
353   name(f, NULL, ptr, ", mode);\n");
354   vol = get_Load_volatility(n);
355   if (vol != volatility_non_volatile) {
356     name(f, "  set_Load_volatility(", n, ", ");
357     fprintf(f, "%s);\n", get_volatility_name(vol));
358   }
359 }
360
361 /**
362  * Generate code for a Store.
363  *
364  * @param f   file handle for output
365  * @param n   the node
366  */
367 static void generate_code_Store(FILE *f, ir_node *n)
368 {
369   ir_volatility vol;
370
371   name(f, "  ", n, " = ");
372   fprintf(f, "new_r_Store(irg, ");
373   name(f, NULL, get_nodes_block(n), ", ");
374   name(f, NULL, get_Store_mem(n), ", ");
375   name(f, NULL, get_Store_ptr(n), ", ");
376   name(f, NULL, get_Store_value(n), ")\n");
377   vol = get_Store_volatility(n);
378   if (vol != volatility_non_volatile) {
379     name(f, "  set_Store_volatility(", n, ", ");
380     fprintf(f, "%s);\n", get_volatility_name(vol));
381   }
382 }
383
384 /**
385  * Generate code for a Return.
386  */
387 static void generate_code_Return(FILE *f, ir_node *n)
388 {
389   int i, n_res = get_Return_n_ress(n);
390
391   if (n_res > 1)
392     for (i = 0; i < n_res; ++i) {
393       fprintf(f, "  in[%d] = ", i);
394       name(f, NULL, get_Return_res(n, i), ";\n");
395     }
396   name(f, "  ", n, " = ");
397   fprintf(f, "new_r_Return(irg, ");
398   name(f, NULL, get_nodes_block(n), ", ");
399   name(f, NULL, get_Return_mem(n), ", ");
400   if (n_res > 1)
401     fprintf(f, "%d, in);\n", n_res);
402   else if (n_res == 1)
403     name(f, "1, &", get_Return_res(n, 0), ");\n");
404   else
405     fprintf(f, "0, NULL);\n");
406 }
407
408 /**
409  * Generate code for a Raise.
410  *
411  * @param f   file handle for output
412  * @param n   the node
413  */
414 static void generate_code_Raise(FILE *f, ir_node *n)
415 {
416   name(f, "  ", n, " = new_r_Return(irg, ");
417   name(f, NULL, get_nodes_block(n), ", ");
418   name(f, NULL, get_Raise_mem(n), ", ");
419   name(f, NULL, get_Raise_exo_ptr(n), ");\n");
420 }
421
422 /**
423  * Generate code for a Bound.
424  *
425  * @param f   file handle for output
426  * @param n   the node
427  */
428 static void generate_code_Bound(FILE *f, ir_node *n)
429 {
430   name(f, NULL, get_nodes_block(n), ", ");
431   name(f, NULL, get_Bound_mem(n), ", ");
432   name(f, NULL, get_Bound_index(n), ", ");
433   name(f, NULL, get_Bound_lower(n), ", ");
434   name(f, NULL, get_Bound_upper(n), ");\n");
435 }
436
437 /**
438  * Generate code for an Unknown.
439  *
440  * @param f   file handle for output
441  * @param n   the node
442  */
443 static void generate_code_Unknown(FILE *f, ir_node *n)
444 {
445   name(f, "  ", n, " = new_r_Unknown(irg, ");
446   fprintf(f, "mode_%s);\n", get_mode_name(get_irn_mode(n)));
447 }
448
449 /**
450  * Generate code for a Bad.
451  *
452  * @param f   file handle for output
453  * @param n   the node
454  */
455 static void generate_code_Bad(FILE *f, ir_node *n)
456 {
457   name(f, "  ", n, " = new_r_Bad(irg);\n");
458 }
459
460 /**
461  * Generate code for a Const.
462  *
463  * @param f   file handle for output
464  * @param n   the node
465  */
466 static void generate_code_Const(FILE *f, ir_node *n)
467 {
468   ir_type *tp = get_Const_type(n);
469   tarval *tv = get_Const_tarval(n);
470   ir_mode *mode = get_irn_mode(n);
471   char buf[256];
472
473   if (tp == get_unknown_type()) {
474     name(f, "  ", n, " = new_r_Const(irg, ");
475   }
476   else {
477     name(f, "  ", n, " = new_r_Const_type(irg, ");
478   }
479   name(f, NULL, get_nodes_block(n), ", ");
480   fprintf(f, "mode_%s, ", get_mode_name(mode));
481
482   if (! mode_is_reference(mode)) {
483     if (tv == get_tarval_null(mode))
484       fprintf(f, "get_tarval_null(mode)");
485     else if (tv == get_tarval_one(mode))
486       fprintf(f, "get_tarval_one(mode)");
487     else if (tv == get_tarval_b_false())
488       fprintf(f, "get_tarval_b_false()");
489     else if (tv == get_tarval_b_true())
490       fprintf(f, "get_tarval_b_true()");
491         else if (tv == get_tarval_minus_one(mode))
492           fprintf(f, "get_tarval_minus_one(mode)");
493     else if (mode_is_float(mode)) {
494                 if (tv == get_tarval_nan(mode))
495                   fprintf(f, "get_tarval_nan(mode)");
496                 else if (tv == get_tarval_minus_inf(mode))
497                   fprintf(f, "get_tarval_minus_inf(mode)");
498                 else if (tv == get_tarval_plus_inf(mode))
499                   fprintf(f, "get_tarval_plus_inf(mode)");
500                 else
501                   goto def_mode;
502         }
503     else
504       goto def_mode;
505   }
506   else {
507     if (tv == get_tarval_null(mode))
508       fprintf(f, "get_tarval_null(mode)");
509     else {
510 def_mode:
511       tarval_snprintf(buf, sizeof(buf), tv);
512       fprintf(f, "new_tarval_from_str(\"%s\", %u, ", buf, (unsigned) strlen(buf));
513       fprintf(f, "mode_%s)", get_mode_name(mode));
514     }
515   }
516
517   if (tp != get_unknown_type())
518     fprintf(f, ", %s", get_type_name(tp));
519   fprintf(f, ");\n");
520 }
521
522 /**
523  * Generate code for a SymConst.
524  *
525  * @param f   file handle for output
526  * @param n   the node
527  */
528 static void generate_code_SymConst(FILE *f, ir_node *n)
529 {
530   ident *id;
531   ir_type *tp;
532   ir_entity *ent;
533   ir_label_t label;
534   symconst_kind kind = get_SymConst_kind(n);
535   const char *k_name = "NULL";
536   const char *str;
537
538   switch (kind) {
539   case symconst_addr_ent:
540     fprintf(f, "  sym.entity_p = ENTITY(%s);\n", get_entity_name(get_SymConst_entity(n)));
541     k_name = "symconst_addr_ent";
542     break;
543   case symconst_addr_name:
544     id = get_SymConst_name(n);
545     str = get_id_str(id);
546     fprintf(f, "  sym.ident_p = new_id_from_chars(\"%s\", %d);\n", str, get_id_strlen(id));
547     k_name = "symconst_addr_name";
548     break;
549   case symconst_type_size:
550     tp = get_SymConst_type(n);
551     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
552     k_name = "symconst_type_size";
553     break;
554   case symconst_type_align:
555     tp = get_SymConst_type(n);
556     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
557     k_name = "symconst_type_align";
558     break;
559   case symconst_type_tag:
560     tp = get_SymConst_type(n);
561     fprintf(f, "  sym.type_p = %s;\n", get_type_name(tp));
562     k_name = "symconst_type_tag";
563     break;
564   case symconst_ofs_ent:
565     ent = get_SymConst_entity(n);
566     fprintf(f, "  sym.entity_p = %s;\n", get_entity_name(ent));
567     k_name = "symconst_ofs_ent";
568     break;
569   case symconst_enum_const:
570     id = get_SymConst_name(n);
571     str = get_id_str(id);
572     fprintf(f, "  sym.ident_p = new_id_from_chars(\"%s\", %d);\n", str, get_id_strlen(id));
573     k_name = "symconst_enum_const";
574     break;
575   case symconst_label:
576     label = get_SymConst_label(n);
577     fprintf(f, "  sym.label = %lu;\n", label);
578     k_name = "symconst_label";
579     break;
580   }
581   name(f, "  ", n, " = new_r_SymConst(irg, ");
582   name(f, NULL, get_nodes_block(n), ", sym, ");
583   fprintf(f, "%s);\n", k_name);
584 }
585
586 /**
587  * Generate code for a Sel.
588  *
589  * @param f   file handle for output
590  * @param n   the node
591  */
592 static void generate_code_Sel(FILE *f, ir_node *n)
593 {
594   int n_index = get_Sel_n_indexs(n);
595   int i;
596   ir_op *op;
597   ir_node *ptr = get_Sel_ptr(n);
598   ir_entity *ent = get_Sel_entity(n);
599   int have_ent = 0;
600
601   if (n_index > 0) {
602     ir_type *tp;
603     ir_entity *up_ent;
604
605     /* try to detect the array entity */
606     op = get_irn_op(ptr);
607     if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
608       up_ent = get_SymConst_entity(ptr);
609       tp = get_entity_type(up_ent);
610       if (is_Array_type(tp) && get_array_element_entity(tp) == ent) {
611         name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
612         fprintf(f, "  ent = get_array_element_entity(get_entity_type(ent));\n");
613         have_ent = 1;
614       }
615     }
616     else if (op == op_Sel) {
617       up_ent = get_Sel_entity(ptr);
618       tp = get_entity_type(up_ent);
619       if (is_Array_type(tp) && get_array_element_entity(tp) == ent) {
620         name(f, "  ent = get_Sel_entity(", ptr, ");\n");
621         fprintf(f, "  ent = get_array_element_entity(get_entity_type(ent));\n");
622         have_ent = 1;
623       }
624     }
625   }
626   if (n_index > 1)
627     for (i = 0; i < n_index; ++i) {
628       fprintf(f, "  in[%d] = ", i);
629       name(f, NULL, get_Sel_index(n, i), ";\n");
630     }
631
632   if (n_index == 0)
633     name(f, "  ", n, " = new_r_simpleSel(irg, ");
634   else
635     name(f, "  ", n, " = new_r_Sel(irg, ");
636   name(f, NULL, get_nodes_block(n), ", ");
637   name(f, NULL, get_Sel_mem(n), ", ");
638   name(f, NULL, ptr, ", ");
639   if (n_index == 1)
640     name(f, "1, &", get_Sel_index(n, 0), ", ");
641   else if (n_index > 0)
642     fprintf(f, "%d, in, ", n_index);
643
644   ent = get_Sel_entity(n);
645   if (have_ent)
646     fprintf(f, "ent);\n");
647   else
648     fprintf(f, "ENTITY(%s));\n", get_entity_name(get_Sel_entity(n)));
649 }
650
651 /**
652  * Generate code for a Block. Break loops here.
653  *
654  * @param f   file handle for output
655  * @param n   the node
656  */
657 static void generate_code_Block(fix_ctx *env, ir_node *n)
658 {
659   FILE *f = env->f;
660   int i, arity = get_irn_arity(n);
661   for (i = 0; i < arity; ++i) {
662     fprintf(f, "  in[%d] = ", i);
663     if (is_backedge(n, i)) {
664       fprintf(f, "unknownX;\n");
665       env->has_backedges = 1;
666     }
667     else
668       name(f, NULL, get_irn_n(n, i), ";\n");
669   }
670
671   name(f, "  ", n, " = new_r_Block(irg, ");
672   fprintf(f, "%d, in);\n", arity);
673 }
674
675 /**
676  * Generate code for a Phi. Break loops here.
677  *
678  * @param f   file handle for output
679  * @param n   the node
680  */
681 static void generate_code_Phi(fix_ctx *env, ir_node *n)
682 {
683   FILE *f = env->f;
684   int i, arity = get_irn_arity(n);
685   ir_mode *mode = get_irn_mode(n);
686
687   if (has_backedges(n)) {
688     fprintf(f, "  unknown = new_r_Unknown(irg, mode_%s);\n", get_mode_name(mode));
689     env->has_backedges = 1;
690   }
691   for (i = 0; i < arity; ++i) {
692     fprintf(f, "  in[%d] = ", i);
693     if (is_backedge(n, i))
694       fprintf(f, "unknown;\n");
695     else
696       name(f, NULL, get_irn_n(n, i), ";\n");
697   }
698
699   name(f, "  ", n, " = new_r_Phi(irg, ");
700   fprintf(f, "%d, in, mode_%s);\n", arity, get_mode_name(mode));
701 }
702
703 /**
704  * Generate code for a Proj(Load).
705  *
706  * @param f   file handle for output
707  * @param n   the node
708  */
709 static void generate_code_Proj_Load(FILE *f, ir_node *n)
710 {
711   ir_node *pred = get_Proj_pred(n);
712   ir_node *block = get_nodes_block(n);
713   long proj_nr = get_Proj_proj(n);
714   const char *mode = "NULL";
715   const char *proj= "-1";
716
717   switch(proj_nr) {
718   case pn_Load_M:
719     mode = "mode_M";
720     proj = "pn_Load_M";
721     break;
722   case pn_Load_X_regular:
723     mode = "mode_X";
724     proj = "pn_Load_X_regular";
725     break;
726   case pn_Load_X_except:
727     mode = "mode_X";
728     proj = "pn_Load_X_except";
729     break;
730   case pn_Load_res:
731     mode = "mode";
732     proj = "pn_Load_res";
733     name(f, "  mode = get_Load_mode(", pred, ");\n");
734     break;
735   }
736   name(f, "  ", n, " = new_r_Proj(irg, ");
737   name(f, NULL, block, ", ");
738   name(f, NULL, pred, ", ");
739   fprintf(f, "%s, %s);\n", mode, proj);
740 }
741
742 /**
743  * Generate code for a Proj(Store).
744  *
745  * @param f   file handle for output
746  * @param n   the node
747  */
748 static void generate_code_Proj_Store(FILE *f, ir_node *n)
749 {
750   ir_node *pred = get_Proj_pred(n);
751   ir_node *block = get_nodes_block(n);
752   long proj_nr = get_Proj_proj(n);
753   const char *mode = "NULL";
754   const char *proj= "-1";
755
756   switch(proj_nr) {
757   case pn_Store_M:
758     mode = "mode_M";
759     proj = "pn_Store_M";
760     break;
761   case pn_Store_X_regular:
762     mode = "mode_X";
763     proj = "pn_Store_X_regular";
764     break;
765   case pn_Store_X_except:
766     mode = "mode_X";
767     proj = "pn_Store_X_except";
768     break;
769   }
770   name(f, "  ", n, " = new_r_Proj(irg, ");
771   name(f, NULL, block, ", ");
772   name(f, NULL, pred, ", ");
773   fprintf(f, "%s, %s);\n", mode, proj);
774 }
775
776 /**
777  * Generate code for a Proj(Div).
778  *
779  * @param f   file handle for output
780  * @param n   the node
781  */
782 static void generate_code_Proj_Div(FILE *f, ir_node *n)
783 {
784   ir_node *pred = get_Proj_pred(n);
785   ir_node *block = get_nodes_block(n);
786   long proj_nr = get_Proj_proj(n);
787   const char *mode = "NULL";
788   const char *proj= "-1";
789
790   switch(proj_nr) {
791   case pn_Div_M:
792     mode = "mode_M";
793     proj = "pn_Div_M";
794     break;
795   case pn_Div_X_regular:
796     mode = "mode_X";
797     proj = "pn_Div_X_regular";
798     break;
799   case pn_Div_X_except:
800     mode = "mode_X";
801     proj = "pn_Div_X_except";
802     break;
803   case pn_Div_res:
804     mode = "mode";
805     proj = "pn_Div_res";
806     name(f, "  mode = get_Div_resmode(", pred, ");\n");
807     break;
808   }
809   name(f, "  ", n, " = new_r_Proj(irg, ");
810   name(f, NULL, block, ", ");
811   name(f, NULL, pred, ", ");
812   fprintf(f, "%s, %s);\n", mode, proj);
813 }
814
815 /**
816  * Generate code for a Proj(Mod).
817  *
818  * @param f   file handle for output
819  * @param n   the node
820  */
821 static void generate_code_Proj_Mod(FILE *f, ir_node *n)
822 {
823   ir_node *pred = get_Proj_pred(n);
824   ir_node *block = get_nodes_block(n);
825   long proj_nr = get_Proj_proj(n);
826   const char *mode = "NULL";
827   const char *proj= "-1";
828
829   switch(proj_nr) {
830   case pn_Mod_M:
831     mode = "mode_M";
832     proj = "pn_Mod_M";
833     break;
834   case pn_Mod_X_regular:
835     mode = "mode_X";
836     proj = "pn_Mod_X_regular";
837     break;
838   case pn_Mod_X_except:
839     mode = "mode_X";
840     proj = "pn_Mod_X_except";
841     break;
842   case pn_Mod_res:
843     mode = "mode";
844     proj = "pn_Mod_res";
845     name(f, "  mode = get_Mod_resmode(", pred, ");\n");
846     break;
847   }
848   name(f, "  ", n, " = new_r_Proj(irg, ");
849   name(f, NULL, block, ", ");
850   name(f, NULL, pred, ", ");
851   fprintf(f, "%s, %s);\n", mode, proj);
852 }
853
854 /**
855  * Generate code for a Proj(DivMod).
856  *
857  * @param f   file handle for output
858  * @param n   the node
859  */
860 static void generate_code_Proj_DivMod(FILE *f, ir_node *n)
861 {
862   ir_node *pred = get_Proj_pred(n);
863   ir_node *block = get_nodes_block(n);
864   long proj_nr = get_Proj_proj(n);
865   const char *mode = "NULL";
866   const char *proj= "-1";
867
868   switch(proj_nr) {
869   case pn_DivMod_M:
870     mode = "mode_M";
871     proj = "pn_DivMod_M";
872     break;
873   case pn_DivMod_X_except:
874     mode = "mode_X";
875     proj = "pn_DivMod_X_except";
876     break;
877   case pn_DivMod_res_div:
878     mode = "mode";
879     proj = "pn_DivMod_res_div";
880     name(f, "  mode = get_DivMod_resmode(", pred, ");\n");
881     break;
882   case pn_DivMod_res_mod:
883     mode = "mode";
884     proj = "pn_DivMod_res_mod";
885     name(f, "  mode = get_DivMod_resmode(", pred, ");\n");
886     break;
887   }
888   name(f, "  ", n, " = new_r_Proj(irg, ");
889   name(f, NULL, block, ", ");
890   name(f, NULL, pred, ", ");
891   fprintf(f, "%s, %s);\n", mode, proj);
892 }
893
894 /**
895  * Generate code for a Proj(Cmp).
896  *
897  * @param f   file handle for output
898  * @param n   the node
899  */
900 static void generate_code_Proj_Cmp(FILE *f, ir_node *n)
901 {
902   long proj_nr = get_Proj_proj(n);
903
904   name(f, "  ", n, " = new_r_Proj(irg, ");
905   name(f, NULL, get_nodes_block(n), ", ");
906   name(f, NULL, get_Proj_pred(n), ", ");
907   fprintf(f, "mode_b, %s);\n", get_pnc_string(proj_nr));
908 }
909
910 /**
911  * Generate code for a Proj(Cond).
912  *
913  * @param f   file handle for output
914  * @param n   the node
915  */
916 static void generate_code_Proj_Cond(FILE *f, ir_node *n)
917 {
918   ir_node *cond = get_Proj_pred(n);
919   ir_node *sel = get_Cond_selector(cond);
920   ir_node *block = get_nodes_block(n);
921   long proj_nr = get_Proj_proj(n);
922
923   if (get_irn_mode(sel) == mode_b) {
924     name(f, "  ", n, " = new_r_Proj(irg, ");
925     name(f, NULL, block, ", ");
926     name(f, NULL, cond, ", ");
927     fprintf(f, "mode_b, %s);\n", proj_nr ? "pn_Cond_true" : "pn_Cond_false");
928   }
929   else {
930     if (proj_nr == get_Cond_default_proj(cond))
931       name(f, "  ", n, " = new_r_defaultProj(irg, ");
932     else
933       name(f, "  ", n, " = new_r_Proj(irg, ");
934
935     name(f, NULL, block, ", ");
936     name(f, NULL, cond, ", ");
937     fprintf(f, "mode_%s, %ld);\n", get_mode_name(get_irn_mode(n)), proj_nr);
938   }
939 }
940
941 /**
942  * Generate code for a Proj.
943  *
944  * @param f   file handle for output
945  * @param n   the node
946  */
947 static void generate_code_Proj(FILE *f, ir_node *n)
948 {
949   ir_node *pred = get_Proj_pred(n);
950
951   switch (get_irn_opcode(pred)) {
952   case iro_Load:
953     generate_code_Proj_Load(f, n);
954     break;
955   case iro_Store:
956     generate_code_Proj_Store(f, n);
957     break;
958   case iro_Div:
959     generate_code_Proj_Div(f, n);
960     break;
961   case iro_Mod:
962     generate_code_Proj_Mod(f, n);
963     break;
964   case iro_DivMod:
965     generate_code_Proj_DivMod(f, n);
966     break;
967   case iro_Cmp:
968     generate_code_Proj_Cmp(f, n);
969     break;
970   case iro_Cond:
971     generate_code_Proj_Cond(f, n);
972     break;
973   default: {
974     const char *mode_name = get_mode_name(get_irn_mode(n));
975     name(f, "  ", n, " = new_r_Proj(irg, ");
976     name(f, NULL, get_nodes_block(n), ", ");
977     name(f, NULL, get_Proj_pred(n), ", ");
978     fprintf(f, "mode_%s, %ld);\n", mode_name, get_Proj_proj(n));
979   }
980   }
981 }
982
983 /**
984  * Generate code for a Jmp.
985  *
986  * @param f   file handle for output
987  * @param n   the node
988  */
989 static void generate_code_Jmp(FILE *f, ir_node *n)
990 {
991   name(f, "  ", n, " = new_r_Jmp(irg, ");
992   name(f, NULL, get_nodes_block(n), ");\n");
993 }
994
995 /**
996  * Generate code for a Cond.
997  *
998  * @param f   file handle for output
999  * @param n   the node
1000  */
1001 static void generate_code_Cond(FILE *f, ir_node *n)
1002 {
1003   name(f, "  ", n, " = new_r_Cond(irg, ");
1004   name(f, NULL, get_nodes_block(n), ", ");
1005   name(f, NULL, get_Cond_selector(n), ");\n");
1006 }
1007
1008 /**
1009  * Generate code for a Call.
1010  *
1011  * @param f   file handle for output
1012  * @param n   the node
1013  */
1014 static void generate_code_Call(FILE *f, ir_node *n)
1015 {
1016   int i, n_param = get_Call_n_params(n);
1017   ir_node *ptr = get_Call_ptr(n);
1018   ir_op *op = get_irn_op(ptr);
1019   ir_entity *ent;
1020   ir_type *tp = get_Call_type(n);
1021   int have_tp = 0;
1022
1023   /* try to detect the type */
1024   if (op == op_Sel) {
1025     ent = get_Sel_entity(ptr);
1026     if (tp == get_entity_type(ent)) {
1027       name(f, "  ent = get_Sel_entity(", ptr, ");\n");
1028       fprintf(f, "  tp = get_entity_type(ent);\n");
1029       have_tp = 1;
1030     }
1031   }
1032   else if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
1033     ent = get_SymConst_entity(ptr);
1034     if (tp == get_entity_type(ent)) {
1035       name(f, "  ent = get_SymConst_entity(", ptr, ");\n");
1036       fprintf(f, "  tp = get_entity_type(ent);\n");
1037       have_tp = 1;
1038     }
1039   }
1040   if (! have_tp)
1041     fprintf(f, "  tp = TYPE(%s);\n", get_type_name(tp));
1042
1043   for (i = 0; i < n_param; ++i) {
1044     fprintf(f, "  in[%d] = ", i);
1045     name(f, NULL, get_Call_param(n, i), ";\n");
1046   }
1047   name(f, "  ", n, " = ");
1048   fprintf(f, "new_r_Call(irg, ");
1049   name(f, NULL, get_nodes_block(n), ", ");
1050   name(f, NULL, get_Call_mem(n), ", ");
1051   if (n_param > 0)
1052     fprintf(f, "%d, in, tp);\n", n_param);
1053   else
1054     fprintf(f, "0, NULL, tp);\n");
1055 }
1056
1057 /**
1058  * Create code for the given Alloc node
1059  *
1060  * @param f   file handle for output
1061  * @param n   the node
1062  */
1063 static void generate_code_Alloc(FILE *f, ir_node *n)
1064 {
1065   name(f, "  ", n, " = new_r_Alloc(irg, ");
1066   name(f, NULL, get_nodes_block(n), ", ");
1067   name(f, NULL, get_Alloc_mem(n), ", ");
1068   name(f, NULL, get_Alloc_size(n), ", tp, ");
1069   fprintf(f, get_Alloc_where(n) == stack_alloc ? "stack_alloc);\n" : "heap_alloc);\n");
1070 }
1071
1072 /**
1073  * Create code for the given Free node
1074  *
1075  * @param f   file handle for output
1076  * @param n   the node
1077  */
1078 static void generate_code_Free(FILE *f, ir_node *n)
1079 {
1080   fprintf(f, "  tp = TYPE(%s);\n", get_type_name(get_Free_type(n)));
1081   name(f, "  ", n, " = new_r_Alloc(irg, ");
1082   name(f, NULL, get_nodes_block(n), ", ");
1083   name(f, NULL, get_Free_ptr(n), ", ");
1084   name(f, NULL, get_Free_size(n), ", tp, ");
1085   fprintf(f, get_Free_where(n) == stack_alloc ? "stack_alloc);\n" : "heap_alloc);\n");
1086 }
1087
1088 /**
1089  * Create code for the given node constructor.
1090  *
1091  * @param f   file handle for output
1092  * @param n   the node
1093  */
1094 static void generate_node(fix_ctx *env, ir_node *n)
1095 {
1096   FILE *f = env->f;
1097   ir_op *op = get_irn_op(n);
1098
1099   if (op == op_Div || op == op_Mod || op == op_DivMod || op == op_Quot)
1100     generate_code_Divop(f, n);
1101   else if (op == op_Load)
1102     generate_code_Load(f, n);
1103   else if (op == op_Store)
1104     generate_code_Store(f, n);
1105   else if (op == op_Return)
1106     generate_code_Return(f, n);
1107   else if (op == op_Raise)
1108     generate_code_Raise(f, n);
1109   else if (op == op_Bound)
1110     generate_code_Bound(f, n);
1111   else if (op == op_Unknown)
1112     generate_code_Unknown(f, n);
1113   else if (op == op_Bad)
1114     generate_code_Bad(f, n);
1115   else if (op == op_Const)
1116     generate_code_Const(f, n);
1117   else if (op == op_SymConst)
1118     generate_code_SymConst(f, n);
1119   else if (op == op_Sel)
1120     generate_code_Sel(f, n);
1121   else if (op == op_Block)
1122     generate_code_Block(env, n);
1123   else if (op == op_Phi)
1124     generate_code_Phi(env, n);
1125   else if (op == op_Proj)
1126     generate_code_Proj(f, n);
1127   else if (op == op_Jmp)
1128     generate_code_Jmp(f, n);
1129   else if (op == op_Cond)
1130     generate_code_Cond(f, n);
1131   else if (op == op_Call)
1132     generate_code_Call(f, n);
1133   else if (op == op_Alloc)
1134     generate_code_Alloc(f, n);
1135   else if (op == op_Free)
1136     generate_code_Free(f, n);
1137   else if (is_binop(n))
1138     generate_code_Binop(f, n);
1139   else if (is_unop(n))
1140     generate_code_Unop(f, n);
1141   else
1142     name(f, "  ", n, " = NULL;\n");
1143 }
1144
1145 /**
1146  * Walker: Create code for the given node.
1147  */
1148 static void dump_code(ir_node *n, void *ctx)
1149 {
1150   fix_ctx *env = ctx;
1151
1152   if (! generate_predef_node(env->f, n))
1153     generate_node(env, n);
1154 }
1155
1156 /**
1157  * Generate Firm code.
1158  *
1159  * @param env  a fix environment
1160  * @param irg  the graph
1161  */
1162 static void generate_code(fix_ctx *env, ir_graph *irg)
1163 {
1164   irg_walk_graph(irg, NULL, dump_code, env);
1165 }
1166
1167 /**
1168  * Generate Firm assembler for a given graph
1169  *
1170  * @param f    the output file handle
1171  * @param irg  the graph
1172  */
1173 static void gen_Firm_assembler_irg(FILE *f, ir_graph *irg)
1174 {
1175   fix_ctx fenv;
1176   var_ctx venv;
1177
1178   venv.f              = f;
1179   venv.max_arity      = 0;
1180   venv.need_tv        = 0;
1181   venv.need_unknown_X = 0;
1182   venv.need_unknown   = 0;
1183
1184   fenv.f              = f;
1185   fenv.start_block    = get_irg_start_block(irg);
1186   fenv.has_backedges  = 0;
1187
1188   /* needed to detect loops */
1189   construct_backedges(irg);
1190
1191   generate_header(f, irg);
1192   generate_var_decls(&venv, irg);
1193   generate_prolog(&venv, irg);
1194   generate_code(&fenv, irg);
1195   generate_epilog(&fenv, irg);
1196 }
1197
1198 void gen_Firm_assembler(const char *input_filename)
1199 {
1200   FILE     *f;
1201   ir_graph *irg;
1202   int      i, n;
1203   (void) input_filename;
1204
1205   f = fopen("firm_output.c", "w");
1206   if (f) {
1207     for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
1208       irg = get_irp_irg(i);
1209       gen_Firm_assembler_irg(f, irg);
1210     }
1211   }
1212   else {
1213     /* report some error here */
1214   }
1215   fclose(f);
1216 }