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