1fd4e5da5Sopenharmony_ci// Copyright (c) 2015-2016 The Khronos Group Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci// Assembler tests for instructions in the "Group Instrucions" section of the
16fd4e5da5Sopenharmony_ci// SPIR-V spec.
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include <cstdint>
19fd4e5da5Sopenharmony_ci#include <limits>
20fd4e5da5Sopenharmony_ci#include <string>
21fd4e5da5Sopenharmony_ci#include <vector>
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
24fd4e5da5Sopenharmony_ci#include "test/test_fixture.h"
25fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_cinamespace spvtools {
28fd4e5da5Sopenharmony_cinamespace {
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ciusing spvtest::Concatenate;
31fd4e5da5Sopenharmony_ciusing spvtest::EnumCase;
32fd4e5da5Sopenharmony_ciusing spvtest::MakeInstruction;
33fd4e5da5Sopenharmony_ciusing ::testing::Eq;
34fd4e5da5Sopenharmony_ci
35fd4e5da5Sopenharmony_ci// Test Sampler Addressing Mode enum values
36fd4e5da5Sopenharmony_ci
37fd4e5da5Sopenharmony_ciusing SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
38fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<EnumCase<spv::SamplerAddressingMode>>>;
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_ciTEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) {
41fd4e5da5Sopenharmony_ci  const std::string input =
42fd4e5da5Sopenharmony_ci      "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest";
43fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input),
44fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpConstantSampler,
45fd4e5da5Sopenharmony_ci                                 {1, 2, uint32_t(GetParam().value()), 0, 0})));
46fd4e5da5Sopenharmony_ci}
47fd4e5da5Sopenharmony_ci
48fd4e5da5Sopenharmony_ci// clang-format off
49fd4e5da5Sopenharmony_ci#define CASE(NAME) { spv::SamplerAddressingMode::NAME, #NAME }
50fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
51fd4e5da5Sopenharmony_ci    TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
52fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerAddressingMode>>{
53fd4e5da5Sopenharmony_ci        CASE(None),
54fd4e5da5Sopenharmony_ci        CASE(ClampToEdge),
55fd4e5da5Sopenharmony_ci        CASE(Clamp),
56fd4e5da5Sopenharmony_ci        CASE(Repeat),
57fd4e5da5Sopenharmony_ci        CASE(RepeatMirrored),
58fd4e5da5Sopenharmony_ci    }));
59fd4e5da5Sopenharmony_ci#undef CASE
60fd4e5da5Sopenharmony_ci// clang-format on
61fd4e5da5Sopenharmony_ci
62fd4e5da5Sopenharmony_ciTEST_F(SamplerAddressingModeTest, WrongMode) {
63fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t xxyyzz 0 Nearest"),
64fd4e5da5Sopenharmony_ci              Eq("Invalid sampler addressing mode 'xxyyzz'."));
65fd4e5da5Sopenharmony_ci}
66fd4e5da5Sopenharmony_ci
67fd4e5da5Sopenharmony_ci// Test Sampler Filter Mode enum values
68fd4e5da5Sopenharmony_ci
69fd4e5da5Sopenharmony_ciusing SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
70fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<EnumCase<spv::SamplerFilterMode>>>;
71fd4e5da5Sopenharmony_ci
72fd4e5da5Sopenharmony_ciTEST_P(SamplerFilterModeTest, AnySamplerFilterMode) {
73fd4e5da5Sopenharmony_ci  const std::string input =
74fd4e5da5Sopenharmony_ci      "%result = OpConstantSampler %type Clamp 0 " + GetParam().name();
75fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input),
76fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpConstantSampler,
77fd4e5da5Sopenharmony_ci                                 {1, 2, 2, 0, uint32_t(GetParam().value())})));
78fd4e5da5Sopenharmony_ci}
79fd4e5da5Sopenharmony_ci
80fd4e5da5Sopenharmony_ci// clang-format off
81fd4e5da5Sopenharmony_ci#define CASE(NAME) { spv::SamplerFilterMode::NAME, #NAME}
82fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
83fd4e5da5Sopenharmony_ci    TextToBinarySamplerFilterMode, SamplerFilterModeTest,
84fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerFilterMode>>{
85fd4e5da5Sopenharmony_ci        CASE(Nearest),
86fd4e5da5Sopenharmony_ci        CASE(Linear),
87fd4e5da5Sopenharmony_ci    }));
88fd4e5da5Sopenharmony_ci#undef CASE
89fd4e5da5Sopenharmony_ci// clang-format on
90fd4e5da5Sopenharmony_ci
91fd4e5da5Sopenharmony_ciTEST_F(SamplerFilterModeTest, WrongMode) {
92fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompileFailure("%r = OpConstantSampler %t Clamp 0 xxyyzz"),
93fd4e5da5Sopenharmony_ci              Eq("Invalid sampler filter mode 'xxyyzz'."));
94fd4e5da5Sopenharmony_ci}
95fd4e5da5Sopenharmony_ci
96fd4e5da5Sopenharmony_cistruct ConstantTestCase {
97fd4e5da5Sopenharmony_ci  std::string constant_type;
98fd4e5da5Sopenharmony_ci  std::string constant_value;
99fd4e5da5Sopenharmony_ci  std::vector<uint32_t> expected_instructions;
100fd4e5da5Sopenharmony_ci};
101fd4e5da5Sopenharmony_ci
102fd4e5da5Sopenharmony_ciusing OpConstantValidTest =
103fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
104fd4e5da5Sopenharmony_ci
105fd4e5da5Sopenharmony_ciTEST_P(OpConstantValidTest, ValidTypes) {
106fd4e5da5Sopenharmony_ci  const std::string input = "%1 = " + GetParam().constant_type +
107fd4e5da5Sopenharmony_ci                            "\n"
108fd4e5da5Sopenharmony_ci                            "%2 = OpConstant %1 " +
109fd4e5da5Sopenharmony_ci                            GetParam().constant_value + "\n";
110fd4e5da5Sopenharmony_ci  std::vector<uint32_t> instructions;
111fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input), Eq(GetParam().expected_instructions))
112fd4e5da5Sopenharmony_ci      << " type: " << GetParam().constant_type
113fd4e5da5Sopenharmony_ci      << " literal: " << GetParam().constant_value;
114fd4e5da5Sopenharmony_ci}
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci// clang-format off
117fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
118fd4e5da5Sopenharmony_ci    TextToBinaryOpConstantValid, OpConstantValidTest,
119fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<ConstantTestCase>{
120fd4e5da5Sopenharmony_ci      // Check 16 bits
121fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0x1234",
122fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
123fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234})})},
124fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0x8000",
125fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
126fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x8000})})},
127fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0",
128fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
129fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
130fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "65535",
131fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
132fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
133fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0xffff",
134fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
135fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
136fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "0x8000", // Test sign extension.
137fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
138fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffff8000})})},
139fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "-32",
140fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
141fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
142fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "0",
143fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
144fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
145fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "-0",
146fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
147fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
148fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "-0x0",
149fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
150fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
151fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "-32768",
152fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
153fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32768)})})},
154fd4e5da5Sopenharmony_ci      // Check 32 bits
155fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 0", "42",
156fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
157fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 42})})},
158fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-32",
159fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
160fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
161fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "0",
162fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
163fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
164fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-0",
165fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
166fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
167fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-0x0",
168fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
169fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
170fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-0x001",
171fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
172fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-1)})})},
173fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "2147483647",
174fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
175fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu})})},
176fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-2147483648",
177fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
178fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x80000000u})})},
179fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "1.0",
180fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
181fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x3f800000})})},
182fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "10.0",
183fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
184fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x41200000})})},
185fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "-0x1p+128", // -infinity
186fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
187fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800000})})},
188fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "0x1p+128", // +infinity
189fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
190fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7F800000})})},
191fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN
192fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
193fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFFC00000})})},
194fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN
195fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
196fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800100})})},
197fd4e5da5Sopenharmony_ci      // Check 48 bits
198fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 0", "0x1234",
199fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
200fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
201fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 0", "0x800000000001",
202fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
203fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 1, 0x00008000})})},
204fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
205fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
206fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0, 0xffff8000})})},
207fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 1", "-32",
208fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
209fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
210fd4e5da5Sopenharmony_ci      // Check 64 bits
211fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "0x1234",
212fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
213fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
214fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "18446744073709551615",
215fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
216fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
217fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "0xffffffffffffffff",
218fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
219fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
220fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "0x1234",
221fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
222fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
223fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "-42",
224fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
225fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
226fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "-0x01",
227fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
228fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
229fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "9223372036854775807",
230fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
231fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
232fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "0x7fffffff",
233fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
234fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu, 0})})},
235fd4e5da5Sopenharmony_ci    }));
236fd4e5da5Sopenharmony_ci// clang-format on
237fd4e5da5Sopenharmony_ci
238fd4e5da5Sopenharmony_ci// A test case for checking OpConstant with invalid literals with a leading
239fd4e5da5Sopenharmony_ci// minus.
240fd4e5da5Sopenharmony_cistruct InvalidLeadingMinusCase {
241fd4e5da5Sopenharmony_ci  std::string type;
242fd4e5da5Sopenharmony_ci  std::string literal;
243fd4e5da5Sopenharmony_ci};
244fd4e5da5Sopenharmony_ci
245fd4e5da5Sopenharmony_ciusing OpConstantInvalidLeadingMinusTest = spvtest::TextToBinaryTestBase<
246fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<InvalidLeadingMinusCase>>;
247fd4e5da5Sopenharmony_ci
248fd4e5da5Sopenharmony_ciTEST_P(OpConstantInvalidLeadingMinusTest, InvalidCase) {
249fd4e5da5Sopenharmony_ci  const std::string input = "%1 = " + GetParam().type +
250fd4e5da5Sopenharmony_ci                            "\n"
251fd4e5da5Sopenharmony_ci                            "%2 = OpConstant %1 " +
252fd4e5da5Sopenharmony_ci                            GetParam().literal;
253fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompileFailure(input),
254fd4e5da5Sopenharmony_ci              Eq("Cannot put a negative number in an unsigned literal"));
255fd4e5da5Sopenharmony_ci}
256fd4e5da5Sopenharmony_ci
257fd4e5da5Sopenharmony_ci// clang-format off
258fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
259fd4e5da5Sopenharmony_ci    TextToBinaryOpConstantInvalidLeadingMinus, OpConstantInvalidLeadingMinusTest,
260fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<InvalidLeadingMinusCase>{
261fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "-0"},
262fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "-0x0"},
263fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "-1"},
264fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 0", "-0"},
265fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 0", "-0x0"},
266fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 0", "-1"},
267fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "-0"},
268fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "-0x0"},
269fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "-1"},
270fd4e5da5Sopenharmony_ci    }));
271fd4e5da5Sopenharmony_ci// clang-format on
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ci// A test case for invalid floating point literals.
274fd4e5da5Sopenharmony_cistruct InvalidFloatConstantCase {
275fd4e5da5Sopenharmony_ci  uint32_t width;
276fd4e5da5Sopenharmony_ci  std::string literal;
277fd4e5da5Sopenharmony_ci};
278fd4e5da5Sopenharmony_ci
279fd4e5da5Sopenharmony_ciusing OpConstantInvalidFloatConstant = spvtest::TextToBinaryTestBase<
280fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<InvalidFloatConstantCase>>;
281fd4e5da5Sopenharmony_ci
282fd4e5da5Sopenharmony_ciTEST_P(OpConstantInvalidFloatConstant, Samples) {
283fd4e5da5Sopenharmony_ci  // Check both kinds of instructions that take literal floats.
284fd4e5da5Sopenharmony_ci  for (const auto& instruction : {"OpConstant", "OpSpecConstant"}) {
285fd4e5da5Sopenharmony_ci    std::stringstream input;
286fd4e5da5Sopenharmony_ci    input << "%1 = OpTypeFloat " << GetParam().width << "\n"
287fd4e5da5Sopenharmony_ci          << "%2 = " << instruction << " %1 " << GetParam().literal;
288fd4e5da5Sopenharmony_ci    std::stringstream expected_error;
289fd4e5da5Sopenharmony_ci    expected_error << "Invalid " << GetParam().width
290fd4e5da5Sopenharmony_ci                   << "-bit float literal: " << GetParam().literal;
291fd4e5da5Sopenharmony_ci    EXPECT_THAT(CompileFailure(input.str()), Eq(expected_error.str()));
292fd4e5da5Sopenharmony_ci  }
293fd4e5da5Sopenharmony_ci}
294fd4e5da5Sopenharmony_ci
295fd4e5da5Sopenharmony_ci// clang-format off
296fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
297fd4e5da5Sopenharmony_ci    TextToBinaryInvalidFloatConstant, OpConstantInvalidFloatConstant,
298fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<InvalidFloatConstantCase>{
299fd4e5da5Sopenharmony_ci        {16, "abc"},
300fd4e5da5Sopenharmony_ci        {16, "--1"},
301fd4e5da5Sopenharmony_ci        {16, "-+1"},
302fd4e5da5Sopenharmony_ci        {16, "+-1"},
303fd4e5da5Sopenharmony_ci        {16, "++1"},
304fd4e5da5Sopenharmony_ci        {16, "1e30"}, // Overflow is an error for 16-bit floats.
305fd4e5da5Sopenharmony_ci        {16, "-1e30"},
306fd4e5da5Sopenharmony_ci        {16, "1e40"},
307fd4e5da5Sopenharmony_ci        {16, "-1e40"},
308fd4e5da5Sopenharmony_ci        {16, "1e400"},
309fd4e5da5Sopenharmony_ci        {16, "-1e400"},
310fd4e5da5Sopenharmony_ci        {32, "abc"},
311fd4e5da5Sopenharmony_ci        {32, "--1"},
312fd4e5da5Sopenharmony_ci        {32, "-+1"},
313fd4e5da5Sopenharmony_ci        {32, "+-1"},
314fd4e5da5Sopenharmony_ci        {32, "++1"},
315fd4e5da5Sopenharmony_ci        {32, "1e40"}, // Overflow is an error for 32-bit floats.
316fd4e5da5Sopenharmony_ci        {32, "-1e40"},
317fd4e5da5Sopenharmony_ci        {32, "1e400"},
318fd4e5da5Sopenharmony_ci        {32, "-1e400"},
319fd4e5da5Sopenharmony_ci        {64, "abc"},
320fd4e5da5Sopenharmony_ci        {64, "--1"},
321fd4e5da5Sopenharmony_ci        {64, "-+1"},
322fd4e5da5Sopenharmony_ci        {64, "+-1"},
323fd4e5da5Sopenharmony_ci        {64, "++1"},
324fd4e5da5Sopenharmony_ci        {32, "1e400"}, // Overflow is an error for 64-bit floats.
325fd4e5da5Sopenharmony_ci        {32, "-1e400"},
326fd4e5da5Sopenharmony_ci    }));
327fd4e5da5Sopenharmony_ci// clang-format on
328fd4e5da5Sopenharmony_ci
329fd4e5da5Sopenharmony_ciusing OpConstantInvalidTypeTest =
330fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
331fd4e5da5Sopenharmony_ciTEST_P(OpConstantInvalidTypeTest, InvalidTypes) {
332fd4e5da5Sopenharmony_ci  const std::string input = "%1 = " + GetParam() +
333fd4e5da5Sopenharmony_ci                            "\n"
334fd4e5da5Sopenharmony_ci                            "%2 = OpConstant %1 0\n";
335fd4e5da5Sopenharmony_ci  EXPECT_THAT(
336fd4e5da5Sopenharmony_ci      CompileFailure(input),
337fd4e5da5Sopenharmony_ci      Eq("Type for Constant must be a scalar floating point or integer type"));
338fd4e5da5Sopenharmony_ci}
339fd4e5da5Sopenharmony_ci
340fd4e5da5Sopenharmony_ci// clang-format off
341fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
342fd4e5da5Sopenharmony_ci    TextToBinaryOpConstantInvalidValidType, OpConstantInvalidTypeTest,
343fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
344fd4e5da5Sopenharmony_ci      {"OpTypeVoid",
345fd4e5da5Sopenharmony_ci       "OpTypeBool",
346fd4e5da5Sopenharmony_ci       "OpTypeVector %a 32",
347fd4e5da5Sopenharmony_ci       "OpTypeMatrix %a 32",
348fd4e5da5Sopenharmony_ci       "OpTypeImage %a 1D 0 0 0 0 Unknown",
349fd4e5da5Sopenharmony_ci       "OpTypeSampler",
350fd4e5da5Sopenharmony_ci       "OpTypeSampledImage %a",
351fd4e5da5Sopenharmony_ci       "OpTypeArray %a %b",
352fd4e5da5Sopenharmony_ci       "OpTypeRuntimeArray %a",
353fd4e5da5Sopenharmony_ci       "OpTypeStruct %a",
354fd4e5da5Sopenharmony_ci       "OpTypeOpaque \"Foo\"",
355fd4e5da5Sopenharmony_ci       "OpTypePointer UniformConstant %a",
356fd4e5da5Sopenharmony_ci       "OpTypeFunction %a %b",
357fd4e5da5Sopenharmony_ci       "OpTypeEvent",
358fd4e5da5Sopenharmony_ci       "OpTypeDeviceEvent",
359fd4e5da5Sopenharmony_ci       "OpTypeReserveId",
360fd4e5da5Sopenharmony_ci       "OpTypeQueue",
361fd4e5da5Sopenharmony_ci       "OpTypePipe ReadOnly",
362fd4e5da5Sopenharmony_ci
363fd4e5da5Sopenharmony_ci       // Skip OpTypeForwardPointer doesn't even produce a result ID.
364fd4e5da5Sopenharmony_ci       // The assembler errors out if we try to check it in this scenario.
365fd4e5da5Sopenharmony_ci
366fd4e5da5Sopenharmony_ci       // Try at least one thing that isn't a type at all
367fd4e5da5Sopenharmony_ci       "OpNot %a %b"
368fd4e5da5Sopenharmony_ci      },
369fd4e5da5Sopenharmony_ci    }));
370fd4e5da5Sopenharmony_ci// clang-format on
371fd4e5da5Sopenharmony_ci
372fd4e5da5Sopenharmony_ciusing OpSpecConstantValidTest =
373fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<ConstantTestCase>>;
374fd4e5da5Sopenharmony_ci
375fd4e5da5Sopenharmony_ciTEST_P(OpSpecConstantValidTest, ValidTypes) {
376fd4e5da5Sopenharmony_ci  const std::string input = "%1 = " + GetParam().constant_type +
377fd4e5da5Sopenharmony_ci                            "\n"
378fd4e5da5Sopenharmony_ci                            "%2 = OpSpecConstant %1 " +
379fd4e5da5Sopenharmony_ci                            GetParam().constant_value + "\n";
380fd4e5da5Sopenharmony_ci  std::vector<uint32_t> instructions;
381fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input),
382fd4e5da5Sopenharmony_ci              Eq(GetParam().expected_instructions));
383fd4e5da5Sopenharmony_ci}
384fd4e5da5Sopenharmony_ci
385fd4e5da5Sopenharmony_ci// clang-format off
386fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
387fd4e5da5Sopenharmony_ci    TextToBinaryOpSpecConstantValid, OpSpecConstantValidTest,
388fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<ConstantTestCase>{
389fd4e5da5Sopenharmony_ci      // Check 16 bits
390fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0x1234",
391fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
392fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234})})},
393fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 0", "0x8000",
394fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
395fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x8000})})},
396fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "0x8000", // Test sign extension.
397fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
398fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0xffff8000})})},
399fd4e5da5Sopenharmony_ci      {"OpTypeInt 16 1", "-32",
400fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
401fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
402fd4e5da5Sopenharmony_ci      // Check 32 bits
403fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 0", "42",
404fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
405fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 42})})},
406fd4e5da5Sopenharmony_ci      {"OpTypeInt 32 1", "-32",
407fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
408fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
409fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "1.0",
410fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
411fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x3f800000})})},
412fd4e5da5Sopenharmony_ci      {"OpTypeFloat 32", "10.0",
413fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
414fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x41200000})})},
415fd4e5da5Sopenharmony_ci      // Check 48 bits
416fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 0", "0x1234",
417fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
418fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
419fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 0", "0x800000000001",
420fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
421fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 1, 0x00008000})})},
422fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
423fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
424fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0, 0xffff8000})})},
425fd4e5da5Sopenharmony_ci      {"OpTypeInt 48 1", "-32",
426fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
427fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
428fd4e5da5Sopenharmony_ci      // Check 64 bits
429fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 0", "0x1234",
430fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
431fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
432fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "0x1234",
433fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
434fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
435fd4e5da5Sopenharmony_ci      {"OpTypeInt 64 1", "-42",
436fd4e5da5Sopenharmony_ci        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
437fd4e5da5Sopenharmony_ci         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
438fd4e5da5Sopenharmony_ci    }));
439fd4e5da5Sopenharmony_ci// clang-format on
440fd4e5da5Sopenharmony_ci
441fd4e5da5Sopenharmony_ciusing OpSpecConstantInvalidTypeTest =
442fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<std::string>>;
443fd4e5da5Sopenharmony_ci
444fd4e5da5Sopenharmony_ciTEST_P(OpSpecConstantInvalidTypeTest, InvalidTypes) {
445fd4e5da5Sopenharmony_ci  const std::string input = "%1 = " + GetParam() +
446fd4e5da5Sopenharmony_ci                            "\n"
447fd4e5da5Sopenharmony_ci                            "%2 = OpSpecConstant %1 0\n";
448fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompileFailure(input),
449fd4e5da5Sopenharmony_ci              Eq("Type for SpecConstant must be a scalar floating point or "
450fd4e5da5Sopenharmony_ci                 "integer type"));
451fd4e5da5Sopenharmony_ci}
452fd4e5da5Sopenharmony_ci
453fd4e5da5Sopenharmony_ci// clang-format off
454fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
455fd4e5da5Sopenharmony_ci    TextToBinaryOpSpecConstantInvalidValidType, OpSpecConstantInvalidTypeTest,
456fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
457fd4e5da5Sopenharmony_ci      {"OpTypeVoid",
458fd4e5da5Sopenharmony_ci       "OpTypeBool",
459fd4e5da5Sopenharmony_ci       "OpTypeVector %a 32",
460fd4e5da5Sopenharmony_ci       "OpTypeMatrix %a 32",
461fd4e5da5Sopenharmony_ci       "OpTypeImage %a 1D 0 0 0 0 Unknown",
462fd4e5da5Sopenharmony_ci       "OpTypeSampler",
463fd4e5da5Sopenharmony_ci       "OpTypeSampledImage %a",
464fd4e5da5Sopenharmony_ci       "OpTypeArray %a %b",
465fd4e5da5Sopenharmony_ci       "OpTypeRuntimeArray %a",
466fd4e5da5Sopenharmony_ci       "OpTypeStruct %a",
467fd4e5da5Sopenharmony_ci       "OpTypeOpaque \"Foo\"",
468fd4e5da5Sopenharmony_ci       "OpTypePointer UniformConstant %a",
469fd4e5da5Sopenharmony_ci       "OpTypeFunction %a %b",
470fd4e5da5Sopenharmony_ci       "OpTypeEvent",
471fd4e5da5Sopenharmony_ci       "OpTypeDeviceEvent",
472fd4e5da5Sopenharmony_ci       "OpTypeReserveId",
473fd4e5da5Sopenharmony_ci       "OpTypeQueue",
474fd4e5da5Sopenharmony_ci       "OpTypePipe ReadOnly",
475fd4e5da5Sopenharmony_ci
476fd4e5da5Sopenharmony_ci       // Skip testing OpTypeForwardPointer because it doesn't even produce a result ID.
477fd4e5da5Sopenharmony_ci
478fd4e5da5Sopenharmony_ci       // Try at least one thing that isn't a type at all
479fd4e5da5Sopenharmony_ci       "OpNot %a %b"
480fd4e5da5Sopenharmony_ci      },
481fd4e5da5Sopenharmony_ci    }));
482fd4e5da5Sopenharmony_ci// clang-format on
483fd4e5da5Sopenharmony_ci
484fd4e5da5Sopenharmony_ciconst int64_t kMaxUnsigned48Bit = (int64_t(1) << 48) - 1;
485fd4e5da5Sopenharmony_ciconst int64_t kMaxSigned48Bit = (int64_t(1) << 47) - 1;
486fd4e5da5Sopenharmony_ciconst int64_t kMinSigned48Bit = -kMaxSigned48Bit - 1;
487fd4e5da5Sopenharmony_ci
488fd4e5da5Sopenharmony_ciusing ConstantRoundTripTest = RoundTripTest;
489fd4e5da5Sopenharmony_ci
490fd4e5da5Sopenharmony_ciTEST_P(ConstantRoundTripTest, DisassemblyEqualsAssemblyInput) {
491fd4e5da5Sopenharmony_ci  const std::string assembly = GetParam();
492fd4e5da5Sopenharmony_ci  EXPECT_THAT(EncodeAndDecodeSuccessfully(assembly), Eq(assembly)) << assembly;
493fd4e5da5Sopenharmony_ci}
494fd4e5da5Sopenharmony_ci
495fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
496fd4e5da5Sopenharmony_ci    OpConstantRoundTrip, ConstantRoundTripTest,
497fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
498fd4e5da5Sopenharmony_ci        // 16 bit
499fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 0\n",
500fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 0\n%2 = OpConstant %1 65535\n",
501fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 -32768\n",
502fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 1\n%2 = OpConstant %1 32767\n",
503fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n",
504fd4e5da5Sopenharmony_ci        // 32 bit
505fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 0\n"),
506fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 0\n%2 = OpConstant %1 ") +
507fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
508fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
509fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
510fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 1\n%2 = OpConstant %1 ") +
511fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
512fd4e5da5Sopenharmony_ci        // 48 bit
513fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 0\n"),
514fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 0\n%2 = OpConstant %1 ") +
515fd4e5da5Sopenharmony_ci            std::to_string(kMaxUnsigned48Bit) + "\n",
516fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
517fd4e5da5Sopenharmony_ci            std::to_string(kMaxSigned48Bit) + "\n",
518fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 1\n%2 = OpConstant %1 ") +
519fd4e5da5Sopenharmony_ci            std::to_string(kMinSigned48Bit) + "\n",
520fd4e5da5Sopenharmony_ci        // 64 bit
521fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 0\n"),
522fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 0\n%2 = OpConstant %1 ") +
523fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
524fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
525fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
526fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 1\n%2 = OpConstant %1 ") +
527fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
528fd4e5da5Sopenharmony_ci        // 32-bit float
529fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0\n",
530fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpConstant %1 13.5\n",
531fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -12.5\n",
532fd4e5da5Sopenharmony_ci        // 64-bit float
533fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0\n",
534fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpConstant %1 1.79767e+308\n",
535fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -1.79767e+308\n",
536fd4e5da5Sopenharmony_ci    }));
537fd4e5da5Sopenharmony_ci
538fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
539fd4e5da5Sopenharmony_ci    OpConstantHalfRoundTrip, ConstantRoundTripTest,
540fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
541fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x0p+0\n",
542fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x0p+0\n",
543fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+0\n",
544fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.1p+0\n",
545fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p-1\n",
546fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.8p+1\n",
547fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+1\n",
548fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+0\n",
549fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.1p+0\n",
550fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p-1\n",
551fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.8p+1\n",
552fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+1\n",
553fd4e5da5Sopenharmony_ci
554fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-16\n",  // some denorms
555fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p-24\n",
556fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p-24\n",
557fd4e5da5Sopenharmony_ci
558fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1p+16\n",       // +inf
559fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1p+16\n",      // -inf
560fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n",   // -inf
561fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.01p+16\n",    // nan
562fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.11p+16\n",    // nan
563fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffp+16\n",    // nan
564fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.ffcp+16\n",   // nan
565fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 0x1.004p+16\n",   // nan
566fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.01p+16\n",   // -nan
567fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.11p+16\n",   // -nan
568fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffp+16\n",   // -nan
569fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.ffcp+16\n",  // -nan
570fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 16\n%2 = OpConstant %1 -0x1.004p+16\n",  // -nan
571fd4e5da5Sopenharmony_ci    }));
572fd4e5da5Sopenharmony_ci
573fd4e5da5Sopenharmony_ci// clang-format off
574fd4e5da5Sopenharmony_ci// (Clang-format really wants to break up these strings across lines.
575fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
576fd4e5da5Sopenharmony_ci    OpConstantRoundTripNonFinite, ConstantRoundTripTest,
577fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
578fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1p+128\n",         // -inf
579fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1p+128\n",          // inf
580fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.8p+128\n",       // -nan
581fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0002p+128\n",    // -nan
582fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.0018p+128\n",    // -nan
583fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.01ep+128\n",     // -nan
584fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 -0x1.fffffep+128\n",  // -nan
585fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.8p+128\n",        // +nan
586fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0002p+128\n",     // +nan
587fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.0018p+128\n",     // +nan
588fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.01ep+128\n",      // +nan
589fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 32\n%2 = OpConstant %1 0x1.fffffep+128\n",   // +nan
590fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1p+1024\n",                // -inf
591fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1p+1024\n",                 // +inf
592fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.8p+1024\n",              // -nan
593fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0fp+1024\n",             // -nan
594fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.0000000000001p+1024\n",  // -nan
595fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.00003p+1024\n",          // -nan
596fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 -0x1.fffffffffffffp+1024\n",  // -nan
597fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.8p+1024\n",               // +nan
598fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0fp+1024\n",              // +nan
599fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.0000000000001p+1024\n",   // -nan
600fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.00003p+1024\n",           // -nan
601fd4e5da5Sopenharmony_ci  "%1 = OpTypeFloat 64\n%2 = OpConstant %1 0x1.fffffffffffffp+1024\n",   // -nan
602fd4e5da5Sopenharmony_ci    }));
603fd4e5da5Sopenharmony_ci// clang-format on
604fd4e5da5Sopenharmony_ci
605fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
606fd4e5da5Sopenharmony_ci    OpSpecConstantRoundTrip, ConstantRoundTripTest,
607fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<std::string>{
608fd4e5da5Sopenharmony_ci        // 16 bit
609fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 0\n",
610fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 0\n%2 = OpSpecConstant %1 65535\n",
611fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 -32768\n",
612fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 16 1\n%2 = OpSpecConstant %1 32767\n",
613fd4e5da5Sopenharmony_ci        "%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n",
614fd4e5da5Sopenharmony_ci        // 32 bit
615fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 0\n"),
616fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 0\n%2 = OpSpecConstant %1 ") +
617fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<uint32_t>::max()) + "\n",
618fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
619fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int32_t>::max()) + "\n",
620fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 32 1\n%2 = OpSpecConstant %1 ") +
621fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int32_t>::min()) + "\n",
622fd4e5da5Sopenharmony_ci        // 48 bit
623fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 0\n"),
624fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 0\n%2 = OpSpecConstant %1 ") +
625fd4e5da5Sopenharmony_ci            std::to_string(kMaxUnsigned48Bit) + "\n",
626fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
627fd4e5da5Sopenharmony_ci            std::to_string(kMaxSigned48Bit) + "\n",
628fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 48 1\n%2 = OpSpecConstant %1 ") +
629fd4e5da5Sopenharmony_ci            std::to_string(kMinSigned48Bit) + "\n",
630fd4e5da5Sopenharmony_ci        // 64 bit
631fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 0\n"),
632fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 0\n%2 = OpSpecConstant %1 ") +
633fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<uint64_t>::max()) + "\n",
634fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
635fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int64_t>::max()) + "\n",
636fd4e5da5Sopenharmony_ci        std::string("%1 = OpTypeInt 64 1\n%2 = OpSpecConstant %1 ") +
637fd4e5da5Sopenharmony_ci            std::to_string(std::numeric_limits<int64_t>::min()) + "\n",
638fd4e5da5Sopenharmony_ci        // 32-bit float
639fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 0\n",
640fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 13.5\n",
641fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 32\n%2 = OpSpecConstant %1 -12.5\n",
642fd4e5da5Sopenharmony_ci        // 64-bit float
643fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 0\n",
644fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 1.79767e+308\n",
645fd4e5da5Sopenharmony_ci        "%1 = OpTypeFloat 64\n%2 = OpSpecConstant %1 -1.79767e+308\n",
646fd4e5da5Sopenharmony_ci    }));
647fd4e5da5Sopenharmony_ci
648fd4e5da5Sopenharmony_ci// Test OpSpecConstantOp
649fd4e5da5Sopenharmony_ci
650fd4e5da5Sopenharmony_ciusing OpSpecConstantOpTestWithIds =
651fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
652fd4e5da5Sopenharmony_ci
653fd4e5da5Sopenharmony_ci// The operands to the OpSpecConstantOp opcode are all Ids.
654fd4e5da5Sopenharmony_ciTEST_P(OpSpecConstantOpTestWithIds, Assembly) {
655fd4e5da5Sopenharmony_ci  std::stringstream input;
656fd4e5da5Sopenharmony_ci  input << "%2 = OpSpecConstantOp %1 " << GetParam().name();
657fd4e5da5Sopenharmony_ci  for (auto id : GetParam().operands()) input << " %" << id;
658fd4e5da5Sopenharmony_ci  input << "\n";
659fd4e5da5Sopenharmony_ci
660fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input.str()),
661fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
662fd4e5da5Sopenharmony_ci                                 {1, 2, uint32_t(GetParam().value())},
663fd4e5da5Sopenharmony_ci                                 GetParam().operands())));
664fd4e5da5Sopenharmony_ci
665fd4e5da5Sopenharmony_ci  // Check the disassembler as well.
666fd4e5da5Sopenharmony_ci  EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
667fd4e5da5Sopenharmony_ci}
668fd4e5da5Sopenharmony_ci
669fd4e5da5Sopenharmony_ci// clang-format off
670fd4e5da5Sopenharmony_ci#define CASE1(NAME) { spv::Op::Op##NAME, #NAME, {3} }
671fd4e5da5Sopenharmony_ci#define CASE2(NAME) { spv::Op::Op##NAME, #NAME, {3, 4} }
672fd4e5da5Sopenharmony_ci#define CASE3(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5} }
673fd4e5da5Sopenharmony_ci#define CASE4(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6} }
674fd4e5da5Sopenharmony_ci#define CASE5(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7} }
675fd4e5da5Sopenharmony_ci#define CASE6(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
676fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
677fd4e5da5Sopenharmony_ci    TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds,
678fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
679fd4e5da5Sopenharmony_ci        // Conversion
680fd4e5da5Sopenharmony_ci        CASE1(SConvert),
681fd4e5da5Sopenharmony_ci        CASE1(FConvert),
682fd4e5da5Sopenharmony_ci        CASE1(ConvertFToS),
683fd4e5da5Sopenharmony_ci        CASE1(ConvertSToF),
684fd4e5da5Sopenharmony_ci        CASE1(ConvertFToU),
685fd4e5da5Sopenharmony_ci        CASE1(ConvertUToF),
686fd4e5da5Sopenharmony_ci        CASE1(UConvert),
687fd4e5da5Sopenharmony_ci        CASE1(ConvertPtrToU),
688fd4e5da5Sopenharmony_ci        CASE1(ConvertUToPtr),
689fd4e5da5Sopenharmony_ci        CASE1(GenericCastToPtr),
690fd4e5da5Sopenharmony_ci        CASE1(PtrCastToGeneric),
691fd4e5da5Sopenharmony_ci        CASE1(Bitcast),
692fd4e5da5Sopenharmony_ci        CASE1(QuantizeToF16),
693fd4e5da5Sopenharmony_ci        // Arithmetic
694fd4e5da5Sopenharmony_ci        CASE1(SNegate),
695fd4e5da5Sopenharmony_ci        CASE1(Not),
696fd4e5da5Sopenharmony_ci        CASE2(IAdd),
697fd4e5da5Sopenharmony_ci        CASE2(ISub),
698fd4e5da5Sopenharmony_ci        CASE2(IMul),
699fd4e5da5Sopenharmony_ci        CASE2(UDiv),
700fd4e5da5Sopenharmony_ci        CASE2(SDiv),
701fd4e5da5Sopenharmony_ci        CASE2(UMod),
702fd4e5da5Sopenharmony_ci        CASE2(SRem),
703fd4e5da5Sopenharmony_ci        CASE2(SMod),
704fd4e5da5Sopenharmony_ci        CASE2(ShiftRightLogical),
705fd4e5da5Sopenharmony_ci        CASE2(ShiftRightArithmetic),
706fd4e5da5Sopenharmony_ci        CASE2(ShiftLeftLogical),
707fd4e5da5Sopenharmony_ci        CASE2(BitwiseOr),
708fd4e5da5Sopenharmony_ci        CASE2(BitwiseAnd),
709fd4e5da5Sopenharmony_ci        CASE2(BitwiseXor),
710fd4e5da5Sopenharmony_ci        CASE1(FNegate),
711fd4e5da5Sopenharmony_ci        CASE2(FAdd),
712fd4e5da5Sopenharmony_ci        CASE2(FSub),
713fd4e5da5Sopenharmony_ci        CASE2(FMul),
714fd4e5da5Sopenharmony_ci        CASE2(FDiv),
715fd4e5da5Sopenharmony_ci        CASE2(FRem),
716fd4e5da5Sopenharmony_ci        CASE2(FMod),
717fd4e5da5Sopenharmony_ci        // Composite operations use literal numbers. So they're in another test.
718fd4e5da5Sopenharmony_ci        // Logical
719fd4e5da5Sopenharmony_ci        CASE2(LogicalOr),
720fd4e5da5Sopenharmony_ci        CASE2(LogicalAnd),
721fd4e5da5Sopenharmony_ci        CASE1(LogicalNot),
722fd4e5da5Sopenharmony_ci        CASE2(LogicalEqual),
723fd4e5da5Sopenharmony_ci        CASE2(LogicalNotEqual),
724fd4e5da5Sopenharmony_ci        CASE3(Select),
725fd4e5da5Sopenharmony_ci        // Comparison
726fd4e5da5Sopenharmony_ci        CASE2(IEqual),
727fd4e5da5Sopenharmony_ci        CASE2(INotEqual), // Allowed in 1.0 Rev 7
728fd4e5da5Sopenharmony_ci        CASE2(ULessThan),
729fd4e5da5Sopenharmony_ci        CASE2(SLessThan),
730fd4e5da5Sopenharmony_ci        CASE2(UGreaterThan),
731fd4e5da5Sopenharmony_ci        CASE2(SGreaterThan),
732fd4e5da5Sopenharmony_ci        CASE2(ULessThanEqual),
733fd4e5da5Sopenharmony_ci        CASE2(SLessThanEqual),
734fd4e5da5Sopenharmony_ci        CASE2(UGreaterThanEqual),
735fd4e5da5Sopenharmony_ci        CASE2(SGreaterThanEqual),
736fd4e5da5Sopenharmony_ci        // Memory
737fd4e5da5Sopenharmony_ci        // For AccessChain, there is a base Id, then a sequence of index Ids.
738fd4e5da5Sopenharmony_ci        // Having no index Ids is a corner case.
739fd4e5da5Sopenharmony_ci        CASE1(AccessChain),
740fd4e5da5Sopenharmony_ci        CASE2(AccessChain),
741fd4e5da5Sopenharmony_ci        CASE6(AccessChain),
742fd4e5da5Sopenharmony_ci        CASE1(InBoundsAccessChain),
743fd4e5da5Sopenharmony_ci        CASE2(InBoundsAccessChain),
744fd4e5da5Sopenharmony_ci        CASE6(InBoundsAccessChain),
745fd4e5da5Sopenharmony_ci        // PtrAccessChain also has an element Id.
746fd4e5da5Sopenharmony_ci        CASE2(PtrAccessChain),
747fd4e5da5Sopenharmony_ci        CASE3(PtrAccessChain),
748fd4e5da5Sopenharmony_ci        CASE6(PtrAccessChain),
749fd4e5da5Sopenharmony_ci        CASE2(InBoundsPtrAccessChain),
750fd4e5da5Sopenharmony_ci        CASE3(InBoundsPtrAccessChain),
751fd4e5da5Sopenharmony_ci        CASE6(InBoundsPtrAccessChain),
752fd4e5da5Sopenharmony_ci    }));
753fd4e5da5Sopenharmony_ci#undef CASE1
754fd4e5da5Sopenharmony_ci#undef CASE2
755fd4e5da5Sopenharmony_ci#undef CASE3
756fd4e5da5Sopenharmony_ci#undef CASE4
757fd4e5da5Sopenharmony_ci#undef CASE5
758fd4e5da5Sopenharmony_ci#undef CASE6
759fd4e5da5Sopenharmony_ci// clang-format on
760fd4e5da5Sopenharmony_ci
761fd4e5da5Sopenharmony_ciusing OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
762fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
763fd4e5da5Sopenharmony_ci
764fd4e5da5Sopenharmony_ci// The operands to the OpSpecConstantOp opcode are two Ids followed by a
765fd4e5da5Sopenharmony_ci// sequence of literal numbers.
766fd4e5da5Sopenharmony_ciTEST_P(OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers, Assembly) {
767fd4e5da5Sopenharmony_ci  std::stringstream input;
768fd4e5da5Sopenharmony_ci  input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3 %4";
769fd4e5da5Sopenharmony_ci  for (auto number : GetParam().operands()) input << " " << number;
770fd4e5da5Sopenharmony_ci  input << "\n";
771fd4e5da5Sopenharmony_ci
772fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input.str()),
773fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
774fd4e5da5Sopenharmony_ci                                 {1, 2, uint32_t(GetParam().value()), 3, 4},
775fd4e5da5Sopenharmony_ci                                 GetParam().operands())));
776fd4e5da5Sopenharmony_ci
777fd4e5da5Sopenharmony_ci  // Check the disassembler as well.
778fd4e5da5Sopenharmony_ci  EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
779fd4e5da5Sopenharmony_ci}
780fd4e5da5Sopenharmony_ci
781fd4e5da5Sopenharmony_ci#define CASE(NAME) spv::Op::Op##NAME, #NAME
782fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
783fd4e5da5Sopenharmony_ci    TextToBinaryOpSpecConstantOp,
784fd4e5da5Sopenharmony_ci    OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers,
785fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
786fd4e5da5Sopenharmony_ci        // For VectorShuffle, there are two vector operands, and at least
787fd4e5da5Sopenharmony_ci        // two selector Ids.  OpenCL can have up to 16-element vectors.
788fd4e5da5Sopenharmony_ci        {CASE(VectorShuffle), {0, 0}},
789fd4e5da5Sopenharmony_ci        {CASE(VectorShuffle), {4, 3, 2, 1}},
790fd4e5da5Sopenharmony_ci        {CASE(VectorShuffle), {0, 2, 4, 6, 1, 3, 5, 7}},
791fd4e5da5Sopenharmony_ci        {CASE(VectorShuffle),
792fd4e5da5Sopenharmony_ci         {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}},
793fd4e5da5Sopenharmony_ci        // For CompositeInsert, there is an object to insert, the target
794fd4e5da5Sopenharmony_ci        // composite, and then literal indices.
795fd4e5da5Sopenharmony_ci        {CASE(CompositeInsert), {0}},
796fd4e5da5Sopenharmony_ci        {CASE(CompositeInsert), {4, 3, 99, 1}},
797fd4e5da5Sopenharmony_ci    }));
798fd4e5da5Sopenharmony_ci
799fd4e5da5Sopenharmony_ciusing OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
800fd4e5da5Sopenharmony_ci    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ci// The operands to the OpSpecConstantOp opcode are one Id followed by a
803fd4e5da5Sopenharmony_ci// sequence of literal numbers.
804fd4e5da5Sopenharmony_ciTEST_P(OpSpecConstantOpTestWithOneIdThenLiteralNumbers, Assembly) {
805fd4e5da5Sopenharmony_ci  std::stringstream input;
806fd4e5da5Sopenharmony_ci  input << "%2 = OpSpecConstantOp %1 " << GetParam().name() << " %3";
807fd4e5da5Sopenharmony_ci  for (auto number : GetParam().operands()) input << " " << number;
808fd4e5da5Sopenharmony_ci  input << "\n";
809fd4e5da5Sopenharmony_ci
810fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input.str()),
811fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
812fd4e5da5Sopenharmony_ci                                 {1, 2, uint32_t(GetParam().value()), 3},
813fd4e5da5Sopenharmony_ci                                 GetParam().operands())));
814fd4e5da5Sopenharmony_ci
815fd4e5da5Sopenharmony_ci  // Check the disassembler as well.
816fd4e5da5Sopenharmony_ci  EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
817fd4e5da5Sopenharmony_ci}
818fd4e5da5Sopenharmony_ci
819fd4e5da5Sopenharmony_ci#define CASE(NAME) spv::Op::Op##NAME, #NAME
820fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
821fd4e5da5Sopenharmony_ci    TextToBinaryOpSpecConstantOp,
822fd4e5da5Sopenharmony_ci    OpSpecConstantOpTestWithOneIdThenLiteralNumbers,
823fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
824fd4e5da5Sopenharmony_ci        // For CompositeExtract, the universal limit permits up to 255 literal
825fd4e5da5Sopenharmony_ci        // indices.  Let's only test a few.
826fd4e5da5Sopenharmony_ci        {CASE(CompositeExtract), {0}},
827fd4e5da5Sopenharmony_ci        {CASE(CompositeExtract), {0, 99, 42, 16, 17, 12, 19}},
828fd4e5da5Sopenharmony_ci    }));
829fd4e5da5Sopenharmony_ci
830fd4e5da5Sopenharmony_ci// TODO(dneto): OpConstantTrue
831fd4e5da5Sopenharmony_ci// TODO(dneto): OpConstantFalse
832fd4e5da5Sopenharmony_ci// TODO(dneto): OpConstantComposite
833fd4e5da5Sopenharmony_ci// TODO(dneto): OpConstantSampler: other variations Param is 0 or 1
834fd4e5da5Sopenharmony_ci// TODO(dneto): OpConstantNull
835fd4e5da5Sopenharmony_ci// TODO(dneto): OpSpecConstantTrue
836fd4e5da5Sopenharmony_ci// TODO(dneto): OpSpecConstantFalse
837fd4e5da5Sopenharmony_ci// TODO(dneto): OpSpecConstantComposite
838fd4e5da5Sopenharmony_ci// TODO(dneto): Negative tests for OpSpecConstantOp
839fd4e5da5Sopenharmony_ci
840fd4e5da5Sopenharmony_ci}  // namespace
841fd4e5da5Sopenharmony_ci}  // namespace spvtools
842