+
+
+
+//---------------------------------------------------------------------------
+
+
+
+typedef struct _be_verify_register_allocation_env_t {
+ const arch_env_t *arch_env;
+ ir_graph *irg;
+ be_lv_t *lv;
+ int problem_found;
+} be_verify_register_allocation_env_t;
+
+static void check_register_allocation(be_verify_register_allocation_env_t *env,
+ const arch_register_class_t *regclass, pset *nodes) {
+ const arch_env_t *arch_env = env->arch_env;
+ ir_node *node;
+ const arch_register_t *reg;
+ int fail = 0;
+
+ bitset_t *registers = bitset_alloca(arch_register_class_n_regs(regclass));
+
+ foreach_pset(nodes, node) {
+ if(arch_get_irn_reg_class(arch_env, node, -1) != regclass)
+ continue;
+
+ reg = arch_get_irn_register(arch_env, node);
+ if(reg == NULL) {
+ ir_fprintf(stderr, "Verify warning: Node %+F in block %+F(%s) should have a register assigned\n",
+ node, get_nodes_block(node), get_irg_dump_name(env->irg));
+ env->problem_found = 1;
+ continue;
+ }
+ if(bitset_is_set(registers, reg->index)) {
+ pset_break(nodes);
+ fail = 1;
+ break;
+ }
+ bitset_set(registers, reg->index);
+ }
+ if (fail) {
+ ir_fprintf(stderr, "Verify warning: Register %s assigned more than once in block %+F(%s)\n",
+ reg->name, get_nodes_block(node), get_irg_dump_name(env->irg));
+ env->problem_found = 1;
+
+ foreach_pset(nodes, node) {
+ if (arch_get_irn_register(arch_env, node) == reg) {
+ ir_fprintf(stderr, " at node %+F\n", node);
+ }
+ }
+ }
+}
+
+static void verify_block_register_allocation(ir_node *block, void *data) {
+ be_verify_register_allocation_env_t *env = data;
+ const arch_env_t *arch_env = env->arch_env;
+ const arch_isa_t *isa = arch_env->isa;
+ int i, nregclasses;
+
+ nregclasses = arch_isa_get_n_reg_class(isa);
+ for (i = 0; i < nregclasses; ++i) {
+ const arch_register_class_t *regclass = arch_isa_get_reg_class(isa, i);
+ ir_node *node;
+ pset *live_nodes = pset_new_ptr_default();
+
+ be_liveness_end_of_block(env->lv, env->arch_env, regclass, block, live_nodes);
+ check_register_allocation(env, regclass, live_nodes);
+
+ sched_foreach_reverse(block, node) {
+ if (is_Phi(node))
+ break;
+
+ be_liveness_transfer(env->arch_env, regclass, node, live_nodes);
+ check_register_allocation(env, regclass, live_nodes);
+ }
+
+ del_pset(live_nodes);
+ }
+}
+
+int be_verify_register_allocation(const arch_env_t *arch_env, ir_graph *irg) {
+ be_verify_register_allocation_env_t env;
+
+ env.arch_env = arch_env;
+ env.irg = irg;
+ env.lv = be_liveness(irg);
+ env.problem_found = 0;
+
+ irg_block_walk_graph(irg, verify_block_register_allocation, NULL, &env);
+
+ be_liveness_free(env.lv);
+
+ return !env.problem_found;
+}