• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Google LLC
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 #include "source/opt/debug_info_manager.h"
16 
17 #include <cassert>
18 
19 #include "source/opt/ir_context.h"
20 
21 // Constants for OpenCL.DebugInfo.100 & NonSemantic.Shader.DebugInfo.100
22 // extension instructions.
23 
24 static const uint32_t kOpLineOperandLineIndex = 1;
25 static const uint32_t kLineOperandIndexDebugFunction = 7;
26 static const uint32_t kLineOperandIndexDebugLexicalBlock = 5;
27 static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
28 static const uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4;
29 static const uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5;
30 static const uint32_t kDebugFunctionOperandParentIndex = 9;
31 static const uint32_t kDebugTypeCompositeOperandParentIndex = 9;
32 static const uint32_t kDebugLexicalBlockOperandParentIndex = 7;
33 static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
34 static const uint32_t kDebugExpressOperandOperationIndex = 4;
35 static const uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
36 static const uint32_t kDebugDeclareOperandVariableIndex = 5;
37 static const uint32_t kDebugValueOperandExpressionIndex = 6;
38 static const uint32_t kDebugOperationOperandOperationIndex = 4;
39 static const uint32_t kOpVariableOperandStorageClassIndex = 2;
40 static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
41 static const uint32_t kExtInstInstructionInIdx = 1;
42 static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
43 static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
44 
45 namespace spvtools {
46 namespace opt {
47 namespace analysis {
48 namespace {
49 
SetInlinedOperand(Instruction * dbg_inlined_at,uint32_t inlined_operand)50 void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) {
51   assert(dbg_inlined_at);
52   assert(dbg_inlined_at->GetCommonDebugOpcode() ==
53          CommonDebugInfoDebugInlinedAt);
54   if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex) {
55     dbg_inlined_at->AddOperand(
56         {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inlined_operand}});
57   } else {
58     dbg_inlined_at->SetOperand(kDebugInlinedAtOperandInlinedIndex,
59                                {inlined_operand});
60   }
61 }
62 
GetInlinedOperand(Instruction * dbg_inlined_at)63 uint32_t GetInlinedOperand(Instruction* dbg_inlined_at) {
64   assert(dbg_inlined_at);
65   assert(dbg_inlined_at->GetCommonDebugOpcode() ==
66          CommonDebugInfoDebugInlinedAt);
67   if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex)
68     return kNoInlinedAt;
69   return dbg_inlined_at->GetSingleWordOperand(
70       kDebugInlinedAtOperandInlinedIndex);
71 }
72 
IsEmptyDebugExpression(Instruction * instr)73 bool IsEmptyDebugExpression(Instruction* instr) {
74   return (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression) &&
75          instr->NumOperands() == kDebugExpressOperandOperationIndex;
76 }
77 
78 }  // namespace
79 
DebugInfoManager(IRContext * c)80 DebugInfoManager::DebugInfoManager(IRContext* c) : context_(c) {
81   AnalyzeDebugInsts(*c->module());
82 }
83 
GetDbgSetImportId()84 uint32_t DebugInfoManager::GetDbgSetImportId() {
85   uint32_t setId =
86       context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo();
87   if (setId == 0) {
88     setId =
89         context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo();
90   }
91   return setId;
92 }
93 
GetDbgInst(uint32_t id)94 Instruction* DebugInfoManager::GetDbgInst(uint32_t id) {
95   auto dbg_inst_it = id_to_dbg_inst_.find(id);
96   return dbg_inst_it == id_to_dbg_inst_.end() ? nullptr : dbg_inst_it->second;
97 }
98 
RegisterDbgInst(Instruction * inst)99 void DebugInfoManager::RegisterDbgInst(Instruction* inst) {
100   assert(inst->NumInOperands() != 0 &&
101          (GetDbgSetImportId() == inst->GetInOperand(0).words[0]) &&
102          "Given instruction is not a debug instruction");
103   id_to_dbg_inst_[inst->result_id()] = inst;
104 }
105 
RegisterDbgFunction(Instruction * inst)106 void DebugInfoManager::RegisterDbgFunction(Instruction* inst) {
107   if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
108     auto fn_id = inst->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
109     // Do not register function that has been optimized away.
110     auto fn_inst = GetDbgInst(fn_id);
111     if (fn_inst != nullptr) {
112       assert(GetDbgInst(fn_id)->GetOpenCL100DebugOpcode() ==
113              OpenCLDebugInfo100DebugInfoNone);
114       return;
115     }
116     assert(
117         fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() &&
118         "Register DebugFunction for a function that already has DebugFunction");
119     fn_id_to_dbg_fn_[fn_id] = inst;
120   } else if (inst->GetShader100DebugOpcode() ==
121              NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
122     auto fn_id = inst->GetSingleWordOperand(
123         kDebugFunctionDefinitionOperandOpFunctionIndex);
124     auto fn_inst = GetDbgInst(inst->GetSingleWordOperand(
125         kDebugFunctionDefinitionOperandDebugFunctionIndex));
126     assert(fn_inst && fn_inst->GetShader100DebugOpcode() ==
127                           NonSemanticShaderDebugInfo100DebugFunction);
128     assert(fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() &&
129            "Register DebugFunctionDefinition for a function that already has "
130            "DebugFunctionDefinition");
131     fn_id_to_dbg_fn_[fn_id] = fn_inst;
132   } else {
133     assert(false && "inst is not a DebugFunction");
134   }
135 }
136 
RegisterDbgDeclare(uint32_t var_id,Instruction * dbg_declare)137 void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id,
138                                           Instruction* dbg_declare) {
139   assert(dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
140          dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugValue);
141   auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_id);
142   if (dbg_decl_itr == var_id_to_dbg_decl_.end()) {
143     var_id_to_dbg_decl_[var_id] = {dbg_declare};
144   } else {
145     dbg_decl_itr->second.insert(dbg_declare);
146   }
147 }
148 
149 // Create new constant directly into global value area, bypassing the
150 // Constant manager. This is used when the DefUse or Constant managers
151 // are invalid and cannot be regenerated due to the module being in an
152 // inconsistant state e.g. in the middle of significant modification
153 // such as inlining. Invalidate Constant and DefUse managers if used.
AddNewConstInGlobals(IRContext * context,uint32_t const_value)154 uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
155   uint32_t id = context->TakeNextId();
156   std::unique_ptr<Instruction> new_const(new Instruction(
157       context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
158       {
159           {spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
160            {const_value}},
161       }));
162   context->module()->AddGlobalValue(std::move(new_const));
163   context->InvalidateAnalyses(IRContext::kAnalysisConstants);
164   context->InvalidateAnalyses(IRContext::kAnalysisDefUse);
165   return id;
166 }
167 
CreateDebugInlinedAt(const Instruction * line,const DebugScope & scope)168 uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
169                                                 const DebugScope& scope) {
170   uint32_t setId = GetDbgSetImportId();
171 
172   if (setId == 0) return kNoInlinedAt;
173 
174   spv_operand_type_t line_number_type =
175       spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER;
176 
177   // In NonSemantic.Shader.DebugInfo.100, all constants are IDs of OpConstant,
178   // not literals.
179   if (setId ==
180       context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo())
181     line_number_type = spv_operand_type_t::SPV_OPERAND_TYPE_ID;
182 
183   uint32_t line_number = 0;
184   if (line == nullptr) {
185     auto* lexical_scope_inst = GetDbgInst(scope.GetLexicalScope());
186     if (lexical_scope_inst == nullptr) return kNoInlinedAt;
187     CommonDebugInfoInstructions debug_opcode =
188         lexical_scope_inst->GetCommonDebugOpcode();
189     switch (debug_opcode) {
190       case CommonDebugInfoDebugFunction:
191         line_number = lexical_scope_inst->GetSingleWordOperand(
192             kLineOperandIndexDebugFunction);
193         break;
194       case CommonDebugInfoDebugLexicalBlock:
195         line_number = lexical_scope_inst->GetSingleWordOperand(
196             kLineOperandIndexDebugLexicalBlock);
197         break;
198       case CommonDebugInfoDebugTypeComposite:
199       case CommonDebugInfoDebugCompilationUnit:
200         assert(false &&
201                "DebugTypeComposite and DebugCompilationUnit are lexical "
202                "scopes, but we inline functions into a function or a block "
203                "of a function, not into a struct/class or a global scope.");
204         break;
205       default:
206         assert(false &&
207                "Unreachable. a debug extension instruction for a "
208                "lexical scope must be DebugFunction, DebugTypeComposite, "
209                "DebugLexicalBlock, or DebugCompilationUnit.");
210         break;
211     }
212   } else {
213     line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
214 
215     // If we need the line number as an ID, generate that constant now.
216     // If Constant or DefUse managers are invalid, generate constant
217     // directly into the global value section of the module; do not
218     // use Constant manager which may attempt to invoke building of the
219     // DefUse manager which cannot be done during inlining. The extra
220     // constants that may be generated here is likely not significant
221     // and will likely be cleaned up in later passes.
222     if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID) {
223       if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
224           !context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
225         line_number = AddNewConstInGlobals(context(), line_number);
226       else
227         line_number = context()->get_constant_mgr()->GetUIntConst(line_number);
228     }
229   }
230 
231   uint32_t result_id = context()->TakeNextId();
232   std::unique_ptr<Instruction> inlined_at(new Instruction(
233       context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
234       result_id,
235       {
236           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}},
237           {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
238            {static_cast<uint32_t>(CommonDebugInfoDebugInlinedAt)}},
239           {line_number_type, {line_number}},
240           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetLexicalScope()}},
241       }));
242   // |scope| already has DebugInlinedAt. We put the existing DebugInlinedAt
243   // into the Inlined operand of this new DebugInlinedAt.
244   if (scope.GetInlinedAt() != kNoInlinedAt) {
245     inlined_at->AddOperand(
246         {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetInlinedAt()}});
247   }
248   RegisterDbgInst(inlined_at.get());
249   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
250     context()->get_def_use_mgr()->AnalyzeInstDefUse(inlined_at.get());
251   context()->module()->AddExtInstDebugInfo(std::move(inlined_at));
252   return result_id;
253 }
254 
BuildDebugScope(const DebugScope & callee_instr_scope,DebugInlinedAtContext * inlined_at_ctx)255 DebugScope DebugInfoManager::BuildDebugScope(
256     const DebugScope& callee_instr_scope,
257     DebugInlinedAtContext* inlined_at_ctx) {
258   return DebugScope(callee_instr_scope.GetLexicalScope(),
259                     BuildDebugInlinedAtChain(callee_instr_scope.GetInlinedAt(),
260                                              inlined_at_ctx));
261 }
262 
BuildDebugInlinedAtChain(uint32_t callee_inlined_at,DebugInlinedAtContext * inlined_at_ctx)263 uint32_t DebugInfoManager::BuildDebugInlinedAtChain(
264     uint32_t callee_inlined_at, DebugInlinedAtContext* inlined_at_ctx) {
265   if (inlined_at_ctx->GetScopeOfCallInstruction().GetLexicalScope() ==
266       kNoDebugScope)
267     return kNoInlinedAt;
268 
269   // Reuse the already generated DebugInlinedAt chain if exists.
270   uint32_t already_generated_chain_head_id =
271       inlined_at_ctx->GetDebugInlinedAtChain(callee_inlined_at);
272   if (already_generated_chain_head_id != kNoInlinedAt) {
273     return already_generated_chain_head_id;
274   }
275 
276   const uint32_t new_dbg_inlined_at_id =
277       CreateDebugInlinedAt(inlined_at_ctx->GetLineOfCallInstruction(),
278                            inlined_at_ctx->GetScopeOfCallInstruction());
279   if (new_dbg_inlined_at_id == kNoInlinedAt) return kNoInlinedAt;
280 
281   if (callee_inlined_at == kNoInlinedAt) {
282     inlined_at_ctx->SetDebugInlinedAtChain(kNoInlinedAt, new_dbg_inlined_at_id);
283     return new_dbg_inlined_at_id;
284   }
285 
286   uint32_t chain_head_id = kNoInlinedAt;
287   uint32_t chain_iter_id = callee_inlined_at;
288   Instruction* last_inlined_at_in_chain = nullptr;
289   do {
290     Instruction* new_inlined_at_in_chain = CloneDebugInlinedAt(
291         chain_iter_id, /* insert_before */ last_inlined_at_in_chain);
292     assert(new_inlined_at_in_chain != nullptr);
293 
294     // Set DebugInlinedAt of the new scope as the head of the chain.
295     if (chain_head_id == kNoInlinedAt)
296       chain_head_id = new_inlined_at_in_chain->result_id();
297 
298     // Previous DebugInlinedAt of the chain must point to the new
299     // DebugInlinedAt as its Inlined operand to build a recursive
300     // chain.
301     if (last_inlined_at_in_chain != nullptr) {
302       SetInlinedOperand(last_inlined_at_in_chain,
303                         new_inlined_at_in_chain->result_id());
304     }
305     last_inlined_at_in_chain = new_inlined_at_in_chain;
306 
307     chain_iter_id = GetInlinedOperand(new_inlined_at_in_chain);
308   } while (chain_iter_id != kNoInlinedAt);
309 
310   // Put |new_dbg_inlined_at_id| into the end of the chain.
311   SetInlinedOperand(last_inlined_at_in_chain, new_dbg_inlined_at_id);
312 
313   // Keep the new chain information that will be reused it.
314   inlined_at_ctx->SetDebugInlinedAtChain(callee_inlined_at, chain_head_id);
315   return chain_head_id;
316 }
317 
GetDebugOperationWithDeref()318 Instruction* DebugInfoManager::GetDebugOperationWithDeref() {
319   if (deref_operation_ != nullptr) return deref_operation_;
320 
321   uint32_t result_id = context()->TakeNextId();
322   std::unique_ptr<Instruction> deref_operation;
323 
324   if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
325     deref_operation = std::unique_ptr<Instruction>(new Instruction(
326         context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
327         result_id,
328         {
329             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
330             {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
331              {static_cast<uint32_t>(OpenCLDebugInfo100DebugOperation)}},
332             {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION,
333              {static_cast<uint32_t>(OpenCLDebugInfo100Deref)}},
334         }));
335   } else {
336     uint32_t deref_id = context()->get_constant_mgr()->GetUIntConst(
337         NonSemanticShaderDebugInfo100Deref);
338 
339     deref_operation = std::unique_ptr<Instruction>(
340         new Instruction(context(), SpvOpExtInst,
341                         context()->get_type_mgr()->GetVoidTypeId(), result_id,
342                         {
343                             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
344                             {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
345                              {static_cast<uint32_t>(
346                                  NonSemanticShaderDebugInfo100DebugOperation)}},
347                             {SPV_OPERAND_TYPE_ID, {deref_id}},
348                         }));
349   }
350 
351   // Add to the front of |ext_inst_debuginfo_|.
352   deref_operation_ =
353       context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
354           std::move(deref_operation));
355 
356   RegisterDbgInst(deref_operation_);
357   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
358     context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_operation_);
359   return deref_operation_;
360 }
361 
DerefDebugExpression(Instruction * dbg_expr)362 Instruction* DebugInfoManager::DerefDebugExpression(Instruction* dbg_expr) {
363   assert(dbg_expr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression);
364   std::unique_ptr<Instruction> deref_expr(dbg_expr->Clone(context()));
365   deref_expr->SetResultId(context()->TakeNextId());
366   deref_expr->InsertOperand(
367       kDebugExpressOperandOperationIndex,
368       {SPV_OPERAND_TYPE_ID, {GetDebugOperationWithDeref()->result_id()}});
369   auto* deref_expr_instr =
370       context()->ext_inst_debuginfo_end()->InsertBefore(std::move(deref_expr));
371   AnalyzeDebugInst(deref_expr_instr);
372   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
373     context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_expr_instr);
374   return deref_expr_instr;
375 }
376 
GetDebugInfoNone()377 Instruction* DebugInfoManager::GetDebugInfoNone() {
378   if (debug_info_none_inst_ != nullptr) return debug_info_none_inst_;
379 
380   uint32_t result_id = context()->TakeNextId();
381   std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
382       context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
383       result_id,
384       {
385           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
386           {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
387            {static_cast<uint32_t>(CommonDebugInfoDebugInfoNone)}},
388       }));
389 
390   // Add to the front of |ext_inst_debuginfo_|.
391   debug_info_none_inst_ =
392       context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
393           std::move(dbg_info_none_inst));
394 
395   RegisterDbgInst(debug_info_none_inst_);
396   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
397     context()->get_def_use_mgr()->AnalyzeInstDefUse(debug_info_none_inst_);
398   return debug_info_none_inst_;
399 }
400 
GetEmptyDebugExpression()401 Instruction* DebugInfoManager::GetEmptyDebugExpression() {
402   if (empty_debug_expr_inst_ != nullptr) return empty_debug_expr_inst_;
403 
404   uint32_t result_id = context()->TakeNextId();
405   std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
406       context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
407       result_id,
408       {
409           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
410           {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
411            {static_cast<uint32_t>(CommonDebugInfoDebugExpression)}},
412       }));
413 
414   // Add to the front of |ext_inst_debuginfo_|.
415   empty_debug_expr_inst_ =
416       context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
417           std::move(empty_debug_expr));
418 
419   RegisterDbgInst(empty_debug_expr_inst_);
420   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
421     context()->get_def_use_mgr()->AnalyzeInstDefUse(empty_debug_expr_inst_);
422   return empty_debug_expr_inst_;
423 }
424 
GetDebugInlinedAt(uint32_t dbg_inlined_at_id)425 Instruction* DebugInfoManager::GetDebugInlinedAt(uint32_t dbg_inlined_at_id) {
426   auto* inlined_at = GetDbgInst(dbg_inlined_at_id);
427   if (inlined_at == nullptr) return nullptr;
428   if (inlined_at->GetCommonDebugOpcode() != CommonDebugInfoDebugInlinedAt) {
429     return nullptr;
430   }
431   return inlined_at;
432 }
433 
CloneDebugInlinedAt(uint32_t clone_inlined_at_id,Instruction * insert_before)434 Instruction* DebugInfoManager::CloneDebugInlinedAt(uint32_t clone_inlined_at_id,
435                                                    Instruction* insert_before) {
436   auto* inlined_at = GetDebugInlinedAt(clone_inlined_at_id);
437   if (inlined_at == nullptr) return nullptr;
438   std::unique_ptr<Instruction> new_inlined_at(inlined_at->Clone(context()));
439   new_inlined_at->SetResultId(context()->TakeNextId());
440   RegisterDbgInst(new_inlined_at.get());
441   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
442     context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inlined_at.get());
443   if (insert_before != nullptr)
444     return insert_before->InsertBefore(std::move(new_inlined_at));
445   return context()->module()->ext_inst_debuginfo_end()->InsertBefore(
446       std::move(new_inlined_at));
447 }
448 
IsVariableDebugDeclared(uint32_t variable_id)449 bool DebugInfoManager::IsVariableDebugDeclared(uint32_t variable_id) {
450   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
451   return dbg_decl_itr != var_id_to_dbg_decl_.end();
452 }
453 
KillDebugDeclares(uint32_t variable_id)454 bool DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
455   bool modified = false;
456   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
457   if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
458     // We intentionally copy the list of DebugDeclare instructions because
459     // context()->KillInst(dbg_decl) will update |var_id_to_dbg_decl_|. If we
460     // directly use |dbg_decl_itr->second|, it accesses a dangling pointer.
461     auto copy_dbg_decls = dbg_decl_itr->second;
462 
463     for (auto* dbg_decl : copy_dbg_decls) {
464       context()->KillInst(dbg_decl);
465       modified = true;
466     }
467     var_id_to_dbg_decl_.erase(dbg_decl_itr);
468   }
469   return modified;
470 }
471 
GetParentScope(uint32_t child_scope)472 uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) {
473   auto dbg_scope_itr = id_to_dbg_inst_.find(child_scope);
474   assert(dbg_scope_itr != id_to_dbg_inst_.end());
475   CommonDebugInfoInstructions debug_opcode =
476       dbg_scope_itr->second->GetCommonDebugOpcode();
477   uint32_t parent_scope = kNoDebugScope;
478   switch (debug_opcode) {
479     case CommonDebugInfoDebugFunction:
480       parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
481           kDebugFunctionOperandParentIndex);
482       break;
483     case CommonDebugInfoDebugLexicalBlock:
484       parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
485           kDebugLexicalBlockOperandParentIndex);
486       break;
487     case CommonDebugInfoDebugTypeComposite:
488       parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
489           kDebugTypeCompositeOperandParentIndex);
490       break;
491     case CommonDebugInfoDebugCompilationUnit:
492       // DebugCompilationUnit does not have a parent scope.
493       break;
494     default:
495       assert(false &&
496              "Unreachable. A debug scope instruction must be "
497              "DebugFunction, DebugTypeComposite, DebugLexicalBlock, "
498              "or DebugCompilationUnit.");
499       break;
500   }
501   return parent_scope;
502 }
503 
IsAncestorOfScope(uint32_t scope,uint32_t ancestor)504 bool DebugInfoManager::IsAncestorOfScope(uint32_t scope, uint32_t ancestor) {
505   uint32_t ancestor_scope_itr = scope;
506   while (ancestor_scope_itr != kNoDebugScope) {
507     if (ancestor == ancestor_scope_itr) return true;
508     ancestor_scope_itr = GetParentScope(ancestor_scope_itr);
509   }
510   return false;
511 }
512 
IsDeclareVisibleToInstr(Instruction * dbg_declare,Instruction * scope)513 bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare,
514                                                Instruction* scope) {
515   assert(dbg_declare != nullptr);
516   assert(scope != nullptr);
517 
518   std::vector<uint32_t> scope_ids;
519   if (scope->opcode() == SpvOpPhi) {
520     scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
521     for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
522       auto* value = context()->get_def_use_mgr()->GetDef(
523           scope->GetSingleWordInOperand(i));
524       if (value != nullptr)
525         scope_ids.push_back(value->GetDebugScope().GetLexicalScope());
526     }
527   } else {
528     scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
529   }
530 
531   uint32_t dbg_local_var_id =
532       dbg_declare->GetSingleWordOperand(kDebugDeclareOperandLocalVariableIndex);
533   auto dbg_local_var_itr = id_to_dbg_inst_.find(dbg_local_var_id);
534   assert(dbg_local_var_itr != id_to_dbg_inst_.end());
535   uint32_t decl_scope_id = dbg_local_var_itr->second->GetSingleWordOperand(
536       kDebugLocalVariableOperandParentIndex);
537 
538   // If the scope of DebugDeclare is an ancestor scope of the instruction's
539   // scope, the local variable is visible to the instruction.
540   for (uint32_t scope_id : scope_ids) {
541     if (scope_id != kNoDebugScope &&
542         IsAncestorOfScope(scope_id, decl_scope_id)) {
543       return true;
544     }
545   }
546   return false;
547 }
548 
AddDebugValueIfVarDeclIsVisible(Instruction * scope_and_line,uint32_t variable_id,uint32_t value_id,Instruction * insert_pos,std::unordered_set<Instruction * > * invisible_decls)549 bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
550     Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
551     Instruction* insert_pos,
552     std::unordered_set<Instruction*>* invisible_decls) {
553   assert(scope_and_line != nullptr);
554 
555   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
556   if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return false;
557 
558   bool modified = false;
559   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
560     if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) {
561       if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
562       continue;
563     }
564 
565     // Avoid inserting the new DebugValue between OpPhi or OpVariable
566     // instructions.
567     Instruction* insert_before = insert_pos->NextNode();
568     while (insert_before->opcode() == SpvOpPhi ||
569            insert_before->opcode() == SpvOpVariable) {
570       insert_before = insert_before->NextNode();
571     }
572     modified |= AddDebugValueForDecl(dbg_decl_or_val, value_id, insert_before,
573                                      scope_and_line) != nullptr;
574   }
575   return modified;
576 }
577 
AddDebugValueForDecl(Instruction * dbg_decl,uint32_t value_id,Instruction * insert_before,Instruction * scope_and_line)578 Instruction* DebugInfoManager::AddDebugValueForDecl(
579     Instruction* dbg_decl, uint32_t value_id, Instruction* insert_before,
580     Instruction* scope_and_line) {
581   if (dbg_decl == nullptr || !IsDebugDeclare(dbg_decl)) return nullptr;
582 
583   std::unique_ptr<Instruction> dbg_val(dbg_decl->Clone(context()));
584   dbg_val->SetResultId(context()->TakeNextId());
585   dbg_val->SetInOperand(kExtInstInstructionInIdx, {CommonDebugInfoDebugValue});
586   dbg_val->SetOperand(kDebugDeclareOperandVariableIndex, {value_id});
587   dbg_val->SetOperand(kDebugValueOperandExpressionIndex,
588                       {GetEmptyDebugExpression()->result_id()});
589   dbg_val->UpdateDebugInfoFrom(scope_and_line);
590 
591   auto* added_dbg_val = insert_before->InsertBefore(std::move(dbg_val));
592   AnalyzeDebugInst(added_dbg_val);
593   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
594     context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_val);
595   if (context()->AreAnalysesValid(
596           IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
597     auto insert_blk = context()->get_instr_block(insert_before);
598     context()->set_instr_block(added_dbg_val, insert_blk);
599   }
600   return added_dbg_val;
601 }
602 
GetVulkanDebugOperation(Instruction * inst)603 uint32_t DebugInfoManager::GetVulkanDebugOperation(Instruction* inst) {
604   assert(inst->GetShader100DebugOpcode() ==
605              NonSemanticShaderDebugInfo100DebugOperation &&
606          "inst must be Vulkan DebugOperation");
607   return context()
608       ->get_constant_mgr()
609       ->GetConstantFromInst(context()->get_def_use_mgr()->GetDef(
610           inst->GetSingleWordOperand(kDebugOperationOperandOperationIndex)))
611       ->GetU32();
612 }
613 
GetVariableIdOfDebugValueUsedForDeclare(Instruction * inst)614 uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
615     Instruction* inst) {
616   if (inst->GetCommonDebugOpcode() != CommonDebugInfoDebugValue) return 0;
617 
618   auto* expr =
619       GetDbgInst(inst->GetSingleWordOperand(kDebugValueOperandExpressionIndex));
620   if (expr == nullptr) return 0;
621   if (expr->NumOperands() != kDebugExpressOperandOperationIndex + 1) return 0;
622 
623   auto* operation = GetDbgInst(
624       expr->GetSingleWordOperand(kDebugExpressOperandOperationIndex));
625   if (operation == nullptr) return 0;
626 
627   // OpenCL.DebugInfo.100 contains a literal for the operation, Vulkan uses an
628   // OpConstant.
629   if (inst->IsOpenCL100DebugInstr()) {
630     if (operation->GetSingleWordOperand(kDebugOperationOperandOperationIndex) !=
631         OpenCLDebugInfo100Deref) {
632       return 0;
633     }
634   } else {
635     uint32_t operation_const = GetVulkanDebugOperation(operation);
636     if (operation_const != NonSemanticShaderDebugInfo100Deref) {
637       return 0;
638     }
639   }
640 
641   uint32_t var_id =
642       inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
643   if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse)) {
644     assert(false &&
645            "Checking a DebugValue can be used for declare needs DefUseManager");
646     return 0;
647   }
648 
649   auto* var = context()->get_def_use_mgr()->GetDef(var_id);
650   if (var->opcode() == SpvOpVariable &&
651       SpvStorageClass(var->GetSingleWordOperand(
652           kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
653     return var_id;
654   }
655   return 0;
656 }
657 
IsDebugDeclare(Instruction * instr)658 bool DebugInfoManager::IsDebugDeclare(Instruction* instr) {
659   if (!instr->IsCommonDebugInstr()) return false;
660   return instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
661          GetVariableIdOfDebugValueUsedForDeclare(instr) != 0;
662 }
663 
ReplaceAllUsesInDebugScopeWithPredicate(uint32_t before,uint32_t after,const std::function<bool (Instruction *)> & predicate)664 void DebugInfoManager::ReplaceAllUsesInDebugScopeWithPredicate(
665     uint32_t before, uint32_t after,
666     const std::function<bool(Instruction*)>& predicate) {
667   auto scope_id_to_users_itr = scope_id_to_users_.find(before);
668   if (scope_id_to_users_itr != scope_id_to_users_.end()) {
669     for (Instruction* inst : scope_id_to_users_itr->second) {
670       if (predicate(inst)) inst->UpdateLexicalScope(after);
671     }
672     scope_id_to_users_[after] = scope_id_to_users_itr->second;
673     scope_id_to_users_.erase(scope_id_to_users_itr);
674   }
675   auto inlinedat_id_to_users_itr = inlinedat_id_to_users_.find(before);
676   if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
677     for (Instruction* inst : inlinedat_id_to_users_itr->second) {
678       if (predicate(inst)) inst->UpdateDebugInlinedAt(after);
679     }
680     inlinedat_id_to_users_[after] = inlinedat_id_to_users_itr->second;
681     inlinedat_id_to_users_.erase(inlinedat_id_to_users_itr);
682   }
683 }
684 
ClearDebugScopeAndInlinedAtUses(Instruction * inst)685 void DebugInfoManager::ClearDebugScopeAndInlinedAtUses(Instruction* inst) {
686   auto scope_id_to_users_itr = scope_id_to_users_.find(inst->result_id());
687   if (scope_id_to_users_itr != scope_id_to_users_.end()) {
688     scope_id_to_users_.erase(scope_id_to_users_itr);
689   }
690   auto inlinedat_id_to_users_itr =
691       inlinedat_id_to_users_.find(inst->result_id());
692   if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
693     inlinedat_id_to_users_.erase(inlinedat_id_to_users_itr);
694   }
695 }
696 
AnalyzeDebugInst(Instruction * inst)697 void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) {
698   if (inst->GetDebugScope().GetLexicalScope() != kNoDebugScope) {
699     auto& users = scope_id_to_users_[inst->GetDebugScope().GetLexicalScope()];
700     users.insert(inst);
701   }
702   if (inst->GetDebugInlinedAt() != kNoInlinedAt) {
703     auto& users = inlinedat_id_to_users_[inst->GetDebugInlinedAt()];
704     users.insert(inst);
705   }
706 
707   if (!inst->IsCommonDebugInstr()) return;
708 
709   RegisterDbgInst(inst);
710 
711   if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction ||
712       inst->GetShader100DebugOpcode() ==
713           NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
714     RegisterDbgFunction(inst);
715   }
716 
717   if (deref_operation_ == nullptr &&
718       inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugOperation &&
719       inst->GetSingleWordOperand(kDebugOperationOperandOperationIndex) ==
720           OpenCLDebugInfo100Deref) {
721     deref_operation_ = inst;
722   }
723 
724   if (deref_operation_ == nullptr &&
725       inst->GetShader100DebugOpcode() ==
726           NonSemanticShaderDebugInfo100DebugOperation) {
727     uint32_t operation_const = GetVulkanDebugOperation(inst);
728     if (operation_const == NonSemanticShaderDebugInfo100Deref) {
729       deref_operation_ = inst;
730     }
731   }
732 
733   if (debug_info_none_inst_ == nullptr &&
734       inst->GetCommonDebugOpcode() == CommonDebugInfoDebugInfoNone) {
735     debug_info_none_inst_ = inst;
736   }
737 
738   if (empty_debug_expr_inst_ == nullptr && IsEmptyDebugExpression(inst)) {
739     empty_debug_expr_inst_ = inst;
740   }
741 
742   if (inst->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
743     uint32_t var_id =
744         inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
745     RegisterDbgDeclare(var_id, inst);
746   }
747 
748   if (uint32_t var_id = GetVariableIdOfDebugValueUsedForDeclare(inst)) {
749     RegisterDbgDeclare(var_id, inst);
750   }
751 }
752 
ConvertDebugGlobalToLocalVariable(Instruction * dbg_global_var,Instruction * local_var)753 void DebugInfoManager::ConvertDebugGlobalToLocalVariable(
754     Instruction* dbg_global_var, Instruction* local_var) {
755   if (dbg_global_var->GetCommonDebugOpcode() !=
756       CommonDebugInfoDebugGlobalVariable) {
757     return;
758   }
759   assert(local_var->opcode() == SpvOpVariable ||
760          local_var->opcode() == SpvOpFunctionParameter);
761 
762   // Convert |dbg_global_var| to DebugLocalVariable
763   dbg_global_var->SetInOperand(kExtInstInstructionInIdx,
764                                {CommonDebugInfoDebugLocalVariable});
765   auto flags = dbg_global_var->GetSingleWordOperand(
766       kDebugGlobalVariableOperandFlagsIndex);
767   for (uint32_t i = dbg_global_var->NumInOperands() - 1;
768        i >= kDebugLocalVariableOperandFlagsIndex; --i) {
769     dbg_global_var->RemoveOperand(i);
770   }
771   dbg_global_var->SetOperand(kDebugLocalVariableOperandFlagsIndex, {flags});
772   context()->ForgetUses(dbg_global_var);
773   context()->AnalyzeUses(dbg_global_var);
774 
775   // Create a DebugDeclare
776   std::unique_ptr<Instruction> new_dbg_decl(new Instruction(
777       context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
778       context()->TakeNextId(),
779       {
780           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
781           {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
782            {static_cast<uint32_t>(CommonDebugInfoDebugDeclare)}},
783           {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
784            {dbg_global_var->result_id()}},
785           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {local_var->result_id()}},
786           {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
787            {GetEmptyDebugExpression()->result_id()}},
788       }));
789   // Must insert after all OpVariables in block
790   Instruction* insert_before = local_var;
791   while (insert_before->opcode() == SpvOpVariable)
792     insert_before = insert_before->NextNode();
793   auto* added_dbg_decl = insert_before->InsertBefore(std::move(new_dbg_decl));
794   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
795     context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_decl);
796   if (context()->AreAnalysesValid(
797           IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
798     auto insert_blk = context()->get_instr_block(local_var);
799     context()->set_instr_block(added_dbg_decl, insert_blk);
800   }
801 }
802 
AnalyzeDebugInsts(Module & module)803 void DebugInfoManager::AnalyzeDebugInsts(Module& module) {
804   deref_operation_ = nullptr;
805   debug_info_none_inst_ = nullptr;
806   empty_debug_expr_inst_ = nullptr;
807   module.ForEachInst([this](Instruction* cpi) { AnalyzeDebugInst(cpi); });
808 
809   // Move |empty_debug_expr_inst_| to the beginning of the debug instruction
810   // list.
811   if (empty_debug_expr_inst_ != nullptr &&
812       empty_debug_expr_inst_->PreviousNode() != nullptr &&
813       empty_debug_expr_inst_->PreviousNode()->IsCommonDebugInstr()) {
814     empty_debug_expr_inst_->InsertBefore(
815         &*context()->module()->ext_inst_debuginfo_begin());
816   }
817 
818   // Move |debug_info_none_inst_| to the beginning of the debug instruction
819   // list.
820   if (debug_info_none_inst_ != nullptr &&
821       debug_info_none_inst_->PreviousNode() != nullptr &&
822       debug_info_none_inst_->PreviousNode()->IsCommonDebugInstr()) {
823     debug_info_none_inst_->InsertBefore(
824         &*context()->module()->ext_inst_debuginfo_begin());
825   }
826 }
827 
ClearDebugInfo(Instruction * instr)828 void DebugInfoManager::ClearDebugInfo(Instruction* instr) {
829   auto scope_id_to_users_itr =
830       scope_id_to_users_.find(instr->GetDebugScope().GetLexicalScope());
831   if (scope_id_to_users_itr != scope_id_to_users_.end()) {
832     scope_id_to_users_itr->second.erase(instr);
833   }
834   auto inlinedat_id_to_users_itr =
835       inlinedat_id_to_users_.find(instr->GetDebugInlinedAt());
836   if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
837     inlinedat_id_to_users_itr->second.erase(instr);
838   }
839 
840   if (instr == nullptr || !instr->IsCommonDebugInstr()) {
841     return;
842   }
843 
844   id_to_dbg_inst_.erase(instr->result_id());
845 
846   if (instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
847     auto fn_id =
848         instr->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
849     fn_id_to_dbg_fn_.erase(fn_id);
850   }
851   if (instr->GetShader100DebugOpcode() ==
852       NonSemanticShaderDebugInfo100DebugFunction) {
853     auto fn_id = instr->GetSingleWordOperand(
854         kDebugFunctionDefinitionOperandOpFunctionIndex);
855     fn_id_to_dbg_fn_.erase(fn_id);
856   }
857 
858   if (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
859       instr->GetCommonDebugOpcode() == CommonDebugInfoDebugValue) {
860     auto var_or_value_id =
861         instr->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
862     auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_or_value_id);
863     if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
864       dbg_decl_itr->second.erase(instr);
865     }
866   }
867 
868   if (deref_operation_ == instr) {
869     deref_operation_ = nullptr;
870     for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
871          dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
872          ++dbg_instr_itr) {
873       // OpenCL.DebugInfo.100 contains the operation as a literal operand, in
874       // Vulkan it's referenced as an OpConstant.
875       if (instr != &*dbg_instr_itr &&
876           dbg_instr_itr->GetOpenCL100DebugOpcode() ==
877               OpenCLDebugInfo100DebugOperation &&
878           dbg_instr_itr->GetSingleWordOperand(
879               kDebugOperationOperandOperationIndex) ==
880               OpenCLDebugInfo100Deref) {
881         deref_operation_ = &*dbg_instr_itr;
882         break;
883       } else if (instr != &*dbg_instr_itr &&
884                  dbg_instr_itr->GetShader100DebugOpcode() ==
885                      NonSemanticShaderDebugInfo100DebugOperation) {
886         uint32_t operation_const = GetVulkanDebugOperation(&*dbg_instr_itr);
887         if (operation_const == NonSemanticShaderDebugInfo100Deref) {
888           deref_operation_ = &*dbg_instr_itr;
889           break;
890         }
891       }
892     }
893   }
894 
895   if (debug_info_none_inst_ == instr) {
896     debug_info_none_inst_ = nullptr;
897     for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
898          dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
899          ++dbg_instr_itr) {
900       if (instr != &*dbg_instr_itr && dbg_instr_itr->GetCommonDebugOpcode() ==
901                                           CommonDebugInfoDebugInfoNone) {
902         debug_info_none_inst_ = &*dbg_instr_itr;
903         break;
904       }
905     }
906   }
907 
908   if (empty_debug_expr_inst_ == instr) {
909     empty_debug_expr_inst_ = nullptr;
910     for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
911          dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
912          ++dbg_instr_itr) {
913       if (instr != &*dbg_instr_itr && IsEmptyDebugExpression(&*dbg_instr_itr)) {
914         empty_debug_expr_inst_ = &*dbg_instr_itr;
915         break;
916       }
917     }
918   }
919 }
920 
921 }  // namespace analysis
922 }  // namespace opt
923 }  // namespace spvtools
924