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 "module.h"
16
17 #include <algorithm>
18 #include <cstring>
19
20 #include "operand.h"
21 #include "reflect.h"
22
23 namespace spvtools {
24 namespace ir {
25
GetTypes()26 std::vector<Instruction*> Module::GetTypes() {
27 std::vector<Instruction*> insts;
28 for (uint32_t i = 0; i < types_values_.size(); ++i) {
29 if (IsTypeInst(types_values_[i]->opcode()))
30 insts.push_back(types_values_[i].get());
31 }
32 return insts;
33 };
34
GetTypes() const35 std::vector<const Instruction*> Module::GetTypes() const {
36 std::vector<const Instruction*> insts;
37 for (uint32_t i = 0; i < types_values_.size(); ++i) {
38 if (IsTypeInst(types_values_[i]->opcode()))
39 insts.push_back(types_values_[i].get());
40 }
41 return insts;
42 };
43
GetConstants()44 std::vector<Instruction*> Module::GetConstants() {
45 std::vector<Instruction*> insts;
46 for (uint32_t i = 0; i < types_values_.size(); ++i) {
47 if (IsConstantInst(types_values_[i]->opcode()))
48 insts.push_back(types_values_[i].get());
49 }
50 return insts;
51 };
52
GetConstants() const53 std::vector<const Instruction*> Module::GetConstants() const {
54 std::vector<const Instruction*> insts;
55 for (uint32_t i = 0; i < types_values_.size(); ++i) {
56 if (IsConstantInst(types_values_[i]->opcode()))
57 insts.push_back(types_values_[i].get());
58 }
59 return insts;
60 };
61
GetGlobalValue(SpvOp opcode) const62 uint32_t Module::GetGlobalValue(SpvOp opcode) const {
63 for (uint32_t i = 0; i < types_values_.size(); ++i) {
64 if (types_values_[i]->opcode() == opcode)
65 return types_values_[i]->result_id();
66 }
67 return 0;
68 }
69
AddGlobalValue(SpvOp opcode,uint32_t result_id,uint32_t type_id)70 void Module::AddGlobalValue(SpvOp opcode, uint32_t result_id,
71 uint32_t type_id) {
72 std::unique_ptr<ir::Instruction> newGlobal(
73 new ir::Instruction(opcode, type_id, result_id, {}));
74 AddGlobalValue(std::move(newGlobal));
75 }
76
ForEachInst(const std::function<void (Instruction *)> & f,bool run_on_debug_line_insts)77 void Module::ForEachInst(const std::function<void(Instruction*)>& f,
78 bool run_on_debug_line_insts) {
79 #define DELEGATE(i) i->ForEachInst(f, run_on_debug_line_insts)
80 for (auto& i : capabilities_) DELEGATE(i);
81 for (auto& i : extensions_) DELEGATE(i);
82 for (auto& i : ext_inst_imports_) DELEGATE(i);
83 if (memory_model_) DELEGATE(memory_model_);
84 for (auto& i : entry_points_) DELEGATE(i);
85 for (auto& i : execution_modes_) DELEGATE(i);
86 for (auto& i : debugs_) DELEGATE(i);
87 for (auto& i : annotations_) DELEGATE(i);
88 for (auto& i : types_values_) DELEGATE(i);
89 for (auto& i : functions_) DELEGATE(i);
90 #undef DELEGATE
91 }
92
ForEachInst(const std::function<void (const Instruction *)> & f,bool run_on_debug_line_insts) const93 void Module::ForEachInst(const std::function<void(const Instruction*)>& f,
94 bool run_on_debug_line_insts) const {
95 #define DELEGATE(i) \
96 static_cast<const Instruction*>(i.get())->ForEachInst( \
97 f, run_on_debug_line_insts)
98 for (auto& i : capabilities_) DELEGATE(i);
99 for (auto& i : extensions_) DELEGATE(i);
100 for (auto& i : ext_inst_imports_) DELEGATE(i);
101 if (memory_model_) DELEGATE(memory_model_);
102 for (auto& i : entry_points_) DELEGATE(i);
103 for (auto& i : execution_modes_) DELEGATE(i);
104 for (auto& i : debugs_) DELEGATE(i);
105 for (auto& i : annotations_) DELEGATE(i);
106 for (auto& i : types_values_) DELEGATE(i);
107 for (auto& i : functions_) {
108 static_cast<const Function*>(i.get())->ForEachInst(f,
109 run_on_debug_line_insts);
110 }
111 #undef DELEGATE
112 }
113
ToBinary(std::vector<uint32_t> * binary,bool skip_nop) const114 void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
115 binary->push_back(header_.magic_number);
116 binary->push_back(header_.version);
117 // TODO(antiagainst): should we change the generator number?
118 binary->push_back(header_.generator);
119 binary->push_back(header_.bound);
120 binary->push_back(header_.reserved);
121
122 auto write_inst = [binary, skip_nop](const Instruction* i) {
123 if (!(skip_nop && i->IsNop())) i->ToBinaryWithoutAttachedDebugInsts(binary);
124 };
125 ForEachInst(write_inst, true);
126 }
127
ComputeIdBound() const128 uint32_t Module::ComputeIdBound() const {
129 uint32_t highest = 0;
130
131 ForEachInst(
132 [&highest](const Instruction* inst) {
133 for (const auto& operand : *inst) {
134 if (spvIsIdType(operand.type)) {
135 highest = std::max(highest, operand.words[0]);
136 }
137 }
138 },
139 true /* scan debug line insts as well */);
140
141 return highest + 1;
142 }
143
HasCapability(uint32_t cap)144 bool Module::HasCapability(uint32_t cap) {
145 for (auto& ci : capabilities_) {
146 uint32_t tcap = ci->GetSingleWordOperand(0);
147 if (tcap == cap) {
148 return true;
149 }
150 }
151 return false;
152 }
153
GetExtInstImportId(const char * extstr)154 uint32_t Module::GetExtInstImportId(const char* extstr) {
155 for (auto& ei : ext_inst_imports_)
156 if (!strcmp(extstr, reinterpret_cast<const char*>(
157 &ei->GetInOperand(0).words[0])))
158 return ei->result_id();
159 return 0;
160 }
161
162 } // namespace ir
163 } // namespace spvtools
164