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