• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 Google 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 #include "opt/instruction.h"
16 
17 #include "gmock/gmock.h"
18 
19 #include "spirv-tools/libspirv.h"
20 #include "unit_spirv.h"
21 
22 namespace {
23 
24 using spvtest::MakeInstruction;
25 using spvtools::ir::Instruction;
26 using spvtools::ir::Operand;
27 using ::testing::Eq;
28 
TEST(InstructionTest,CreateTrivial)29 TEST(InstructionTest, CreateTrivial) {
30   Instruction empty;
31   EXPECT_EQ(SpvOpNop, empty.opcode());
32   EXPECT_EQ(0u, empty.type_id());
33   EXPECT_EQ(0u, empty.result_id());
34   EXPECT_EQ(0u, empty.NumOperands());
35   EXPECT_EQ(0u, empty.NumOperandWords());
36   EXPECT_EQ(0u, empty.NumInOperandWords());
37   EXPECT_EQ(empty.cend(), empty.cbegin());
38   EXPECT_EQ(empty.end(), empty.begin());
39 }
40 
TEST(InstructionTest,CreateWithOpcodeAndNoOperands)41 TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
42   Instruction inst(SpvOpReturn);
43   EXPECT_EQ(SpvOpReturn, inst.opcode());
44   EXPECT_EQ(0u, inst.type_id());
45   EXPECT_EQ(0u, inst.result_id());
46   EXPECT_EQ(0u, inst.NumOperands());
47   EXPECT_EQ(0u, inst.NumOperandWords());
48   EXPECT_EQ(0u, inst.NumInOperandWords());
49   EXPECT_EQ(inst.cend(), inst.cbegin());
50   EXPECT_EQ(inst.end(), inst.begin());
51 }
52 
53 // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
54 uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
55                                       32, 1};
56 // The operands that would be parsed from kSampleInstructionWords
57 spv_parsed_operand_t kSampleParsedOperands[] = {
58     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
59     {2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
60     {3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
61 };
62 
63 // A valid parse of kSampleParsedOperands.
64 spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
65                                                      uint16_t(4),
66                                                      uint16_t(SpvOpTypeInt),
67                                                      SPV_EXT_INST_TYPE_NONE,
68                                                      0,   // type id
69                                                      44,  // result id
70                                                      kSampleParsedOperands,
71                                                      3};
72 
73 // The words for an OpAccessChain instruction.
74 uint32_t kSampleAccessChainInstructionWords[] = {
75     (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
76 
77 // The operands that would be parsed from kSampleAccessChainInstructionWords.
78 spv_parsed_operand_t kSampleAccessChainOperands[] = {
79     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
80     {2, 1, SPV_OPERAND_TYPE_TYPE_ID, SPV_NUMBER_NONE, 0},
81     {3, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
82     {4, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
83     {5, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
84     {6, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
85 };
86 
87 // A valid parse of kSampleAccessChainInstructionWords
88 spv_parsed_instruction_t kSampleAccessChainInstruction = {
89     kSampleAccessChainInstructionWords,
90     uint16_t(7),
91     uint16_t(SpvOpAccessChain),
92     SPV_EXT_INST_TYPE_NONE,
93     100,  // type id
94     101,  // result id
95     kSampleAccessChainOperands,
96     6};
97 
98 // The words for an OpControlBarrier instruction.
99 uint32_t kSampleControlBarrierInstructionWords[] = {
100     (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
101 
102 // The operands that would be parsed from kSampleControlBarrierInstructionWords.
103 spv_parsed_operand_t kSampleControlBarrierOperands[] = {
104     {1, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0},  // Execution
105     {2, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0},  // Memory
106     {3, 1, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_NUMBER_NONE,
107      0},  // Semantics
108 };
109 
110 // A valid parse of kSampleControlBarrierInstructionWords
111 spv_parsed_instruction_t kSampleControlBarrierInstruction = {
112     kSampleControlBarrierInstructionWords,
113     uint16_t(4),
114     uint16_t(SpvOpControlBarrier),
115     SPV_EXT_INST_TYPE_NONE,
116     0,  // type id
117     0,  // result id
118     kSampleControlBarrierOperands,
119     3};
120 
TEST(InstructionTest,CreateWithOpcodeAndOperands)121 TEST(InstructionTest, CreateWithOpcodeAndOperands) {
122   Instruction inst(kSampleParsedInstruction);
123   EXPECT_EQ(SpvOpTypeInt, inst.opcode());
124   EXPECT_EQ(0u, inst.type_id());
125   EXPECT_EQ(44u, inst.result_id());
126   EXPECT_EQ(3u, inst.NumOperands());
127   EXPECT_EQ(3u, inst.NumOperandWords());
128   EXPECT_EQ(2u, inst.NumInOperandWords());
129 }
130 
TEST(InstructionTest,GetOperand)131 TEST(InstructionTest, GetOperand) {
132   Instruction inst(kSampleParsedInstruction);
133   EXPECT_THAT(inst.GetOperand(0).words, Eq(std::vector<uint32_t>{44}));
134   EXPECT_THAT(inst.GetOperand(1).words, Eq(std::vector<uint32_t>{32}));
135   EXPECT_THAT(inst.GetOperand(2).words, Eq(std::vector<uint32_t>{1}));
136 }
137 
TEST(InstructionTest,GetInOperand)138 TEST(InstructionTest, GetInOperand) {
139   Instruction inst(kSampleParsedInstruction);
140   EXPECT_THAT(inst.GetInOperand(0).words, Eq(std::vector<uint32_t>{32}));
141   EXPECT_THAT(inst.GetInOperand(1).words, Eq(std::vector<uint32_t>{1}));
142 }
143 
TEST(InstructionTest,OperandConstIterators)144 TEST(InstructionTest, OperandConstIterators) {
145   Instruction inst(kSampleParsedInstruction);
146   // Spot check iteration across operands.
147   auto cbegin = inst.cbegin();
148   auto cend = inst.cend();
149   EXPECT_NE(cend, inst.cbegin());
150 
151   auto citer = inst.cbegin();
152   for (int i = 0; i < 3; ++i, ++citer) {
153     const auto& operand = *citer;
154     EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
155     EXPECT_THAT(operand.words,
156                 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
157     EXPECT_NE(cend, citer);
158   }
159   EXPECT_EQ(cend, citer);
160 
161   // Check that cbegin and cend have not changed.
162   EXPECT_EQ(cbegin, inst.cbegin());
163   EXPECT_EQ(cend, inst.cend());
164 
165   // Check arithmetic.
166   const Operand& operand2 = *(inst.cbegin() + 2);
167   EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
168 }
169 
TEST(InstructionTest,OperandIterators)170 TEST(InstructionTest, OperandIterators) {
171   Instruction inst(kSampleParsedInstruction);
172   // Spot check iteration across operands, with mutable iterators.
173   auto begin = inst.begin();
174   auto end = inst.end();
175   EXPECT_NE(end, inst.begin());
176 
177   auto iter = inst.begin();
178   for (int i = 0; i < 3; ++i, ++iter) {
179     const auto& operand = *iter;
180     EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
181     EXPECT_THAT(operand.words,
182                 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
183     EXPECT_NE(end, iter);
184   }
185   EXPECT_EQ(end, iter);
186 
187   // Check that begin and end have not changed.
188   EXPECT_EQ(begin, inst.begin());
189   EXPECT_EQ(end, inst.end());
190 
191   // Check arithmetic.
192   Operand& operand2 = *(inst.begin() + 2);
193   EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
194 
195   // Check mutation through an iterator.
196   operand2.type = SPV_OPERAND_TYPE_TYPE_ID;
197   EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type);
198 }
199 
TEST(InstructionTest,ForInIdStandardIdTypes)200 TEST(InstructionTest, ForInIdStandardIdTypes) {
201   Instruction inst(kSampleAccessChainInstruction);
202 
203   std::vector<uint32_t> ids;
204   inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
205   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
206 
207   ids.clear();
208   inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
209   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
210 }
211 
TEST(InstructionTest,ForInIdNonstandardIdTypes)212 TEST(InstructionTest, ForInIdNonstandardIdTypes) {
213   Instruction inst(kSampleControlBarrierInstruction);
214 
215   std::vector<uint32_t> ids;
216   inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
217   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
218 
219   ids.clear();
220   inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
221   EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
222 }
223 
224 }  // anonymous namespace
225