#include <stdbool.h>
#include "irgwalk.h"
+#include "iredges_t.h"
#include "bearch.h"
+#include "besched.h"
+#include "bedump_minir.h"
+
+typedef enum yaml_state_t {
+ STATE_BLOCK_MAPPING,
+ STATE_BLOCK_SEQUENCE,
+ STATE_LIST,
+ STATE_MAPPING,
+ STATE_EXPECT_VALUE
+} yaml_state_t;
static const arch_env_t *arch_env;
static FILE *out;
static int indent;
-static int item_indent_add;
static bool had_list_item;
+static bool had_dict_item;
static bool no_newline;
+static unsigned state_pos;
+static yaml_state_t state_stack[1024];
+static yaml_state_t state;
+
+static void init_yaml(FILE *new_out)
+{
+ out = new_out;
+ indent = 0;
+ state_pos = 0;
+ state = STATE_BLOCK_MAPPING;
+}
+
+static void exit_yaml(void)
+{
+ assert(indent == 0);
+ assert(state_pos == 0);
+ fputs("\n", out);
+}
+
+static void push_state(yaml_state_t new_state)
+{
+ assert(state_pos < sizeof(state_stack)/sizeof(yaml_state_t));
+ state_stack[state_pos++] = state;
+ state = new_state;
+}
+
+static void pop_state(void)
+{
+ assert(state_pos > 0);
+ state = state_stack[--state_pos];
+}
static void newline(void)
{
}
fputc('\n', out);
- for (i = 0; i < indent + item_indent_add; ++i) {
+ for (i = 0; i < indent; ++i) {
fputs(" ", out);
}
}
-static void begin_key(const char *name)
-{
- newline();
- fprintf(out, "%s: ", name);
-}
+static void list_item(void);
+static void mapping_item(const char *name);
-static void end_key(const char *name)
+static void start(const char *name)
{
- /* TODO verify */
- (void) name;
+ if (name != NULL) {
+ mapping_item(name);
+ } else if (state == STATE_LIST || state == STATE_BLOCK_SEQUENCE) {
+ list_item();
+ }
+
+ assert(state == STATE_EXPECT_VALUE);
+ pop_state();
}
static void begin_block_sequence(const char *name)
{
- begin_key(name);
- indent++;
+ start(name);
+ push_state(STATE_BLOCK_SEQUENCE);
}
static void end_block_sequence(const char *name)
{
- end_key(name);
- indent--;
- item_indent_add = 0;
+ (void) name;
+ assert(state == STATE_BLOCK_SEQUENCE);
+ pop_state();
}
-static void block_sequence_item(void)
+static void begin_block_mapping(const char *name)
{
- item_indent_add = 0;
- newline();
- fputs("- ", out);
- item_indent_add = 1;
- no_newline = true;
+ start(name);
+ ++indent;
+ push_state(STATE_BLOCK_MAPPING);
+ if (name == NULL) {
+ no_newline = true;
+ }
}
-static void begin_mapping(const char *name)
+static void end_block_mapping(const char *name)
{
- begin_key(name);
- indent++;
+ (void) name;
+ --indent;
+ assert(state == STATE_BLOCK_MAPPING);
+ pop_state();
}
-static void end_maping(const char *name)
+static void mapping_item(const char *name)
{
- end_key(name);
- indent--;
+ if (state == STATE_BLOCK_MAPPING) {
+ newline();
+ } else {
+ assert(state == STATE_MAPPING);
+ if (had_dict_item)
+ fputs(", ", out);
+ had_dict_item = true;
+ }
+ fprintf(out, "%s: ", name);
+ push_state(STATE_EXPECT_VALUE);
+}
+
+static void list_item(void)
+{
+ if (state == STATE_BLOCK_SEQUENCE) {
+ newline();
+ fputs("- ", out);
+ } else {
+ assert(state == STATE_LIST);
+ if (had_list_item)
+ fputs(", ", out);
+ had_list_item = true;
+ }
+ push_state(STATE_EXPECT_VALUE);
}
static void value(const char *val)
{
+ if (state == STATE_BLOCK_SEQUENCE
+ || state == STATE_LIST) {
+ list_item();
+ }
+
+ assert(state == STATE_EXPECT_VALUE);
+ pop_state();
fputs(val, out);
}
static void key_value(const char *name, const char *val)
{
- begin_key(name);
+ mapping_item(name);
value(val);
- end_key(name);
}
static void begin_list(const char *name)
{
- begin_key(name);
+ start(name);
fputs("[", out);
had_list_item = false;
+ push_state(STATE_LIST);
}
static void end_list(const char *name)
{
- /* TODO: verify that we started a list */
fputs("]", out);
- end_key(name);
+ (void) name;
+ assert(state == STATE_LIST);
+ pop_state();
}
-static void list_item(void)
+static void begin_mapping(const char *name)
{
- if (had_list_item)
- fputs(", ", out);
- had_list_item = true;
+ start(name);
+ fputs("{", out);
+ had_dict_item = false;
+ push_state(STATE_MAPPING);
}
-static void list_item_value(const char *val)
+static void end_mapping(const char *name)
{
- list_item();
- value(val);
+ fputs("}", out);
+ (void) name;
+ assert(state == STATE_MAPPING);
+ pop_state();
}
static void print_regclasses(void)
n_regs = arch_register_class_n_regs(cls);
- block_sequence_item();
+ begin_block_mapping(NULL);
key_value("name", cls->name);
begin_list("registers");
for (r = 0; r < n_regs; ++r) {
const arch_register_t *reg = arch_register_for_index(cls, r);
- list_item_value(reg->name);
+ value(reg->name);
}
end_list("registers");
- begin_mapping("flags");
- for (r = 0; r < n_regs; ++r) {
- const arch_register_t *reg = arch_register_for_index(cls, r);
- unsigned type = reg->type;
- if (type & arch_register_type_ignore) {
- begin_list(reg->name);
- list_item_value("reserved");
- list_item_value("nossa"); /* do we need this? */
- end_list(reg->name);
- }
+ begin_block_mapping("flags");
+ for (r = 0; r < n_regs; ++r) {
+ const arch_register_t *reg = arch_register_for_index(cls, r);
+ unsigned type = reg->type;
+ if (type & arch_register_type_ignore) {
+ begin_list(reg->name);
+ value("reserved");
+ value("nossa"); /* do we need this? */
+ end_list(reg->name);
}
- end_maping("flags");
+ }
+ end_block_mapping("flags");
+
+ end_block_mapping(NULL);
}
end_block_sequence("regclasses");
}
+static void print_value_name(ir_node *node)
+{
+ char name[128];
+ const arch_register_req_t *req = arch_get_register_req_out(node);
+ snprintf(name, sizeof(name), "V%ld.%s", get_irn_node_nr(node),
+ req->cls->name);
+
+ value(name);
+}
+
+static void print_node(ir_node *node)
+{
+ ir_op *op = get_irn_op(node);
+ int arity;
+ int i;
+
+ begin_mapping(NULL);
+
+ mapping_item("op");
+ value(get_op_name(op));
+
+ mapping_item("defs");
+ begin_list(NULL);
+ if (get_irn_mode(node) == mode_T) {
+ const ir_edge_t *edge;
+ foreach_out_edge(node, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+ const arch_register_req_t *req = arch_get_register_req_out(proj);
+
+ if (req->cls == NULL || (req->type & arch_register_req_type_ignore))
+ continue;
+
+ list_item();
+ print_value_name(proj);
+ }
+ } else {
+ const arch_register_req_t *req = arch_get_register_req_out(node);
+ if (req->cls != NULL && !(req->type & arch_register_req_type_ignore)) {
+ list_item();
+ print_value_name(node);
+ }
+ }
+ end_list(NULL);
+
+ mapping_item("uses");
+ begin_list(NULL);
+ arity = get_irn_arity(node);
+ for (i = 0; i < arity; ++i) {
+ const arch_register_req_t *req = arch_get_register_req(node, i);
+ ir_node *op = get_irn_n(node, i);
+
+ if (req->cls == NULL || (req->type & arch_register_req_type_ignore))
+ continue;
+
+ list_item();
+ print_value_name(op);
+ }
+ end_list(NULL);
+
+ end_mapping(NULL);
+}
+
static void dump_block(ir_node *block, void *data)
{
+ ir_graph *irg = get_irn_irg(block);
+ ir_node *node;
(void) data;
- block_sequence_item();
- ir_graph *irg = get_irn_irg(block);
+ begin_block_mapping(NULL);
+
if (block == get_irg_start_block(irg)) {
key_value("label", "start");
} else if (block == get_irg_end_block(irg)) {
key_value("label", "end");
} else {
char name[128];
- snprintf(name, sizeof(name), "bb%ld", get_irn_node_nr(block));
+ snprintf(name, sizeof(name), "BB%ld", get_irn_node_nr(block));
key_value("label", name);
}
begin_block_sequence("ops");
+
+ sched_foreach(block, node) {
+ print_node(node);
+ }
+
end_block_sequence("ops");
+
+ end_block_mapping(NULL);
}
static void print_function(ir_graph *irg)
{
ir_entity *entity = get_irg_entity(irg);
- block_sequence_item();
+ begin_block_mapping(NULL);
key_value("label", get_entity_name(entity));
- begin_list("entries"); list_item_value("start"); end_list("entries");
- begin_list("exit"); list_item_value("end"); end_list("entries");
+ begin_list("entries"); value("start"); end_list("entries");
+ begin_list("exit"); value("end"); end_list("exit");
begin_block_sequence("bbs");
irg_block_walk_graph(irg, dump_block, NULL, NULL);
end_block_sequence("bbs");
+
+ end_block_mapping(NULL);
}
-void be_export_minir(const arch_env_t *new_arch_env, FILE *new_out, ir_graph *irg)
+void be_export_minir(FILE *out, ir_graph *irg)
{
- arch_env = new_arch_env;
- out = new_out;
-
- no_newline = true;
+ arch_env = be_get_irg_arch_env(irg);
+ init_yaml(out);
print_regclasses();
print_function(irg);
end_block_sequence("functions");
- assert(indent == 0);
- fputs("\n", out);
-
+ exit_yaml();
}