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#ifndef SOURCE_VAL_INSTRUCTION_H_
16#define SOURCE_VAL_INSTRUCTION_H_
17
18#include <cassert>
19#include <cstdint>
20#include <functional>
21#include <utility>
22#include <vector>
23
24#include "source/ext_inst.h"
25#include "source/table.h"
26#include "spirv-tools/libspirv.h"
27
28namespace spvtools {
29namespace val {
30
31class BasicBlock;
32class Function;
33
34/// Wraps the spv_parsed_instruction struct along with use and definition of the
35/// instruction's result id
36class Instruction {
37 public:
38 explicit Instruction(const spv_parsed_instruction_t* inst);
39
40 /// Registers the use of the Instruction in instruction \p inst at \p index
41 void RegisterUse(const Instruction* inst, uint32_t index);
42
43 uint32_t id() const { return inst_.result_id; }
44 uint32_t type_id() const { return inst_.type_id; }
45 SpvOp opcode() const { return static_cast<SpvOp>(inst_.opcode); }
46
47 /// Returns the Function where the instruction was defined. nullptr if it was
48 /// defined outside of a Function
49 const Function* function() const { return function_; }
50 void set_function(Function* func) { function_ = func; }
51
52 /// Returns the BasicBlock where the instruction was defined. nullptr if it
53 /// was defined outside of a BasicBlock
54 const BasicBlock* block() const { return block_; }
55 void set_block(BasicBlock* b) { block_ = b; }
56
57 /// Returns a vector of pairs of all references to this instruction's result
58 /// id. The first element is the instruction in which this result id was
59 /// referenced and the second is the index of the word in that instruction
60 /// where this result id appeared
61 const std::vector<std::pair<const Instruction*, uint32_t>>& uses() const {
62 return uses_;
63 }
64
65 /// The word used to define the Instruction
66 uint32_t word(size_t index) const { return words_[index]; }
67
68 /// The words used to define the Instruction
69 const std::vector<uint32_t>& words() const { return words_; }
70
71 /// Returns the operand at |idx|.
72 const spv_parsed_operand_t& operand(size_t idx) const {
73 return operands_[idx];
74 }
75
76 /// The operands of the Instruction
77 const std::vector<spv_parsed_operand_t>& operands() const {
78 return operands_;
79 }
80
81 /// Provides direct access to the stored C instruction object.
82 const spv_parsed_instruction_t& c_inst() const { return inst_; }
83
84 /// Provides direct access to instructions spv_ext_inst_type_t object.
85 const spv_ext_inst_type_t& ext_inst_type() const {
86 return inst_.ext_inst_type;
87 }
88
89 bool IsNonSemantic() const {
90 return opcode() == SpvOp::SpvOpExtInst &&
91 spvExtInstIsNonSemantic(inst_.ext_inst_type);
92 }
93
94 /// True if this is an OpExtInst for debug info extension.
95 bool IsDebugInfo() const {
96 return opcode() == SpvOp::SpvOpExtInst &&
97 spvExtInstIsDebugInfo(inst_.ext_inst_type);
98 }
99
100 // Casts the words belonging to the operand under |index| to |T| and returns.
101 template <typename T>
102 T GetOperandAs(size_t index) const {
103 const spv_parsed_operand_t& o = operands_.at(index);
104 assert(o.num_words * 4 >= sizeof(T));
105 assert(o.offset + o.num_words <= inst_.num_words);
106 return *reinterpret_cast<const T*>(&words_[o.offset]);
107 }
108
109 size_t LineNum() const { return line_num_; }
110 void SetLineNum(size_t pos) { line_num_ = pos; }
111
112 private:
113 const std::vector<uint32_t> words_;
114 const std::vector<spv_parsed_operand_t> operands_;
115 spv_parsed_instruction_t inst_;
116 size_t line_num_ = 0;
117
118 /// The function in which this instruction was declared
119 Function* function_ = nullptr;
120
121 /// The basic block in which this instruction was declared
122 BasicBlock* block_ = nullptr;
123
124 /// This is a vector of pairs of all references to this instruction's result
125 /// id. The first element is the instruction in which this result id was
126 /// referenced and the second is the index of the word in the referencing
127 /// instruction where this instruction appeared
128 std::vector<std::pair<const Instruction*, uint32_t>> uses_;
129};
130
131bool operator<(const Instruction& lhs, const Instruction& rhs);
132bool operator<(const Instruction& lhs, uint32_t rhs);
133bool operator==(const Instruction& lhs, const Instruction& rhs);
134bool operator==(const Instruction& lhs, uint32_t rhs);
135
136} // namespace val
137} // namespace spvtools
138
139// custom specialization of std::hash for Instruction
140namespace std {
141template <>
142struct hash<spvtools::val::Instruction> {
143 typedef spvtools::val::Instruction argument_type;
144 typedef std::size_t result_type;
145 result_type operator()(const argument_type& inst) const {
146 return hash<uint32_t>()(inst.id());
147 }
148};
149
150} // namespace std
151
152#endif // SOURCE_VAL_INSTRUCTION_H_
153