function.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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_FUNCTION_H_
  15. #define SOURCE_OPT_FUNCTION_H_
  16. #include <algorithm>
  17. #include <functional>
  18. #include <memory>
  19. #include <string>
  20. #include <utility>
  21. #include <vector>
  22. #include "source/opt/basic_block.h"
  23. #include "source/opt/instruction.h"
  24. #include "source/opt/iterator.h"
  25. namespace spvtools {
  26. namespace opt {
  27. class CFG;
  28. class IRContext;
  29. class Module;
  30. // A SPIR-V function.
  31. class Function {
  32. public:
  33. using iterator = UptrVectorIterator<BasicBlock>;
  34. using const_iterator = UptrVectorIterator<BasicBlock, true>;
  35. // Creates a function instance declared by the given OpFunction instruction
  36. // |def_inst|.
  37. inline explicit Function(std::unique_ptr<Instruction> def_inst);
  38. explicit Function(const Function& f) = delete;
  39. // Creates a clone of the instruction in the given |context|
  40. //
  41. // The parent module will default to null and needs to be explicitly set by
  42. // the user.
  43. Function* Clone(IRContext*) const;
  44. // The OpFunction instruction that begins the definition of this function.
  45. Instruction& DefInst() { return *def_inst_; }
  46. const Instruction& DefInst() const { return *def_inst_; }
  47. // Appends a parameter to this function.
  48. inline void AddParameter(std::unique_ptr<Instruction> p);
  49. // Appends a debug instruction in function header to this function.
  50. inline void AddDebugInstructionInHeader(std::unique_ptr<Instruction> p);
  51. // Appends a basic block to this function.
  52. inline void AddBasicBlock(std::unique_ptr<BasicBlock> b);
  53. // Appends a basic block to this function at the position |ip|.
  54. inline void AddBasicBlock(std::unique_ptr<BasicBlock> b, iterator ip);
  55. template <typename T>
  56. inline void AddBasicBlocks(T begin, T end, iterator ip);
  57. // Move basic block with |id| to the position after |ip|. Both have to be
  58. // contained in this function.
  59. inline void MoveBasicBlockToAfter(uint32_t id, BasicBlock* ip);
  60. // Delete all basic blocks that contain no instructions.
  61. inline void RemoveEmptyBlocks();
  62. // Removes a parameter from the function with result id equal to |id|.
  63. // Does nothing if the function doesn't have such a parameter.
  64. inline void RemoveParameter(uint32_t id);
  65. // Saves the given function end instruction.
  66. inline void SetFunctionEnd(std::unique_ptr<Instruction> end_inst);
  67. // Add a non-semantic instruction that succeeds this function in the module.
  68. // These instructions are maintained in the order they are added.
  69. inline void AddNonSemanticInstruction(
  70. std::unique_ptr<Instruction> non_semantic);
  71. // Returns the given function end instruction.
  72. inline Instruction* EndInst() { return end_inst_.get(); }
  73. inline const Instruction* EndInst() const { return end_inst_.get(); }
  74. // Returns function's id
  75. inline uint32_t result_id() const { return def_inst_->result_id(); }
  76. // Returns function's return type id
  77. inline uint32_t type_id() const { return def_inst_->type_id(); }
  78. // Returns the function's control mask
  79. inline uint32_t control_mask() const { return def_inst_->GetSingleWordInOperand(0); }
  80. // Returns the entry basic block for this function.
  81. const std::unique_ptr<BasicBlock>& entry() const { return blocks_.front(); }
  82. // Returns the last basic block in this function.
  83. BasicBlock* tail() { return blocks_.back().get(); }
  84. const BasicBlock* tail() const { return blocks_.back().get(); }
  85. iterator begin() { return iterator(&blocks_, blocks_.begin()); }
  86. iterator end() { return iterator(&blocks_, blocks_.end()); }
  87. const_iterator begin() const { return cbegin(); }
  88. const_iterator end() const { return cend(); }
  89. const_iterator cbegin() const {
  90. return const_iterator(&blocks_, blocks_.cbegin());
  91. }
  92. const_iterator cend() const {
  93. return const_iterator(&blocks_, blocks_.cend());
  94. }
  95. // Returns an iterator to the basic block |id|.
  96. iterator FindBlock(uint32_t bb_id) {
  97. return std::find_if(begin(), end(), [bb_id](const BasicBlock& it_bb) {
  98. return bb_id == it_bb.id();
  99. });
  100. }
  101. // Runs the given function |f| on instructions in this function, in order,
  102. // and optionally on debug line instructions that might precede them and
  103. // non-semantic instructions that succceed the function.
  104. void ForEachInst(const std::function<void(Instruction*)>& f,
  105. bool run_on_debug_line_insts = false,
  106. bool run_on_non_semantic_insts = false);
  107. void ForEachInst(const std::function<void(const Instruction*)>& f,
  108. bool run_on_debug_line_insts = false,
  109. bool run_on_non_semantic_insts = false) const;
  110. // Runs the given function |f| on instructions in this function, in order,
  111. // and optionally on debug line instructions that might precede them and
  112. // non-semantic instructions that succeed the function. If |f| returns
  113. // false, iteration is terminated and this function returns false.
  114. bool WhileEachInst(const std::function<bool(Instruction*)>& f,
  115. bool run_on_debug_line_insts = false,
  116. bool run_on_non_semantic_insts = false);
  117. bool WhileEachInst(const std::function<bool(const Instruction*)>& f,
  118. bool run_on_debug_line_insts = false,
  119. bool run_on_non_semantic_insts = false) const;
  120. // Runs the given function |f| on each parameter instruction in this function,
  121. // in order, and optionally on debug line instructions that might precede
  122. // them.
  123. void ForEachParam(const std::function<void(const Instruction*)>& f,
  124. bool run_on_debug_line_insts = false) const;
  125. void ForEachParam(const std::function<void(Instruction*)>& f,
  126. bool run_on_debug_line_insts = false);
  127. // Runs the given function |f| on each debug instruction in this function's
  128. // header in order.
  129. void ForEachDebugInstructionsInHeader(
  130. const std::function<void(Instruction*)>& f);
  131. BasicBlock* InsertBasicBlockAfter(std::unique_ptr<BasicBlock>&& new_block,
  132. BasicBlock* position);
  133. BasicBlock* InsertBasicBlockBefore(std::unique_ptr<BasicBlock>&& new_block,
  134. BasicBlock* position);
  135. // Returns true if the function has a return block other than the exit block.
  136. bool HasEarlyReturn() const;
  137. // Returns true if the function calls itself either directly or indirectly.
  138. bool IsRecursive() const;
  139. // Pretty-prints all the basic blocks in this function into a std::string.
  140. //
  141. // |options| are the disassembly options. SPV_BINARY_TO_TEXT_OPTION_NO_HEADER
  142. // is always added to |options|.
  143. std::string PrettyPrint(uint32_t options = 0u) const;
  144. // Dump this function on stderr. Useful when running interactive
  145. // debuggers.
  146. void Dump() const;
  147. // Returns true is a function declaration and not a function definition.
  148. bool IsDeclaration() { return begin() == end(); }
  149. private:
  150. // The OpFunction instruction that begins the definition of this function.
  151. std::unique_ptr<Instruction> def_inst_;
  152. // All parameters to this function.
  153. std::vector<std::unique_ptr<Instruction>> params_;
  154. // All debug instructions in this function's header.
  155. InstructionList debug_insts_in_header_;
  156. // All basic blocks inside this function in specification order
  157. std::vector<std::unique_ptr<BasicBlock>> blocks_;
  158. // The OpFunctionEnd instruction.
  159. std::unique_ptr<Instruction> end_inst_;
  160. // Non-semantic instructions succeeded by this function.
  161. std::vector<std::unique_ptr<Instruction>> non_semantic_;
  162. };
  163. // Pretty-prints |func| to |str|. Returns |str|.
  164. std::ostream& operator<<(std::ostream& str, const Function& func);
  165. inline Function::Function(std::unique_ptr<Instruction> def_inst)
  166. : def_inst_(std::move(def_inst)), end_inst_() {}
  167. inline void Function::AddParameter(std::unique_ptr<Instruction> p) {
  168. params_.emplace_back(std::move(p));
  169. }
  170. inline void Function::AddDebugInstructionInHeader(
  171. std::unique_ptr<Instruction> p) {
  172. debug_insts_in_header_.push_back(std::move(p));
  173. }
  174. inline void Function::AddBasicBlock(std::unique_ptr<BasicBlock> b) {
  175. AddBasicBlock(std::move(b), end());
  176. }
  177. inline void Function::AddBasicBlock(std::unique_ptr<BasicBlock> b,
  178. iterator ip) {
  179. b->SetParent(this);
  180. ip.InsertBefore(std::move(b));
  181. }
  182. template <typename T>
  183. inline void Function::AddBasicBlocks(T src_begin, T src_end, iterator ip) {
  184. blocks_.insert(ip.Get(), std::make_move_iterator(src_begin),
  185. std::make_move_iterator(src_end));
  186. }
  187. inline void Function::MoveBasicBlockToAfter(uint32_t id, BasicBlock* ip) {
  188. std::unique_ptr<BasicBlock> block_to_move = std::move(*FindBlock(id).Get());
  189. blocks_.erase(std::find(std::begin(blocks_), std::end(blocks_), nullptr));
  190. assert(block_to_move->GetParent() == ip->GetParent() &&
  191. "Both blocks have to be in the same function.");
  192. InsertBasicBlockAfter(std::move(block_to_move), ip);
  193. }
  194. inline void Function::RemoveEmptyBlocks() {
  195. auto first_empty =
  196. std::remove_if(std::begin(blocks_), std::end(blocks_),
  197. [](const std::unique_ptr<BasicBlock>& bb) -> bool {
  198. return bb->GetLabelInst()->opcode() == SpvOpNop;
  199. });
  200. blocks_.erase(first_empty, std::end(blocks_));
  201. }
  202. inline void Function::RemoveParameter(uint32_t id) {
  203. params_.erase(std::remove_if(params_.begin(), params_.end(),
  204. [id](const std::unique_ptr<Instruction>& param) {
  205. return param->result_id() == id;
  206. }),
  207. params_.end());
  208. }
  209. inline void Function::SetFunctionEnd(std::unique_ptr<Instruction> end_inst) {
  210. end_inst_ = std::move(end_inst);
  211. }
  212. inline void Function::AddNonSemanticInstruction(
  213. std::unique_ptr<Instruction> non_semantic) {
  214. non_semantic_.emplace_back(std::move(non_semantic));
  215. }
  216. } // namespace opt
  217. } // namespace spvtools
  218. #endif // SOURCE_OPT_FUNCTION_H_