module.h 20 KB

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