module.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. #ifndef SOURCE_OPT_MODULE_H_
  15. #define SOURCE_OPT_MODULE_H_
  16. #include <functional>
  17. #include <memory>
  18. #include <utility>
  19. #include <vector>
  20. #include "source/opt/function.h"
  21. #include "source/opt/instruction.h"
  22. #include "source/opt/iterator.h"
  23. namespace spvtools {
  24. namespace opt {
  25. class IRContext;
  26. // A struct for containing the module header information.
  27. struct ModuleHeader {
  28. uint32_t magic_number;
  29. uint32_t version;
  30. uint32_t generator;
  31. uint32_t bound;
  32. uint32_t reserved;
  33. };
  34. // A SPIR-V module. It contains all the information for a SPIR-V module and
  35. // serves as the backbone of optimization transformations.
  36. class Module {
  37. public:
  38. using iterator = UptrVectorIterator<Function>;
  39. using const_iterator = UptrVectorIterator<Function, true>;
  40. using inst_iterator = InstructionList::iterator;
  41. using const_inst_iterator = InstructionList::const_iterator;
  42. // Creates an empty module with zero'd header.
  43. Module() : header_({}) {}
  44. // Sets the header to the given |header|.
  45. void SetHeader(const ModuleHeader& header) { header_ = header; }
  46. // Sets the Id bound. The Id bound cannot be set to 0.
  47. void SetIdBound(uint32_t bound) {
  48. assert(bound != 0);
  49. header_.bound = bound;
  50. }
  51. // Returns the Id bound.
  52. uint32_t IdBound() { return header_.bound; }
  53. // Returns the current Id bound and increases it to the next available value.
  54. // If the id bound has already reached its maximum value, then 0 is returned.
  55. // The maximum value for the id bound is obtained from the context. If there
  56. // is none, then the minimum that limit can be according to the spir-v
  57. // specification.
  58. // TODO(1841): Update the uses to check for a 0 return value.
  59. uint32_t TakeNextIdBound();
  60. // Appends a capability instruction to this module.
  61. inline void AddCapability(std::unique_ptr<Instruction> c);
  62. // Appends an extension instruction to this module.
  63. inline void AddExtension(std::unique_ptr<Instruction> e);
  64. // Appends an extended instruction set instruction to this module.
  65. inline void AddExtInstImport(std::unique_ptr<Instruction> e);
  66. // Set the memory model for this module.
  67. inline void SetMemoryModel(std::unique_ptr<Instruction> m);
  68. // Appends an entry point instruction to this module.
  69. inline void AddEntryPoint(std::unique_ptr<Instruction> e);
  70. // Appends an execution mode instruction to this module.
  71. inline void AddExecutionMode(std::unique_ptr<Instruction> e);
  72. // Appends a debug 1 instruction (excluding OpLine & OpNoLine) to this module.
  73. // "debug 1" instructions are the ones in layout section 7.a), see section
  74. // 2.4 Logical Layout of a Module from the SPIR-V specification.
  75. inline void AddDebug1Inst(std::unique_ptr<Instruction> d);
  76. // Appends a debug 2 instruction (excluding OpLine & OpNoLine) to this module.
  77. // "debug 2" instructions are the ones in layout section 7.b), see section
  78. // 2.4 Logical Layout of a Module from the SPIR-V specification.
  79. inline void AddDebug2Inst(std::unique_ptr<Instruction> d);
  80. // Appends a debug 3 instruction (OpModuleProcessed) to this module.
  81. // This is due to decision by the SPIR Working Group, pending publication.
  82. inline void AddDebug3Inst(std::unique_ptr<Instruction> d);
  83. // Appends an annotation instruction to this module.
  84. inline void AddAnnotationInst(std::unique_ptr<Instruction> a);
  85. // Appends a type-declaration instruction to this module.
  86. inline void AddType(std::unique_ptr<Instruction> t);
  87. // Appends a constant, global variable, or OpUndef instruction to this module.
  88. inline void AddGlobalValue(std::unique_ptr<Instruction> v);
  89. // Appends a function to this module.
  90. inline void AddFunction(std::unique_ptr<Function> f);
  91. // Returns a vector of pointers to type-declaration instructions in this
  92. // module.
  93. std::vector<Instruction*> GetTypes();
  94. std::vector<const Instruction*> GetTypes() const;
  95. // Returns a vector of pointers to constant-creation instructions in this
  96. // module.
  97. std::vector<Instruction*> GetConstants();
  98. std::vector<const Instruction*> GetConstants() const;
  99. // Return result id of global value with |opcode|, 0 if not present.
  100. uint32_t GetGlobalValue(SpvOp opcode) const;
  101. // Add global value with |opcode|, |result_id| and |type_id|
  102. void AddGlobalValue(SpvOp opcode, uint32_t result_id, uint32_t type_id);
  103. inline uint32_t id_bound() const { return header_.bound; }
  104. inline uint32_t version() const { return header_.version; }
  105. inline void set_version(uint32_t v) { header_.version = v; }
  106. // Iterators for capabilities instructions contained in this module.
  107. inline inst_iterator capability_begin();
  108. inline inst_iterator capability_end();
  109. inline IteratorRange<inst_iterator> capabilities();
  110. inline IteratorRange<const_inst_iterator> capabilities() const;
  111. // Iterators for ext_inst_imports instructions contained in this module.
  112. inline inst_iterator ext_inst_import_begin();
  113. inline inst_iterator ext_inst_import_end();
  114. inline IteratorRange<inst_iterator> ext_inst_imports();
  115. inline IteratorRange<const_inst_iterator> ext_inst_imports() const;
  116. // Return the memory model instruction contained inthis module.
  117. inline Instruction* GetMemoryModel() { return memory_model_.get(); }
  118. inline const Instruction* GetMemoryModel() const {
  119. return memory_model_.get();
  120. }
  121. // There are several kinds of debug instructions, according to where they can
  122. // appear in the logical layout of a module:
  123. // - Section 7a: OpString, OpSourceExtension, OpSource, OpSourceContinued
  124. // - Section 7b: OpName, OpMemberName
  125. // - Section 7c: OpModuleProcessed
  126. // - Mostly anywhere: OpLine and OpNoLine
  127. //
  128. // Iterators for debug 1 instructions (excluding OpLine & OpNoLine) contained
  129. // in this module. These are for layout section 7a.
  130. inline inst_iterator debug1_begin();
  131. inline inst_iterator debug1_end();
  132. inline IteratorRange<inst_iterator> debugs1();
  133. inline IteratorRange<const_inst_iterator> debugs1() const;
  134. // Iterators for debug 2 instructions (excluding OpLine & OpNoLine) contained
  135. // in this module. These are for layout section 7b.
  136. inline inst_iterator debug2_begin();
  137. inline inst_iterator debug2_end();
  138. inline IteratorRange<inst_iterator> debugs2();
  139. inline IteratorRange<const_inst_iterator> debugs2() const;
  140. // Iterators for debug 3 instructions (excluding OpLine & OpNoLine) contained
  141. // in this module. These are for layout section 7c.
  142. inline inst_iterator debug3_begin();
  143. inline inst_iterator debug3_end();
  144. inline IteratorRange<inst_iterator> debugs3();
  145. inline IteratorRange<const_inst_iterator> debugs3() const;
  146. // Iterators for entry point instructions contained in this module
  147. inline IteratorRange<inst_iterator> entry_points();
  148. inline IteratorRange<const_inst_iterator> entry_points() const;
  149. // Iterators for execution_modes instructions contained in this module.
  150. inline inst_iterator execution_mode_begin();
  151. inline inst_iterator execution_mode_end();
  152. inline IteratorRange<inst_iterator> execution_modes();
  153. inline IteratorRange<const_inst_iterator> execution_modes() const;
  154. // Iterators for annotation instructions contained in this module.
  155. inline inst_iterator annotation_begin();
  156. inline inst_iterator annotation_end();
  157. IteratorRange<inst_iterator> annotations();
  158. IteratorRange<const_inst_iterator> annotations() const;
  159. // Iterators for extension instructions contained in this module.
  160. inline inst_iterator extension_begin();
  161. inline inst_iterator extension_end();
  162. IteratorRange<inst_iterator> extensions();
  163. IteratorRange<const_inst_iterator> extensions() const;
  164. // Iterators for types, constants and global variables instructions.
  165. inline inst_iterator types_values_begin();
  166. inline inst_iterator types_values_end();
  167. inline IteratorRange<inst_iterator> types_values();
  168. inline IteratorRange<const_inst_iterator> types_values() const;
  169. // Iterators for functions contained in this module.
  170. iterator begin() { return iterator(&functions_, functions_.begin()); }
  171. iterator end() { return iterator(&functions_, functions_.end()); }
  172. const_iterator begin() const { return cbegin(); }
  173. const_iterator end() const { return cend(); }
  174. inline const_iterator cbegin() const;
  175. inline const_iterator cend() const;
  176. // Invokes function |f| on all instructions in this module, and optionally on
  177. // the debug line instructions that precede them.
  178. void ForEachInst(const std::function<void(Instruction*)>& f,
  179. bool run_on_debug_line_insts = false);
  180. void ForEachInst(const std::function<void(const Instruction*)>& f,
  181. bool run_on_debug_line_insts = false) const;
  182. // Pushes the binary segments for this instruction into the back of *|binary|.
  183. // If |skip_nop| is true and this is a OpNop, do nothing.
  184. void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
  185. // Returns 1 more than the maximum Id value mentioned in the module.
  186. uint32_t ComputeIdBound() const;
  187. // Returns true if module has capability |cap|
  188. bool HasExplicitCapability(uint32_t cap);
  189. // Returns id for OpExtInst instruction for extension |extstr|.
  190. // Returns 0 if not found.
  191. uint32_t GetExtInstImportId(const char* extstr);
  192. // Sets the associated context for this module
  193. void SetContext(IRContext* c) { context_ = c; }
  194. // Gets the associated context for this module
  195. IRContext* context() const { return context_; }
  196. // Sets the trailing debug line info to |dbg_line_info|.
  197. void SetTrailingDbgLineInfo(std::vector<Instruction>&& dbg_line_info) {
  198. trailing_dbg_line_info_ = std::move(dbg_line_info);
  199. }
  200. std::vector<Instruction>& trailing_dbg_line_info() {
  201. return trailing_dbg_line_info_;
  202. }
  203. const std::vector<Instruction>& trailing_dbg_line_info() const {
  204. return trailing_dbg_line_info_;
  205. }
  206. private:
  207. ModuleHeader header_; // Module header
  208. // The following fields respect the "Logical Layout of a Module" in
  209. // Section 2.4 of the SPIR-V specification.
  210. IRContext* context_;
  211. InstructionList capabilities_;
  212. InstructionList extensions_;
  213. InstructionList ext_inst_imports_;
  214. // A module only has one memory model instruction.
  215. std::unique_ptr<Instruction> memory_model_;
  216. InstructionList entry_points_;
  217. InstructionList execution_modes_;
  218. InstructionList debugs1_;
  219. InstructionList debugs2_;
  220. InstructionList debugs3_;
  221. InstructionList annotations_;
  222. // Type declarations, constants, and global variable declarations.
  223. InstructionList types_values_;
  224. std::vector<std::unique_ptr<Function>> functions_;
  225. // If the module ends with Op*Line instruction, they will not be attached to
  226. // any instruction. We record them here, so they will not be lost.
  227. std::vector<Instruction> trailing_dbg_line_info_;
  228. };
  229. // Pretty-prints |module| to |str|. Returns |str|.
  230. std::ostream& operator<<(std::ostream& str, const Module& module);
  231. inline void Module::AddCapability(std::unique_ptr<Instruction> c) {
  232. capabilities_.push_back(std::move(c));
  233. }
  234. inline void Module::AddExtension(std::unique_ptr<Instruction> e) {
  235. extensions_.push_back(std::move(e));
  236. }
  237. inline void Module::AddExtInstImport(std::unique_ptr<Instruction> e) {
  238. ext_inst_imports_.push_back(std::move(e));
  239. }
  240. inline void Module::SetMemoryModel(std::unique_ptr<Instruction> m) {
  241. memory_model_ = std::move(m);
  242. }
  243. inline void Module::AddEntryPoint(std::unique_ptr<Instruction> e) {
  244. entry_points_.push_back(std::move(e));
  245. }
  246. inline void Module::AddExecutionMode(std::unique_ptr<Instruction> e) {
  247. execution_modes_.push_back(std::move(e));
  248. }
  249. inline void Module::AddDebug1Inst(std::unique_ptr<Instruction> d) {
  250. debugs1_.push_back(std::move(d));
  251. }
  252. inline void Module::AddDebug2Inst(std::unique_ptr<Instruction> d) {
  253. debugs2_.push_back(std::move(d));
  254. }
  255. inline void Module::AddDebug3Inst(std::unique_ptr<Instruction> d) {
  256. debugs3_.push_back(std::move(d));
  257. }
  258. inline void Module::AddAnnotationInst(std::unique_ptr<Instruction> a) {
  259. annotations_.push_back(std::move(a));
  260. }
  261. inline void Module::AddType(std::unique_ptr<Instruction> t) {
  262. types_values_.push_back(std::move(t));
  263. }
  264. inline void Module::AddGlobalValue(std::unique_ptr<Instruction> v) {
  265. types_values_.push_back(std::move(v));
  266. }
  267. inline void Module::AddFunction(std::unique_ptr<Function> f) {
  268. functions_.emplace_back(std::move(f));
  269. }
  270. inline Module::inst_iterator Module::capability_begin() {
  271. return capabilities_.begin();
  272. }
  273. inline Module::inst_iterator Module::capability_end() {
  274. return capabilities_.end();
  275. }
  276. inline IteratorRange<Module::inst_iterator> Module::capabilities() {
  277. return make_range(capabilities_.begin(), capabilities_.end());
  278. }
  279. inline IteratorRange<Module::const_inst_iterator> Module::capabilities() const {
  280. return make_range(capabilities_.begin(), capabilities_.end());
  281. }
  282. inline Module::inst_iterator Module::ext_inst_import_begin() {
  283. return ext_inst_imports_.begin();
  284. }
  285. inline Module::inst_iterator Module::ext_inst_import_end() {
  286. return ext_inst_imports_.end();
  287. }
  288. inline IteratorRange<Module::inst_iterator> Module::ext_inst_imports() {
  289. return make_range(ext_inst_imports_.begin(), ext_inst_imports_.end());
  290. }
  291. inline IteratorRange<Module::const_inst_iterator> Module::ext_inst_imports()
  292. const {
  293. return make_range(ext_inst_imports_.begin(), ext_inst_imports_.end());
  294. }
  295. inline Module::inst_iterator Module::debug1_begin() { return debugs1_.begin(); }
  296. inline Module::inst_iterator Module::debug1_end() { return debugs1_.end(); }
  297. inline IteratorRange<Module::inst_iterator> Module::debugs1() {
  298. return make_range(debugs1_.begin(), debugs1_.end());
  299. }
  300. inline IteratorRange<Module::const_inst_iterator> Module::debugs1() const {
  301. return make_range(debugs1_.begin(), debugs1_.end());
  302. }
  303. inline Module::inst_iterator Module::debug2_begin() { return debugs2_.begin(); }
  304. inline Module::inst_iterator Module::debug2_end() { return debugs2_.end(); }
  305. inline IteratorRange<Module::inst_iterator> Module::debugs2() {
  306. return make_range(debugs2_.begin(), debugs2_.end());
  307. }
  308. inline IteratorRange<Module::const_inst_iterator> Module::debugs2() const {
  309. return make_range(debugs2_.begin(), debugs2_.end());
  310. }
  311. inline Module::inst_iterator Module::debug3_begin() { return debugs3_.begin(); }
  312. inline Module::inst_iterator Module::debug3_end() { return debugs3_.end(); }
  313. inline IteratorRange<Module::inst_iterator> Module::debugs3() {
  314. return make_range(debugs3_.begin(), debugs3_.end());
  315. }
  316. inline IteratorRange<Module::const_inst_iterator> Module::debugs3() const {
  317. return make_range(debugs3_.begin(), debugs3_.end());
  318. }
  319. inline IteratorRange<Module::inst_iterator> Module::entry_points() {
  320. return make_range(entry_points_.begin(), entry_points_.end());
  321. }
  322. inline IteratorRange<Module::const_inst_iterator> Module::entry_points() const {
  323. return make_range(entry_points_.begin(), entry_points_.end());
  324. }
  325. inline Module::inst_iterator Module::execution_mode_begin() {
  326. return execution_modes_.begin();
  327. }
  328. inline Module::inst_iterator Module::execution_mode_end() {
  329. return execution_modes_.end();
  330. }
  331. inline IteratorRange<Module::inst_iterator> Module::execution_modes() {
  332. return make_range(execution_modes_.begin(), execution_modes_.end());
  333. }
  334. inline IteratorRange<Module::const_inst_iterator> Module::execution_modes()
  335. const {
  336. return make_range(execution_modes_.begin(), execution_modes_.end());
  337. }
  338. inline Module::inst_iterator Module::annotation_begin() {
  339. return annotations_.begin();
  340. }
  341. inline Module::inst_iterator Module::annotation_end() {
  342. return annotations_.end();
  343. }
  344. inline IteratorRange<Module::inst_iterator> Module::annotations() {
  345. return make_range(annotations_.begin(), annotations_.end());
  346. }
  347. inline IteratorRange<Module::const_inst_iterator> Module::annotations() const {
  348. return make_range(annotations_.begin(), annotations_.end());
  349. }
  350. inline Module::inst_iterator Module::extension_begin() {
  351. return extensions_.begin();
  352. }
  353. inline Module::inst_iterator Module::extension_end() {
  354. return extensions_.end();
  355. }
  356. inline IteratorRange<Module::inst_iterator> Module::extensions() {
  357. return make_range(extensions_.begin(), extensions_.end());
  358. }
  359. inline IteratorRange<Module::const_inst_iterator> Module::extensions() const {
  360. return make_range(extensions_.begin(), extensions_.end());
  361. }
  362. inline Module::inst_iterator Module::types_values_begin() {
  363. return types_values_.begin();
  364. }
  365. inline Module::inst_iterator Module::types_values_end() {
  366. return types_values_.end();
  367. }
  368. inline IteratorRange<Module::inst_iterator> Module::types_values() {
  369. return make_range(types_values_.begin(), types_values_.end());
  370. }
  371. inline IteratorRange<Module::const_inst_iterator> Module::types_values() const {
  372. return make_range(types_values_.begin(), types_values_.end());
  373. }
  374. inline Module::const_iterator Module::cbegin() const {
  375. return const_iterator(&functions_, functions_.cbegin());
  376. }
  377. inline Module::const_iterator Module::cend() const {
  378. return const_iterator(&functions_, functions_.cend());
  379. }
  380. } // namespace opt
  381. } // namespace spvtools
  382. #endif // SOURCE_OPT_MODULE_H_