#include #include #include #include #include #include #include #include #include #include static b_status write_operand_const(struct mie_value *value, b_stream *out) { struct mie_const *c = MIE_CONST(value); switch (c->c_type->t_id) { case MIE_TYPE_INT: { struct mie_int *v = MIE_INT(c); b_stream_write_fmt(out, NULL, "%" PRId64, v->i_value); break; } case MIE_TYPE_PTR: case MIE_TYPE_ID: b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str); break; case MIE_TYPE_STR: { struct mie_string *v = MIE_STRING(c); b_stream_write_fmt(out, NULL, "\"%s\"", v->s_value); break; } case MIE_TYPE_ATOM: { struct mie_atom *v = MIE_ATOM(c); b_stream_write_fmt(out, NULL, "\"%s\"", v->a_value); break; } case MIE_TYPE_SELECTOR: { struct mie_selector *v = MIE_SELECTOR(c); b_stream_write_fmt(out, NULL, "\"%s\"", v->sel_value); break; } case MIE_TYPE_CLASS: b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str); break; default: break; } return B_SUCCESS; } static void write_operand(struct mie_value *value, b_stream *out) { if (!value) { b_stream_write_fmt(out, NULL, ""); return; } switch (value->v_type->t_id) { case MIE_VALUE_CONST: write_operand_const(value, out); break; case MIE_VALUE_INSTR: case MIE_VALUE_BLOCK: case MIE_VALUE_ARG: b_stream_write_fmt(out, NULL, "%%%s", value->v_name.n_str); break; case MIE_VALUE_DATA: case MIE_VALUE_FUNC: b_stream_write_fmt(out, NULL, "@%s", value->v_name.n_str); break; default: b_stream_write_fmt( out, NULL, "", value->v_type->t_id); break; } } static void node_dump_text(struct mie_select_node *node) { printf("N%zu: ", node->n_id); char tmp[128]; for (size_t i = 0; i < node->n_nr_results; i++) { if (i > 0) { printf(","); } if (node->n_results[i]->t_id == MIE_TYPE_OTHER) { printf("ch"); } else { mie_type_to_string(node->n_results[i], tmp, sizeof tmp); printf("%s", tmp); } } if (node->n_nr_results > 0) { printf(" = "); } mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp); printf("%s", tmp); if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) { printf("<"); } if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) { printf("%lld", node->n_value_i); } if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE) && (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) { printf(","); } if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) { write_operand(node->n_value_p, b_stdout); } if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) { printf(">"); } if (node->n_nr_operands) { printf("("); } for (size_t i = 0; i < node->n_nr_operands; i++) { if (i > 0) { printf(", "); } const struct mie_select_value *value = &node->n_operands[i].u_value; printf("N%zu:%u", value->v_node->n_id, value->v_index); } if (node->n_nr_operands) { printf(")"); } printf("\n"); } static void node_dump_dot(struct mie_select_node *node, b_stream *out) { b_stream_write_fmt(out, NULL, "\tN%zu [label=\"{", node->n_id); if (node->n_nr_operands > 0) { b_stream_write_string(out, "{", NULL); } for (size_t i = 0; i < node->n_nr_operands; i++) { if (i > 0) { b_stream_write_string(out, "|", NULL); } b_stream_write_fmt(out, NULL, " %zu", i, i); } if (node->n_nr_operands > 0) { b_stream_write_string(out, "}|", NULL); } char tmp[256]; mie_target_select_node_name(node->n_target, node->n_opcode, tmp, sizeof tmp); b_stream_write_fmt(out, NULL, " %s", tmp); if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) { b_stream_write_string(out, "\\<", NULL); } if (node->n_flags & MIE_SELECT_NODE_F_IVALUE) { b_stream_write_fmt(out, NULL, "%lld", node->n_value_i); } if ((node->n_flags & MIE_SELECT_NODE_F_IVALUE) && (node->n_flags & MIE_SELECT_NODE_F_PVALUE)) { b_stream_write_string(out, ",", NULL); } if (node->n_flags & MIE_SELECT_NODE_F_PVALUE) { write_operand(node->n_value_p, out); } if (node->n_flags & (MIE_SELECT_NODE_F_IVALUE | MIE_SELECT_NODE_F_PVALUE)) { b_stream_write_string(out, "\\>", NULL); } b_stream_write_fmt(out, NULL, "|{N%zu}", node->n_id); if (node->n_nr_results > 0) { b_stream_write_string(out, "|{", NULL); } for (size_t i = 0; i < node->n_nr_results; i++) { if (i > 0) { b_stream_write_string(out, "|", NULL); } b_stream_write_fmt(out, NULL, " ", i, i); if (node->n_results[i]->t_id == MIE_TYPE_OTHER) { b_stream_write_string(out, "ch", NULL); } else { mie_type_to_string(node->n_results[i], tmp, sizeof tmp); b_stream_write_string(out, tmp, NULL); } } if (node->n_nr_results > 0) { b_stream_write_string(out, "}", NULL); } b_stream_write_string(out, "}\"];\n", NULL); } static void node_links_dump_dot(struct mie_select_node *node, b_stream *out) { for (size_t i = 0; i < node->n_nr_operands; i++) { struct mie_select_use *use = &node->n_operands[i]; b_stream_write_fmt( out, NULL, "\tN%zu:in%zu -> N%zu:out%zu", node->n_id, i, use->u_value.v_node->n_id, use->u_value.v_index); if (use->u_value.v_node->n_results[use->u_value.v_index]->t_id == MIE_TYPE_OTHER) { b_stream_write_string( out, "[style=dashed,color=blue]", NULL); } b_stream_write_string(out, ";\n", NULL); } } void mie_select_graph_dump_text(struct mie_select_graph *graph) { b_queue_iterator it; b_queue_foreach (&it, &graph->g_nodes) { struct mie_select_node *node = b_unbox(struct mie_select_node, it.entry, n_entry); node_dump_text(node); } } void mie_select_graph_dump_dot(struct mie_select_graph *graph) { FILE *fp = fopen("graph.dot", "w"); b_stream *tmpstream = b_stream_open_fp(fp); b_stream_write_string(tmpstream, "digraph G {\n", NULL); b_stream_write_string(tmpstream, "\tnode [shape=Mrecord];\n", NULL); b_stream_write_string(tmpstream, "\trankdir=\"BT\";\n", NULL); b_queue_iterator it; b_queue_foreach (&it, &graph->g_nodes) { struct mie_select_node *node = b_unbox(struct mie_select_node, it.entry, n_entry); node_dump_dot(node, tmpstream); } b_queue_foreach (&it, &graph->g_nodes) { struct mie_select_node *node = b_unbox(struct mie_select_node, it.entry, n_entry); node_links_dump_dot(node, tmpstream); } b_stream_write_string(tmpstream, "}\n", NULL); b_stream_close(tmpstream); system("open graph.dot"); fclose(fp); }