[tint] Substitute overrides IR report zero array size error
Substitute was simply missing a (pipeline) error when substituting
a override (expression) into an array count when this value is zero.
This is a backport to M135 with some merge conflicts addressed.
Bug: 407368915
Change-Id: I4577b301ec3cd2adacf44a2740e6df11ddd66754
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/234935
Commit-Queue: Peter McNeeley <petermcneeley@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Peter McNeeley <petermcneeley@google.com>
Commit-Queue: James Price <jrprice@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/tint/lang/core/ir/transform/substitute_overrides.cc b/src/tint/lang/core/ir/transform/substitute_overrides.cc
index c4168bd..5cd5feb 100644
--- a/src/tint/lang/core/ir/transform/substitute_overrides.cc
+++ b/src/tint/lang/core/ir/transform/substitute_overrides.cc
@@ -195,6 +195,17 @@
return new_value.Failure();
}
+ // Pipeline creation error for zero or negative sized array. This is important as we do
+ // not check constant evaluation access against zero size.
+ int64_t cnt_size_check = new_value.Get()->Value()->ValueAs<AInt>();
+ if (cnt_size_check < 1) {
+ diag::Diagnostic error{};
+ error.severity = diag::Severity::Error;
+ error.source = ir.SourceOf(var);
+ error << "array count (" << cnt_size_check << ") must be greater than 0";
+ return Failure(error);
+ }
+
uint32_t num_elements = new_value.Get()->Value()->ValueAs<uint32_t>();
auto* new_cnt = ty.Get<core::type::ConstantArrayCount>(num_elements);
auto* new_ty = ty.Get<core::type::Array>(old_ty->ElemType(), new_cnt, old_ty->Align(),
diff --git a/src/tint/lang/core/ir/transform/substitute_overrides_test.cc b/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
index 74d3c8b..40999db 100644
--- a/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
+++ b/src/tint/lang/core/ir/transform/substitute_overrides_test.cc
@@ -31,9 +31,11 @@
#include <utility>
#include "gtest/gtest.h"
+#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/ir/transform/helper_test.h"
#include "src/tint/lang/core/ir/type/array_count.h"
#include "src/tint/lang/core/ir/var.h"
+#include "src/tint/lang/core/type/array.h"
namespace tint::core::ir::transform {
namespace {
@@ -1662,5 +1664,92 @@
R"(error: Pipeline overridable constant 2 with value (65505.0) is not representable in type (f16))");
}
+TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeZeroFailure) {
+ ir::Var* v = nullptr;
+ b.Append(mod.root_block, [&] {
+ auto* x = b.Override("x", ty.u32());
+ x->SetOverrideId({2});
+
+ auto* cnt = ty.Get<core::ir::type::ValueArrayCount>(x->Result(0));
+ auto* ary = ty.Get<core::type::Array>(ty.u32(), cnt, 4_u, 4_u, 4_u, 4_u);
+ v = b.Var("v", ty.ptr(core::AddressSpace::kWorkgroup, ary, core::Access::kReadWrite));
+ mod.SetSource(v, Source{{7, 8}});
+ });
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* access = b.Access(ty.ptr<workgroup, u32>(), v, 0_u);
+ auto* load = b.Load(access);
+ b.Return(func, load);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %x:u32 = override undef @id(2)
+ %v:ptr<workgroup, array<u32, %x>, read_write> = var undef
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<workgroup, u32, read_write> = access %v, 0u
+ %5:u32 = load %4
+ ret %5
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ SubstituteOverridesConfig cfg{};
+ cfg.map[OverrideId{2}] = 0;
+ auto result = RunWithFailure(SubstituteOverrides, cfg);
+ ASSERT_NE(result, Success);
+ EXPECT_EQ(result.Failure().reason.Str(),
+ R"(7:8 error: array count (0) must be greater than 0)");
+}
+
+TEST_F(IR_SubstituteOverridesTest, OverrideArraySizeNegativeFailure) {
+ ir::Var* v = nullptr;
+ b.Append(mod.root_block, [&] {
+ auto* x = b.Override("x", ty.i32());
+ x->SetOverrideId({2});
+
+ auto* cnt = ty.Get<core::ir::type::ValueArrayCount>(x->Result(0));
+ auto* ary = ty.Get<core::type::Array>(ty.u32(), cnt, 4_u, 4_u, 4_u, 4_u);
+ v = b.Var("v", ty.ptr(core::AddressSpace::kWorkgroup, ary, core::Access::kReadWrite));
+ mod.SetSource(v, Source{{7, 8}});
+ });
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* access = b.Access(ty.ptr<workgroup, u32>(), v, 0_u);
+ auto* load = b.Load(access);
+ b.Return(func, load);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %x:i32 = override undef @id(2)
+ %v:ptr<workgroup, array<u32, %x>, read_write> = var undef
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<workgroup, u32, read_write> = access %v, 0u
+ %5:u32 = load %4
+ ret %5
+ }
+}
+)";
+
+ EXPECT_EQ(src, str());
+
+ SubstituteOverridesConfig cfg{};
+ cfg.map[OverrideId{2}] = -1;
+ auto result = RunWithFailure(SubstituteOverrides, cfg);
+ ASSERT_NE(result, Success);
+ EXPECT_EQ(result.Failure().reason.Str(),
+ R"(7:8 error: array count (-1) must be greater than 0)");
+}
+
} // namespace
} // namespace tint::core::ir::transform