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] = █
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