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 "Memory Instructions" section of
16fd4e5da5Sopenharmony_ci// the SPIR-V spec.
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include <sstream>
19fd4e5da5Sopenharmony_ci#include <string>
20fd4e5da5Sopenharmony_ci#include <vector>
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
23fd4e5da5Sopenharmony_ci#include "test/test_fixture.h"
24fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_cinamespace spvtools {
27fd4e5da5Sopenharmony_cinamespace {
28fd4e5da5Sopenharmony_ci
29fd4e5da5Sopenharmony_ciusing spvtest::EnumCase;
30fd4e5da5Sopenharmony_ciusing spvtest::MakeInstruction;
31fd4e5da5Sopenharmony_ciusing spvtest::TextToBinaryTest;
32fd4e5da5Sopenharmony_ciusing ::testing::Eq;
33fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
34fd4e5da5Sopenharmony_ci
35fd4e5da5Sopenharmony_ci// Test assembly of Memory Access masks
36fd4e5da5Sopenharmony_ci
37fd4e5da5Sopenharmony_ciusing MemoryAccessTest = spvtest::TextToBinaryTestBase<
38fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<EnumCase<spv::MemoryAccessMask>>>;
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_ciTEST_P(MemoryAccessTest, AnySingleMemoryAccessMask) {
41fd4e5da5Sopenharmony_ci  std::stringstream input;
42fd4e5da5Sopenharmony_ci  input << "OpStore %ptr %value " << GetParam().name();
43fd4e5da5Sopenharmony_ci  for (auto operand : GetParam().operands()) input << " " << operand;
44fd4e5da5Sopenharmony_ci  EXPECT_THAT(
45fd4e5da5Sopenharmony_ci      CompiledInstructions(input.str()),
46fd4e5da5Sopenharmony_ci      Eq(MakeInstruction(spv::Op::OpStore, {1, 2, (uint32_t)GetParam().value()},
47fd4e5da5Sopenharmony_ci                         GetParam().operands())));
48fd4e5da5Sopenharmony_ci}
49fd4e5da5Sopenharmony_ci
50fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
51fd4e5da5Sopenharmony_ci    TextToBinaryMemoryAccessTest, MemoryAccessTest,
52fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::MemoryAccessMask>>{
53fd4e5da5Sopenharmony_ci        {spv::MemoryAccessMask::MaskNone, "None", {}},
54fd4e5da5Sopenharmony_ci        {spv::MemoryAccessMask::Volatile, "Volatile", {}},
55fd4e5da5Sopenharmony_ci        {spv::MemoryAccessMask::Aligned, "Aligned", {16}},
56fd4e5da5Sopenharmony_ci        {spv::MemoryAccessMask::Nontemporal, "Nontemporal", {}},
57fd4e5da5Sopenharmony_ci    }));
58fd4e5da5Sopenharmony_ci
59fd4e5da5Sopenharmony_ciTEST_F(TextToBinaryTest, CombinedMemoryAccessMask) {
60fd4e5da5Sopenharmony_ci  const std::string input = "OpStore %ptr %value Volatile|Aligned 16";
61fd4e5da5Sopenharmony_ci  const uint32_t expected_mask = uint32_t(spv::MemoryAccessMask::Volatile |
62fd4e5da5Sopenharmony_ci                                          spv::MemoryAccessMask::Aligned);
63fd4e5da5Sopenharmony_ci  EXPECT_THAT(expected_mask, Eq(3u));
64fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input),
65fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpStore, {1, 2, expected_mask, 16})));
66fd4e5da5Sopenharmony_ci}
67fd4e5da5Sopenharmony_ci
68fd4e5da5Sopenharmony_ci// Test Storage Class enum values
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ciusing StorageClassTest = spvtest::TextToBinaryTestBase<
71fd4e5da5Sopenharmony_ci    ::testing::TestWithParam<EnumCase<spv::StorageClass>>>;
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ciTEST_P(StorageClassTest, AnyStorageClass) {
74fd4e5da5Sopenharmony_ci  const std::string input = "%1 = OpVariable %2 " + GetParam().name();
75fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(input),
76fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpVariable,
77fd4e5da5Sopenharmony_ci                                 {1, 2, (uint32_t)GetParam().value()})));
78fd4e5da5Sopenharmony_ci}
79fd4e5da5Sopenharmony_ci
80fd4e5da5Sopenharmony_ci// clang-format off
81fd4e5da5Sopenharmony_ci#define CASE(NAME) { spv::StorageClass::NAME, #NAME, {} }
82fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
83fd4e5da5Sopenharmony_ci    TextToBinaryStorageClassTest, StorageClassTest,
84fd4e5da5Sopenharmony_ci    ::testing::ValuesIn(std::vector<EnumCase<spv::StorageClass>>{
85fd4e5da5Sopenharmony_ci        CASE(UniformConstant),
86fd4e5da5Sopenharmony_ci        CASE(Input),
87fd4e5da5Sopenharmony_ci        CASE(Uniform),
88fd4e5da5Sopenharmony_ci        CASE(Output),
89fd4e5da5Sopenharmony_ci        CASE(Workgroup),
90fd4e5da5Sopenharmony_ci        CASE(CrossWorkgroup),
91fd4e5da5Sopenharmony_ci        CASE(Private),
92fd4e5da5Sopenharmony_ci        CASE(Function),
93fd4e5da5Sopenharmony_ci        CASE(Generic),
94fd4e5da5Sopenharmony_ci        CASE(PushConstant),
95fd4e5da5Sopenharmony_ci        CASE(AtomicCounter),
96fd4e5da5Sopenharmony_ci        CASE(Image),
97fd4e5da5Sopenharmony_ci    }));
98fd4e5da5Sopenharmony_ci#undef CASE
99fd4e5da5Sopenharmony_ci// clang-format on
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ciusing MemoryRoundTripTest = RoundTripTest;
102fd4e5da5Sopenharmony_ci
103fd4e5da5Sopenharmony_ci// OpPtrEqual appeared in SPIR-V 1.4
104fd4e5da5Sopenharmony_ci
105fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrEqualGood) {
106fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n";
107fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
108fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpPtrEqual, {1, 2, 3, 4})));
109fd4e5da5Sopenharmony_ci  std::string disassembly = EncodeAndDecodeSuccessfully(
110fd4e5da5Sopenharmony_ci      spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
111fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
112fd4e5da5Sopenharmony_ci}
113fd4e5da5Sopenharmony_ci
114fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrEqualV13Bad) {
115fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n";
116fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv, SPV_ENV_UNIVERSAL_1_3);
117fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Invalid Opcode name 'OpPtrEqual'"));
118fd4e5da5Sopenharmony_ci}
119fd4e5da5Sopenharmony_ci
120fd4e5da5Sopenharmony_ci// OpPtrNotEqual appeared in SPIR-V 1.4
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrNotEqualGood) {
123fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n";
124fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
125fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpPtrNotEqual, {1, 2, 3, 4})));
126fd4e5da5Sopenharmony_ci  std::string disassembly = EncodeAndDecodeSuccessfully(
127fd4e5da5Sopenharmony_ci      spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
128fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
129fd4e5da5Sopenharmony_ci}
130fd4e5da5Sopenharmony_ci
131fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrNotEqualV13Bad) {
132fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n";
133fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv, SPV_ENV_UNIVERSAL_1_3);
134fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Invalid Opcode name 'OpPtrNotEqual'"));
135fd4e5da5Sopenharmony_ci}
136fd4e5da5Sopenharmony_ci
137fd4e5da5Sopenharmony_ci// OpPtrDiff appeared in SPIR-V 1.4
138fd4e5da5Sopenharmony_ci
139fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrDiffGood) {
140fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n";
141fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
142fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpPtrDiff, {1, 2, 3, 4})));
143fd4e5da5Sopenharmony_ci  std::string disassembly = EncodeAndDecodeSuccessfully(
144fd4e5da5Sopenharmony_ci      spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
145fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
146fd4e5da5Sopenharmony_ci}
147fd4e5da5Sopenharmony_ci
148fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpPtrDiffV13Good) {
149fd4e5da5Sopenharmony_ci  // OpPtrDiff is enabled by a capability as well, so we can assemble
150fd4e5da5Sopenharmony_ci  // it even in older SPIR-V environments.  We do that so we can
151fd4e5da5Sopenharmony_ci  // write tests.
152fd4e5da5Sopenharmony_ci  std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n";
153fd4e5da5Sopenharmony_ci  std::string disassembly = EncodeAndDecodeSuccessfully(
154fd4e5da5Sopenharmony_ci      spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
155fd4e5da5Sopenharmony_ci}
156fd4e5da5Sopenharmony_ci
157fd4e5da5Sopenharmony_ci// OpCopyMemory
158fd4e5da5Sopenharmony_ci
159fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryNoMemAccessGood) {
160fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2\n";
161fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
162fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2})));
163fd4e5da5Sopenharmony_ci  std::string disassembly =
164fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
165fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
166fd4e5da5Sopenharmony_ci}
167fd4e5da5Sopenharmony_ci
168fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryTooFewArgsBad) {
169fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1\n";
170fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv);
171fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Expected operand for OpCopyMemory instruction, "
172fd4e5da5Sopenharmony_ci                             "but found the end of the stream."));
173fd4e5da5Sopenharmony_ci}
174fd4e5da5Sopenharmony_ci
175fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryTooManyArgsBad) {
176fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 %3\n";
177fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv);
178fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Invalid memory access operand '%3'"));
179fd4e5da5Sopenharmony_ci}
180fd4e5da5Sopenharmony_ci
181fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNoneGood) {
182fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 None\n";
183fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
184fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 0})));
185fd4e5da5Sopenharmony_ci  std::string disassembly =
186fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
187fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
188fd4e5da5Sopenharmony_ci}
189fd4e5da5Sopenharmony_ci
190fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVolatileGood) {
191fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 Volatile\n";
192fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
193fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1})));
194fd4e5da5Sopenharmony_ci  std::string disassembly =
195fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
196fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
197fd4e5da5Sopenharmony_ci}
198fd4e5da5Sopenharmony_ci
199fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAligned8Good) {
200fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 Aligned 8\n";
201fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
202fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 2, 8})));
203fd4e5da5Sopenharmony_ci  std::string disassembly =
204fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
205fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
206fd4e5da5Sopenharmony_ci}
207fd4e5da5Sopenharmony_ci
208fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNontemporalGood) {
209fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 Nontemporal\n";
210fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
211fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 4})));
212fd4e5da5Sopenharmony_ci  std::string disassembly =
213fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
214fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
215fd4e5da5Sopenharmony_ci}
216fd4e5da5Sopenharmony_ci
217fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAvGood) {
218fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 MakePointerAvailable %3\n";
219fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
220fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 8, 3})));
221fd4e5da5Sopenharmony_ci  std::string disassembly =
222fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
223fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
224fd4e5da5Sopenharmony_ci}
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVisGood) {
227fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 MakePointerVisible %3\n";
228fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
229fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 16, 3})));
230fd4e5da5Sopenharmony_ci  std::string disassembly =
231fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
232fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
233fd4e5da5Sopenharmony_ci}
234fd4e5da5Sopenharmony_ci
235fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNonPrivateGood) {
236fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 NonPrivatePointer\n";
237fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
238fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 32})));
239fd4e5da5Sopenharmony_ci  std::string disassembly =
240fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
241fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
242fd4e5da5Sopenharmony_ci}
243fd4e5da5Sopenharmony_ci
244fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryAccessMixedGood) {
245fd4e5da5Sopenharmony_ci  std::string spirv =
246fd4e5da5Sopenharmony_ci      "OpCopyMemory %1 %2 "
247fd4e5da5Sopenharmony_ci      "Volatile|Aligned|Nontemporal|MakePointerAvailable|"
248fd4e5da5Sopenharmony_ci      "MakePointerVisible|NonPrivatePointer 16 %3 %4\n";
249fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
250fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 63, 16, 3, 4})));
251fd4e5da5Sopenharmony_ci  std::string disassembly =
252fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
253fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
254fd4e5da5Sopenharmony_ci}
255fd4e5da5Sopenharmony_ci
256fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV13Good) {
257fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
258fd4e5da5Sopenharmony_ci  // Note: This will assemble but should not validate for SPIR-V 1.3
259fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
260fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
261fd4e5da5Sopenharmony_ci  std::string disassembly =
262fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
263fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
264fd4e5da5Sopenharmony_ci}
265fd4e5da5Sopenharmony_ci
266fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV14Good) {
267fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
268fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
269fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
270fd4e5da5Sopenharmony_ci  std::string disassembly =
271fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
272fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
273fd4e5da5Sopenharmony_ci}
274fd4e5da5Sopenharmony_ci
275fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessMixedV14Good) {
276fd4e5da5Sopenharmony_ci  std::string spirv =
277fd4e5da5Sopenharmony_ci      "OpCopyMemory %1 %2 Volatile|Nontemporal|"
278fd4e5da5Sopenharmony_ci      "MakePointerVisible %3 "
279fd4e5da5Sopenharmony_ci      "Aligned|MakePointerAvailable|NonPrivatePointer 16 %4\n";
280fd4e5da5Sopenharmony_ci  EXPECT_THAT(
281fd4e5da5Sopenharmony_ci      CompiledInstructions(spirv),
282fd4e5da5Sopenharmony_ci      Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 21, 3, 42, 16, 4})));
283fd4e5da5Sopenharmony_ci  std::string disassembly =
284fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
285fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
286fd4e5da5Sopenharmony_ci}
287fd4e5da5Sopenharmony_ci
288fd4e5da5Sopenharmony_ci// OpCopyMemorySized
289fd4e5da5Sopenharmony_ci
290fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedNoMemAccessGood) {
291fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3\n";
292fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
293fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3})));
294fd4e5da5Sopenharmony_ci  std::string disassembly =
295fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
296fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
297fd4e5da5Sopenharmony_ci}
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedTooFewArgsBad) {
300fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2\n";
301fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv);
302fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Expected operand for OpCopyMemorySized "
303fd4e5da5Sopenharmony_ci                             "instruction, but found the end of the stream."));
304fd4e5da5Sopenharmony_ci}
305fd4e5da5Sopenharmony_ci
306fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedTooManyArgsBad) {
307fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 %4\n";
308fd4e5da5Sopenharmony_ci  std::string err = CompileFailure(spirv);
309fd4e5da5Sopenharmony_ci  EXPECT_THAT(err, HasSubstr("Invalid memory access operand '%4'"));
310fd4e5da5Sopenharmony_ci}
311fd4e5da5Sopenharmony_ci
312fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNoneGood) {
313fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 None\n";
314fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
315fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 0})));
316fd4e5da5Sopenharmony_ci  std::string disassembly =
317fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
318fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
319fd4e5da5Sopenharmony_ci}
320fd4e5da5Sopenharmony_ci
321fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVolatileGood) {
322fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile\n";
323fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
324fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1})));
325fd4e5da5Sopenharmony_ci  std::string disassembly =
326fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
327fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
328fd4e5da5Sopenharmony_ci}
329fd4e5da5Sopenharmony_ci
330fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAligned8Good) {
331fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 Aligned 8\n";
332fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
333fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 2, 8})));
334fd4e5da5Sopenharmony_ci  std::string disassembly =
335fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
336fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
337fd4e5da5Sopenharmony_ci}
338fd4e5da5Sopenharmony_ci
339fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNontemporalGood) {
340fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 Nontemporal\n";
341fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
342fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 4})));
343fd4e5da5Sopenharmony_ci  std::string disassembly =
344fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
345fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
346fd4e5da5Sopenharmony_ci}
347fd4e5da5Sopenharmony_ci
348fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAvGood) {
349fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerAvailable %4\n";
350fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
351fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 8, 4})));
352fd4e5da5Sopenharmony_ci  std::string disassembly =
353fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
354fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
355fd4e5da5Sopenharmony_ci}
356fd4e5da5Sopenharmony_ci
357fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVisGood) {
358fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerVisible %4\n";
359fd4e5da5Sopenharmony_ci  EXPECT_THAT(
360fd4e5da5Sopenharmony_ci      CompiledInstructions(spirv),
361fd4e5da5Sopenharmony_ci      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 16, 4})));
362fd4e5da5Sopenharmony_ci  std::string disassembly =
363fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
364fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
365fd4e5da5Sopenharmony_ci}
366fd4e5da5Sopenharmony_ci
367fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNonPrivateGood) {
368fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 NonPrivatePointer\n";
369fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
370fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 32})));
371fd4e5da5Sopenharmony_ci  std::string disassembly =
372fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
373fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
374fd4e5da5Sopenharmony_ci}
375fd4e5da5Sopenharmony_ci
376fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessMixedGood) {
377fd4e5da5Sopenharmony_ci  std::string spirv =
378fd4e5da5Sopenharmony_ci      "OpCopyMemorySized %1 %2 %3 "
379fd4e5da5Sopenharmony_ci      "Volatile|Aligned|Nontemporal|MakePointerAvailable|"
380fd4e5da5Sopenharmony_ci      "MakePointerVisible|NonPrivatePointer 16 %4 %5\n";
381fd4e5da5Sopenharmony_ci  EXPECT_THAT(
382fd4e5da5Sopenharmony_ci      CompiledInstructions(spirv),
383fd4e5da5Sopenharmony_ci      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5})));
384fd4e5da5Sopenharmony_ci  std::string disassembly =
385fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
386fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
387fd4e5da5Sopenharmony_ci}
388fd4e5da5Sopenharmony_ci
389fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV13Good) {
390fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
391fd4e5da5Sopenharmony_ci  // Note: This will assemble but should not validate for SPIR-V 1.3
392fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
393fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
394fd4e5da5Sopenharmony_ci  std::string disassembly =
395fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
396fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
397fd4e5da5Sopenharmony_ci}
398fd4e5da5Sopenharmony_ci
399fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV14Good) {
400fd4e5da5Sopenharmony_ci  std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
401fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
402fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
403fd4e5da5Sopenharmony_ci  std::string disassembly =
404fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
405fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
406fd4e5da5Sopenharmony_ci}
407fd4e5da5Sopenharmony_ci
408fd4e5da5Sopenharmony_ciTEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessMixedV14Good) {
409fd4e5da5Sopenharmony_ci  std::string spirv =
410fd4e5da5Sopenharmony_ci      "OpCopyMemorySized %1 %2 %3 Volatile|Nontemporal|"
411fd4e5da5Sopenharmony_ci      "MakePointerVisible %4 "
412fd4e5da5Sopenharmony_ci      "Aligned|MakePointerAvailable|NonPrivatePointer 16 %5\n";
413fd4e5da5Sopenharmony_ci  EXPECT_THAT(CompiledInstructions(spirv),
414fd4e5da5Sopenharmony_ci              Eq(MakeInstruction(spv::Op::OpCopyMemorySized,
415fd4e5da5Sopenharmony_ci                                 {1, 2, 3, 21, 4, 42, 16, 5})));
416fd4e5da5Sopenharmony_ci  std::string disassembly =
417fd4e5da5Sopenharmony_ci      EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
418fd4e5da5Sopenharmony_ci  EXPECT_THAT(disassembly, Eq(spirv));
419fd4e5da5Sopenharmony_ci}
420fd4e5da5Sopenharmony_ci
421fd4e5da5Sopenharmony_ci// TODO(dneto): OpVariable with initializers
422fd4e5da5Sopenharmony_ci// TODO(dneto): OpImageTexelPointer
423fd4e5da5Sopenharmony_ci// TODO(dneto): OpLoad
424fd4e5da5Sopenharmony_ci// TODO(dneto): OpStore
425fd4e5da5Sopenharmony_ci// TODO(dneto): OpAccessChain
426fd4e5da5Sopenharmony_ci// TODO(dneto): OpInBoundsAccessChain
427fd4e5da5Sopenharmony_ci// TODO(dneto): OpPtrAccessChain
428fd4e5da5Sopenharmony_ci// TODO(dneto): OpArrayLength
429fd4e5da5Sopenharmony_ci// TODO(dneto): OpGenercPtrMemSemantics
430fd4e5da5Sopenharmony_ci
431fd4e5da5Sopenharmony_ci}  // namespace
432fd4e5da5Sopenharmony_ci}  // namespace spvtools
433