Let the length of tarval be of type size_t.
[libfirm] / ir / be / bedump_minir.c
index d5eb65b..0809a98 100644 (file)
 #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)
 {
@@ -47,178 +89,292 @@ 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)
 {
-       int n_classes = arch_env_get_n_reg_class(arch_env);
+       int n_classes = arch_env->n_register_classes;
        int c;
 
        begin_block_sequence("regclasses");
        for (c = 0; c < n_classes; ++c) {
                int                          n_regs;
                int                          r;
-               const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, c);
+               const arch_register_class_t *cls = &arch_env->register_classes[c];
                if (arch_register_class_flags(cls) & arch_register_class_flag_manual_ra)
                        continue;
 
                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);
-                               }
+#if 0
+               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");
+#endif
+
+               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();
+       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();
 
@@ -226,7 +382,5 @@ void be_export_minir(const arch_env_t *new_arch_env, FILE *new_out, ir_graph *ir
        print_function(irg);
        end_block_sequence("functions");
 
-       assert(indent == 0);
-       fputs("\n", out);
-
+       exit_yaml();
 }