[tint][ir][fuzz] Check for invalid @input_attachment_index
This also adds emitting this attribute in the IR disassembler.
Fixes: 354005988
Change-Id: Ib9e05573c002fd35ffa8af79869f05519b13f5e9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/199194
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index 6e0ee31..52024b3 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -212,6 +212,10 @@
<< StyleLiteral(p.binding) << ")";
}
+void Disassembler::EmitInputAttachmentIndex(uint32_t i) {
+ out_ << StyleAttribute("@input_attachment_index") << "(" << StyleLiteral(i) << ")";
+}
+
void Disassembler::EmitInterpolation(Interpolation interp) {
out_ << StyleAttribute("@interpolate") << "(";
out_ << StyleEnum(interp.type);
@@ -513,6 +517,12 @@
out_ << " ";
EmitBindingPoint(v->BindingPoint().value());
}
+
+ if (v->InputAttachmentIndex().has_value()) {
+ out_ << " ";
+ EmitInputAttachmentIndex(v->InputAttachmentIndex().value());
+ }
+
if (v->Attributes().invariant) {
out_ << " " << StyleAttribute("@invariant");
}
diff --git a/src/tint/lang/core/ir/disassembler.h b/src/tint/lang/core/ir/disassembler.h
index 45fedd1..b96f496 100644
--- a/src/tint/lang/core/ir/disassembler.h
+++ b/src/tint/lang/core/ir/disassembler.h
@@ -232,6 +232,7 @@
void EmitParamAttributes(const FunctionParam* p);
void EmitReturnAttributes(const Function* func);
void EmitBindingPoint(BindingPoint p);
+ void EmitInputAttachmentIndex(uint32_t i);
void EmitInterpolation(Interpolation interp);
void EmitInstruction(const Instruction* inst);
void EmitValueWithType(const Instruction* val);
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index f63a499..cef04d5 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -1148,25 +1148,32 @@
}
}
- // Check that resource variables have @group and @binding set
- auto* type = var->Result(0)->Type();
- if (type == nullptr) {
+ auto* result_type = var->Result(0)->Type();
+ if (result_type == nullptr) {
+ AddError(var) << "result result_type is undefined";
return;
}
- if (auto* mv = type->As<type::MemoryView>()) {
+ if (auto* mv = result_type->As<type::MemoryView>()) {
+ // Check that only resource variables have @group and @binding set
switch (mv->AddressSpace()) {
case AddressSpace::kHandle:
case AddressSpace::kStorage:
case AddressSpace::kUniform:
if (!var->BindingPoint().has_value()) {
AddError(var) << "resource variable missing binding points";
- return;
}
break;
default:
break;
}
+
+ // Check that non-handle variables don't have @input_attachment_index set
+ if (var->InputAttachmentIndex().has_value() &&
+ mv->AddressSpace() != AddressSpace::kHandle) {
+ AddError(var) << "'@input_attachment_index' is not valid for non-handle var";
+ return;
+ }
}
}
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index b4e6c0b..b2aac77 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -2023,6 +2023,189 @@
)");
}
+TEST_F(IR_ValidatorTest, Var_Function_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<function, f32>();
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:41 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<function, f32, read_write> = var @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<function, f32, read_write> = var @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Var_Private_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<private_, f32>();
+
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:40 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<private, f32, read_write> = var @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<private, f32, read_write> = var @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Var_PushConstant_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<push_constant, f32>();
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:40 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<push_constant, f32, read> = var @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<push_constant, f32, read> = var @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Var_Storage_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<storage, f32>();
+ v->SetBindingPoint(0, 0);
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:40 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<storage, f32, read_write> = var @binding_point(0, 0) @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<storage, f32, read_write> = var @binding_point(0, 0) @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Var_Uniform_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<uniform, f32>();
+ v->SetBindingPoint(0, 0);
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:34 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<uniform, f32, read> = var @binding_point(0, 0) @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<uniform, f32, read> = var @binding_point(0, 0) @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Var_Workgroup_UnexpectedInputAttachmentIndex) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<workgroup, f32>();
+ v->SetInputAttachmentIndex(0);
+ b.Return(f);
+ });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:42 error: var: '@input_attachment_index' is not valid for non-handle var
+ %2:ptr<workgroup, f32, read_write> = var @input_attachment_index(0)
+ ^^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:ptr<workgroup, f32, read_write> = var @input_attachment_index(0)
+ ret
+ }
+}
+)");
+}
+
TEST_F(IR_ValidatorTest, Var_Init_WrongType) {
auto* f = b.Function("my_func", ty.void_());
@@ -5293,16 +5476,24 @@
auto* f = b.Function("my_func", ty.void_());
b.Append(f->Block(), [&] {
- auto* var = b.Var(ty.ptr<function, i32>());
- var->Result(0)->SetType(nullptr);
- b.Append(mod.allocators.instructions.Create<ir::Store>(var->Result(0), b.Constant(42_u)));
+ auto* result = b.InstructionResult(ty.u32());
+ result->SetType(nullptr);
+ b.Append(mod.allocators.instructions.Create<ir::Store>(result, b.Constant(42_u)));
b.Return(f);
});
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:11 error: store: store target operand is not a memory view
+ R"(:3:11 error: store: %2 is not in scope
+ store %2, 42u
+ ^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+:3:11 error: store: store target operand is not a memory view
store %2, 42u
^^
@@ -5313,7 +5504,6 @@
note: # Disassembly
%my_func = func():void {
$B1: {
- %2:null = var
store %2, 42u
ret
}