debug_info_manager.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  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. #include "source/opt/debug_info_manager.h"
  15. #include <cassert>
  16. #include "source/opt/ir_context.h"
  17. // Constants for OpenCL.DebugInfo.100 extension instructions.
  18. static const uint32_t kOpLineOperandLineIndex = 1;
  19. static const uint32_t kLineOperandIndexDebugFunction = 7;
  20. static const uint32_t kLineOperandIndexDebugLexicalBlock = 5;
  21. static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
  22. static const uint32_t kDebugFunctionOperandParentIndex = 9;
  23. static const uint32_t kDebugTypeCompositeOperandParentIndex = 9;
  24. static const uint32_t kDebugLexicalBlockOperandParentIndex = 7;
  25. static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
  26. static const uint32_t kDebugExpressOperandOperationIndex = 4;
  27. static const uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
  28. static const uint32_t kDebugDeclareOperandVariableIndex = 5;
  29. static const uint32_t kDebugValueOperandLocalVariableIndex = 4;
  30. static const uint32_t kDebugValueOperandExpressionIndex = 6;
  31. static const uint32_t kDebugOperationOperandOperationIndex = 4;
  32. static const uint32_t kOpVariableOperandStorageClassIndex = 2;
  33. static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
  34. static const uint32_t kDebugOperationOperandOpCodeIndex = 4;
  35. namespace spvtools {
  36. namespace opt {
  37. namespace analysis {
  38. namespace {
  39. void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) {
  40. assert(dbg_inlined_at);
  41. assert(dbg_inlined_at->GetOpenCL100DebugOpcode() ==
  42. OpenCLDebugInfo100DebugInlinedAt);
  43. if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex) {
  44. dbg_inlined_at->AddOperand(
  45. {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inlined_operand}});
  46. } else {
  47. dbg_inlined_at->SetOperand(kDebugInlinedAtOperandInlinedIndex,
  48. {inlined_operand});
  49. }
  50. }
  51. uint32_t GetInlinedOperand(Instruction* dbg_inlined_at) {
  52. assert(dbg_inlined_at);
  53. assert(dbg_inlined_at->GetOpenCL100DebugOpcode() ==
  54. OpenCLDebugInfo100DebugInlinedAt);
  55. if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex)
  56. return kNoInlinedAt;
  57. return dbg_inlined_at->GetSingleWordOperand(
  58. kDebugInlinedAtOperandInlinedIndex);
  59. }
  60. bool IsEmptyDebugExpression(Instruction* instr) {
  61. return instr->GetOpenCL100DebugOpcode() ==
  62. OpenCLDebugInfo100DebugExpression &&
  63. instr->NumOperands() == kDebugExpressOperandOperationIndex;
  64. }
  65. } // namespace
  66. DebugInfoManager::DebugInfoManager(IRContext* c) : context_(c) {
  67. AnalyzeDebugInsts(*c->module());
  68. }
  69. Instruction* DebugInfoManager::GetDbgInst(uint32_t id) {
  70. auto dbg_inst_it = id_to_dbg_inst_.find(id);
  71. return dbg_inst_it == id_to_dbg_inst_.end() ? nullptr : dbg_inst_it->second;
  72. }
  73. void DebugInfoManager::RegisterDbgInst(Instruction* inst) {
  74. assert(
  75. inst->NumInOperands() != 0 &&
  76. context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() ==
  77. inst->GetInOperand(0).words[0] &&
  78. "Given instruction is not a debug instruction");
  79. id_to_dbg_inst_[inst->result_id()] = inst;
  80. }
  81. void DebugInfoManager::RegisterDbgFunction(Instruction* inst) {
  82. assert(inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction &&
  83. "inst is not a DebugFunction");
  84. auto fn_id = inst->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
  85. assert(
  86. fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() &&
  87. "Register DebugFunction for a function that already has DebugFunction");
  88. fn_id_to_dbg_fn_[fn_id] = inst;
  89. }
  90. void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id,
  91. Instruction* dbg_declare) {
  92. assert(dbg_declare->GetOpenCL100DebugOpcode() ==
  93. OpenCLDebugInfo100DebugDeclare ||
  94. dbg_declare->GetOpenCL100DebugOpcode() ==
  95. OpenCLDebugInfo100DebugValue);
  96. auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_id);
  97. if (dbg_decl_itr == var_id_to_dbg_decl_.end()) {
  98. var_id_to_dbg_decl_[var_id] = {dbg_declare};
  99. } else {
  100. dbg_decl_itr->second.insert(dbg_declare);
  101. }
  102. }
  103. uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
  104. const DebugScope& scope) {
  105. if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() ==
  106. 0)
  107. return kNoInlinedAt;
  108. uint32_t line_number = 0;
  109. if (line == nullptr) {
  110. auto* lexical_scope_inst = GetDbgInst(scope.GetLexicalScope());
  111. if (lexical_scope_inst == nullptr) return kNoInlinedAt;
  112. OpenCLDebugInfo100Instructions debug_opcode =
  113. lexical_scope_inst->GetOpenCL100DebugOpcode();
  114. switch (debug_opcode) {
  115. case OpenCLDebugInfo100DebugFunction:
  116. line_number = lexical_scope_inst->GetSingleWordOperand(
  117. kLineOperandIndexDebugFunction);
  118. break;
  119. case OpenCLDebugInfo100DebugLexicalBlock:
  120. line_number = lexical_scope_inst->GetSingleWordOperand(
  121. kLineOperandIndexDebugLexicalBlock);
  122. break;
  123. case OpenCLDebugInfo100DebugTypeComposite:
  124. case OpenCLDebugInfo100DebugCompilationUnit:
  125. assert(false &&
  126. "DebugTypeComposite and DebugCompilationUnit are lexical "
  127. "scopes, but we inline functions into a function or a block "
  128. "of a function, not into a struct/class or a global scope.");
  129. break;
  130. default:
  131. assert(false &&
  132. "Unreachable. a debug extension instruction for a "
  133. "lexical scope must be DebugFunction, DebugTypeComposite, "
  134. "DebugLexicalBlock, or DebugCompilationUnit.");
  135. break;
  136. }
  137. } else {
  138. line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
  139. }
  140. uint32_t result_id = context()->TakeNextId();
  141. std::unique_ptr<Instruction> inlined_at(new Instruction(
  142. context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
  143. result_id,
  144. {
  145. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  146. {context()
  147. ->get_feature_mgr()
  148. ->GetExtInstImportId_OpenCL100DebugInfo()}},
  149. {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
  150. {static_cast<uint32_t>(OpenCLDebugInfo100DebugInlinedAt)}},
  151. {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
  152. {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetLexicalScope()}},
  153. }));
  154. // |scope| already has DebugInlinedAt. We put the existing DebugInlinedAt
  155. // into the Inlined operand of this new DebugInlinedAt.
  156. if (scope.GetInlinedAt() != kNoInlinedAt) {
  157. inlined_at->AddOperand(
  158. {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetInlinedAt()}});
  159. }
  160. RegisterDbgInst(inlined_at.get());
  161. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  162. context()->get_def_use_mgr()->AnalyzeInstDefUse(inlined_at.get());
  163. context()->module()->AddExtInstDebugInfo(std::move(inlined_at));
  164. return result_id;
  165. }
  166. DebugScope DebugInfoManager::BuildDebugScope(
  167. const DebugScope& callee_instr_scope,
  168. DebugInlinedAtContext* inlined_at_ctx) {
  169. return DebugScope(callee_instr_scope.GetLexicalScope(),
  170. BuildDebugInlinedAtChain(callee_instr_scope.GetInlinedAt(),
  171. inlined_at_ctx));
  172. }
  173. uint32_t DebugInfoManager::BuildDebugInlinedAtChain(
  174. uint32_t callee_inlined_at, DebugInlinedAtContext* inlined_at_ctx) {
  175. if (inlined_at_ctx->GetScopeOfCallInstruction().GetLexicalScope() ==
  176. kNoDebugScope)
  177. return kNoInlinedAt;
  178. // Reuse the already generated DebugInlinedAt chain if exists.
  179. uint32_t already_generated_chain_head_id =
  180. inlined_at_ctx->GetDebugInlinedAtChain(callee_inlined_at);
  181. if (already_generated_chain_head_id != kNoInlinedAt) {
  182. return already_generated_chain_head_id;
  183. }
  184. const uint32_t new_dbg_inlined_at_id =
  185. CreateDebugInlinedAt(inlined_at_ctx->GetLineOfCallInstruction(),
  186. inlined_at_ctx->GetScopeOfCallInstruction());
  187. if (new_dbg_inlined_at_id == kNoInlinedAt) return kNoInlinedAt;
  188. if (callee_inlined_at == kNoInlinedAt) {
  189. inlined_at_ctx->SetDebugInlinedAtChain(kNoInlinedAt, new_dbg_inlined_at_id);
  190. return new_dbg_inlined_at_id;
  191. }
  192. uint32_t chain_head_id = kNoInlinedAt;
  193. uint32_t chain_iter_id = callee_inlined_at;
  194. Instruction* last_inlined_at_in_chain = nullptr;
  195. do {
  196. Instruction* new_inlined_at_in_chain = CloneDebugInlinedAt(
  197. chain_iter_id, /* insert_before */ last_inlined_at_in_chain);
  198. assert(new_inlined_at_in_chain != nullptr);
  199. // Set DebugInlinedAt of the new scope as the head of the chain.
  200. if (chain_head_id == kNoInlinedAt)
  201. chain_head_id = new_inlined_at_in_chain->result_id();
  202. // Previous DebugInlinedAt of the chain must point to the new
  203. // DebugInlinedAt as its Inlined operand to build a recursive
  204. // chain.
  205. if (last_inlined_at_in_chain != nullptr) {
  206. SetInlinedOperand(last_inlined_at_in_chain,
  207. new_inlined_at_in_chain->result_id());
  208. }
  209. last_inlined_at_in_chain = new_inlined_at_in_chain;
  210. chain_iter_id = GetInlinedOperand(new_inlined_at_in_chain);
  211. } while (chain_iter_id != kNoInlinedAt);
  212. // Put |new_dbg_inlined_at_id| into the end of the chain.
  213. SetInlinedOperand(last_inlined_at_in_chain, new_dbg_inlined_at_id);
  214. // Keep the new chain information that will be reused it.
  215. inlined_at_ctx->SetDebugInlinedAtChain(callee_inlined_at, chain_head_id);
  216. return chain_head_id;
  217. }
  218. Instruction* DebugInfoManager::GetDebugOperationWithDeref() {
  219. if (deref_operation_ != nullptr) return deref_operation_;
  220. uint32_t result_id = context()->TakeNextId();
  221. std::unique_ptr<Instruction> deref_operation(new Instruction(
  222. context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
  223. result_id,
  224. {
  225. {SPV_OPERAND_TYPE_ID,
  226. {context()
  227. ->get_feature_mgr()
  228. ->GetExtInstImportId_OpenCL100DebugInfo()}},
  229. {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
  230. {static_cast<uint32_t>(OpenCLDebugInfo100DebugOperation)}},
  231. {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION,
  232. {static_cast<uint32_t>(OpenCLDebugInfo100Deref)}},
  233. }));
  234. // Add to the front of |ext_inst_debuginfo_|.
  235. deref_operation_ =
  236. context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
  237. std::move(deref_operation));
  238. RegisterDbgInst(deref_operation_);
  239. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  240. context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_operation_);
  241. return deref_operation_;
  242. }
  243. Instruction* DebugInfoManager::DerefDebugExpression(Instruction* dbg_expr) {
  244. assert(dbg_expr->GetOpenCL100DebugOpcode() ==
  245. OpenCLDebugInfo100DebugExpression);
  246. std::unique_ptr<Instruction> deref_expr(dbg_expr->Clone(context()));
  247. deref_expr->SetResultId(context()->TakeNextId());
  248. deref_expr->InsertOperand(
  249. kDebugExpressOperandOperationIndex,
  250. {SPV_OPERAND_TYPE_ID, {GetDebugOperationWithDeref()->result_id()}});
  251. auto* deref_expr_instr =
  252. context()->ext_inst_debuginfo_end()->InsertBefore(std::move(deref_expr));
  253. AnalyzeDebugInst(deref_expr_instr);
  254. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  255. context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_expr_instr);
  256. return deref_expr_instr;
  257. }
  258. Instruction* DebugInfoManager::GetDebugInfoNone() {
  259. if (debug_info_none_inst_ != nullptr) return debug_info_none_inst_;
  260. uint32_t result_id = context()->TakeNextId();
  261. std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
  262. context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
  263. result_id,
  264. {
  265. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  266. {context()
  267. ->get_feature_mgr()
  268. ->GetExtInstImportId_OpenCL100DebugInfo()}},
  269. {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
  270. {static_cast<uint32_t>(OpenCLDebugInfo100DebugInfoNone)}},
  271. }));
  272. // Add to the front of |ext_inst_debuginfo_|.
  273. debug_info_none_inst_ =
  274. context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
  275. std::move(dbg_info_none_inst));
  276. RegisterDbgInst(debug_info_none_inst_);
  277. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  278. context()->get_def_use_mgr()->AnalyzeInstDefUse(debug_info_none_inst_);
  279. return debug_info_none_inst_;
  280. }
  281. Instruction* DebugInfoManager::GetEmptyDebugExpression() {
  282. if (empty_debug_expr_inst_ != nullptr) return empty_debug_expr_inst_;
  283. uint32_t result_id = context()->TakeNextId();
  284. std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
  285. context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
  286. result_id,
  287. {
  288. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  289. {context()
  290. ->get_feature_mgr()
  291. ->GetExtInstImportId_OpenCL100DebugInfo()}},
  292. {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
  293. {static_cast<uint32_t>(OpenCLDebugInfo100DebugExpression)}},
  294. }));
  295. // Add to the front of |ext_inst_debuginfo_|.
  296. empty_debug_expr_inst_ =
  297. context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
  298. std::move(empty_debug_expr));
  299. RegisterDbgInst(empty_debug_expr_inst_);
  300. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  301. context()->get_def_use_mgr()->AnalyzeInstDefUse(empty_debug_expr_inst_);
  302. return empty_debug_expr_inst_;
  303. }
  304. Instruction* DebugInfoManager::GetDebugInlinedAt(uint32_t dbg_inlined_at_id) {
  305. auto* inlined_at = GetDbgInst(dbg_inlined_at_id);
  306. if (inlined_at == nullptr) return nullptr;
  307. if (inlined_at->GetOpenCL100DebugOpcode() !=
  308. OpenCLDebugInfo100DebugInlinedAt) {
  309. return nullptr;
  310. }
  311. return inlined_at;
  312. }
  313. Instruction* DebugInfoManager::CloneDebugInlinedAt(uint32_t clone_inlined_at_id,
  314. Instruction* insert_before) {
  315. auto* inlined_at = GetDebugInlinedAt(clone_inlined_at_id);
  316. if (inlined_at == nullptr) return nullptr;
  317. std::unique_ptr<Instruction> new_inlined_at(inlined_at->Clone(context()));
  318. new_inlined_at->SetResultId(context()->TakeNextId());
  319. RegisterDbgInst(new_inlined_at.get());
  320. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  321. context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inlined_at.get());
  322. if (insert_before != nullptr)
  323. return insert_before->InsertBefore(std::move(new_inlined_at));
  324. return context()->module()->ext_inst_debuginfo_end()->InsertBefore(
  325. std::move(new_inlined_at));
  326. }
  327. bool DebugInfoManager::IsDebugDeclared(uint32_t variable_id) {
  328. auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  329. return dbg_decl_itr != var_id_to_dbg_decl_.end();
  330. }
  331. void DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
  332. bool done = false;
  333. while (!done) {
  334. Instruction* kill_inst = nullptr;
  335. auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  336. if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
  337. for (auto dbg_decl : dbg_decl_itr->second) {
  338. kill_inst = dbg_decl;
  339. break;
  340. }
  341. }
  342. if (kill_inst)
  343. context()->KillInst(kill_inst);
  344. else
  345. done = true;
  346. }
  347. }
  348. uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) {
  349. auto dbg_scope_itr = id_to_dbg_inst_.find(child_scope);
  350. assert(dbg_scope_itr != id_to_dbg_inst_.end());
  351. OpenCLDebugInfo100Instructions debug_opcode =
  352. dbg_scope_itr->second->GetOpenCL100DebugOpcode();
  353. uint32_t parent_scope = kNoDebugScope;
  354. switch (debug_opcode) {
  355. case OpenCLDebugInfo100DebugFunction:
  356. parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
  357. kDebugFunctionOperandParentIndex);
  358. break;
  359. case OpenCLDebugInfo100DebugLexicalBlock:
  360. parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
  361. kDebugLexicalBlockOperandParentIndex);
  362. break;
  363. case OpenCLDebugInfo100DebugTypeComposite:
  364. parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
  365. kDebugTypeCompositeOperandParentIndex);
  366. break;
  367. case OpenCLDebugInfo100DebugCompilationUnit:
  368. // DebugCompilationUnit does not have a parent scope.
  369. break;
  370. default:
  371. assert(false &&
  372. "Unreachable. A debug scope instruction must be "
  373. "DebugFunction, DebugTypeComposite, DebugLexicalBlock, "
  374. "or DebugCompilationUnit.");
  375. break;
  376. }
  377. return parent_scope;
  378. }
  379. bool DebugInfoManager::IsAncestorOfScope(uint32_t scope, uint32_t ancestor) {
  380. uint32_t ancestor_scope_itr = scope;
  381. while (ancestor_scope_itr != kNoDebugScope) {
  382. if (ancestor == ancestor_scope_itr) return true;
  383. ancestor_scope_itr = GetParentScope(ancestor_scope_itr);
  384. }
  385. return false;
  386. }
  387. bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare,
  388. uint32_t instr_scope_id) {
  389. if (instr_scope_id == kNoDebugScope) return false;
  390. uint32_t dbg_local_var_id =
  391. dbg_declare->GetSingleWordOperand(kDebugDeclareOperandLocalVariableIndex);
  392. auto dbg_local_var_itr = id_to_dbg_inst_.find(dbg_local_var_id);
  393. assert(dbg_local_var_itr != id_to_dbg_inst_.end());
  394. uint32_t decl_scope_id = dbg_local_var_itr->second->GetSingleWordOperand(
  395. kDebugLocalVariableOperandParentIndex);
  396. // If the scope of DebugDeclare is an ancestor scope of the instruction's
  397. // scope, the local variable is visible to the instruction.
  398. return IsAncestorOfScope(instr_scope_id, decl_scope_id);
  399. }
  400. void DebugInfoManager::AddDebugValue(Instruction* scope_and_line,
  401. uint32_t variable_id, uint32_t value_id,
  402. Instruction* insert_pos) {
  403. auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  404. if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return;
  405. uint32_t instr_scope_id = scope_and_line->GetDebugScope().GetLexicalScope();
  406. for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
  407. if (!IsDeclareVisibleToInstr(dbg_decl_or_val, instr_scope_id)) continue;
  408. uint32_t result_id = context()->TakeNextId();
  409. std::unique_ptr<Instruction> new_dbg_value(new Instruction(
  410. context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
  411. result_id,
  412. {
  413. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  414. {context()
  415. ->get_feature_mgr()
  416. ->GetExtInstImportId_OpenCL100DebugInfo()}},
  417. {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
  418. {static_cast<uint32_t>(OpenCLDebugInfo100DebugValue)}},
  419. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  420. {dbg_decl_or_val->GetSingleWordOperand(
  421. kDebugValueOperandLocalVariableIndex)}},
  422. {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {value_id}},
  423. {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  424. {GetEmptyDebugExpression()->result_id()}},
  425. }));
  426. if (dbg_decl_or_val->NumOperands() >
  427. kDebugValueOperandExpressionIndex + 1) {
  428. assert(dbg_decl_or_val->GetOpenCL100DebugOpcode() ==
  429. OpenCLDebugInfo100DebugValue);
  430. for (uint32_t i = kDebugValueOperandExpressionIndex + 1;
  431. i < dbg_decl_or_val->NumOperands(); ++i) {
  432. new_dbg_value->AddOperand({spv_operand_type_t::SPV_OPERAND_TYPE_ID,
  433. {dbg_decl_or_val->GetSingleWordOperand(i)}});
  434. }
  435. }
  436. // Avoid inserting the new DebugValue between OpPhi or OpVariable
  437. // instructions.
  438. Instruction* insert_before = insert_pos->NextNode();
  439. while (insert_before->opcode() == SpvOpPhi ||
  440. insert_before->opcode() == SpvOpVariable) {
  441. insert_before = insert_before->NextNode();
  442. }
  443. Instruction* added_dbg_value =
  444. insert_before->InsertBefore(std::move(new_dbg_value));
  445. added_dbg_value->UpdateDebugInfo(scope_and_line);
  446. AnalyzeDebugInst(added_dbg_value);
  447. if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
  448. context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_value);
  449. if (context()->AreAnalysesValid(
  450. IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
  451. auto insert_blk = context()->get_instr_block(insert_before);
  452. context()->set_instr_block(added_dbg_value, insert_blk);
  453. }
  454. }
  455. }
  456. uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
  457. Instruction* inst) {
  458. if (inst->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugValue) return 0;
  459. auto* expr =
  460. GetDbgInst(inst->GetSingleWordOperand(kDebugValueOperandExpressionIndex));
  461. if (expr == nullptr) return 0;
  462. if (expr->NumOperands() != kDebugExpressOperandOperationIndex + 1) return 0;
  463. auto* operation = GetDbgInst(
  464. expr->GetSingleWordOperand(kDebugExpressOperandOperationIndex));
  465. if (operation == nullptr) return 0;
  466. if (operation->GetSingleWordOperand(kDebugOperationOperandOperationIndex) !=
  467. OpenCLDebugInfo100Deref) {
  468. return 0;
  469. }
  470. uint32_t var_id =
  471. inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
  472. if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse)) {
  473. assert(false &&
  474. "Checking a DebugValue can be used for declare needs DefUseManager");
  475. return 0;
  476. }
  477. auto* var = context()->get_def_use_mgr()->GetDef(var_id);
  478. if (var->opcode() == SpvOpVariable &&
  479. SpvStorageClass(var->GetSingleWordOperand(
  480. kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
  481. return var_id;
  482. }
  483. return 0;
  484. }
  485. void DebugInfoManager::AnalyzeDebugInst(Instruction* dbg_inst) {
  486. if (!dbg_inst->IsOpenCL100DebugInstr()) return;
  487. RegisterDbgInst(dbg_inst);
  488. if (dbg_inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
  489. assert(GetDebugFunction(dbg_inst->GetSingleWordOperand(
  490. kDebugFunctionOperandFunctionIndex)) == nullptr &&
  491. "Two DebugFunction instruction exists for a single OpFunction.");
  492. RegisterDbgFunction(dbg_inst);
  493. }
  494. if (deref_operation_ == nullptr &&
  495. dbg_inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugOperation &&
  496. dbg_inst->GetSingleWordOperand(kDebugOperationOperandOpCodeIndex) ==
  497. OpenCLDebugInfo100Deref) {
  498. deref_operation_ = dbg_inst;
  499. }
  500. if (debug_info_none_inst_ == nullptr &&
  501. dbg_inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) {
  502. debug_info_none_inst_ = dbg_inst;
  503. }
  504. if (empty_debug_expr_inst_ == nullptr && IsEmptyDebugExpression(dbg_inst)) {
  505. empty_debug_expr_inst_ = dbg_inst;
  506. }
  507. if (dbg_inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare) {
  508. uint32_t var_id =
  509. dbg_inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
  510. RegisterDbgDeclare(var_id, dbg_inst);
  511. }
  512. if (uint32_t var_id = GetVariableIdOfDebugValueUsedForDeclare(dbg_inst)) {
  513. RegisterDbgDeclare(var_id, dbg_inst);
  514. }
  515. }
  516. void DebugInfoManager::AnalyzeDebugInsts(Module& module) {
  517. deref_operation_ = nullptr;
  518. debug_info_none_inst_ = nullptr;
  519. empty_debug_expr_inst_ = nullptr;
  520. module.ForEachInst([this](Instruction* cpi) { AnalyzeDebugInst(cpi); });
  521. // Move |empty_debug_expr_inst_| to the beginning of the debug instruction
  522. // list.
  523. if (empty_debug_expr_inst_ != nullptr &&
  524. empty_debug_expr_inst_->PreviousNode() != nullptr &&
  525. empty_debug_expr_inst_->PreviousNode()->IsOpenCL100DebugInstr()) {
  526. empty_debug_expr_inst_->InsertBefore(
  527. &*context()->module()->ext_inst_debuginfo_begin());
  528. }
  529. // Move |debug_info_none_inst_| to the beginning of the debug instruction
  530. // list.
  531. if (debug_info_none_inst_ != nullptr &&
  532. debug_info_none_inst_->PreviousNode() != nullptr &&
  533. debug_info_none_inst_->PreviousNode()->IsOpenCL100DebugInstr()) {
  534. debug_info_none_inst_->InsertBefore(
  535. &*context()->module()->ext_inst_debuginfo_begin());
  536. }
  537. }
  538. void DebugInfoManager::ClearDebugInfo(Instruction* instr) {
  539. if (instr == nullptr || !instr->IsOpenCL100DebugInstr()) {
  540. return;
  541. }
  542. id_to_dbg_inst_.erase(instr->result_id());
  543. if (instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
  544. auto fn_id =
  545. instr->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
  546. fn_id_to_dbg_fn_.erase(fn_id);
  547. }
  548. if (instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare ||
  549. instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugValue) {
  550. auto var_or_value_id =
  551. instr->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
  552. auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_or_value_id);
  553. if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
  554. dbg_decl_itr->second.erase(instr);
  555. }
  556. }
  557. if (deref_operation_ == instr) {
  558. deref_operation_ = nullptr;
  559. for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
  560. dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
  561. ++dbg_instr_itr) {
  562. if (instr != &*dbg_instr_itr &&
  563. dbg_instr_itr->GetOpenCL100DebugOpcode() ==
  564. OpenCLDebugInfo100DebugOperation &&
  565. dbg_instr_itr->GetSingleWordOperand(
  566. kDebugOperationOperandOpCodeIndex) == OpenCLDebugInfo100Deref) {
  567. deref_operation_ = &*dbg_instr_itr;
  568. break;
  569. }
  570. }
  571. }
  572. if (debug_info_none_inst_ == instr) {
  573. debug_info_none_inst_ = nullptr;
  574. for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
  575. dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
  576. ++dbg_instr_itr) {
  577. if (instr != &*dbg_instr_itr &&
  578. dbg_instr_itr->GetOpenCL100DebugOpcode() ==
  579. OpenCLDebugInfo100DebugInfoNone) {
  580. debug_info_none_inst_ = &*dbg_instr_itr;
  581. break;
  582. }
  583. }
  584. }
  585. if (empty_debug_expr_inst_ == instr) {
  586. empty_debug_expr_inst_ = nullptr;
  587. for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
  588. dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
  589. ++dbg_instr_itr) {
  590. if (instr != &*dbg_instr_itr && IsEmptyDebugExpression(&*dbg_instr_itr)) {
  591. empty_debug_expr_inst_ = &*dbg_instr_itr;
  592. break;
  593. }
  594. }
  595. }
  596. }
  597. } // namespace analysis
  598. } // namespace opt
  599. } // namespace spvtools