[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;
     }