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