2 * Generate Firm assembler from Firm graphs.
4 * (C) 2005-2006 Michael Beck beck@ipd.info.uni-karlsruhe.de
8 #include <libfirm/firm.h>
12 * The variable context. Contains information
13 * about needed variables.
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. */
24 * A context for backedge fixes.
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. */
33 * Print the name of an IR-node as <prefix><op>_<idx><suffix>.
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
40 static void name(FILE *f, const char *prefix, ir_node *n, const char *suffix)
42 const char *op_name = get_op_name(get_irn_op(n));
43 unsigned index = get_irn_idx(n);
49 fprintf(f, "%s%s_%u%s", prefix, op_name, index, suffix);
53 * Generate the header of the function.
55 * @param f the output file handle
56 * @param irg the graph
58 static void generate_header(FILE *f, ir_graph *irg)
61 ir_entity *ent = get_irg_entity(irg);
62 ir_type *tp = get_entity_type(ent);
63 const char *s = get_entity_name(ent);
66 " * Generates the Firm code for\n"
69 if (get_method_n_ress(tp) == 0)
72 fprintf(f, get_type_name(get_method_res_type(tp, 0)));
73 fprintf(f, " %s(", s);
74 n = get_method_n_params(tp);
76 fprintf(f, get_method_variadicity(tp) == variadicity_variadic ? "" : "void");
78 for (i = 0; i < n; ++i) {
81 fprintf(f, get_type_name(get_method_param_type(tp, i)));
83 if (get_method_variadicity(tp) == variadicity_variadic)
90 " * @param func the entity for the generated graph\n"
92 "void gen_firm_%s(ir_entity *func)\n"
95 " ir_graph *rem = current_ir_graph;\n");
99 * Generate the function prolog.
101 * @param env a variable context
102 * @param irg the graph
104 static void generate_prolog(var_ctx *env, ir_graph *irg)
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");
119 * Walker: Fix Block and Phi nodes containing backedges.
121 static void fix_block_and_phi(ir_node *n, void *ctx)
127 if (is_Block(n) || is_Phi(n)) {
128 arity = get_irn_arity(n);
130 /* ignore the start block */
131 if (n == env->start_block)
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");
146 * Generate the function epilog.
148 * @param env the backedge fix context
149 * @param irg the graph
151 static void generate_epilog(fix_ctx *env, ir_graph *irg)
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);
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");
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)));
177 * Walker: Create a variable declaration for a given node.
178 * The variable name is <op>_<node idx>, see name().
180 * @param n the current IR-node
181 * @param ctx a variable context
183 static void dump_var_def(ir_node *n, void *ctx)
186 int arity = get_irn_arity(n);
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)
193 if (has_backedges(n)) {
195 env->need_unknown_X = 1;
197 env->need_unknown = 1;
202 * Generate all needed variable declarations for a graph.
204 * @param env a variable context
205 * @param irg the graph
207 static void generate_var_decls(var_ctx *env, ir_graph *irg)
211 irg_walk_graph(irg, NULL, dump_var_def, env);
212 fprintf(f, " ir_node *in[%d];\n", env->max_arity);
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");
229 * Generate code for a predefined node.
231 * @param f file handle for output
234 * @return non-zero if n was a predefined node, 0 else
236 static int generate_predef_node(FILE *f, ir_node *n)
238 ir_graph *irg = current_ir_graph;
241 else if (n == code) \
242 name(f, " ", n, " = " #code ";\n");
245 X(get_irg_start(irg))
246 X(get_irg_start_block(irg))
248 X(get_irg_end_block(irg))
249 X(get_irg_frame(irg))
250 X(get_irg_globals(irg))
252 X(get_irg_value_param_base(irg))
253 X(get_irg_initial_mem(irg))
254 X(get_irg_no_mem(irg))
263 * Generate code for a Binop node.
265 * @param f file handle for output
268 static void generate_code_Binop(FILE *f, ir_node *n)
270 ir_op *op = get_irn_op(n);
271 ir_node *right = get_binop_right(n);
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");
282 * Generate code for a Divop node.
284 * @param f file handle for output
287 static void generate_code_Divop(FILE *f, ir_node *n)
289 ir_op *op = get_irn_op(n);
290 ir_node *right = get_binop_right(n);
291 ir_mode *mode = get_divop_resmod(n);
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, ", ");
300 /* avoid to print the mode name if possible */
301 if (mode == get_irn_mode(right)) {
302 name(f, "get_irn_mode(", right, ");\n");
304 fprintf(f, "mode_%s);\n", get_mode_name(mode));
309 * Generate code for an Unop node.
311 * @param f file handle for output
314 static void generate_code_Unop(FILE *f, ir_node *n)
316 ir_op *op = get_irn_op(n);
317 ir_node *irn = get_unop_op(n);
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");
327 * Generate code for a Load.
329 * @param f file handle for output
332 static void generate_code_Load(FILE *f, ir_node *n)
334 ir_node *ptr = get_Load_ptr(n);
335 ir_op *op = get_irn_op(ptr);
338 /* try to detect the mode */
340 name(f, " ent = get_Sel_entity(", ptr, ");\n");
341 fprintf(f, " mode = get_type_mode(get_entity_type(ent));\n");
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");
348 fprintf(f, " mode = mode_%s;\n", get_mode_name(get_Load_mode(n)));
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));
363 * Generate code for a Store.
365 * @param f file handle for output
368 static void generate_code_Store(FILE *f, ir_node *n)
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));
386 * Generate code for a Return.
388 static void generate_code_Return(FILE *f, ir_node *n)
390 int i, n_res = get_Return_n_ress(n);
393 for (i = 0; i < n_res; ++i) {
394 fprintf(f, " in[%d] = ", i);
395 name(f, NULL, get_Return_res(n, i), ";\n");
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), ", ");
402 fprintf(f, "%d, in);\n", n_res);
404 name(f, "1, &", get_Return_res(n, 0), ");\n");
406 fprintf(f, "0, NULL);\n");
410 * Generate code for a Raise.
412 * @param f file handle for output
415 static void generate_code_Raise(FILE *f, ir_node *n)
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");
424 * Generate code for a Bound.
426 * @param f file handle for output
429 static void generate_code_Bound(FILE *f, ir_node *n)
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");
439 * Generate code for an Unknown.
441 * @param f file handle for output
444 static void generate_code_Unknown(FILE *f, ir_node *n)
446 name(f, " ", n, " = new_r_Unknown(irg, ");
447 fprintf(f, "mode_%s);\n", get_mode_name(get_irn_mode(n)));
451 * Generate code for a Bad.
453 * @param f file handle for output
456 static void generate_code_Bad(FILE *f, ir_node *n)
458 name(f, " ", n, " = new_r_Bad(irg);\n");
462 * Generate code for a Const.
464 * @param f file handle for output
467 static void generate_code_Const(FILE *f, ir_node *n)
469 ir_type *tp = get_Const_type(n);
470 tarval *tv = get_Const_tarval(n);
471 ir_mode *mode = get_irn_mode(n);
474 if (tp == get_unknown_type()) {
475 name(f, " ", n, " = new_r_Const(irg, ");
478 name(f, " ", n, " = new_r_Const_type(irg, ");
480 name(f, NULL, get_nodes_block(n), ", ");
481 fprintf(f, "mode_%s, ", get_mode_name(mode));
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)");
508 if (tv == get_tarval_null(mode))
509 fprintf(f, "get_tarval_null(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));
518 if (tp != get_unknown_type())
519 fprintf(f, ", %s", get_type_name(tp));
524 * Generate code for a SymConst.
526 * @param f file handle for output
529 static void generate_code_SymConst(FILE *f, ir_node *n)
535 symconst_kind kind = get_SymConst_kind(n);
536 const char *k_name = "NULL";
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";
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";
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";
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";
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";
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";
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";
577 label = get_SymConst_label(n);
578 fprintf(f, " sym.label = %lu;\n", label);
579 k_name = "symconst_label";
582 name(f, " ", n, " = new_r_SymConst(irg, ");
583 name(f, NULL, get_nodes_block(n), ", sym, ");
584 fprintf(f, "%s);\n", k_name);
588 * Generate code for a Sel.
590 * @param f file handle for output
593 static void generate_code_Sel(FILE *f, ir_node *n)
595 int n_index = get_Sel_n_indexs(n);
598 ir_node *ptr = get_Sel_ptr(n);
599 ir_entity *ent = get_Sel_entity(n);
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");
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");
628 for (i = 0; i < n_index; ++i) {
629 fprintf(f, " in[%d] = ", i);
630 name(f, NULL, get_Sel_index(n, i), ";\n");
634 name(f, " ", n, " = new_r_simpleSel(irg, ");
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, ", ");
641 name(f, "1, &", get_Sel_index(n, 0), ", ");
642 else if (n_index > 0)
643 fprintf(f, "%d, in, ", n_index);
645 ent = get_Sel_entity(n);
647 fprintf(f, "ent);\n");
649 fprintf(f, "ENTITY(%s));\n", get_entity_name(get_Sel_entity(n)));
653 * Generate code for a Block. Break loops here.
655 * @param f file handle for output
658 static void generate_code_Block(fix_ctx *env, ir_node *n)
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;
669 name(f, NULL, get_irn_n(n, i), ";\n");
672 name(f, " ", n, " = new_r_Block(irg, ");
673 fprintf(f, "%d, in);\n", arity);
677 * Generate code for a Phi. Break loops here.
679 * @param f file handle for output
682 static void generate_code_Phi(fix_ctx *env, ir_node *n)
685 int i, arity = get_irn_arity(n);
686 ir_mode *mode = get_irn_mode(n);
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;
692 for (i = 0; i < arity; ++i) {
693 fprintf(f, " in[%d] = ", i);
694 if (is_backedge(n, i))
695 fprintf(f, "unknown;\n");
697 name(f, NULL, get_irn_n(n, i), ";\n");
700 name(f, " ", n, " = new_r_Phi(irg, ");
701 fprintf(f, "%d, in, mode_%s);\n", arity, get_mode_name(mode));
705 * Generate code for a Proj(Load).
707 * @param f file handle for output
710 static void generate_code_Proj_Load(FILE *f, ir_node *n)
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";
723 case pn_Load_X_regular:
725 proj = "pn_Load_X_regular";
727 case pn_Load_X_except:
729 proj = "pn_Load_X_except";
733 proj = "pn_Load_res";
734 name(f, " mode = get_Load_mode(", pred, ");\n");
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);
744 * Generate code for a Proj(Store).
746 * @param f file handle for output
749 static void generate_code_Proj_Store(FILE *f, ir_node *n)
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";
762 case pn_Store_X_regular:
764 proj = "pn_Store_X_regular";
766 case pn_Store_X_except:
768 proj = "pn_Store_X_except";
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);
778 * Generate code for a Proj(Div).
780 * @param f file handle for output
783 static void generate_code_Proj_Div(FILE *f, ir_node *n)
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";
796 case pn_Div_X_regular:
798 proj = "pn_Div_X_regular";
800 case pn_Div_X_except:
802 proj = "pn_Div_X_except";
807 name(f, " mode = get_Div_resmode(", pred, ");\n");
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);
817 * Generate code for a Proj(Mod).
819 * @param f file handle for output
822 static void generate_code_Proj_Mod(FILE *f, ir_node *n)
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";
835 case pn_Mod_X_regular:
837 proj = "pn_Mod_X_regular";
839 case pn_Mod_X_except:
841 proj = "pn_Mod_X_except";
846 name(f, " mode = get_Mod_resmode(", pred, ");\n");
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);
856 * Generate code for a Proj(DivMod).
858 * @param f file handle for output
861 static void generate_code_Proj_DivMod(FILE *f, ir_node *n)
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";
872 proj = "pn_DivMod_M";
874 case pn_DivMod_X_except:
876 proj = "pn_DivMod_X_except";
878 case pn_DivMod_res_div:
880 proj = "pn_DivMod_res_div";
881 name(f, " mode = get_DivMod_resmode(", pred, ");\n");
883 case pn_DivMod_res_mod:
885 proj = "pn_DivMod_res_mod";
886 name(f, " mode = get_DivMod_resmode(", pred, ");\n");
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);
896 * Generate code for a Proj(Cmp).
898 * @param f file handle for output
901 static void generate_code_Proj_Cmp(FILE *f, ir_node *n)
903 long proj_nr = get_Proj_proj(n);
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));
912 * Generate code for a Proj(Cond).
914 * @param f file handle for output
917 static void generate_code_Proj_Cond(FILE *f, ir_node *n)
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);
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");
931 if (proj_nr == get_Cond_defaultProj(cond))
932 name(f, " ", n, " = new_r_defaultProj(irg, ");
934 name(f, " ", n, " = new_r_Proj(irg, ");
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);
943 * Generate code for a Proj.
945 * @param f file handle for output
948 static void generate_code_Proj(FILE *f, ir_node *n)
950 ir_node *pred = get_Proj_pred(n);
952 switch (get_irn_opcode(pred)) {
954 generate_code_Proj_Load(f, n);
957 generate_code_Proj_Store(f, n);
960 generate_code_Proj_Div(f, n);
963 generate_code_Proj_Mod(f, n);
966 generate_code_Proj_DivMod(f, n);
969 generate_code_Proj_Cmp(f, n);
972 generate_code_Proj_Cond(f, n);
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));
985 * Generate code for a Jmp.
987 * @param f file handle for output
990 static void generate_code_Jmp(FILE *f, ir_node *n)
992 name(f, " ", n, " = new_r_Jmp(irg, ");
993 name(f, NULL, get_nodes_block(n), ");\n");
997 * Generate code for a Cond.
999 * @param f file handle for output
1002 static void generate_code_Cond(FILE *f, ir_node *n)
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");
1010 * Generate code for a Call.
1012 * @param f file handle for output
1015 static void generate_code_Call(FILE *f, ir_node *n)
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);
1021 ir_type *tp = get_Call_type(n);
1024 /* try to detect the type */
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");
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");
1042 fprintf(f, " tp = TYPE(%s);\n", get_type_name(tp));
1044 for (i = 0; i < n_param; ++i) {
1045 fprintf(f, " in[%d] = ", i);
1046 name(f, NULL, get_Call_param(n, i), ";\n");
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), ", ");
1053 fprintf(f, "%d, in, tp);\n", n_param);
1055 fprintf(f, "0, NULL, tp);\n");
1059 * Create code for the given Alloc node
1061 * @param f file handle for output
1064 static void generate_code_Alloc(FILE *f, ir_node *n)
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");
1074 * Create code for the given Free node
1076 * @param f file handle for output
1079 static void generate_code_Free(FILE *f, ir_node *n)
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");
1090 * Create code for the given node constructor.
1092 * @param f file handle for output
1095 static void generate_node(fix_ctx *env, ir_node *n)
1098 ir_op *op = get_irn_op(n);
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);
1143 name(f, " ", n, " = NULL;\n");
1147 * Walker: Create code for the given node.
1149 static void dump_code(ir_node *n, void *ctx)
1153 if (! generate_predef_node(env->f, n))
1154 generate_node(env, n);
1158 * Generate Firm code.
1160 * @param env a fix environment
1161 * @param irg the graph
1163 static void generate_code(fix_ctx *env, ir_graph *irg)
1165 irg_walk_graph(irg, NULL, dump_code, env);
1169 * Generate Firm assembler for a given graph
1171 * @param f the output file handle
1172 * @param irg the graph
1174 static void gen_Firm_assembler_irg(FILE *f, ir_graph *irg)
1182 venv.need_unknown_X = 0;
1183 venv.need_unknown = 0;
1186 fenv.start_block = get_irg_start_block(irg);
1187 fenv.has_backedges = 0;
1189 /* needed to detect loops */
1190 construct_backedges(irg);
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);
1199 void gen_Firm_assembler(const char *input_filename)
1204 (void) input_filename;
1206 f = fopen("firm_output.c", "w");
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);
1214 /* report some error here */