HLSL: workaround FXC error "continue cannot be used in a switch"

Added a new transform::RemoveContinueInSwitch that replaces continue
statements in switch cases with setting a bool variable, and checking if
the variable is set after the switch to continue.

Bug: tint:1080
Change-Id: I3c0a6c790e1bb612fac3f927a4bd5beb2d0d4ed1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/84960
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Antonio Maiorano 2022-03-31 15:02:25 +00:00 committed by Tint LUCI CQ
parent a9d2f636fb
commit b349710476
14 changed files with 782 additions and 671 deletions

View File

@ -471,6 +471,8 @@ libtint_source_set("libtint_core_all_src") {
"transform/promote_initializers_to_const_var.h",
"transform/promote_side_effects_to_decl.cc",
"transform/promote_side_effects_to_decl.h",
"transform/remove_continue_in_switch.cc",
"transform/remove_continue_in_switch.h",
"transform/remove_phonies.cc",
"transform/remove_phonies.h",
"transform/remove_unreachable_statements.cc",

View File

@ -351,6 +351,8 @@ set(TINT_LIB_SRCS
transform/promote_side_effects_to_decl.h
transform/remove_phonies.cc
transform/remove_phonies.h
transform/remove_continue_in_switch.cc
transform/remove_continue_in_switch.h
transform/remove_unreachable_statements.cc
transform/remove_unreachable_statements.h
transform/renamer.cc
@ -1027,6 +1029,7 @@ if(TINT_BUILD_TESTS)
transform/num_workgroups_from_uniform_test.cc
transform/promote_initializers_to_const_var_test.cc
transform/promote_side_effects_to_decl_test.cc
transform/remove_continue_in_switch_test.cc
transform/remove_phonies_test.cc
transform/remove_unreachable_statements_test.cc
transform/renamer_test.cc

View File

@ -0,0 +1,145 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/transform/remove_continue_in_switch.h"
#include <string>
#include <unordered_map>
#include <utility>
#include "src/tint/ast/continue_statement.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/for_loop_statement.h"
#include "src/tint/sem/loop_statement.h"
#include "src/tint/sem/switch_statement.h"
#include "src/tint/transform/utils/get_insertion_point.h"
#include "src/tint/utils/map.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::RemoveContinueInSwitch);
namespace tint::transform {
namespace {
class State {
private:
CloneContext& ctx;
ProgramBuilder& b;
const sem::Info& sem;
// Map of switch statement to 'tint_continue' variable.
std::unordered_map<const ast::SwitchStatement*, Symbol>
switch_to_cont_var_name;
// If `cont` is within a switch statement within a loop, returns a pointer to
// that switch statement.
static const ast::SwitchStatement* GetParentSwitchInLoop(
const sem::Info& sem,
const ast::ContinueStatement* cont) {
// Find whether first parent is a switch or a loop
auto* sem_stmt = sem.Get(cont);
auto* sem_parent =
sem_stmt->FindFirstParent<sem::SwitchStatement, sem::LoopBlockStatement,
sem::ForLoopStatement>();
if (!sem_parent) {
return nullptr;
}
return sem_parent->Declaration()->As<ast::SwitchStatement>();
}
public:
/// Constructor
/// @param ctx_in the context
explicit State(CloneContext& ctx_in)
: ctx(ctx_in), b(*ctx_in.dst), sem(ctx_in.src->Sem()) {}
/// Returns true if this transform should be run for the given program
static bool ShouldRun(const Program* program) {
for (auto* node : program->ASTNodes().Objects()) {
auto* stmt = node->As<ast::ContinueStatement>();
if (!stmt) {
continue;
}
if (GetParentSwitchInLoop(program->Sem(), stmt)) {
return true;
}
}
return false;
}
/// Runs the transform
void Run() {
for (auto* node : ctx.src->ASTNodes().Objects()) {
auto* cont = node->As<ast::ContinueStatement>();
if (!cont) {
continue;
}
// If first parent is not a switch within a loop, skip
auto* switch_stmt = GetParentSwitchInLoop(sem, cont);
if (!switch_stmt) {
continue;
}
auto cont_var_name =
tint::utils::GetOrCreate(switch_to_cont_var_name, switch_stmt, [&]() {
// Create and insert 'var tint_continue : bool = false;' before the
// switch.
auto var_name = b.Symbols().New("tint_continue");
auto* decl = b.Decl(b.Var(var_name, b.ty.bool_(), b.Expr(false)));
auto ip = utils::GetInsertionPoint(ctx, switch_stmt);
ctx.InsertBefore(ip.first->Declaration()->statements, ip.second,
decl);
// Create and insert 'if (tint_continue) { continue; }' after
// switch.
auto* if_stmt = b.If(b.Expr(var_name), b.Block(b.Continue()));
ctx.InsertAfter(ip.first->Declaration()->statements, ip.second,
if_stmt);
// Return the new var name
return var_name;
});
// Replace 'continue;' with '{ tint_continue = true; break; }'
auto* new_stmt = b.Block( //
b.Assign(b.Expr(cont_var_name), true), //
b.Break());
ctx.Replace(cont, new_stmt);
}
ctx.Clone();
}
};
} // namespace
RemoveContinueInSwitch::RemoveContinueInSwitch() = default;
RemoveContinueInSwitch::~RemoveContinueInSwitch() = default;
bool RemoveContinueInSwitch::ShouldRun(const Program* program,
const DataMap& /*data*/) const {
return State::ShouldRun(program);
}
void RemoveContinueInSwitch::Run(CloneContext& ctx,
const DataMap&,
DataMap&) const {
State state(ctx);
state.Run();
}
} // namespace tint::transform

View File

@ -0,0 +1,55 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_TINT_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_
#define SRC_TINT_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_
#include "src/tint/transform/transform.h"
namespace tint::transform {
/// This transform replaces continue statements in switch cases with setting a
/// bool variable, and checking if the variable is set after the switch to
/// continue. It is necessary to work around FXC "error X3708: continue cannot
/// be used in a switch". See crbug.com/tint/1080.
class RemoveContinueInSwitch
: public Castable<RemoveContinueInSwitch, Transform> {
public:
/// Constructor
RemoveContinueInSwitch();
/// Destructor
~RemoveContinueInSwitch() override;
protected:
/// @param program the program to inspect
/// @param data optional extra transform-specific input data
/// @returns true if this transform should be run for the given program
bool ShouldRun(const Program* program,
const DataMap& data = {}) const override;
/// Runs the transform using the CloneContext built for transforming a
/// program. Run() is responsible for calling Clone() on the CloneContext.
/// @param ctx the CloneContext primed with the input program and
/// ProgramBuilder
/// @param inputs optional extra transform-specific input data
/// @param outputs optional extra transform-specific output data
void Run(CloneContext& ctx,
const DataMap& inputs,
DataMap& outputs) const override;
};
} // namespace tint::transform
#endif // SRC_TINT_TRANSFORM_REMOVE_CONTINUE_IN_SWITCH_H_

View File

@ -0,0 +1,565 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/transform/remove_continue_in_switch.h"
#include "src/tint/transform/test_helper.h"
namespace tint {
namespace transform {
namespace {
using RemoveContinueInSwitchTest = TransformTest;
TEST_F(RemoveContinueInSwitchTest, ShouldRun_True) {
auto* src = R"(
fn f() {
var i = 0;
loop {
switch(i) {
case 0: {
continue;
break;
}
default: {
break;
}
}
break;
}
}
)";
EXPECT_TRUE(ShouldRun<RemoveContinueInSwitch>(src));
}
TEST_F(RemoveContinueInSwitchTest, ShouldRunEmptyModule_False) {
auto* src = "";
EXPECT_FALSE(ShouldRun<RemoveContinueInSwitch>(src));
}
TEST_F(RemoveContinueInSwitchTest, ShouldRunContinueNotInSwitch_False) {
auto* src = R"(
fn f() {
var i = 0;
loop {
switch(i) {
case 0: {
break;
}
default: {
break;
}
}
if (true) {
continue;
}
break;
}
}
)";
EXPECT_FALSE(ShouldRun<RemoveContinueInSwitch>(src));
}
TEST_F(RemoveContinueInSwitchTest, ShouldRunContinueInLoopInSwitch_False) {
auto* src = R"(
fn f() {
var i = 0;
switch(i) {
case 0: {
loop {
if (true) {
continue;
}
break;
}
break;
}
default: {
break;
}
}
}
)";
EXPECT_FALSE(ShouldRun<RemoveContinueInSwitch>(src));
}
TEST_F(RemoveContinueInSwitchTest, EmptyModule) {
auto* src = "";
auto* expect = src;
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, SingleContinue) {
auto* src = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
switch(i) {
case 0: {
continue;
break;
}
default: {
break;
}
}
let marker2 = 0;
break;
continuing {
let marker3 = 0;
}
}
}
)";
auto* expect = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
var tint_continue : bool = false;
switch(i) {
case 0: {
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker2 = 0;
break;
continuing {
let marker3 = 0;
}
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, MultipleContinues) {
auto* src = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
switch(i) {
case 0: {
continue;
break;
}
case 1: {
continue;
break;
}
case 2: {
continue;
break;
}
default: {
break;
}
}
let marker2 = 0;
break;
continuing {
let marker3 = 0;
}
}
}
)";
auto* expect = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
var tint_continue : bool = false;
switch(i) {
case 0: {
{
tint_continue = true;
break;
}
break;
}
case 1: {
{
tint_continue = true;
break;
}
break;
}
case 2: {
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker2 = 0;
break;
continuing {
let marker3 = 0;
}
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, MultipleSwitch) {
auto* src = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
switch(i) {
case 0: {
continue;
break;
}
default: {
break;
}
}
let marker2 = 0;
let marker3 = 0;
switch(i) {
case 0: {
continue;
break;
}
default: {
break;
}
}
let marker4 = 0;
break;
}
}
)";
auto* expect = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
var tint_continue : bool = false;
switch(i) {
case 0: {
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker2 = 0;
let marker3 = 0;
var tint_continue_1 : bool = false;
switch(i) {
case 0: {
{
tint_continue_1 = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue_1) {
continue;
}
let marker4 = 0;
break;
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, NestedLoopSwitch) {
auto* src = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
switch(i) {
case 0: {
var j = 0;
loop {
let marker3 = 0;
switch(j) {
case 0: {
continue;
break;
}
default: {
break;
}
}
let marker4 = 0;
break;
}
continue;
break;
}
default: {
break;
}
}
let marker2 = 0;
break;
}
}
)";
auto* expect = R"(
fn f() {
var i = 0;
loop {
let marker1 = 0;
var tint_continue_1 : bool = false;
switch(i) {
case 0: {
var j = 0;
loop {
let marker3 = 0;
var tint_continue : bool = false;
switch(j) {
case 0: {
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker4 = 0;
break;
}
{
tint_continue_1 = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue_1) {
continue;
}
let marker2 = 0;
break;
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, ExtraScopes) {
auto* src = R"(
fn f() {
var i = 0;
var a = true;
var b = true;
var c = true;
var d = true;
loop {
if (a) {
if (b) {
let marker1 = 0;
switch(i) {
case 0: {
if (c) {
if (d) {
continue;
}
}
break;
}
default: {
break;
}
}
let marker2 = 0;
break;
}
}
}
}
)";
auto* expect = R"(
fn f() {
var i = 0;
var a = true;
var b = true;
var c = true;
var d = true;
loop {
if (a) {
if (b) {
let marker1 = 0;
var tint_continue : bool = false;
switch(i) {
case 0: {
if (c) {
if (d) {
{
tint_continue = true;
break;
}
}
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker2 = 0;
break;
}
}
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
TEST_F(RemoveContinueInSwitchTest, ForLoop) {
auto* src = R"(
fn f() {
for (var i = 0; i < 4; i = i + 1) {
let marker1 = 0;
switch(i) {
case 0: {
continue;
break;
}
default: {
break;
}
}
let marker2 = 0;
break;
}
}
)";
auto* expect = R"(
fn f() {
for(var i = 0; (i < 4); i = (i + 1)) {
let marker1 = 0;
var tint_continue : bool = false;
switch(i) {
case 0: {
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
let marker2 = 0;
break;
}
}
)";
DataMap data;
auto got = Run<RemoveContinueInSwitch>(src, data);
EXPECT_EQ(expect, str(got));
}
} // namespace
} // namespace transform
} // namespace tint

View File

@ -59,6 +59,7 @@
#include "src/tint/transform/num_workgroups_from_uniform.h"
#include "src/tint/transform/promote_initializers_to_const_var.h"
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_continue_in_switch.h"
#include "src/tint/transform/remove_phonies.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/transform/unshadow.h"
@ -210,6 +211,8 @@ SanitizedResult Sanitize(
manager.Add<transform::CalculateArrayLength>();
manager.Add<transform::PromoteInitializersToConstVar>();
manager.Add<transform::RemoveContinueInSwitch>();
manager.Add<transform::AddEmptyEntryPoint>();
data.Add<transform::CanonicalizeEntryPointIO::Config>(

View File

@ -329,6 +329,7 @@ tint_unittests_source_set("tint_unittests_transform_src") {
"../../src/tint/transform/num_workgroups_from_uniform_test.cc",
"../../src/tint/transform/promote_initializers_to_const_var_test.cc",
"../../src/tint/transform/promote_side_effects_to_decl_test.cc",
"../../src/tint/transform/remove_continue_in_switch_test.cc",
"../../src/tint/transform/remove_phonies_test.cc",
"../../src/tint/transform/remove_unreachable_statements_test.cc",
"../../src/tint/transform/renamer_test.cc",

View File

@ -1,20 +1,24 @@
SKIP: FAILED
[numthreads(1, 1, 1)]
void f() {
{
[loop] for(int i = 0; (i < 4); i = (i + 1)) {
bool tint_continue = false;
switch(i) {
case 0: {
continue;
{
tint_continue = true;
break;
}
break;
}
default: {
break;
}
}
if (tint_continue) {
continue;
}
}
}
return;
}
C:\src\tint\test\Shader@0x000001A817AB3700(7,11-19): error X3708: continue cannot be used in a switch

View File

@ -1,122 +0,0 @@
SKIP: FAILED
warning: code is unreachable
cbuffer cbuffer_x_6 : register(b0, space0) {
uint4 x_6[1];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
int data[10] = (int[10])0;
int x_40 = 0;
int x_40_phi = 0;
int x_11_phi = 0;
const int x_7 = data[1];
const int x_10 = ((1 < x_7) ? 2 : 1);
x_40_phi = 1;
x_11_phi = x_10;
[loop] while (true) {
int x_54 = 0;
int x_41 = 0;
int x_41_phi = 0;
x_40 = x_40_phi;
const int x_11 = x_11_phi;
if ((x_11 < 3)) {
} else {
break;
}
int x_54_phi = 0;
const int x_8 = (x_11 + 1);
const float x_47 = asfloat(x_6[0].x);
x_54_phi = x_40;
switch(int(x_47)) {
case 78: {
x_GLF_color = float4(1.0f, 1.0f, 1.0f, 1.0f);
/* fallthrough */
{
x_54_phi = asint((x_40 + asint(1)));
/* fallthrough */
}
{
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
}
break;
}
case 19: {
x_54_phi = asint((x_40 + asint(1)));
/* fallthrough */
{
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
}
break;
}
case 23:
case 38: {
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
break;
}
default: {
x_41_phi = x_40;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
break;
}
}
x_41_phi = 0;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
}
data[x_40] = 1;
x_GLF_color = float4(1.0f, 0.0f, 0.0f, 1.0f);
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_2 = {x_GLF_color};
return tint_symbol_2;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x0000022C8EAC8720(45,11-19): error X3708: continue cannot be used in a switch

View File

@ -1,125 +0,0 @@
SKIP: FAILED
vk-gl-cts/graphicsfuzz/call-if-while-switch/0-opt.wgsl:52:5 warning: code is unreachable
x_41_phi = 0;
^^^^^^^^
cbuffer cbuffer_x_6 : register(b0, space0) {
uint4 x_6[1];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
int data[10] = (int[10])0;
int x_40 = 0;
int x_40_phi = 0;
int x_11_phi = 0;
const int x_7 = data[1];
const int x_10 = ((1 < x_7) ? 2 : 1);
x_40_phi = 1;
x_11_phi = x_10;
[loop] while (true) {
int x_54 = 0;
int x_41 = 0;
int x_41_phi = 0;
x_40 = x_40_phi;
const int x_11 = x_11_phi;
if ((x_11 < 3)) {
} else {
break;
}
int x_54_phi = 0;
const int x_8 = (x_11 + 1);
const float x_47 = asfloat(x_6[0].x);
x_54_phi = x_40;
switch(int(x_47)) {
case 78: {
x_GLF_color = float4(1.0f, 1.0f, 1.0f, 1.0f);
/* fallthrough */
{
x_54_phi = asint((x_40 + asint(1)));
/* fallthrough */
}
{
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
}
break;
}
case 19: {
x_54_phi = asint((x_40 + asint(1)));
/* fallthrough */
{
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
}
break;
}
case 23:
case 38: {
x_54 = x_54_phi;
x_41_phi = x_54;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
break;
}
default: {
x_41_phi = x_40;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
continue;
break;
}
}
x_41_phi = 0;
{
x_41 = x_41_phi;
x_40_phi = x_41;
x_11_phi = x_8;
}
}
data[x_40] = 1;
x_GLF_color = float4(1.0f, 0.0f, 0.0f, 1.0f);
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_2 = {x_GLF_color};
return tint_symbol_2;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x0000025D82F36130(45,11-19): error X3708: continue cannot be used in a switch

View File

@ -1,124 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_x_6 : register(b1, space0) {
uint4 x_6[3];
};
cbuffer cbuffer_x_9 : register(b0, space0) {
uint4 x_9[4];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
float A[2] = (float[2])0;
int i = 0;
int j = 0;
bool x_101 = false;
bool x_102_phi = false;
const float x_39 = asfloat(x_6[1].x);
A[0] = x_39;
const float x_42 = asfloat(x_6[1].x);
A[1] = x_42;
const uint scalar_offset = ((16u * uint(0))) / 4;
const int x_45 = asint(x_9[scalar_offset / 4][scalar_offset % 4]);
i = x_45;
[loop] while (true) {
const int x_50 = i;
const int x_52 = asint(x_9[3].x);
if ((x_50 < x_52)) {
} else {
break;
}
const uint scalar_offset_1 = ((16u * uint(0))) / 4;
const int x_56 = asint(x_9[scalar_offset_1 / 4][scalar_offset_1 % 4]);
j = x_56;
[loop] while (true) {
const int x_61 = j;
const int x_63 = asint(x_9[2].x);
if ((x_61 < x_63)) {
} else {
break;
}
switch(j) {
case 1: {
const int x_78 = i;
const uint scalar_offset_2 = ((16u * uint(0))) / 4;
const float x_80 = asfloat(x_6[scalar_offset_2 / 4][scalar_offset_2 % 4]);
A[x_78] = x_80;
break;
}
case 0: {
if ((-2147483648 < i)) {
{
j = (j + 1);
}
continue;
}
const int x_74 = i;
const float x_76 = asfloat(x_6[2].x);
A[x_74] = x_76;
break;
}
default: {
break;
}
}
{
j = (j + 1);
}
}
{
i = (i + 1);
}
}
const uint scalar_offset_3 = ((16u * uint(0))) / 4;
const int x_87 = asint(x_9[scalar_offset_3 / 4][scalar_offset_3 % 4]);
const float x_89 = A[x_87];
const uint scalar_offset_4 = ((16u * uint(0))) / 4;
const float x_91 = asfloat(x_6[scalar_offset_4 / 4][scalar_offset_4 % 4]);
const bool x_92 = (x_89 == x_91);
x_102_phi = x_92;
if (x_92) {
const int x_96 = asint(x_9[1].x);
const float x_98 = A[x_96];
const uint scalar_offset_5 = ((16u * uint(0))) / 4;
const float x_100 = asfloat(x_6[scalar_offset_5 / 4][scalar_offset_5 % 4]);
x_101 = (x_98 == x_100);
x_102_phi = x_101;
}
if (x_102_phi) {
const int x_107 = asint(x_9[1].x);
const uint scalar_offset_6 = ((16u * uint(0))) / 4;
const int x_110 = asint(x_9[scalar_offset_6 / 4][scalar_offset_6 % 4]);
const uint scalar_offset_7 = ((16u * uint(0))) / 4;
const int x_113 = asint(x_9[scalar_offset_7 / 4][scalar_offset_7 % 4]);
const int x_116 = asint(x_9[1].x);
x_GLF_color = float4(float(x_107), float(x_110), float(x_113), float(x_116));
} else {
const int x_120 = asint(x_9[1].x);
const float x_121 = float(x_120);
x_GLF_color = float4(x_121, x_121, x_121, x_121);
}
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_3 = {x_GLF_color};
return tint_symbol_3;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x000001CAF72F14F0(52,13-21): error X3708: continue cannot be used in a switch

View File

@ -1,124 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_x_6 : register(b1, space0) {
uint4 x_6[3];
};
cbuffer cbuffer_x_9 : register(b0, space0) {
uint4 x_9[4];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
float A[2] = (float[2])0;
int i = 0;
int j = 0;
bool x_101 = false;
bool x_102_phi = false;
const float x_39 = asfloat(x_6[1].x);
A[0] = x_39;
const float x_42 = asfloat(x_6[1].x);
A[1] = x_42;
const uint scalar_offset = ((16u * uint(0))) / 4;
const int x_45 = asint(x_9[scalar_offset / 4][scalar_offset % 4]);
i = x_45;
[loop] while (true) {
const int x_50 = i;
const int x_52 = asint(x_9[3].x);
if ((x_50 < x_52)) {
} else {
break;
}
const uint scalar_offset_1 = ((16u * uint(0))) / 4;
const int x_56 = asint(x_9[scalar_offset_1 / 4][scalar_offset_1 % 4]);
j = x_56;
[loop] while (true) {
const int x_61 = j;
const int x_63 = asint(x_9[2].x);
if ((x_61 < x_63)) {
} else {
break;
}
switch(j) {
case 1: {
const int x_78 = i;
const uint scalar_offset_2 = ((16u * uint(0))) / 4;
const float x_80 = asfloat(x_6[scalar_offset_2 / 4][scalar_offset_2 % 4]);
A[x_78] = x_80;
break;
}
case 0: {
if ((-2147483648 < i)) {
{
j = (j + 1);
}
continue;
}
const int x_74 = i;
const float x_76 = asfloat(x_6[2].x);
A[x_74] = x_76;
break;
}
default: {
break;
}
}
{
j = (j + 1);
}
}
{
i = (i + 1);
}
}
const uint scalar_offset_3 = ((16u * uint(0))) / 4;
const int x_87 = asint(x_9[scalar_offset_3 / 4][scalar_offset_3 % 4]);
const float x_89 = A[x_87];
const uint scalar_offset_4 = ((16u * uint(0))) / 4;
const float x_91 = asfloat(x_6[scalar_offset_4 / 4][scalar_offset_4 % 4]);
const bool x_92 = (x_89 == x_91);
x_102_phi = x_92;
if (x_92) {
const int x_96 = asint(x_9[1].x);
const float x_98 = A[x_96];
const uint scalar_offset_5 = ((16u * uint(0))) / 4;
const float x_100 = asfloat(x_6[scalar_offset_5 / 4][scalar_offset_5 % 4]);
x_101 = (x_98 == x_100);
x_102_phi = x_101;
}
if (x_102_phi) {
const int x_107 = asint(x_9[1].x);
const uint scalar_offset_6 = ((16u * uint(0))) / 4;
const int x_110 = asint(x_9[scalar_offset_6 / 4][scalar_offset_6 % 4]);
const uint scalar_offset_7 = ((16u * uint(0))) / 4;
const int x_113 = asint(x_9[scalar_offset_7 / 4][scalar_offset_7 % 4]);
const int x_116 = asint(x_9[1].x);
x_GLF_color = float4(float(x_107), float(x_110), float(x_113), float(x_116));
} else {
const int x_120 = asint(x_9[1].x);
const float x_121 = float(x_120);
x_GLF_color = float4(x_121, x_121, x_121, x_121);
}
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_3 = {x_GLF_color};
return tint_symbol_3;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x0000027536C22E40(52,13-21): error X3708: continue cannot be used in a switch

View File

@ -1,86 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_x_6 : register(b0, space0) {
uint4 x_6[1];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
int i = 0;
const float x_51 = asfloat(x_6[0].x);
i = int(x_51);
switch(i) {
case 0: {
[loop] while (true) {
i = (i + 1);
switch(i) {
case 2: {
i = (i + 5);
break;
}
case 1: {
{
if ((i > 200)) {
} else {
break;
}
}
continue;
break;
}
default: {
i = (i + 7);
break;
}
}
{
if ((i > 200)) {
} else {
break;
}
}
}
if ((i > 100)) {
i = (i - 2);
break;
}
/* fallthrough */
{
i = (i - 3);
}
break;
}
default: {
i = (i - 3);
break;
}
}
if ((i == -2)) {
x_GLF_color = float4(1.0f, 0.0f, 0.0f, 1.0f);
} else {
x_GLF_color = float4(0.0f, 0.0f, 0.0f, 1.0f);
}
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_2 = {x_GLF_color};
return tint_symbol_2;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x0000013B8CBD6FE0(26,13-21): error X3708: continue cannot be used in a switch

View File

@ -1,86 +0,0 @@
SKIP: FAILED
cbuffer cbuffer_x_6 : register(b0, space0) {
uint4 x_6[1];
};
static float4 x_GLF_color = float4(0.0f, 0.0f, 0.0f, 0.0f);
void main_1() {
int i = 0;
const float x_51 = asfloat(x_6[0].x);
i = int(x_51);
switch(i) {
case 0: {
[loop] while (true) {
i = (i + 1);
switch(i) {
case 2: {
i = (i + 5);
break;
}
case 1: {
{
if ((i > 200)) {
} else {
break;
}
}
continue;
break;
}
default: {
i = (i + 7);
break;
}
}
{
if ((i > 200)) {
} else {
break;
}
}
}
if ((i > 100)) {
i = (i - 2);
break;
}
/* fallthrough */
{
i = (i - 3);
}
break;
}
default: {
i = (i - 3);
break;
}
}
if ((i == -2)) {
x_GLF_color = float4(1.0f, 0.0f, 0.0f, 1.0f);
} else {
x_GLF_color = float4(0.0f, 0.0f, 0.0f, 1.0f);
}
return;
}
struct main_out {
float4 x_GLF_color_1;
};
struct tint_symbol {
float4 x_GLF_color_1 : SV_Target0;
};
main_out main_inner() {
main_1();
const main_out tint_symbol_2 = {x_GLF_color};
return tint_symbol_2;
}
tint_symbol main() {
const main_out inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.x_GLF_color_1 = inner_result.x_GLF_color_1;
return wrapper_result;
}
C:\src\tint\test\Shader@0x0000019C85DE9DB0(26,13-21): error X3708: continue cannot be used in a switch