module.h 20 KB

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