[spirv-reader] Handle integer types and constants
Change test helper to check for substrings instead of full matches.
Bug: tint:1907
Change-Id: Ib27ade51be64f026a356fe545cf31da51b68b915
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/165525
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.bazel b/src/tint/lang/spirv/reader/parser/BUILD.bazel
index ff01e93..b3388d9 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/parser/BUILD.bazel
@@ -79,6 +79,7 @@
name = "test",
alwayslink = True,
srcs = [
+ "constant_test.cc",
"function_test.cc",
"helper_test.h",
],
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.cmake b/src/tint/lang/spirv/reader/parser/BUILD.cmake
index 2b6ba04..0b75f13 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/parser/BUILD.cmake
@@ -85,6 +85,7 @@
# Condition: TINT_BUILD_SPV_READER
################################################################################
tint_add_target(tint_lang_spirv_reader_parser_test test
+ lang/spirv/reader/parser/constant_test.cc
lang/spirv/reader/parser/function_test.cc
lang/spirv/reader/parser/helper_test.h
)
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.gn b/src/tint/lang/spirv/reader/parser/BUILD.gn
index f2cd647..ed0a990 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.gn
+++ b/src/tint/lang/spirv/reader/parser/BUILD.gn
@@ -86,6 +86,7 @@
if (tint_build_spv_reader) {
tint_unittests_source_set("unittests") {
sources = [
+ "constant_test.cc",
"function_test.cc",
"helper_test.h",
]
diff --git a/src/tint/lang/spirv/reader/parser/constant_test.cc b/src/tint/lang/spirv/reader/parser/constant_test.cc
new file mode 100644
index 0000000..e37e214
--- /dev/null
+++ b/src/tint/lang/spirv/reader/parser/constant_test.cc
@@ -0,0 +1,172 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/reader/parser/helper_test.h"
+
+namespace tint::spirv::reader {
+namespace {
+
+TEST_F(SpirvParserTest, Constant_Bool) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %bool = OpTypeBool
+ %true = OpConstantTrue %bool
+ %false = OpConstantTrue %bool
+ %void_fn = OpTypeFunction %void
+ %fn_type = OpTypeFunction %void %bool
+
+ %main = OpFunction %void None %void_fn
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %foo = OpFunction %void None %fn_type
+ %param = OpFunctionParameter %bool
+ %foo_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %bar = OpFunction %void None %void_fn
+ %bar_start = OpLabel
+ %1 = OpFunctionCall %void %foo %true
+ %2 = OpFunctionCall %void %foo %false
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+%4 = func():void -> %b3 {
+ %b3 = block {
+ %5:void = call %2, true
+ %6:void = call %2, true
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, Constant_I32) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %i32 = OpTypeInt 32 1
+ %i32_0 = OpConstant %i32 0
+ %i32_1 = OpConstant %i32 1
+ %i32_n1 = OpConstant %i32 -1
+ %i32_max = OpConstant %i32 2147483647
+ %i32_min = OpConstant %i32 -2147483648
+ %void_fn = OpTypeFunction %void
+ %fn_type = OpTypeFunction %void %i32
+
+ %main = OpFunction %void None %void_fn
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %foo = OpFunction %void None %fn_type
+ %param = OpFunctionParameter %i32
+ %foo_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %bar = OpFunction %void None %void_fn
+ %bar_start = OpLabel
+ %1 = OpFunctionCall %void %foo %i32_0
+ %2 = OpFunctionCall %void %foo %i32_1
+ %3 = OpFunctionCall %void %foo %i32_n1
+ %4 = OpFunctionCall %void %foo %i32_max
+ %5 = OpFunctionCall %void %foo %i32_min
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+%4 = func():void -> %b3 {
+ %b3 = block {
+ %5:void = call %2, 0i
+ %6:void = call %2, 1i
+ %7:void = call %2, -1i
+ %8:void = call %2, 2147483647i
+ %9:void = call %2, -2147483648i
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, Constant_U32) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %u32 = OpTypeInt 32 0
+ %u32_0 = OpConstant %u32 0
+ %u32_1 = OpConstant %u32 1
+ %u32_max = OpConstant %u32 4294967295
+ %void_fn = OpTypeFunction %void
+ %fn_type = OpTypeFunction %void %u32
+
+ %main = OpFunction %void None %void_fn
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %foo = OpFunction %void None %fn_type
+ %param = OpFunctionParameter %u32
+ %foo_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %bar = OpFunction %void None %void_fn
+ %bar_start = OpLabel
+ %1 = OpFunctionCall %void %foo %u32_0
+ %2 = OpFunctionCall %void %foo %u32_1
+ %3 = OpFunctionCall %void %foo %u32_max
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+%4 = func():void -> %b3 {
+ %b3 = block {
+ %5:void = call %2, 0u
+ %6:void = call %2, 1u
+ %7:void = call %2, 4294967295u
+ ret
+ }
+}
+)");
+}
+
+} // namespace
+} // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/helper_test.h b/src/tint/lang/spirv/reader/parser/helper_test.h
index 9b03490..7b2b547 100644
--- a/src/tint/lang/spirv/reader/parser/helper_test.h
+++ b/src/tint/lang/spirv/reader/parser/helper_test.h
@@ -43,7 +43,11 @@
// Helper macro to run the parser and compare the disassembled IR to a string.
// Automatically prefixes the IR disassembly with a newline to improve formatting of tests.
-#define EXPECT_IR(asm, ir) ASSERT_EQ("\n" + Run(asm), ir) << ir
+#define EXPECT_IR(asm, ir) \
+ do { \
+ auto got = "\n" + Run(asm); \
+ ASSERT_THAT(got, testing::HasSubstr(ir)) << got; \
+ } while (false)
/// Base helper class for testing the SPIR-V parser implementation.
template <typename BASE>
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index b72a042..160c131 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -45,6 +45,8 @@
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/spirv/validate/validate.h"
+using namespace tint::core::fluent_types; // NOLINT
+
namespace tint::spirv::reader {
namespace {
@@ -93,6 +95,15 @@
return ty_.void_();
case spvtools::opt::analysis::Type::kBool:
return ty_.bool_();
+ case spvtools::opt::analysis::Type::kInteger: {
+ auto* int_ty = type->AsInteger();
+ TINT_ASSERT_OR_RETURN_VALUE(int_ty->width() == 32, ty_.void_());
+ if (int_ty->IsSigned()) {
+ return ty_.i32();
+ } else {
+ return ty_.u32();
+ }
+ }
default:
TINT_UNIMPLEMENTED() << "unhandled SPIR-V type: " << type->str();
return ty_.void_();
@@ -132,6 +143,15 @@
if (auto* bool_ = constant->AsBoolConstant()) {
return b_.Constant(bool_->value());
}
+ if (auto* i = constant->AsIntConstant()) {
+ auto* int_ty = i->type()->AsInteger();
+ TINT_ASSERT_OR_RETURN_VALUE(int_ty->width() == 32, nullptr);
+ if (int_ty->IsSigned()) {
+ return b_.Constant(i32(i->GetS32BitValue()));
+ } else {
+ return b_.Constant(u32(i->GetU32BitValue()));
+ }
+ }
TINT_UNIMPLEMENTED() << "unhandled constant type";
return nullptr;
}