tint: Support @diagnostic on continuing statements
Bug: tint:1809 Change-Id: I01725dc3b5aa3a91f7a3d3b0077667a1072debce Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/124360 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
abe6db26d2
commit
498e91826e
|
@ -1975,8 +1975,13 @@ Maybe<const ast::Statement*> ParserImpl::break_if_statement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// continuing_compound_statement:
|
// continuing_compound_statement:
|
||||||
// brace_left statement* break_if_statement? brace_right
|
// attribute* BRACE_LEFT statement* break_if_statement? BRACE_RIGHT
|
||||||
Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
||||||
|
auto attrs = attribute_list();
|
||||||
|
if (attrs.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
|
||||||
auto source_start = peek().source();
|
auto source_start = peek().source();
|
||||||
auto body = expect_brace_block("", [&]() -> Expect<StatementList> {
|
auto body = expect_brace_block("", [&]() -> Expect<StatementList> {
|
||||||
StatementList stmts;
|
StatementList stmts;
|
||||||
|
@ -2010,7 +2015,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
||||||
auto source_end = last_source();
|
auto source_end = last_source();
|
||||||
|
|
||||||
return create<ast::BlockStatement>(Source::Combine(source_start, source_end), body.value,
|
return create<ast::BlockStatement>(Source::Combine(source_start, source_end), body.value,
|
||||||
utils::Empty);
|
std::move(attrs.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// continuing_statement
|
// continuing_statement
|
||||||
|
|
|
@ -28,6 +28,16 @@ TEST_F(ParserImplTest, ContinuingStmt) {
|
||||||
ASSERT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
ASSERT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, ContinuingStmt_WithAttributes) {
|
||||||
|
auto p = parser("continuing @diagnostic(off, derivative_uniformity) { discard; }");
|
||||||
|
auto e = p->continuing_statement();
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_EQ(e->attributes.Length(), 1u);
|
||||||
|
EXPECT_TRUE(e->attributes[0]->Is<ast::DiagnosticAttribute>());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
||||||
auto p = parser("continuing { discard }");
|
auto p = parser("continuing { discard }");
|
||||||
auto e = p->continuing_statement();
|
auto e = p->continuing_statement();
|
||||||
|
|
|
@ -8655,6 +8655,33 @@ fn foo() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnLoopContinuing_CallInContinuing) {
|
||||||
|
auto& param = GetParam();
|
||||||
|
utils::StringStream ss;
|
||||||
|
ss << R"(
|
||||||
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
|
fn foo() {
|
||||||
|
loop {
|
||||||
|
continuing )"
|
||||||
|
<< "@diagnostic(" << param << ", derivative_uniformity)"
|
||||||
|
<< R"( {
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
break if non_uniform == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(ss.str(), param != builtin::DiagnosticSeverity::kError);
|
||||||
|
if (param == builtin::DiagnosticSeverity::kOff) {
|
||||||
|
EXPECT_TRUE(error_.empty());
|
||||||
|
} else {
|
||||||
|
utils::StringStream err;
|
||||||
|
err << ToStr(param) << ": 'dpdx' must only be called";
|
||||||
|
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnSwitchStatement_CallInCondition) {
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnSwitchStatement_CallInCondition) {
|
||||||
auto& param = GetParam();
|
auto& param = GetParam();
|
||||||
utils::StringStream ss;
|
utils::StringStream ss;
|
||||||
|
|
|
@ -59,6 +59,9 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
// @diagnostic(warning, chromium_unreachable_code)
|
// @diagnostic(warning, chromium_unreachable_code)
|
||||||
// loop @diagnostic(off, chromium_unreachable_code) {
|
// loop @diagnostic(off, chromium_unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
|
// continuing @diagnostic(info, chromium_unreachable_code) {
|
||||||
|
// break if true;
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @diagnostic(error, chromium_unreachable_code)
|
// @diagnostic(error, chromium_unreachable_code)
|
||||||
|
@ -83,6 +86,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
auto for_body_severity = builtin::DiagnosticSeverity::kWarning;
|
auto for_body_severity = builtin::DiagnosticSeverity::kWarning;
|
||||||
auto loop_severity = builtin::DiagnosticSeverity::kWarning;
|
auto loop_severity = builtin::DiagnosticSeverity::kWarning;
|
||||||
auto loop_body_severity = builtin::DiagnosticSeverity::kOff;
|
auto loop_body_severity = builtin::DiagnosticSeverity::kOff;
|
||||||
|
auto continuing_severity = builtin::DiagnosticSeverity::kInfo;
|
||||||
auto while_severity = builtin::DiagnosticSeverity::kError;
|
auto while_severity = builtin::DiagnosticSeverity::kError;
|
||||||
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
|
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
|
||||||
auto attr = [&](auto severity) {
|
auto attr = [&](auto severity) {
|
||||||
|
@ -98,6 +102,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
auto* return_foo_for = Return();
|
auto* return_foo_for = Return();
|
||||||
auto* return_foo_loop = Return();
|
auto* return_foo_loop = Return();
|
||||||
auto* return_foo_while = Return();
|
auto* return_foo_while = Return();
|
||||||
|
auto* breakif_foo_continuing = BreakIf(Expr(true));
|
||||||
auto* else_stmt = Block(utils::Vector{return_foo_else}, attr(else_body_severity));
|
auto* else_stmt = Block(utils::Vector{return_foo_else}, attr(else_body_severity));
|
||||||
auto* elseif = If(Expr(false), Block(return_foo_elseif), Else(else_stmt));
|
auto* elseif = If(Expr(false), Block(return_foo_elseif), Else(else_stmt));
|
||||||
auto* if_foo = If(Expr(true), Block(utils::Vector{return_foo_if}, attr(if_body_severity)),
|
auto* if_foo = If(Expr(true), Block(utils::Vector{return_foo_if}, attr(if_body_severity)),
|
||||||
|
@ -109,7 +114,8 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
auto* fl =
|
auto* fl =
|
||||||
For(Decl(Var("i", ty.i32())), false, Increment("i"),
|
For(Decl(Var("i", ty.i32())), false, Increment("i"),
|
||||||
Block(utils::Vector{return_foo_for}, attr(for_body_severity)), attr(for_severity));
|
Block(utils::Vector{return_foo_for}, attr(for_body_severity)), attr(for_severity));
|
||||||
auto* l = Loop(Block(utils::Vector{return_foo_loop}, attr(loop_body_severity)), Block(),
|
auto* l = Loop(Block(utils::Vector{return_foo_loop}, attr(loop_body_severity)),
|
||||||
|
Block(utils::Vector{breakif_foo_continuing}, attr(continuing_severity)),
|
||||||
attr(loop_severity));
|
attr(loop_severity));
|
||||||
auto* wl = While(false, Block(utils::Vector{return_foo_while}, attr(while_body_severity)),
|
auto* wl = While(false, Block(utils::Vector{return_foo_while}, attr(while_body_severity)),
|
||||||
attr(while_severity));
|
attr(while_severity));
|
||||||
|
@ -150,6 +156,8 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_for, rule), for_body_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_for, rule), for_body_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(l, rule), loop_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(l, rule), loop_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(l->body, rule), loop_body_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(l->body, rule), loop_body_severity);
|
||||||
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(l->continuing, rule), continuing_severity);
|
||||||
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(breakif_foo_continuing, rule), continuing_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_loop, rule), loop_body_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_loop, rule), loop_body_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl, rule), while_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl, rule), while_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->condition, rule), while_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->condition, rule), while_severity);
|
||||||
|
|
|
@ -1048,7 +1048,17 @@ bool GeneratorImpl::EmitLoop(const ast::LoopStatement* stmt) {
|
||||||
|
|
||||||
if (stmt->continuing && !stmt->continuing->Empty()) {
|
if (stmt->continuing && !stmt->continuing->Empty()) {
|
||||||
line();
|
line();
|
||||||
line() << "continuing {";
|
{
|
||||||
|
auto out = line();
|
||||||
|
out << "continuing ";
|
||||||
|
if (!stmt->continuing->attributes.IsEmpty()) {
|
||||||
|
if (!EmitAttributes(out, stmt->continuing->attributes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
out << "{";
|
||||||
|
}
|
||||||
if (!EmitStatementsWithIndent(stmt->continuing->statements)) {
|
if (!EmitStatementsWithIndent(stmt->continuing->statements)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
loop {
|
||||||
|
continuing @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
break if x > 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
while (true) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
while (true) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
while (true) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
while (true) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 21
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%4 = OpTypeFunction %void %float
|
||||||
|
%13 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%16 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %4
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%8 = OpLabel
|
||||||
|
OpBranch %9
|
||||||
|
%9 = OpLabel
|
||||||
|
OpLoopMerge %10 %11 None
|
||||||
|
OpBranch %12
|
||||||
|
%12 = OpLabel
|
||||||
|
OpBranch %11
|
||||||
|
%11 = OpLabel
|
||||||
|
%14 = OpFOrdGreaterThan %bool %x %13
|
||||||
|
OpBranchConditional %14 %10 %9
|
||||||
|
%10 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %16
|
||||||
|
%18 = OpLabel
|
||||||
|
%20 = OpLoad %float %x_1
|
||||||
|
%19 = OpFunctionCall %void %main_inner %20
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,22 @@
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:5:11 warning: 'dpdx' must only be called from uniform control flow
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:7 note: control flow depends on possibly non-uniform value
|
||||||
|
break if x > 0.0;
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/loop_continuing_attribute.wgsl:6:16 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
break if x > 0.0;
|
||||||
|
^
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
loop {
|
||||||
|
|
||||||
|
continuing @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = dpdx(1.0);
|
||||||
|
break if (x > 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue