279 lines
6.4 KiB
C
279 lines
6.4 KiB
C
|
|
#include <blue/io/file.h>
|
||
|
|
#include <blue/io/path.h>
|
||
|
|
#include <inttypes.h>
|
||
|
|
#include <mie/ir/const.h>
|
||
|
|
#include <mie/ir/value.h>
|
||
|
|
#include <mie/select/graph.h>
|
||
|
|
#include <mie/select/node.h>
|
||
|
|
#include <mie/target/select.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
|
||
|
|
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, "<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, "<unknown-value:%d>", 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, "<in%zu> %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, "<Name> %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, "<out%zu> ", 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);
|
||
|
|
}
|