From 7a069bea5dd76daf531d0febef1d0a2cf154d6d9 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 5 Jan 2016 16:18:01 -0800 Subject: [PATCH] nir/spirv: Fix switch statements with duplicate cases --- src/glsl/nir/spirv/vtn_cfg.c | 17 +++++------------ src/glsl/nir/spirv/vtn_private.h | 3 +++ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/glsl/nir/spirv/vtn_cfg.c b/src/glsl/nir/spirv/vtn_cfg.c index 646b960d179..9330ac03769 100644 --- a/src/glsl/nir/spirv/vtn_cfg.c +++ b/src/glsl/nir/spirv/vtn_cfg.c @@ -164,6 +164,7 @@ vtn_add_case(struct vtn_builder *b, struct vtn_switch *swtch, struct vtn_case *c = ralloc(b, struct vtn_case); list_inithead(&c->body); + c->start_block = case_block; c->fallthrough = NULL; nir_array_init(&c->values, b); c->is_default = false; @@ -399,18 +400,10 @@ vtn_cfg_walk_blocks(struct vtn_builder *b, struct list_head *cf_list, * the blocks, we also gather the much-needed fall-through * information. */ - for (const uint32_t *w = block->branch + 2; w < branch_end; w += 2) { - struct vtn_block *case_block = - vtn_value(b, *w, vtn_value_type_block)->block; - - if (case_block == break_block) - continue; - - assert(case_block->switch_case); - - vtn_cfg_walk_blocks(b, &case_block->switch_case->body, case_block, - case_block->switch_case, break_block, - NULL, loop_cont, NULL); + list_for_each_entry(struct vtn_case, cse, &swtch->cases, link) { + assert(cse->start_block != break_block); + vtn_cfg_walk_blocks(b, &cse->body, cse->start_block, cse, + break_block, NULL, loop_cont, NULL); } /* Finally, we walk over all of the cases one more time and put diff --git a/src/glsl/nir/spirv/vtn_private.h b/src/glsl/nir/spirv/vtn_private.h index 5e2b3563d15..0fa7dd4b041 100644 --- a/src/glsl/nir/spirv/vtn_private.h +++ b/src/glsl/nir/spirv/vtn_private.h @@ -105,6 +105,9 @@ struct vtn_case { struct list_head body; + /* The block that starts this case */ + struct vtn_block *start_block; + /* The fallthrough case, if any */ struct vtn_case *fallthrough; -- 2.30.2