Coverage Report

Created: 2024-09-11 07:09

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