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 fprintf(f, "%s%s_%u%s",
44 get_op_name(get_irn_op(n)),
46 suffix ? suffix : "");
50 * Generate the header of the function.
52 * @param f the output file handle
53 * @param irg the graph
55 static void generate_header(FILE *f, ir_graph *irg)
58 ir_entity *ent = get_irg_entity(irg);
59 ir_type *tp = get_entity_type(ent);
60 const char *s = get_entity_name(ent);
63 " * Generates the Firm code for\n"
66 if (get_method_n_ress(tp) == 0)
69 fprintf(f, get_type_name(get_method_res_type(tp, 0)));
70 fprintf(f, " %s(", s);
71 n = get_method_n_params(tp);
73 fprintf(f, get_method_variadicity(tp) == variadicity_variadic ? "" : "void");
75 for (i = 0; i < n; ++i) {
78 fprintf(f, get_type_name(get_method_param_type(tp, i)));
80 if (get_method_variadicity(tp) == variadicity_variadic)
87 " * @param func the entity for the generated graph\n"
89 "void gen_firm_%s(ir_entity *func)\n"
92 " ir_graph *rem = current_ir_graph;\n");
96 * Generate the function prolog.
98 * @param env a variable context
99 * @param irg the graph
101 static void generate_prolog(var_ctx *env, ir_graph *irg)
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");
116 * Walker: Fix Block and Phi nodes containing backedges.
118 static void fix_block_and_phi(ir_node *n, void *ctx)
124 if (is_Block(n) || is_Phi(n)) {
125 arity = get_irn_arity(n);
127 /* ignore the start block */
128 if (n == env->start_block)
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");
143 * Generate the function epilog.
145 * @param env the backedge fix context
146 * @param irg the graph
148 static void generate_epilog(fix_ctx *env, ir_graph *irg)
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);
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");
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)));
174 * Walker: Create a variable declaration for a given node.
175 * The variable name is <op>_<node idx>, see name().
177 * @param n the current IR-node
178 * @param ctx a variable context
180 static void dump_var_def(ir_node *n, void *ctx)
183 int arity = get_irn_arity(n);
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)
190 if (has_backedges(n)) {
192 env->need_unknown_X = 1;
194 env->need_unknown = 1;
199 * Generate all needed variable declarations for a graph.
201 * @param env a variable context
202 * @param irg the graph
204 static void generate_var_decls(var_ctx *env, ir_graph *irg)
208 irg_walk_graph(irg, NULL, dump_var_def, env);
209 fprintf(f, " ir_node *in[%d];\n", env->max_arity);
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");
226 * Generate code for a predefined node.
228 * @param f file handle for output
231 * @return non-zero if n was a predefined node, 0 else
233 static int generate_predef_node(FILE *f, ir_node *n)
235 ir_graph *irg = current_ir_graph;
238 else if (n == code) \
239 name(f, " ", n, " = " #code ";\n");
242 X(get_irg_start(irg))
243 X(get_irg_start_block(irg))
245 X(get_irg_end_block(irg))
246 X(get_irg_frame(irg))
247 X(get_irg_globals(irg))
249 X(get_irg_value_param_base(irg))
250 X(get_irg_initial_mem(irg))
251 X(get_irg_no_mem(irg))
260 * Generate code for a Binop node.
262 * @param f file handle for output
265 static void generate_code_Binop(FILE *f, ir_node *n)
267 ir_op *op = get_irn_op(n);
268 ir_node *right = get_binop_right(n);
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");
279 * Generate code for a Divop node.
281 * @param f file handle for output
284 static void generate_code_Divop(FILE *f, ir_node *n)
286 ir_op *op = get_irn_op(n);
287 ir_node *right = get_binop_right(n);
288 ir_mode *mode = get_divop_resmod(n);
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, ", ");
297 /* avoid to print the mode name if possible */
298 if (mode == get_irn_mode(right)) {
299 name(f, "get_irn_mode(", right, ");\n");
301 fprintf(f, "mode_%s);\n", get_mode_name(mode));
306 * Generate code for an Unop node.
308 * @param f file handle for output
311 static void generate_code_Unop(FILE *f, ir_node *n)
313 ir_op *op = get_irn_op(n);
314 ir_node *irn = get_unop_op(n);
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");
324 * Generate code for a Load.
326 * @param f file handle for output
329 static void generate_code_Load(FILE *f, ir_node *n)
331 ir_node *ptr = get_Load_ptr(n);
332 ir_op *op = get_irn_op(ptr);
335 /* try to detect the mode */
337 name(f, " ent = get_Sel_entity(", ptr, ");\n");
338 fprintf(f, " mode = get_type_mode(get_entity_type(ent));\n");
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");
345 fprintf(f, " mode = mode_%s;\n", get_mode_name(get_Load_mode(n)));
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));
360 * Generate code for a Store.
362 * @param f file handle for output
365 static void generate_code_Store(FILE *f, ir_node *n)
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));
383 * Generate code for a Return.
385 static void generate_code_Return(FILE *f, ir_node *n)
387 int i, n_res = get_Return_n_ress(n);
390 for (i = 0; i < n_res; ++i) {
391 fprintf(f, " in[%d] = ", i);
392 name(f, NULL, get_Return_res(n, i), ";\n");
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), ", ");
399 fprintf(f, "%d, in);\n", n_res);
401 name(f, "1, &", get_Return_res(n, 0), ");\n");
403 fprintf(f, "0, NULL);\n");
407 * Generate code for a Raise.
409 * @param f file handle for output
412 static void generate_code_Raise(FILE *f, ir_node *n)
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");
421 * Generate code for a Bound.
423 * @param f file handle for output
426 static void generate_code_Bound(FILE *f, ir_node *n)
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");
436 * Generate code for an Unknown.
438 * @param f file handle for output
441 static void generate_code_Unknown(FILE *f, ir_node *n)
443 name(f, " ", n, " = new_r_Unknown(irg, ");
444 fprintf(f, "mode_%s);\n", get_mode_name(get_irn_mode(n)));
448 * Generate code for a Bad.
450 * @param f file handle for output
453 static void generate_code_Bad(FILE *f, ir_node *n)
455 name(f, " ", n, " = new_r_Bad(irg);\n");
459 * Generate code for a Const.
461 * @param f file handle for output
464 static void generate_code_Const(FILE *f, ir_node *n)
466 ir_type *tp = get_Const_type(n);
467 tarval *tv = get_Const_tarval(n);
468 ir_mode *mode = get_irn_mode(n);
471 if (tp == get_unknown_type()) {
472 name(f, " ", n, " = new_r_Const(irg, ");
475 name(f, " ", n, " = new_r_Const_type(irg, ");
477 name(f, NULL, get_nodes_block(n), ", ");
478 fprintf(f, "mode_%s, ", get_mode_name(mode));
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)");
505 if (tv == get_tarval_null(mode))
506 fprintf(f, "get_tarval_null(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));
515 if (tp != get_unknown_type())
516 fprintf(f, ", %s", get_type_name(tp));
521 * Generate code for a SymConst.
523 * @param f file handle for output
526 static void generate_code_SymConst(FILE *f, ir_node *n)
532 symconst_kind kind = get_SymConst_kind(n);
533 const char *k_name = "NULL";
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";
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";
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";
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";
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";
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";
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";
571 label = get_SymConst_label(n);
572 fprintf(f, " sym.label = %lu;\n", label);
573 k_name = "symconst_label";
576 name(f, " ", n, " = new_r_SymConst(irg, ");
577 name(f, NULL, get_nodes_block(n), ", sym, ");
578 fprintf(f, "%s);\n", k_name);
582 * Generate code for a Sel.
584 * @param f file handle for output
587 static void generate_code_Sel(FILE *f, ir_node *n)
589 int n_index = get_Sel_n_indexs(n);
592 ir_node *ptr = get_Sel_ptr(n);
593 ir_entity *ent = get_Sel_entity(n);
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");
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");
622 for (i = 0; i < n_index; ++i) {
623 fprintf(f, " in[%d] = ", i);
624 name(f, NULL, get_Sel_index(n, i), ";\n");
628 name(f, " ", n, " = new_r_simpleSel(irg, ");
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, ", ");
635 name(f, "1, &", get_Sel_index(n, 0), ", ");
636 else if (n_index > 0)
637 fprintf(f, "%d, in, ", n_index);
639 ent = get_Sel_entity(n);
641 fprintf(f, "ent);\n");
643 fprintf(f, "ENTITY(%s));\n", get_entity_name(get_Sel_entity(n)));
647 * Generate code for a Block. Break loops here.
649 * @param f file handle for output
652 static void generate_code_Block(fix_ctx *env, ir_node *n)
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;
663 name(f, NULL, get_irn_n(n, i), ";\n");
666 name(f, " ", n, " = new_r_Block(irg, ");
667 fprintf(f, "%d, in);\n", arity);
671 * Generate code for a Phi. Break loops here.
673 * @param f file handle for output
676 static void generate_code_Phi(fix_ctx *env, ir_node *n)
679 int i, arity = get_irn_arity(n);
680 ir_mode *mode = get_irn_mode(n);
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;
686 for (i = 0; i < arity; ++i) {
687 fprintf(f, " in[%d] = ", i);
688 if (is_backedge(n, i))
689 fprintf(f, "unknown;\n");
691 name(f, NULL, get_irn_n(n, i), ";\n");
694 name(f, " ", n, " = new_r_Phi(irg, ");
695 fprintf(f, "%d, in, mode_%s);\n", arity, get_mode_name(mode));
699 * Generate code for a Proj(Load).
701 * @param f file handle for output
704 static void generate_code_Proj_Load(FILE *f, ir_node *n)
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";
717 case pn_Load_X_regular:
719 proj = "pn_Load_X_regular";
721 case pn_Load_X_except:
723 proj = "pn_Load_X_except";
727 proj = "pn_Load_res";
728 name(f, " mode = get_Load_mode(", pred, ");\n");
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);
738 * Generate code for a Proj(Store).
740 * @param f file handle for output
743 static void generate_code_Proj_Store(FILE *f, ir_node *n)
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";
756 case pn_Store_X_regular:
758 proj = "pn_Store_X_regular";
760 case pn_Store_X_except:
762 proj = "pn_Store_X_except";
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);
772 * Generate code for a Proj(Div).
774 * @param f file handle for output
777 static void generate_code_Proj_Div(FILE *f, ir_node *n)
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";
790 case pn_Div_X_regular:
792 proj = "pn_Div_X_regular";
794 case pn_Div_X_except:
796 proj = "pn_Div_X_except";
801 name(f, " mode = get_Div_resmode(", pred, ");\n");
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);
811 * Generate code for a Proj(Mod).
813 * @param f file handle for output
816 static void generate_code_Proj_Mod(FILE *f, ir_node *n)
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";
829 case pn_Mod_X_regular:
831 proj = "pn_Mod_X_regular";
833 case pn_Mod_X_except:
835 proj = "pn_Mod_X_except";
840 name(f, " mode = get_Mod_resmode(", pred, ");\n");
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);
850 * Generate code for a Proj(DivMod).
852 * @param f file handle for output
855 static void generate_code_Proj_DivMod(FILE *f, ir_node *n)
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";
866 proj = "pn_DivMod_M";
868 case pn_DivMod_X_except:
870 proj = "pn_DivMod_X_except";
872 case pn_DivMod_res_div:
874 proj = "pn_DivMod_res_div";
875 name(f, " mode = get_DivMod_resmode(", pred, ");\n");
877 case pn_DivMod_res_mod:
879 proj = "pn_DivMod_res_mod";
880 name(f, " mode = get_DivMod_resmode(", pred, ");\n");
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);
890 * Generate code for a Proj(Cmp).
892 * @param f file handle for output
895 static void generate_code_Proj_Cmp(FILE *f, ir_node *n)
897 long proj_nr = get_Proj_proj(n);
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));
906 * Generate code for a Proj(Cond).
908 * @param f file handle for output
911 static void generate_code_Proj_Cond(FILE *f, ir_node *n)
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);
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");
925 if (proj_nr == get_Cond_defaultProj(cond))
926 name(f, " ", n, " = new_r_defaultProj(irg, ");
928 name(f, " ", n, " = new_r_Proj(irg, ");
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);
937 * Generate code for a Proj.
939 * @param f file handle for output
942 static void generate_code_Proj(FILE *f, ir_node *n)
944 ir_node *pred = get_Proj_pred(n);
946 switch (get_irn_opcode(pred)) {
948 generate_code_Proj_Load(f, n);
951 generate_code_Proj_Store(f, n);
954 generate_code_Proj_Div(f, n);
957 generate_code_Proj_Mod(f, n);
960 generate_code_Proj_DivMod(f, n);
963 generate_code_Proj_Cmp(f, n);
966 generate_code_Proj_Cond(f, n);
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));
977 * Generate code for a Jmp.
979 * @param f file handle for output
982 static void generate_code_Jmp(FILE *f, ir_node *n)
984 name(f, " ", n, " = new_r_Jmp(irg, ");
985 name(f, NULL, get_nodes_block(n), ");\n");
989 * Generate code for a Cond.
991 * @param f file handle for output
994 static void generate_code_Cond(FILE *f, ir_node *n)
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");
1002 * Generate code for a Call.
1004 * @param f file handle for output
1007 static void generate_code_Call(FILE *f, ir_node *n)
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);
1013 ir_type *tp = get_Call_type(n);
1016 /* try to detect the type */
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");
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");
1034 fprintf(f, " tp = TYPE(%s);\n", get_type_name(tp));
1036 for (i = 0; i < n_param; ++i) {
1037 fprintf(f, " in[%d] = ", i);
1038 name(f, NULL, get_Call_param(n, i), ";\n");
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), ", ");
1045 fprintf(f, "%d, in, tp);\n", n_param);
1047 fprintf(f, "0, NULL, tp);\n");
1051 * Create code for the given Alloc node
1053 * @param f file handle for output
1056 static void generate_code_Alloc(FILE *f, ir_node *n)
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");
1066 * Create code for the given Free node
1068 * @param f file handle for output
1071 static void generate_code_Free(FILE *f, ir_node *n)
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");
1082 * Create code for the given node constructor.
1084 * @param f file handle for output
1087 static void generate_node(fix_ctx *env, ir_node *n)
1090 ir_op *op = get_irn_op(n);
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);
1135 name(f, " ", n, " = NULL;\n");
1139 * Walker: Create code for the given node.
1141 static void dump_code(ir_node *n, void *ctx)
1145 if (! generate_predef_node(env->f, n))
1146 generate_node(env, n);
1150 * Generate Firm code.
1152 * @param env a fix environment
1153 * @param irg the graph
1155 static void generate_code(fix_ctx *env, ir_graph *irg)
1157 irg_walk_graph(irg, NULL, dump_code, env);
1161 * Generate Firm assembler for a given graph
1163 * @param f the output file handle
1164 * @param irg the graph
1166 static void gen_Firm_assembler_irg(FILE *f, ir_graph *irg)
1174 venv.need_unknown_X = 0;
1175 venv.need_unknown = 0;
1178 fenv.start_block = get_irg_start_block(irg);
1179 fenv.has_backedges = 0;
1181 /* needed to detect loops */
1182 construct_backedges(irg);
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);
1191 void gen_Firm_assembler(const char *input_filename)
1196 (void) input_filename;
1198 f = fopen("firm_output.c", "w");
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);
1206 /* report some error here */