From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 39 ++++++++++++++++++++++++++++++++ tests/hlsl/switch.shader_test | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index fef871e3..534d5e92 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2167,6 +2167,44 @@ static bool remove_trivial_conditional_branches(struct hlsl_ctx *ctx, struct hls return true; }
+static bool validate_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_switch_case *c; + bool terminal_break = false; + struct hlsl_ir_node *node; + struct hlsl_ir_jump *jump; + struct hlsl_ir_switch *s; + + if (instr->type != HLSL_IR_SWITCH) + return false; + s = hlsl_ir_switch(instr); + + LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry) + { + if (list_empty(&c->body.instrs)) + continue; + + terminal_break = false; + node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry); + if (node->type == HLSL_IR_JUMP) + { + jump = hlsl_ir_jump(node); + terminal_break = jump->type == HLSL_IR_JUMP_BREAK; + } + + if (!terminal_break) + break; + } + + if (!terminal_break) + { + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "Fallthrough is only allowed for empty switch cases."); + } + + return true; +} + static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { struct hlsl_ir_node *idx; @@ -4627,6 +4665,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry } while (progress); remove_unreachable_code(ctx, body); + hlsl_transform_ir(ctx, validate_switch_cases, body, NULL);
lower_ir(ctx, lower_nonconstant_vector_derefs, body); lower_ir(ctx, lower_casts_to_bool, body); diff --git a/tests/hlsl/switch.shader_test b/tests/hlsl/switch.shader_test index 999158c1..02e499c9 100644 --- a/tests/hlsl/switch.shader_test +++ b/tests/hlsl/switch.shader_test @@ -183,7 +183,7 @@ float4 main() : sv_target }
% unterminated cases -[pixel shader fail todo] +[pixel shader fail] uint4 v;
float4 main() : sv_target