xref: /aosp_15_r20/external/swiftshader/third_party/SPIRV-Tools/source/opt/ir_context.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 // Copyright (c) 2017 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 
15 #ifndef SOURCE_OPT_IR_CONTEXT_H_
16 #define SOURCE_OPT_IR_CONTEXT_H_
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <limits>
21 #include <map>
22 #include <memory>
23 #include <queue>
24 #include <unordered_map>
25 #include <unordered_set>
26 #include <utility>
27 #include <vector>
28 
29 #include "source/assembly_grammar.h"
30 #include "source/enum_string_mapping.h"
31 #include "source/opt/cfg.h"
32 #include "source/opt/constants.h"
33 #include "source/opt/debug_info_manager.h"
34 #include "source/opt/decoration_manager.h"
35 #include "source/opt/def_use_manager.h"
36 #include "source/opt/dominator_analysis.h"
37 #include "source/opt/feature_manager.h"
38 #include "source/opt/fold.h"
39 #include "source/opt/liveness.h"
40 #include "source/opt/loop_descriptor.h"
41 #include "source/opt/module.h"
42 #include "source/opt/register_pressure.h"
43 #include "source/opt/scalar_analysis.h"
44 #include "source/opt/struct_cfg_analysis.h"
45 #include "source/opt/type_manager.h"
46 #include "source/opt/value_number_table.h"
47 #include "source/util/make_unique.h"
48 #include "source/util/string_utils.h"
49 
50 namespace spvtools {
51 namespace opt {
52 
53 class IRContext {
54  public:
55   // Available analyses.
56   //
57   // When adding a new analysis:
58   //
59   // 1. Enum values should be powers of 2. These are cast into uint32_t
60   //    bitmasks, so we can have at most 31 analyses represented.
61   //
62   // 2. Make sure it gets invalidated or preserved by IRContext methods that add
63   //    or remove IR elements (e.g., KillDef, KillInst, ReplaceAllUsesWith).
64   //
65   // 3. Add handling code in BuildInvalidAnalyses and InvalidateAnalyses
66   enum Analysis {
67     kAnalysisNone = 0 << 0,
68     kAnalysisBegin = 1 << 0,
69     kAnalysisDefUse = kAnalysisBegin,
70     kAnalysisInstrToBlockMapping = 1 << 1,
71     kAnalysisDecorations = 1 << 2,
72     kAnalysisCombinators = 1 << 3,
73     kAnalysisCFG = 1 << 4,
74     kAnalysisDominatorAnalysis = 1 << 5,
75     kAnalysisLoopAnalysis = 1 << 6,
76     kAnalysisNameMap = 1 << 7,
77     kAnalysisScalarEvolution = 1 << 8,
78     kAnalysisRegisterPressure = 1 << 9,
79     kAnalysisValueNumberTable = 1 << 10,
80     kAnalysisStructuredCFG = 1 << 11,
81     kAnalysisBuiltinVarId = 1 << 12,
82     kAnalysisIdToFuncMapping = 1 << 13,
83     kAnalysisConstants = 1 << 14,
84     kAnalysisTypes = 1 << 15,
85     kAnalysisDebugInfo = 1 << 16,
86     kAnalysisLiveness = 1 << 17,
87     kAnalysisEnd = 1 << 18
88   };
89 
90   using ProcessFunction = std::function<bool(Function*)>;
91 
92   friend inline Analysis operator|(Analysis lhs, Analysis rhs);
93   friend inline Analysis& operator|=(Analysis& lhs, Analysis rhs);
94   friend inline Analysis operator<<(Analysis a, int shift);
95   friend inline Analysis& operator<<=(Analysis& a, int shift);
96 
97   // Creates an |IRContext| that contains an owned |Module|
IRContext(spv_target_env env,MessageConsumer c)98   IRContext(spv_target_env env, MessageConsumer c)
99       : syntax_context_(spvContextCreate(env)),
100         grammar_(syntax_context_),
101         unique_id_(0),
102         module_(new Module()),
103         consumer_(std::move(c)),
104         def_use_mgr_(nullptr),
105         feature_mgr_(nullptr),
106         valid_analyses_(kAnalysisNone),
107         constant_mgr_(nullptr),
108         type_mgr_(nullptr),
109         id_to_name_(nullptr),
110         max_id_bound_(kDefaultMaxIdBound),
111         preserve_bindings_(false),
112         preserve_spec_constants_(false) {
113     SetContextMessageConsumer(syntax_context_, consumer_);
114     module_->SetContext(this);
115   }
116 
IRContext(spv_target_env env,std::unique_ptr<Module> && m,MessageConsumer c)117   IRContext(spv_target_env env, std::unique_ptr<Module>&& m, MessageConsumer c)
118       : syntax_context_(spvContextCreate(env)),
119         grammar_(syntax_context_),
120         unique_id_(0),
121         module_(std::move(m)),
122         consumer_(std::move(c)),
123         def_use_mgr_(nullptr),
124         feature_mgr_(nullptr),
125         valid_analyses_(kAnalysisNone),
126         type_mgr_(nullptr),
127         id_to_name_(nullptr),
128         max_id_bound_(kDefaultMaxIdBound),
129         preserve_bindings_(false),
130         preserve_spec_constants_(false) {
131     SetContextMessageConsumer(syntax_context_, consumer_);
132     module_->SetContext(this);
133     InitializeCombinators();
134   }
135 
~IRContext()136   ~IRContext() { spvContextDestroy(syntax_context_); }
137 
module()138   Module* module() const { return module_.get(); }
139 
140   // Returns a vector of pointers to constant-creation instructions in this
141   // context.
142   inline std::vector<Instruction*> GetConstants();
143   inline std::vector<const Instruction*> GetConstants() const;
144 
145   // Iterators for annotation instructions contained in this context.
146   inline Module::inst_iterator annotation_begin();
147   inline Module::inst_iterator annotation_end();
148   inline IteratorRange<Module::inst_iterator> annotations();
149   inline IteratorRange<Module::const_inst_iterator> annotations() const;
150 
151   // Iterators for capabilities instructions contained in this module.
152   inline Module::inst_iterator capability_begin();
153   inline Module::inst_iterator capability_end();
154   inline IteratorRange<Module::inst_iterator> capabilities();
155   inline IteratorRange<Module::const_inst_iterator> capabilities() const;
156 
157   // Iterators for extensions instructions contained in this module.
158   inline Module::inst_iterator extension_begin();
159   inline Module::inst_iterator extension_end();
160   inline IteratorRange<Module::inst_iterator> extensions();
161   inline IteratorRange<Module::const_inst_iterator> extensions() const;
162 
163   // Iterators for types, constants and global variables instructions.
164   inline Module::inst_iterator types_values_begin();
165   inline Module::inst_iterator types_values_end();
166   inline IteratorRange<Module::inst_iterator> types_values();
167   inline IteratorRange<Module::const_inst_iterator> types_values() const;
168 
169   // Iterators for ext_inst import instructions contained in this module.
170   inline Module::inst_iterator ext_inst_import_begin();
171   inline Module::inst_iterator ext_inst_import_end();
172   inline IteratorRange<Module::inst_iterator> ext_inst_imports();
173   inline IteratorRange<Module::const_inst_iterator> ext_inst_imports() const;
174 
175   // There are several kinds of debug instructions, according to where they can
176   // appear in the logical layout of a module:
177   //  - Section 7a:  OpString, OpSourceExtension, OpSource, OpSourceContinued
178   //  - Section 7b:  OpName, OpMemberName
179   //  - Section 7c:  OpModuleProcessed
180   //  - Mostly anywhere: OpLine and OpNoLine
181   //
182 
183   // Iterators for debug 1 instructions (excluding OpLine & OpNoLine) contained
184   // in this module.  These are for layout section 7a.
185   inline Module::inst_iterator debug1_begin();
186   inline Module::inst_iterator debug1_end();
187   inline IteratorRange<Module::inst_iterator> debugs1();
188   inline IteratorRange<Module::const_inst_iterator> debugs1() const;
189 
190   // Iterators for debug 2 instructions (excluding OpLine & OpNoLine) contained
191   // in this module.  These are for layout section 7b.
192   inline Module::inst_iterator debug2_begin();
193   inline Module::inst_iterator debug2_end();
194   inline IteratorRange<Module::inst_iterator> debugs2();
195   inline IteratorRange<Module::const_inst_iterator> debugs2() const;
196 
197   // Iterators for debug 3 instructions (excluding OpLine & OpNoLine) contained
198   // in this module.  These are for layout section 7c.
199   inline Module::inst_iterator debug3_begin();
200   inline Module::inst_iterator debug3_end();
201   inline IteratorRange<Module::inst_iterator> debugs3();
202   inline IteratorRange<Module::const_inst_iterator> debugs3() const;
203 
204   // Iterators for debug info instructions (excluding OpLine & OpNoLine)
205   // contained in this module.  These are OpExtInst for DebugInfo extension
206   // placed between section 9 and 10.
207   inline Module::inst_iterator ext_inst_debuginfo_begin();
208   inline Module::inst_iterator ext_inst_debuginfo_end();
209   inline IteratorRange<Module::inst_iterator> ext_inst_debuginfo();
210   inline IteratorRange<Module::const_inst_iterator> ext_inst_debuginfo() const;
211 
212   // Add |capability| to the module, if it is not already enabled.
213   inline void AddCapability(spv::Capability capability);
214   // Appends a capability instruction to this module.
215   inline void AddCapability(std::unique_ptr<Instruction>&& c);
216   // Removes instruction declaring `capability` from this module.
217   // Returns true if the capability was removed, false otherwise.
218   bool RemoveCapability(spv::Capability capability);
219 
220   // Appends an extension instruction to this module.
221   inline void AddExtension(const std::string& ext_name);
222   inline void AddExtension(std::unique_ptr<Instruction>&& e);
223   // Removes instruction declaring `extension` from this module.
224   // Returns true if the extension was removed, false otherwise.
225   bool RemoveExtension(Extension extension);
226 
227   // Appends an extended instruction set instruction to this module.
228   inline void AddExtInstImport(const std::string& name);
229   inline void AddExtInstImport(std::unique_ptr<Instruction>&& e);
230   // Set the memory model for this module.
231   inline void SetMemoryModel(std::unique_ptr<Instruction>&& m);
232   // Get the memory model for this module.
233   inline const Instruction* GetMemoryModel() const;
234   // Appends an entry point instruction to this module.
235   inline void AddEntryPoint(std::unique_ptr<Instruction>&& e);
236   // Appends an execution mode instruction to this module.
237   inline void AddExecutionMode(std::unique_ptr<Instruction>&& e);
238   // Appends a debug 1 instruction (excluding OpLine & OpNoLine) to this module.
239   // "debug 1" instructions are the ones in layout section 7.a), see section
240   // 2.4 Logical Layout of a Module from the SPIR-V specification.
241   inline void AddDebug1Inst(std::unique_ptr<Instruction>&& d);
242   // Appends a debug 2 instruction (excluding OpLine & OpNoLine) to this module.
243   // "debug 2" instructions are the ones in layout section 7.b), see section
244   // 2.4 Logical Layout of a Module from the SPIR-V specification.
245   inline void AddDebug2Inst(std::unique_ptr<Instruction>&& d);
246   // Appends a debug 3 instruction (OpModuleProcessed) to this module.
247   // This is due to decision by the SPIR Working Group, pending publication.
248   inline void AddDebug3Inst(std::unique_ptr<Instruction>&& d);
249   // Appends a OpExtInst for DebugInfo to this module.
250   inline void AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d);
251   // Appends an annotation instruction to this module.
252   inline void AddAnnotationInst(std::unique_ptr<Instruction>&& a);
253   // Appends a type-declaration instruction to this module.
254   inline void AddType(std::unique_ptr<Instruction>&& t);
255   // Appends a constant, global variable, or OpUndef instruction to this module.
256   inline void AddGlobalValue(std::unique_ptr<Instruction>&& v);
257   // Prepends a function declaration to this module.
258   inline void AddFunctionDeclaration(std::unique_ptr<Function>&& f);
259   // Appends a function to this module.
260   inline void AddFunction(std::unique_ptr<Function>&& f);
261 
262   // Returns a pointer to a def-use manager.  If the def-use manager is
263   // invalid, it is rebuilt first.
get_def_use_mgr()264   analysis::DefUseManager* get_def_use_mgr() {
265     if (!AreAnalysesValid(kAnalysisDefUse)) {
266       BuildDefUseManager();
267     }
268     return def_use_mgr_.get();
269   }
270 
271   // Returns a pointer to a liveness manager.  If the liveness manager is
272   // invalid, it is rebuilt first.
get_liveness_mgr()273   analysis::LivenessManager* get_liveness_mgr() {
274     if (!AreAnalysesValid(kAnalysisLiveness)) {
275       BuildLivenessManager();
276     }
277     return liveness_mgr_.get();
278   }
279 
280   // Returns a pointer to a value number table.  If the liveness analysis is
281   // invalid, it is rebuilt first.
GetValueNumberTable()282   ValueNumberTable* GetValueNumberTable() {
283     if (!AreAnalysesValid(kAnalysisValueNumberTable)) {
284       BuildValueNumberTable();
285     }
286     return vn_table_.get();
287   }
288 
289   // Returns a pointer to a StructuredCFGAnalysis.  If the analysis is invalid,
290   // it is rebuilt first.
GetStructuredCFGAnalysis()291   StructuredCFGAnalysis* GetStructuredCFGAnalysis() {
292     if (!AreAnalysesValid(kAnalysisStructuredCFG)) {
293       BuildStructuredCFGAnalysis();
294     }
295     return struct_cfg_analysis_.get();
296   }
297 
298   // Returns a pointer to a liveness analysis.  If the liveness analysis is
299   // invalid, it is rebuilt first.
GetLivenessAnalysis()300   LivenessAnalysis* GetLivenessAnalysis() {
301     if (!AreAnalysesValid(kAnalysisRegisterPressure)) {
302       BuildRegPressureAnalysis();
303     }
304     return reg_pressure_.get();
305   }
306 
307   // Returns the basic block for instruction |instr|. Re-builds the instruction
308   // block map, if needed.
get_instr_block(Instruction * instr)309   BasicBlock* get_instr_block(Instruction* instr) {
310     if (!AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
311       BuildInstrToBlockMapping();
312     }
313     auto entry = instr_to_block_.find(instr);
314     return (entry != instr_to_block_.end()) ? entry->second : nullptr;
315   }
316 
317   // Returns the basic block for |id|. Re-builds the instruction block map, if
318   // needed.
319   //
320   // |id| must be a registered definition.
get_instr_block(uint32_t id)321   BasicBlock* get_instr_block(uint32_t id) {
322     Instruction* def = get_def_use_mgr()->GetDef(id);
323     return get_instr_block(def);
324   }
325 
326   // Sets the basic block for |inst|. Re-builds the mapping if it has become
327   // invalid.
set_instr_block(Instruction * inst,BasicBlock * block)328   void set_instr_block(Instruction* inst, BasicBlock* block) {
329     if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
330       instr_to_block_[inst] = block;
331     }
332   }
333 
334   // Returns a pointer the decoration manager.  If the decoration manager is
335   // invalid, it is rebuilt first.
get_decoration_mgr()336   analysis::DecorationManager* get_decoration_mgr() {
337     if (!AreAnalysesValid(kAnalysisDecorations)) {
338       BuildDecorationManager();
339     }
340     return decoration_mgr_.get();
341   }
342 
343   // Returns a pointer to the constant manager.  If no constant manager has been
344   // created yet, it creates one.  NOTE: Once created, the constant manager
345   // remains active and it is never re-built.
get_constant_mgr()346   analysis::ConstantManager* get_constant_mgr() {
347     if (!AreAnalysesValid(kAnalysisConstants)) {
348       BuildConstantManager();
349     }
350     return constant_mgr_.get();
351   }
352 
353   // Returns a pointer to the type manager.  If no type manager has been created
354   // yet, it creates one. NOTE: Once created, the type manager remains active it
355   // is never re-built.
get_type_mgr()356   analysis::TypeManager* get_type_mgr() {
357     if (!AreAnalysesValid(kAnalysisTypes)) {
358       BuildTypeManager();
359     }
360     return type_mgr_.get();
361   }
362 
363   // Returns a pointer to the debug information manager.  If no debug
364   // information manager has been created yet, it creates one.
365   // NOTE: Once created, the debug information manager remains active
366   // it is never re-built.
get_debug_info_mgr()367   analysis::DebugInfoManager* get_debug_info_mgr() {
368     if (!AreAnalysesValid(kAnalysisDebugInfo)) {
369       BuildDebugInfoManager();
370     }
371     return debug_info_mgr_.get();
372   }
373 
374   // Returns a pointer to the scalar evolution analysis. If it is invalid it
375   // will be rebuilt first.
GetScalarEvolutionAnalysis()376   ScalarEvolutionAnalysis* GetScalarEvolutionAnalysis() {
377     if (!AreAnalysesValid(kAnalysisScalarEvolution)) {
378       BuildScalarEvolutionAnalysis();
379     }
380     return scalar_evolution_analysis_.get();
381   }
382 
383   // Build the map from the ids to the OpName and OpMemberName instruction
384   // associated with it.
385   inline void BuildIdToNameMap();
386 
387   // Returns a range of instrucions that contain all of the OpName and
388   // OpMemberNames associated with the given id.
389   inline IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
390   GetNames(uint32_t id);
391 
392   // Returns an OpMemberName instruction that targets |struct_type_id| at
393   // index |index|. Returns nullptr if no such instruction exists.
394   // While the SPIR-V spec does not prohibit having multiple OpMemberName
395   // instructions for the same structure member, it is hard to imagine a member
396   // having more than one name. This method returns the first one it finds.
397   inline Instruction* GetMemberName(uint32_t struct_type_id, uint32_t index);
398 
399   // Copy names from |old_id| to |new_id|. Only copy member name if index is
400   // less than |max_member_index|.
401   inline void CloneNames(const uint32_t old_id, const uint32_t new_id,
402                          const uint32_t max_member_index = UINT32_MAX);
403 
404   // Sets the message consumer to the given |consumer|. |consumer| which will be
405   // invoked every time there is a message to be communicated to the outside.
SetMessageConsumer(MessageConsumer c)406   void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
407 
408   // Returns the reference to the message consumer for this pass.
consumer()409   const MessageConsumer& consumer() const { return consumer_; }
410 
411   // Rebuilds the analyses in |set| that are invalid.
412   void BuildInvalidAnalyses(Analysis set);
413 
414   // Invalidates all of the analyses except for those in |preserved_analyses|.
415   void InvalidateAnalysesExceptFor(Analysis preserved_analyses);
416 
417   // Invalidates the analyses marked in |analyses_to_invalidate|.
418   void InvalidateAnalyses(Analysis analyses_to_invalidate);
419 
420   // Deletes the instruction defining the given |id|. Returns true on
421   // success, false if the given |id| is not defined at all. This method also
422   // erases the name, decorations, and definition of |id|.
423   //
424   // Pointers and iterators pointing to the deleted instructions become invalid.
425   // However other pointers and iterators are still valid.
426   bool KillDef(uint32_t id);
427 
428   // Deletes the given instruction |inst|. This method erases the
429   // information of the given instruction's uses of its operands. If |inst|
430   // defines a result id, its name and decorations will also be deleted.
431   //
432   // Pointer and iterator pointing to the deleted instructions become invalid.
433   // However other pointers and iterators are still valid.
434   //
435   // Note that if an instruction is not in an instruction list, the memory may
436   // not be safe to delete, so the instruction is turned into a OpNop instead.
437   // This can happen with OpLabel.
438   //
439   // Returns a pointer to the instruction after |inst| or |nullptr| if no such
440   // instruction exists.
441   Instruction* KillInst(Instruction* inst);
442 
443   // Deletes all the instruction in the range [`begin`; `end`[, for which the
444   // unary predicate `condition` returned true.
445   // Returns true if at least one instruction was removed, false otherwise.
446   //
447   // Pointer and iterator pointing to the deleted instructions become invalid.
448   // However other pointers and iterators are still valid.
449   bool KillInstructionIf(Module::inst_iterator begin, Module::inst_iterator end,
450                          std::function<bool(Instruction*)> condition);
451 
452   // Collects the non-semantic instruction tree that uses |inst|'s result id
453   // to be killed later.
454   void CollectNonSemanticTree(Instruction* inst,
455                               std::unordered_set<Instruction*>* to_kill);
456 
457   // Collect function reachable from |entryId|, returns |funcs|
458   void CollectCallTreeFromRoots(unsigned entryId,
459                                 std::unordered_set<uint32_t>* funcs);
460 
461   // Returns true if all of the given analyses are valid.
AreAnalysesValid(Analysis set)462   bool AreAnalysesValid(Analysis set) { return (set & valid_analyses_) == set; }
463 
464   // Replaces all uses of |before| id with |after| id. Returns true if any
465   // replacement happens. This method does not kill the definition of the
466   // |before| id. If |after| is the same as |before|, does nothing and returns
467   // false.
468   //
469   // |before| and |after| must be registered definitions in the DefUseManager.
470   bool ReplaceAllUsesWith(uint32_t before, uint32_t after);
471 
472   // Replace all uses of |before| id with |after| id if those uses
473   // (instruction) return true for |predicate|. Returns true if
474   // any replacement happens. This method does not kill the definition of the
475   // |before| id. If |after| is the same as |before|, does nothing and return
476   // false.
477   bool ReplaceAllUsesWithPredicate(
478       uint32_t before, uint32_t after,
479       const std::function<bool(Instruction*)>& predicate);
480 
481   // Returns true if all of the analyses that are suppose to be valid are
482   // actually valid.
483   bool IsConsistent();
484 
485   // The IRContext will look at the def and uses of |inst| and update any valid
486   // analyses will be updated accordingly.
487   inline void AnalyzeDefUse(Instruction* inst);
488 
489   // Informs the IRContext that the uses of |inst| are going to change, and that
490   // is should forget everything it know about the current uses.  Any valid
491   // analyses will be updated accordingly.
492   void ForgetUses(Instruction* inst);
493 
494   // The IRContext will look at the uses of |inst| and update any valid analyses
495   // will be updated accordingly.
496   void AnalyzeUses(Instruction* inst);
497 
498   // Kill all name and decorate ops targeting |id|.
499   void KillNamesAndDecorates(uint32_t id);
500 
501   // Kill all name and decorate ops targeting the result id of |inst|.
502   void KillNamesAndDecorates(Instruction* inst);
503 
504   // Change operands of debug instruction to DebugInfoNone.
505   void KillOperandFromDebugInstructions(Instruction* inst);
506 
507   // Returns the next unique id for use by an instruction.
TakeNextUniqueId()508   inline uint32_t TakeNextUniqueId() {
509     assert(unique_id_ != std::numeric_limits<uint32_t>::max());
510 
511     // Skip zero.
512     return ++unique_id_;
513   }
514 
515   // Returns true if |inst| is a combinator in the current context.
516   // |combinator_ops_| is built if it has not been already.
IsCombinatorInstruction(const Instruction * inst)517   inline bool IsCombinatorInstruction(const Instruction* inst) {
518     if (!AreAnalysesValid(kAnalysisCombinators)) {
519       InitializeCombinators();
520     }
521     constexpr uint32_t kExtInstSetIdInIndx = 0;
522     constexpr uint32_t kExtInstInstructionInIndx = 1;
523 
524     if (inst->opcode() != spv::Op::OpExtInst) {
525       return combinator_ops_[0].count(uint32_t(inst->opcode())) != 0;
526     } else {
527       uint32_t set = inst->GetSingleWordInOperand(kExtInstSetIdInIndx);
528       auto op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
529       return combinator_ops_[set].count(op) != 0;
530     }
531   }
532 
533   // Returns a pointer to the CFG for all the functions in |module_|.
cfg()534   CFG* cfg() {
535     if (!AreAnalysesValid(kAnalysisCFG)) {
536       BuildCFG();
537     }
538     return cfg_.get();
539   }
540 
541   // Gets the loop descriptor for function |f|.
542   LoopDescriptor* GetLoopDescriptor(const Function* f);
543 
544   // Gets the dominator analysis for function |f|.
545   DominatorAnalysis* GetDominatorAnalysis(const Function* f);
546 
547   // Gets the postdominator analysis for function |f|.
548   PostDominatorAnalysis* GetPostDominatorAnalysis(const Function* f);
549 
550   // Remove the dominator tree of |f| from the cache.
RemoveDominatorAnalysis(const Function * f)551   inline void RemoveDominatorAnalysis(const Function* f) {
552     dominator_trees_.erase(f);
553   }
554 
555   // Remove the postdominator tree of |f| from the cache.
RemovePostDominatorAnalysis(const Function * f)556   inline void RemovePostDominatorAnalysis(const Function* f) {
557     post_dominator_trees_.erase(f);
558   }
559 
560   // Return the next available SSA id and increment it.  Returns 0 if the
561   // maximum SSA id has been reached.
TakeNextId()562   inline uint32_t TakeNextId() {
563     uint32_t next_id = module()->TakeNextIdBound();
564     if (next_id == 0) {
565       if (consumer()) {
566         std::string message = "ID overflow. Try running compact-ids.";
567         consumer()(SPV_MSG_ERROR, "", {0, 0, 0}, message.c_str());
568       }
569 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
570       // If TakeNextId returns 0, it is very likely that execution will
571       // subsequently fail. Such failures are false alarms from a fuzzing point
572       // of view: they are due to the fact that too many ids were used, rather
573       // than being due to an actual bug. Thus, during a fuzzing build, it is
574       // preferable to bail out when ID overflow occurs.
575       //
576       // A zero exit code is returned here because a non-zero code would cause
577       // ClusterFuzz/OSS-Fuzz to regard the termination as a crash, and spurious
578       // crash reports is what this guard aims to avoid.
579       exit(0);
580 #endif
581     }
582     return next_id;
583   }
584 
get_feature_mgr()585   FeatureManager* get_feature_mgr() {
586     if (!feature_mgr_.get()) {
587       AnalyzeFeatures();
588     }
589     return feature_mgr_.get();
590   }
591 
ResetFeatureManager()592   void ResetFeatureManager() { feature_mgr_.reset(nullptr); }
593 
594   // Returns the grammar for this context.
grammar()595   const AssemblyGrammar& grammar() const { return grammar_; }
596 
597   // If |inst| has not yet been analysed by the def-use manager, then analyse
598   // its definitions and uses.
599   inline void UpdateDefUse(Instruction* inst);
600 
get_instruction_folder()601   const InstructionFolder& get_instruction_folder() {
602     if (!inst_folder_) {
603       inst_folder_ = MakeUnique<InstructionFolder>(this);
604     }
605     return *inst_folder_;
606   }
607 
max_id_bound()608   uint32_t max_id_bound() const { return max_id_bound_; }
set_max_id_bound(uint32_t new_bound)609   void set_max_id_bound(uint32_t new_bound) { max_id_bound_ = new_bound; }
610 
preserve_bindings()611   bool preserve_bindings() const { return preserve_bindings_; }
set_preserve_bindings(bool should_preserve_bindings)612   void set_preserve_bindings(bool should_preserve_bindings) {
613     preserve_bindings_ = should_preserve_bindings;
614   }
615 
preserve_spec_constants()616   bool preserve_spec_constants() const { return preserve_spec_constants_; }
set_preserve_spec_constants(bool should_preserve_spec_constants)617   void set_preserve_spec_constants(bool should_preserve_spec_constants) {
618     preserve_spec_constants_ = should_preserve_spec_constants;
619   }
620 
621   // Return id of input variable only decorated with |builtin|, if in module.
622   // Create variable and return its id otherwise. If builtin not currently
623   // supported, return 0.
624   uint32_t GetBuiltinInputVarId(uint32_t builtin);
625 
626   // Returns the function whose id is |id|, if one exists.  Returns |nullptr|
627   // otherwise.
GetFunction(uint32_t id)628   Function* GetFunction(uint32_t id) {
629     if (!AreAnalysesValid(kAnalysisIdToFuncMapping)) {
630       BuildIdToFuncMapping();
631     }
632     auto entry = id_to_func_.find(id);
633     return (entry != id_to_func_.end()) ? entry->second : nullptr;
634   }
635 
GetFunction(Instruction * inst)636   Function* GetFunction(Instruction* inst) {
637     if (inst->opcode() != spv::Op::OpFunction) {
638       return nullptr;
639     }
640     return GetFunction(inst->result_id());
641   }
642 
643   // Add to |todo| all ids of functions called directly from |func|.
644   void AddCalls(const Function* func, std::queue<uint32_t>* todo);
645 
646   // Applies |pfn| to every function in the call trees that are rooted at the
647   // entry points.  Returns true if any call |pfn| returns true.  By convention
648   // |pfn| should return true if it modified the module.
649   bool ProcessEntryPointCallTree(ProcessFunction& pfn);
650 
651   // Applies |pfn| to every function in the call trees rooted at the entry
652   // points and exported functions.  Returns true if any call |pfn| returns
653   // true.  By convention |pfn| should return true if it modified the module.
654   bool ProcessReachableCallTree(ProcessFunction& pfn);
655 
656   // Applies |pfn| to every function in the call trees rooted at the elements of
657   // |roots|.  Returns true if any call to |pfn| returns true.  By convention
658   // |pfn| should return true if it modified the module.  After returning
659   // |roots| will be empty.
660   bool ProcessCallTreeFromRoots(ProcessFunction& pfn,
661                                 std::queue<uint32_t>* roots);
662 
663   // Emits a error message to the message consumer indicating the error
664   // described by |message| occurred in |inst|.
665   void EmitErrorMessage(std::string message, Instruction* inst);
666 
667   // Returns true if and only if there is a path to |bb| from the entry block of
668   // the function that contains |bb|.
669   bool IsReachable(const opt::BasicBlock& bb);
670 
671   // Return the stage of the module. Will generate error if entry points don't
672   // all have the same stage.
673   spv::ExecutionModel GetStage();
674 
675   // Returns true of the current target environment is at least that of the
676   // given environment.
IsTargetEnvAtLeast(spv_target_env env)677   bool IsTargetEnvAtLeast(spv_target_env env) {
678     // A bit of a hack. We assume that the target environments are appended to
679     // the enum, so that there is an appropriate order.
680     return syntax_context_->target_env >= env;
681   }
682 
683   // Return the target environment for the current context.
GetTargetEnv()684   spv_target_env GetTargetEnv() const { return syntax_context_->target_env; }
685 
686  private:
687   // Builds the def-use manager from scratch, even if it was already valid.
BuildDefUseManager()688   void BuildDefUseManager() {
689     def_use_mgr_ = MakeUnique<analysis::DefUseManager>(module());
690     valid_analyses_ = valid_analyses_ | kAnalysisDefUse;
691   }
692 
693   // Builds the liveness manager from scratch, even if it was already valid.
BuildLivenessManager()694   void BuildLivenessManager() {
695     liveness_mgr_ = MakeUnique<analysis::LivenessManager>(this);
696     valid_analyses_ = valid_analyses_ | kAnalysisLiveness;
697   }
698 
699   // Builds the instruction-block map for the whole module.
BuildInstrToBlockMapping()700   void BuildInstrToBlockMapping() {
701     instr_to_block_.clear();
702     for (auto& fn : *module_) {
703       for (auto& block : fn) {
704         block.ForEachInst([this, &block](Instruction* inst) {
705           instr_to_block_[inst] = &block;
706         });
707       }
708     }
709     valid_analyses_ = valid_analyses_ | kAnalysisInstrToBlockMapping;
710   }
711 
712   // Builds the instruction-function map for the whole module.
BuildIdToFuncMapping()713   void BuildIdToFuncMapping() {
714     id_to_func_.clear();
715     for (auto& fn : *module_) {
716       id_to_func_[fn.result_id()] = &fn;
717     }
718     valid_analyses_ = valid_analyses_ | kAnalysisIdToFuncMapping;
719   }
720 
BuildDecorationManager()721   void BuildDecorationManager() {
722     decoration_mgr_ = MakeUnique<analysis::DecorationManager>(module());
723     valid_analyses_ = valid_analyses_ | kAnalysisDecorations;
724   }
725 
BuildCFG()726   void BuildCFG() {
727     cfg_ = MakeUnique<CFG>(module());
728     valid_analyses_ = valid_analyses_ | kAnalysisCFG;
729   }
730 
BuildScalarEvolutionAnalysis()731   void BuildScalarEvolutionAnalysis() {
732     scalar_evolution_analysis_ = MakeUnique<ScalarEvolutionAnalysis>(this);
733     valid_analyses_ = valid_analyses_ | kAnalysisScalarEvolution;
734   }
735 
736   // Builds the liveness analysis from scratch, even if it was already valid.
BuildRegPressureAnalysis()737   void BuildRegPressureAnalysis() {
738     reg_pressure_ = MakeUnique<LivenessAnalysis>(this);
739     valid_analyses_ = valid_analyses_ | kAnalysisRegisterPressure;
740   }
741 
742   // Builds the value number table analysis from scratch, even if it was already
743   // valid.
BuildValueNumberTable()744   void BuildValueNumberTable() {
745     vn_table_ = MakeUnique<ValueNumberTable>(this);
746     valid_analyses_ = valid_analyses_ | kAnalysisValueNumberTable;
747   }
748 
749   // Builds the structured CFG analysis from scratch, even if it was already
750   // valid.
BuildStructuredCFGAnalysis()751   void BuildStructuredCFGAnalysis() {
752     struct_cfg_analysis_ = MakeUnique<StructuredCFGAnalysis>(this);
753     valid_analyses_ = valid_analyses_ | kAnalysisStructuredCFG;
754   }
755 
756   // Builds the constant manager from scratch, even if it was already
757   // valid.
BuildConstantManager()758   void BuildConstantManager() {
759     constant_mgr_ = MakeUnique<analysis::ConstantManager>(this);
760     valid_analyses_ = valid_analyses_ | kAnalysisConstants;
761   }
762 
763   // Builds the type manager from scratch, even if it was already
764   // valid.
BuildTypeManager()765   void BuildTypeManager() {
766     type_mgr_ = MakeUnique<analysis::TypeManager>(consumer(), this);
767     valid_analyses_ = valid_analyses_ | kAnalysisTypes;
768   }
769 
770   // Builds the debug information manager from scratch, even if it was
771   // already valid.
BuildDebugInfoManager()772   void BuildDebugInfoManager() {
773     debug_info_mgr_ = MakeUnique<analysis::DebugInfoManager>(this);
774     valid_analyses_ = valid_analyses_ | kAnalysisDebugInfo;
775   }
776 
777   // Removes all computed dominator and post-dominator trees. This will force
778   // the context to rebuild the trees on demand.
ResetDominatorAnalysis()779   void ResetDominatorAnalysis() {
780     // Clear the cache.
781     dominator_trees_.clear();
782     post_dominator_trees_.clear();
783     valid_analyses_ = valid_analyses_ | kAnalysisDominatorAnalysis;
784   }
785 
786   // Removes all computed loop descriptors.
ResetLoopAnalysis()787   void ResetLoopAnalysis() {
788     // Clear the cache.
789     loop_descriptors_.clear();
790     valid_analyses_ = valid_analyses_ | kAnalysisLoopAnalysis;
791   }
792 
793   // Removes all computed loop descriptors.
ResetBuiltinAnalysis()794   void ResetBuiltinAnalysis() {
795     // Clear the cache.
796     builtin_var_id_map_.clear();
797     valid_analyses_ = valid_analyses_ | kAnalysisBuiltinVarId;
798   }
799 
800   // Analyzes the features in the owned module. Builds the manager if required.
AnalyzeFeatures()801   void AnalyzeFeatures() {
802     feature_mgr_ =
803         std::unique_ptr<FeatureManager>(new FeatureManager(grammar_));
804     feature_mgr_->Analyze(module());
805   }
806 
807   // Scans a module looking for it capabilities, and initializes combinator_ops_
808   // accordingly.
809   void InitializeCombinators();
810 
811   // Add the combinator opcode for the given capability to combinator_ops_.
812   void AddCombinatorsForCapability(uint32_t capability);
813 
814   // Add the combinator opcode for the given extension to combinator_ops_.
815   void AddCombinatorsForExtension(Instruction* extension);
816 
817   // Remove |inst| from |id_to_name_| if it is in map.
818   void RemoveFromIdToName(const Instruction* inst);
819 
820   // Returns true if it is suppose to be valid but it is incorrect.  Returns
821   // true if the cfg is invalidated.
822   bool CheckCFG();
823 
824   // Return id of input variable only decorated with |builtin|, if in module.
825   // Return 0 otherwise.
826   uint32_t FindBuiltinInputVar(uint32_t builtin);
827 
828   // Add |var_id| to all entry points in module.
829   void AddVarToEntryPoints(uint32_t var_id);
830 
831   // The SPIR-V syntax context containing grammar tables for opcodes and
832   // operands.
833   spv_context syntax_context_;
834 
835   // Auxiliary object for querying SPIR-V grammar facts.
836   AssemblyGrammar grammar_;
837 
838   // An unique identifier for instructions in |module_|. Can be used to order
839   // instructions in a container.
840   //
841   // This member is initialized to 0, but always issues this value plus one.
842   // Therefore, 0 is not a valid unique id for an instruction.
843   uint32_t unique_id_;
844 
845   // The module being processed within this IR context.
846   std::unique_ptr<Module> module_;
847 
848   // A message consumer for diagnostics.
849   MessageConsumer consumer_;
850 
851   // The def-use manager for |module_|.
852   std::unique_ptr<analysis::DefUseManager> def_use_mgr_;
853 
854   // The instruction decoration manager for |module_|.
855   std::unique_ptr<analysis::DecorationManager> decoration_mgr_;
856 
857   // The feature manager for |module_|.
858   std::unique_ptr<FeatureManager> feature_mgr_;
859 
860   // A map from instructions to the basic block they belong to. This mapping is
861   // built on-demand when get_instr_block() is called.
862   //
863   // NOTE: Do not traverse this map. Ever. Use the function and basic block
864   // iterators to traverse instructions.
865   std::unordered_map<Instruction*, BasicBlock*> instr_to_block_;
866 
867   // A map from ids to the function they define. This mapping is
868   // built on-demand when GetFunction() is called.
869   //
870   // NOTE: Do not traverse this map. Ever. Use the function and basic block
871   // iterators to traverse instructions.
872   std::unordered_map<uint32_t, Function*> id_to_func_;
873 
874   // A bitset indicating which analyzes are currently valid.
875   Analysis valid_analyses_;
876 
877   // Opcodes of shader capability core executable instructions
878   // without side-effect.
879   std::unordered_map<uint32_t, std::unordered_set<uint32_t>> combinator_ops_;
880 
881   // Opcodes of shader capability core executable instructions
882   // without side-effect.
883   std::unordered_map<uint32_t, uint32_t> builtin_var_id_map_;
884 
885   // The CFG for all the functions in |module_|.
886   std::unique_ptr<CFG> cfg_;
887 
888   // Each function in the module will create its own dominator tree. We cache
889   // the result so it doesn't need to be rebuilt each time.
890   std::map<const Function*, DominatorAnalysis> dominator_trees_;
891   std::map<const Function*, PostDominatorAnalysis> post_dominator_trees_;
892 
893   // Cache of loop descriptors for each function.
894   std::unordered_map<const Function*, LoopDescriptor> loop_descriptors_;
895 
896   // Constant manager for |module_|.
897   std::unique_ptr<analysis::ConstantManager> constant_mgr_;
898 
899   // Type manager for |module_|.
900   std::unique_ptr<analysis::TypeManager> type_mgr_;
901 
902   // Debug information manager for |module_|.
903   std::unique_ptr<analysis::DebugInfoManager> debug_info_mgr_;
904 
905   // A map from an id to its corresponding OpName and OpMemberName instructions.
906   std::unique_ptr<std::multimap<uint32_t, Instruction*>> id_to_name_;
907 
908   // The cache scalar evolution analysis node.
909   std::unique_ptr<ScalarEvolutionAnalysis> scalar_evolution_analysis_;
910 
911   // The liveness analysis |module_|.
912   std::unique_ptr<LivenessAnalysis> reg_pressure_;
913 
914   std::unique_ptr<ValueNumberTable> vn_table_;
915 
916   std::unique_ptr<InstructionFolder> inst_folder_;
917 
918   std::unique_ptr<StructuredCFGAnalysis> struct_cfg_analysis_;
919 
920   // The liveness manager for |module_|.
921   std::unique_ptr<analysis::LivenessManager> liveness_mgr_;
922 
923   // The maximum legal value for the id bound.
924   uint32_t max_id_bound_;
925 
926   // Whether all bindings within |module_| should be preserved.
927   bool preserve_bindings_;
928 
929   // Whether all specialization constants within |module_|
930   // should be preserved.
931   bool preserve_spec_constants_;
932 };
933 
934 inline IRContext::Analysis operator|(IRContext::Analysis lhs,
935                                      IRContext::Analysis rhs) {
936   return static_cast<IRContext::Analysis>(static_cast<int>(lhs) |
937                                           static_cast<int>(rhs));
938 }
939 
940 inline IRContext::Analysis& operator|=(IRContext::Analysis& lhs,
941                                        IRContext::Analysis rhs) {
942   lhs = lhs | rhs;
943   return lhs;
944 }
945 
946 inline IRContext::Analysis operator<<(IRContext::Analysis a, int shift) {
947   return static_cast<IRContext::Analysis>(static_cast<int>(a) << shift);
948 }
949 
950 inline IRContext::Analysis& operator<<=(IRContext::Analysis& a, int shift) {
951   a = static_cast<IRContext::Analysis>(static_cast<int>(a) << shift);
952   return a;
953 }
954 
GetConstants()955 std::vector<Instruction*> IRContext::GetConstants() {
956   return module()->GetConstants();
957 }
958 
GetConstants()959 std::vector<const Instruction*> IRContext::GetConstants() const {
960   return ((const Module*)module())->GetConstants();
961 }
962 
annotation_begin()963 Module::inst_iterator IRContext::annotation_begin() {
964   return module()->annotation_begin();
965 }
966 
annotation_end()967 Module::inst_iterator IRContext::annotation_end() {
968   return module()->annotation_end();
969 }
970 
annotations()971 IteratorRange<Module::inst_iterator> IRContext::annotations() {
972   return module_->annotations();
973 }
974 
annotations()975 IteratorRange<Module::const_inst_iterator> IRContext::annotations() const {
976   return ((const Module*)module_.get())->annotations();
977 }
978 
capability_begin()979 Module::inst_iterator IRContext::capability_begin() {
980   return module()->capability_begin();
981 }
982 
capability_end()983 Module::inst_iterator IRContext::capability_end() {
984   return module()->capability_end();
985 }
986 
capabilities()987 IteratorRange<Module::inst_iterator> IRContext::capabilities() {
988   return module()->capabilities();
989 }
990 
capabilities()991 IteratorRange<Module::const_inst_iterator> IRContext::capabilities() const {
992   return ((const Module*)module())->capabilities();
993 }
994 
extension_begin()995 Module::inst_iterator IRContext::extension_begin() {
996   return module()->extension_begin();
997 }
998 
extension_end()999 Module::inst_iterator IRContext::extension_end() {
1000   return module()->extension_end();
1001 }
1002 
extensions()1003 IteratorRange<Module::inst_iterator> IRContext::extensions() {
1004   return module()->extensions();
1005 }
1006 
extensions()1007 IteratorRange<Module::const_inst_iterator> IRContext::extensions() const {
1008   return ((const Module*)module())->extensions();
1009 }
1010 
types_values_begin()1011 Module::inst_iterator IRContext::types_values_begin() {
1012   return module()->types_values_begin();
1013 }
1014 
types_values_end()1015 Module::inst_iterator IRContext::types_values_end() {
1016   return module()->types_values_end();
1017 }
1018 
types_values()1019 IteratorRange<Module::inst_iterator> IRContext::types_values() {
1020   return module()->types_values();
1021 }
1022 
types_values()1023 IteratorRange<Module::const_inst_iterator> IRContext::types_values() const {
1024   return ((const Module*)module_.get())->types_values();
1025 }
1026 
ext_inst_import_begin()1027 Module::inst_iterator IRContext::ext_inst_import_begin() {
1028   return module()->ext_inst_import_begin();
1029 }
1030 
ext_inst_import_end()1031 Module::inst_iterator IRContext::ext_inst_import_end() {
1032   return module()->ext_inst_import_end();
1033 }
1034 
ext_inst_imports()1035 IteratorRange<Module::inst_iterator> IRContext::ext_inst_imports() {
1036   return module()->ext_inst_imports();
1037 }
1038 
ext_inst_imports()1039 IteratorRange<Module::const_inst_iterator> IRContext::ext_inst_imports() const {
1040   return ((const Module*)module_.get())->ext_inst_imports();
1041 }
1042 
debug1_begin()1043 Module::inst_iterator IRContext::debug1_begin() {
1044   return module()->debug1_begin();
1045 }
1046 
debug1_end()1047 Module::inst_iterator IRContext::debug1_end() { return module()->debug1_end(); }
1048 
debugs1()1049 IteratorRange<Module::inst_iterator> IRContext::debugs1() {
1050   return module()->debugs1();
1051 }
1052 
debugs1()1053 IteratorRange<Module::const_inst_iterator> IRContext::debugs1() const {
1054   return ((const Module*)module_.get())->debugs1();
1055 }
1056 
debug2_begin()1057 Module::inst_iterator IRContext::debug2_begin() {
1058   return module()->debug2_begin();
1059 }
debug2_end()1060 Module::inst_iterator IRContext::debug2_end() { return module()->debug2_end(); }
1061 
debugs2()1062 IteratorRange<Module::inst_iterator> IRContext::debugs2() {
1063   return module()->debugs2();
1064 }
1065 
debugs2()1066 IteratorRange<Module::const_inst_iterator> IRContext::debugs2() const {
1067   return ((const Module*)module_.get())->debugs2();
1068 }
1069 
debug3_begin()1070 Module::inst_iterator IRContext::debug3_begin() {
1071   return module()->debug3_begin();
1072 }
1073 
debug3_end()1074 Module::inst_iterator IRContext::debug3_end() { return module()->debug3_end(); }
1075 
debugs3()1076 IteratorRange<Module::inst_iterator> IRContext::debugs3() {
1077   return module()->debugs3();
1078 }
1079 
debugs3()1080 IteratorRange<Module::const_inst_iterator> IRContext::debugs3() const {
1081   return ((const Module*)module_.get())->debugs3();
1082 }
1083 
ext_inst_debuginfo_begin()1084 Module::inst_iterator IRContext::ext_inst_debuginfo_begin() {
1085   return module()->ext_inst_debuginfo_begin();
1086 }
1087 
ext_inst_debuginfo_end()1088 Module::inst_iterator IRContext::ext_inst_debuginfo_end() {
1089   return module()->ext_inst_debuginfo_end();
1090 }
1091 
ext_inst_debuginfo()1092 IteratorRange<Module::inst_iterator> IRContext::ext_inst_debuginfo() {
1093   return module()->ext_inst_debuginfo();
1094 }
1095 
ext_inst_debuginfo()1096 IteratorRange<Module::const_inst_iterator> IRContext::ext_inst_debuginfo()
1097     const {
1098   return ((const Module*)module_.get())->ext_inst_debuginfo();
1099 }
1100 
AddCapability(spv::Capability capability)1101 void IRContext::AddCapability(spv::Capability capability) {
1102   if (!get_feature_mgr()->HasCapability(capability)) {
1103     std::unique_ptr<Instruction> capability_inst(new Instruction(
1104         this, spv::Op::OpCapability, 0, 0,
1105         {{SPV_OPERAND_TYPE_CAPABILITY, {static_cast<uint32_t>(capability)}}}));
1106     AddCapability(std::move(capability_inst));
1107   }
1108 }
1109 
AddCapability(std::unique_ptr<Instruction> && c)1110 void IRContext::AddCapability(std::unique_ptr<Instruction>&& c) {
1111   AddCombinatorsForCapability(c->GetSingleWordInOperand(0));
1112   if (feature_mgr_ != nullptr) {
1113     feature_mgr_->AddCapability(
1114         static_cast<spv::Capability>(c->GetSingleWordInOperand(0)));
1115   }
1116   if (AreAnalysesValid(kAnalysisDefUse)) {
1117     get_def_use_mgr()->AnalyzeInstDefUse(c.get());
1118   }
1119   module()->AddCapability(std::move(c));
1120 }
1121 
AddExtension(const std::string & ext_name)1122 void IRContext::AddExtension(const std::string& ext_name) {
1123   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(ext_name);
1124   AddExtension(std::unique_ptr<Instruction>(
1125       new Instruction(this, spv::Op::OpExtension, 0u, 0u,
1126                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
1127 }
1128 
AddExtension(std::unique_ptr<Instruction> && e)1129 void IRContext::AddExtension(std::unique_ptr<Instruction>&& e) {
1130   if (AreAnalysesValid(kAnalysisDefUse)) {
1131     get_def_use_mgr()->AnalyzeInstDefUse(e.get());
1132   }
1133   if (feature_mgr_ != nullptr) {
1134     feature_mgr_->AddExtension(&*e);
1135   }
1136   module()->AddExtension(std::move(e));
1137 }
1138 
AddExtInstImport(const std::string & name)1139 void IRContext::AddExtInstImport(const std::string& name) {
1140   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(name);
1141   AddExtInstImport(std::unique_ptr<Instruction>(
1142       new Instruction(this, spv::Op::OpExtInstImport, 0u, TakeNextId(),
1143                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
1144 }
1145 
AddExtInstImport(std::unique_ptr<Instruction> && e)1146 void IRContext::AddExtInstImport(std::unique_ptr<Instruction>&& e) {
1147   AddCombinatorsForExtension(e.get());
1148   if (AreAnalysesValid(kAnalysisDefUse)) {
1149     get_def_use_mgr()->AnalyzeInstDefUse(e.get());
1150   }
1151   module()->AddExtInstImport(std::move(e));
1152   if (feature_mgr_ != nullptr) {
1153     feature_mgr_->AddExtInstImportIds(module());
1154   }
1155 }
1156 
SetMemoryModel(std::unique_ptr<Instruction> && m)1157 void IRContext::SetMemoryModel(std::unique_ptr<Instruction>&& m) {
1158   module()->SetMemoryModel(std::move(m));
1159 }
1160 
GetMemoryModel()1161 const Instruction* IRContext::GetMemoryModel() const {
1162   return module()->GetMemoryModel();
1163 }
1164 
AddEntryPoint(std::unique_ptr<Instruction> && e)1165 void IRContext::AddEntryPoint(std::unique_ptr<Instruction>&& e) {
1166   module()->AddEntryPoint(std::move(e));
1167 }
1168 
AddExecutionMode(std::unique_ptr<Instruction> && e)1169 void IRContext::AddExecutionMode(std::unique_ptr<Instruction>&& e) {
1170   module()->AddExecutionMode(std::move(e));
1171 }
1172 
AddDebug1Inst(std::unique_ptr<Instruction> && d)1173 void IRContext::AddDebug1Inst(std::unique_ptr<Instruction>&& d) {
1174   module()->AddDebug1Inst(std::move(d));
1175 }
1176 
AddDebug2Inst(std::unique_ptr<Instruction> && d)1177 void IRContext::AddDebug2Inst(std::unique_ptr<Instruction>&& d) {
1178   if (AreAnalysesValid(kAnalysisNameMap)) {
1179     if (d->opcode() == spv::Op::OpName ||
1180         d->opcode() == spv::Op::OpMemberName) {
1181       // OpName and OpMemberName do not have result-ids. The target of the
1182       // instruction is at InOperand index 0.
1183       id_to_name_->insert({d->GetSingleWordInOperand(0), d.get()});
1184     }
1185   }
1186   if (AreAnalysesValid(kAnalysisDefUse)) {
1187     get_def_use_mgr()->AnalyzeInstDefUse(d.get());
1188   }
1189   module()->AddDebug2Inst(std::move(d));
1190 }
1191 
AddDebug3Inst(std::unique_ptr<Instruction> && d)1192 void IRContext::AddDebug3Inst(std::unique_ptr<Instruction>&& d) {
1193   module()->AddDebug3Inst(std::move(d));
1194 }
1195 
AddExtInstDebugInfo(std::unique_ptr<Instruction> && d)1196 void IRContext::AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d) {
1197   module()->AddExtInstDebugInfo(std::move(d));
1198 }
1199 
AddAnnotationInst(std::unique_ptr<Instruction> && a)1200 void IRContext::AddAnnotationInst(std::unique_ptr<Instruction>&& a) {
1201   if (AreAnalysesValid(kAnalysisDecorations)) {
1202     get_decoration_mgr()->AddDecoration(a.get());
1203   }
1204   if (AreAnalysesValid(kAnalysisDefUse)) {
1205     get_def_use_mgr()->AnalyzeInstDefUse(a.get());
1206   }
1207   module()->AddAnnotationInst(std::move(a));
1208 }
1209 
AddType(std::unique_ptr<Instruction> && t)1210 void IRContext::AddType(std::unique_ptr<Instruction>&& t) {
1211   module()->AddType(std::move(t));
1212   if (AreAnalysesValid(kAnalysisDefUse)) {
1213     get_def_use_mgr()->AnalyzeInstDefUse(&*(--types_values_end()));
1214   }
1215 }
1216 
AddGlobalValue(std::unique_ptr<Instruction> && v)1217 void IRContext::AddGlobalValue(std::unique_ptr<Instruction>&& v) {
1218   if (AreAnalysesValid(kAnalysisDefUse)) {
1219     get_def_use_mgr()->AnalyzeInstDefUse(&*v);
1220   }
1221   module()->AddGlobalValue(std::move(v));
1222 }
1223 
AddFunctionDeclaration(std::unique_ptr<Function> && f)1224 void IRContext::AddFunctionDeclaration(std::unique_ptr<Function>&& f) {
1225   module()->AddFunctionDeclaration(std::move(f));
1226 }
1227 
AddFunction(std::unique_ptr<Function> && f)1228 void IRContext::AddFunction(std::unique_ptr<Function>&& f) {
1229   module()->AddFunction(std::move(f));
1230 }
1231 
AnalyzeDefUse(Instruction * inst)1232 void IRContext::AnalyzeDefUse(Instruction* inst) {
1233   if (AreAnalysesValid(kAnalysisDefUse)) {
1234     get_def_use_mgr()->AnalyzeInstDefUse(inst);
1235   }
1236 }
1237 
UpdateDefUse(Instruction * inst)1238 void IRContext::UpdateDefUse(Instruction* inst) {
1239   if (AreAnalysesValid(kAnalysisDefUse)) {
1240     get_def_use_mgr()->UpdateDefUse(inst);
1241   }
1242 }
1243 
BuildIdToNameMap()1244 void IRContext::BuildIdToNameMap() {
1245   id_to_name_ = MakeUnique<std::multimap<uint32_t, Instruction*>>();
1246   for (Instruction& debug_inst : debugs2()) {
1247     if (debug_inst.opcode() == spv::Op::OpMemberName ||
1248         debug_inst.opcode() == spv::Op::OpName) {
1249       id_to_name_->insert({debug_inst.GetSingleWordInOperand(0), &debug_inst});
1250     }
1251   }
1252   valid_analyses_ = valid_analyses_ | kAnalysisNameMap;
1253 }
1254 
1255 IteratorRange<std::multimap<uint32_t, Instruction*>::iterator>
GetNames(uint32_t id)1256 IRContext::GetNames(uint32_t id) {
1257   if (!AreAnalysesValid(kAnalysisNameMap)) {
1258     BuildIdToNameMap();
1259   }
1260   auto result = id_to_name_->equal_range(id);
1261   return make_range(std::move(result.first), std::move(result.second));
1262 }
1263 
GetMemberName(uint32_t struct_type_id,uint32_t index)1264 Instruction* IRContext::GetMemberName(uint32_t struct_type_id, uint32_t index) {
1265   if (!AreAnalysesValid(kAnalysisNameMap)) {
1266     BuildIdToNameMap();
1267   }
1268   auto result = id_to_name_->equal_range(struct_type_id);
1269   for (auto i = result.first; i != result.second; ++i) {
1270     auto* name_instr = i->second;
1271     if (name_instr->opcode() == spv::Op::OpMemberName &&
1272         name_instr->GetSingleWordInOperand(1) == index) {
1273       return name_instr;
1274     }
1275   }
1276   return nullptr;
1277 }
1278 
CloneNames(const uint32_t old_id,const uint32_t new_id,const uint32_t max_member_index)1279 void IRContext::CloneNames(const uint32_t old_id, const uint32_t new_id,
1280                            const uint32_t max_member_index) {
1281   std::vector<std::unique_ptr<Instruction>> names_to_add;
1282   auto names = GetNames(old_id);
1283   for (auto n : names) {
1284     Instruction* old_name_inst = n.second;
1285     if (old_name_inst->opcode() == spv::Op::OpMemberName) {
1286       auto midx = old_name_inst->GetSingleWordInOperand(1);
1287       if (midx >= max_member_index) continue;
1288     }
1289     std::unique_ptr<Instruction> new_name_inst(old_name_inst->Clone(this));
1290     new_name_inst->SetInOperand(0, {new_id});
1291     names_to_add.push_back(std::move(new_name_inst));
1292   }
1293   // We can't add the new names when we are iterating over name range above.
1294   // We can add all the new names now.
1295   for (auto& new_name : names_to_add) AddDebug2Inst(std::move(new_name));
1296 }
1297 
1298 }  // namespace opt
1299 }  // namespace spvtools
1300 
1301 #endif  // SOURCE_OPT_IR_CONTEXT_H_
1302