SortDebugInfoVisitor.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //===--- SortDebugInfoVisitor.cpp - Valid order debug instrs -----*- C++ -*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "SortDebugInfoVisitor.h"
  10. namespace clang {
  11. namespace spirv {
  12. void SortDebugInfoVisitor::whileEachOperandOfDebugInstruction(
  13. SpirvDebugInstruction *di,
  14. llvm::function_ref<bool(SpirvDebugInstruction *)> visitor) {
  15. if (di == nullptr)
  16. return;
  17. if (di->getDebugType() != nullptr) {
  18. if (!visitor(di->getDebugType()))
  19. return;
  20. }
  21. if (di->getParentScope() != nullptr) {
  22. if (!visitor(di->getParentScope()))
  23. return;
  24. }
  25. switch (di->getKind()) {
  26. case SpirvInstruction::IK_DebugCompilationUnit: {
  27. SpirvDebugCompilationUnit *inst = dyn_cast<SpirvDebugCompilationUnit>(di);
  28. assert(inst != nullptr);
  29. if (!visitor(inst->getDebugSource()))
  30. break;
  31. } break;
  32. case SpirvInstruction::IK_DebugFunctionDecl: {
  33. SpirvDebugFunctionDeclaration *inst =
  34. dyn_cast<SpirvDebugFunctionDeclaration>(di);
  35. assert(inst != nullptr);
  36. if (!visitor(inst->getSource()))
  37. break;
  38. } break;
  39. case SpirvInstruction::IK_DebugFunction: {
  40. SpirvDebugFunction *inst = dyn_cast<SpirvDebugFunction>(di);
  41. assert(inst != nullptr);
  42. if (!visitor(inst->getSource()))
  43. break;
  44. if (!visitor(inst->getDebugInfoNone()))
  45. break;
  46. } break;
  47. case SpirvInstruction::IK_DebugLocalVariable: {
  48. SpirvDebugLocalVariable *inst = dyn_cast<SpirvDebugLocalVariable>(di);
  49. assert(inst != nullptr);
  50. if (!visitor(inst->getSource()))
  51. break;
  52. } break;
  53. case SpirvInstruction::IK_DebugGlobalVariable: {
  54. SpirvDebugGlobalVariable *inst = dyn_cast<SpirvDebugGlobalVariable>(di);
  55. assert(inst != nullptr);
  56. if (!visitor(inst->getSource()))
  57. break;
  58. } break;
  59. case SpirvInstruction::IK_DebugExpression: {
  60. SpirvDebugExpression *inst = dyn_cast<SpirvDebugExpression>(di);
  61. assert(inst != nullptr);
  62. for (auto *op : inst->getOperations())
  63. if (!visitor(op))
  64. break;
  65. } break;
  66. case SpirvInstruction::IK_DebugLexicalBlock: {
  67. SpirvDebugLexicalBlock *inst = dyn_cast<SpirvDebugLexicalBlock>(di);
  68. assert(inst != nullptr);
  69. if (!visitor(inst->getSource()))
  70. break;
  71. } break;
  72. case SpirvInstruction::IK_DebugTypeArray: {
  73. SpirvDebugTypeArray *inst = dyn_cast<SpirvDebugTypeArray>(di);
  74. assert(inst != nullptr);
  75. if (!visitor(inst->getElementType()))
  76. break;
  77. } break;
  78. case SpirvInstruction::IK_DebugTypeVector: {
  79. SpirvDebugTypeVector *inst = dyn_cast<SpirvDebugTypeVector>(di);
  80. assert(inst != nullptr);
  81. if (!visitor(inst->getElementType()))
  82. break;
  83. } break;
  84. case SpirvInstruction::IK_DebugTypeFunction: {
  85. SpirvDebugTypeFunction *inst = dyn_cast<SpirvDebugTypeFunction>(di);
  86. assert(inst != nullptr);
  87. if (!visitor(inst->getReturnType()))
  88. break;
  89. for (auto *param : inst->getParamTypes())
  90. if (!visitor(param))
  91. break;
  92. } break;
  93. case SpirvInstruction::IK_DebugTypeComposite: {
  94. SpirvDebugTypeComposite *inst = dyn_cast<SpirvDebugTypeComposite>(di);
  95. assert(inst != nullptr);
  96. // Note that DebugTypeComposite always has forward references to
  97. // members. Therefore, the edge direction in DAG must be from
  98. // DebugTypeMember to DebugTypeComposite. DO NOT visit members here.
  99. // In terms of DebugTypeTemplate used for a HLSL resource, it has
  100. // to reference DebugTypeComposite but DebugTypeComposite does not
  101. // reference DebugTypeTemplate. DO NOT visit DebugTypeTemplate here.
  102. if (!visitor(inst->getSource()))
  103. break;
  104. if (!visitor(inst->getDebugInfoNone()))
  105. break;
  106. } break;
  107. case SpirvInstruction::IK_DebugTypeMember: {
  108. SpirvDebugTypeMember *inst = dyn_cast<SpirvDebugTypeMember>(di);
  109. assert(inst != nullptr);
  110. if (!visitor(inst->getDebugType()))
  111. break;
  112. if (!visitor(inst->getSource()))
  113. break;
  114. } break;
  115. case SpirvInstruction::IK_DebugTypeTemplate: {
  116. SpirvDebugTypeTemplate *inst = dyn_cast<SpirvDebugTypeTemplate>(di);
  117. assert(inst != nullptr);
  118. if (!visitor(inst->getTarget()))
  119. break;
  120. for (auto *param : inst->getParams())
  121. if (!visitor(param))
  122. break;
  123. } break;
  124. case SpirvInstruction::IK_DebugTypeTemplateParameter: {
  125. SpirvDebugTypeTemplateParameter *inst =
  126. dyn_cast<SpirvDebugTypeTemplateParameter>(di);
  127. assert(inst != nullptr);
  128. if (!visitor(inst->getActualType()))
  129. break;
  130. // Value operand of DebugTypeTemplateParameter must be DebugInfoNone
  131. // when it is used for a type not used for a integer value.
  132. if (auto *value = dyn_cast<SpirvDebugInstruction>(inst->getValue())) {
  133. if (!visitor(value))
  134. break;
  135. }
  136. if (!visitor(inst->getSource()))
  137. break;
  138. } break;
  139. case SpirvInstruction::IK_DebugInfoNone:
  140. case SpirvInstruction::IK_DebugSource:
  141. case SpirvInstruction::IK_DebugOperation:
  142. case SpirvInstruction::IK_DebugTypeBasic:
  143. break;
  144. default:
  145. // DebugDeclare and DebugScope must be placed within a function.
  146. assert(false && "unsupported debug instruction");
  147. break;
  148. }
  149. }
  150. bool SortDebugInfoVisitor::visit(SpirvModule *mod, Phase phase) {
  151. if (phase == Phase::Done)
  152. return true;
  153. auto &debugInstructions = mod->getDebugInfo();
  154. // Keep the number of unique debug instructions to verify that it is not
  155. // changed at the end of this visitor.
  156. llvm::SmallSet<SpirvDebugInstruction *, 32> uniqueDebugInstructions;
  157. uniqueDebugInstructions.insert(debugInstructions.begin(),
  158. debugInstructions.end());
  159. auto numberOfDebugInstrs = uniqueDebugInstructions.size();
  160. (void)numberOfDebugInstrs;
  161. // Collect nodes without predecessor.
  162. llvm::SmallSet<SpirvDebugInstruction *, 32> visited;
  163. for (auto *di : debugInstructions) {
  164. whileEachOperandOfDebugInstruction(
  165. di, [&visited](SpirvDebugInstruction *operand) {
  166. if (operand != nullptr)
  167. visited.insert(operand);
  168. return true;
  169. });
  170. }
  171. llvm::SmallVector<SpirvDebugInstruction *, 32> stack;
  172. for (auto *di : debugInstructions) {
  173. if (visited.count(di) == 0)
  174. stack.push_back(di);
  175. }
  176. // Sort debug instructions in a post order. We puts successors in the first
  177. // places of `debugInstructions`. For example, `DebugInfoNone` does not have
  178. // any operand, which means it does not have any successors. We have to place
  179. // it earlier than the instructions using it.
  180. debugInstructions.clear();
  181. visited.clear();
  182. while (!stack.empty()) {
  183. auto *di = stack.back();
  184. visited.insert(di);
  185. whileEachOperandOfDebugInstruction(
  186. di, [&visited, &stack](SpirvDebugInstruction *operand) {
  187. if (operand != nullptr && visited.count(operand) == 0) {
  188. stack.push_back(operand);
  189. return false;
  190. }
  191. return true;
  192. });
  193. if (stack.back() == di) {
  194. debugInstructions.push_back(di);
  195. stack.pop_back();
  196. }
  197. }
  198. // The sort result must have the same number of debug instructions.
  199. assert(numberOfDebugInstrs == debugInstructions.size());
  200. return true;
  201. }
  202. } // end namespace spirv
  203. } // end namespace clang