module.h 19 KB

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