mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-16 16:37:08 +00:00
tint/hlsl: for default-only switch, only emit condition if it has side-effects
This fixes edge-cases, like the condition expression being a type-cast,
which DXC apparently sees as a variable re-declaration. Example:
fn foo(x : f32) {
switch (i32(x)) {
default {
}
}
}
was emitted as HLSL:
void foo(float x) {
int(x);
do {
} while (false);
}
The `int(x)` is seen as a re-declaration of `x` by DXC.
We fix this by only emitted the condition expression if it has
side-effects (which currently means it contains a call expression).
Bug: tint:1820
Change-Id: I7e4320fa09ea2d634c9e324cb0b752b0ee7dcde9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118161
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
98bd83a8fc
commit
eab1f62629
@@ -3859,10 +3859,9 @@ bool GeneratorImpl::EmitDefaultOnlySwitch(const ast::SwitchStatement* stmt) {
|
||||
// default case body. We work around this here by emitting the default case
|
||||
// without the switch.
|
||||
|
||||
// Emit the switch condition as-is in case it has side-effects (e.g.
|
||||
// function call). Note that's it's fine not to assign the result of the
|
||||
// expression.
|
||||
{
|
||||
// Emit the switch condition as-is if it has side-effects (e.g.
|
||||
// function call). Note that we can ignore the result of the expression (if any).
|
||||
if (auto* sem_cond = builder_.Sem().Get(stmt->condition); sem_cond->HasSideEffects()) {
|
||||
auto out = line();
|
||||
if (!EmitExpression(out, stmt->condition)) {
|
||||
return false;
|
||||
|
||||
@@ -66,7 +66,16 @@ TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch_MixedDefault) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch_OnlyDefaultCase) {
|
||||
TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch_OnlyDefaultCase_NoSideEffectsCondition) {
|
||||
// var<private> cond : i32;
|
||||
// var<private> a : i32;
|
||||
// fn test() {
|
||||
// switch(cond) {
|
||||
// default: {
|
||||
// a = 42;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
GlobalVar("cond", ty.i32(), type::AddressSpace::kPrivate);
|
||||
GlobalVar("a", ty.i32(), type::AddressSpace::kPrivate);
|
||||
auto* s = Switch( //
|
||||
@@ -79,7 +88,45 @@ TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch_OnlyDefaultCase) {
|
||||
gen.increment_indent();
|
||||
|
||||
ASSERT_TRUE(gen.EmitStatement(s)) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"( cond;
|
||||
EXPECT_EQ(gen.result(), R"( do {
|
||||
a = 42;
|
||||
} while (false);
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch_OnlyDefaultCase_SideEffectsCondition) {
|
||||
// var<private> global : i32;
|
||||
// fn bar() -> i32 {
|
||||
// global = 84;
|
||||
// return global;
|
||||
// }
|
||||
//
|
||||
// var<private> a : i32;
|
||||
// fn test() {
|
||||
// switch(bar()) {
|
||||
// default: {
|
||||
// a = 42;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
GlobalVar("global", ty.i32(), type::AddressSpace::kPrivate);
|
||||
Func("bar", {}, ty.i32(),
|
||||
utils::Vector{ //
|
||||
Assign("global", Expr(84_i)), //
|
||||
Return("global")});
|
||||
|
||||
GlobalVar("a", ty.i32(), type::AddressSpace::kPrivate);
|
||||
auto* s = Switch( //
|
||||
Call("bar"), //
|
||||
DefaultCase(Block(Assign(Expr("a"), Expr(42_i)))));
|
||||
WrapInFunction(s);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
gen.increment_indent();
|
||||
|
||||
ASSERT_TRUE(gen.EmitStatement(s)) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"( bar();
|
||||
do {
|
||||
a = 42;
|
||||
} while (false);
|
||||
|
||||
Reference in New Issue
Block a user