+
+/*--------------------------------------------------------------------------- */
+
+typedef struct lv_walker_t {
+ be_lv_t *lv;
+ void *data;
+} lv_walker_t;
+
+static const char *lv_flags_to_str(unsigned flags)
+{
+ static const char *states[] = {
+ "---",
+ "i--",
+ "-e-",
+ "ie-",
+ "--o",
+ "i-o",
+ "-eo",
+ "ieo"
+ };
+
+ return states[flags & 7];
+}
+
+static void lv_check_walker(ir_node *bl, void *data)
+{
+ lv_walker_t *w = (lv_walker_t*)data;
+ be_lv_t *fresh = (be_lv_t*)w->data;
+
+ be_lv_info_t *curr = ir_nodehashmap_get(be_lv_info_t, &fresh->map, bl);
+ be_lv_info_t *fr = ir_nodehashmap_get(be_lv_info_t, &fresh->map, bl);
+
+ if (!fr && curr && curr[0].head.n_members > 0) {
+ ir_fprintf(stderr, "%+F liveness should be empty but current liveness contains:\n", bl);
+ for (unsigned i = 0; i < curr[0].head.n_members; ++i) {
+ ir_fprintf(stderr, "\t%+F\n", curr[1 + i].node.node);
+ }
+ } else if (curr) {
+ unsigned n_curr = curr[0].head.n_members;
+ unsigned n_fresh = fr[0].head.n_members;
+
+ if (n_curr != n_fresh) {
+ ir_fprintf(stderr, "%+F: liveness set sizes differ. curr %d, correct %d\n", bl, n_curr, n_fresh);
+
+ ir_fprintf(stderr, "current:\n");
+ for (unsigned i = 0; i < n_curr; ++i) {
+ be_lv_info_node_t *n = &curr[1 + i].node;
+ ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, n->node, lv_flags_to_str(n->flags));
+ }
+
+ ir_fprintf(stderr, "correct:\n");
+ for (unsigned i = 0; i < n_fresh; ++i) {
+ be_lv_info_node_t *n = &fr[1 + i].node;
+ ir_fprintf(stderr, "%+F %u %+F %s\n", bl, i, n->node, lv_flags_to_str(n->flags));
+ }
+ }
+ }
+}
+
+void be_liveness_check(be_lv_t *lv)
+{
+ lv_walker_t w;
+ be_lv_t *fresh = be_liveness_new(lv->irg);
+
+ w.lv = lv;
+ w.data = fresh;
+ irg_block_walk_graph(lv->irg, lv_check_walker, NULL, &w);
+ be_liveness_free(fresh);
+}