DxcPixDxilDebugInfo.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxcPixDxilDebugInfo.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Defines the main class for dxcompiler's API for PIX support. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/Support/WinIncludes.h"
  12. #include "dxc/Support/exception.h"
  13. #include "llvm/IR/Instructions.h"
  14. #include "llvm/IR/DebugInfo.h"
  15. #include "llvm/IR/DebugInfoMetadata.h"
  16. #include "DxcPixLiveVariables.h"
  17. #include "DxcPixDxilDebugInfo.h"
  18. #include "DxcPixBase.h"
  19. #include "dxc/DxilPixPasses/DxilPixVirtualRegisters.h"
  20. STDMETHODIMP dxil_debug_info::DxcPixDxilDebugInfo::GetLiveVariablesAt(
  21. _In_ DWORD InstructionOffset,
  22. _COM_Outptr_ IDxcPixDxilLiveVariables **ppLiveVariables)
  23. {
  24. return m_LiveVars->GetLiveVariablesAtInstruction(
  25. FindInstruction(InstructionOffset),
  26. ppLiveVariables);
  27. }
  28. STDMETHODIMP dxil_debug_info::DxcPixDxilDebugInfo::IsVariableInRegister(
  29. _In_ DWORD InstructionOffset,
  30. _In_ const wchar_t *VariableName)
  31. {
  32. return S_OK;
  33. }
  34. STDMETHODIMP dxil_debug_info::DxcPixDxilDebugInfo::GetFunctionName(
  35. _In_ DWORD InstructionOffset,
  36. _Outptr_result_z_ BSTR *ppFunctionName)
  37. {
  38. llvm::Instruction *IP = FindInstruction(InstructionOffset);
  39. const llvm::DITypeIdentifierMap EmptyMap;
  40. if (const llvm::DebugLoc &DL = IP->getDebugLoc())
  41. {
  42. auto *S = llvm::dyn_cast<llvm::DIScope>(DL.getScope());
  43. while(S != nullptr && !llvm::isa<llvm::DICompileUnit>(S))
  44. {
  45. if (auto *SS = llvm::dyn_cast<llvm::DISubprogram>(S))
  46. {
  47. *ppFunctionName = CComBSTR(CA2W(SS->getName().data())).Detach();
  48. return S_OK;
  49. }
  50. S = S->getScope().resolve(EmptyMap);
  51. }
  52. }
  53. *ppFunctionName = CComBSTR(L"<???>").Detach();
  54. return S_FALSE;
  55. }
  56. STDMETHODIMP dxil_debug_info::DxcPixDxilDebugInfo::GetStackDepth(
  57. _In_ DWORD InstructionOffset,
  58. _Outptr_ DWORD *StackDepth
  59. )
  60. {
  61. llvm::Instruction *IP = FindInstruction(InstructionOffset);
  62. DWORD Depth = 0;
  63. llvm::DebugLoc DL = IP->getDebugLoc();
  64. while (DL && DL.getInlinedAtScope() != nullptr)
  65. {
  66. DL = DL.getInlinedAt();
  67. ++Depth;
  68. }
  69. *StackDepth = Depth;
  70. return S_OK;
  71. }
  72. #include "DxilDiaSession.h"
  73. dxil_debug_info::DxcPixDxilDebugInfo::DxcPixDxilDebugInfo(
  74. IMalloc *pMalloc,
  75. dxil_dia::Session *pSession)
  76. : m_pMalloc(pMalloc)
  77. , m_pSession(pSession)
  78. , m_LiveVars(new LiveVariables())
  79. {
  80. m_LiveVars->Init(this);
  81. }
  82. dxil_debug_info::DxcPixDxilDebugInfo::~DxcPixDxilDebugInfo() = default;
  83. llvm::Module* dxil_debug_info::DxcPixDxilDebugInfo::GetModuleRef()
  84. {
  85. return &m_pSession->ModuleRef();
  86. }
  87. llvm::Instruction* dxil_debug_info::DxcPixDxilDebugInfo::FindInstruction(
  88. DWORD InstructionOffset
  89. ) const
  90. {
  91. const auto Instructions = m_pSession->InstructionsRef();
  92. auto it = Instructions.find(InstructionOffset);
  93. if (it == Instructions.end())
  94. {
  95. throw hlsl::Exception(E_BOUNDS, "Out-of-bounds: Instruction offset");
  96. }
  97. return const_cast<llvm::Instruction *>(it->second);
  98. }
  99. STDMETHODIMP
  100. dxil_debug_info::DxcPixDxilDebugInfo::InstructionOffsetsFromSourceLocation(
  101. _In_ const wchar_t *FileName, _In_ DWORD SourceLine,
  102. _In_ DWORD SourceColumn,
  103. _COM_Outptr_ IDxcPixDxilInstructionOffsets **ppOffsets)
  104. {
  105. return dxil_debug_info::NewDxcPixDxilDebugInfoObjectOrThrow<
  106. dxil_debug_info::DxcPixDxilInstructionOffsets>(
  107. ppOffsets, m_pMalloc, m_pSession, FileName, SourceLine, SourceColumn);
  108. }
  109. static bool CompareFilenames(const wchar_t * l, const char * r)
  110. {
  111. while (*l && *r) {
  112. bool theSame = false;
  113. if (*l == L'/' && *r == '\\') {
  114. theSame = true;
  115. }
  116. if (*l == L'\\' && *r == '/') {
  117. theSame = true;
  118. }
  119. if (!theSame) {
  120. if (::tolower(*l) != ::tolower(*r)) {
  121. return false;
  122. }
  123. }
  124. l++;
  125. r++;
  126. }
  127. if (*l || *r) {
  128. return false;
  129. }
  130. return true;
  131. }
  132. dxil_debug_info::DxcPixDxilInstructionOffsets::DxcPixDxilInstructionOffsets(
  133. IMalloc *pMalloc,
  134. dxil_dia::Session *pSession,
  135. const wchar_t *FileName,
  136. DWORD SourceLine,
  137. DWORD SourceColumn)
  138. {
  139. assert(SourceColumn == 0);
  140. (void)SourceColumn;
  141. auto files = pSession->Contents()->operands();
  142. for (const auto& file : files)
  143. {
  144. auto candidateFilename = llvm::dyn_cast<llvm::MDString>(file->getOperand(0))
  145. ->getString();
  146. if (CompareFilenames(FileName, candidateFilename.str().c_str()))
  147. {
  148. auto Fn = pSession->DxilModuleRef().GetEntryFunction();
  149. auto &Blocks = Fn->getBasicBlockList();
  150. for (auto& CurrentBlock : Blocks) {
  151. auto& Is = CurrentBlock.getInstList();
  152. for (auto& Inst : Is) {
  153. auto & debugLoc = Inst.getDebugLoc();
  154. if (debugLoc)
  155. {
  156. unsigned line = debugLoc.getLine();
  157. if (line == SourceLine)
  158. {
  159. std::uint32_t InstructionNumber;
  160. if (pix_dxil::PixDxilInstNum::FromInst(&Inst, &InstructionNumber))
  161. {
  162. m_offsets.push_back(InstructionNumber);
  163. }
  164. }
  165. }
  166. }
  167. }
  168. }
  169. }
  170. }
  171. DWORD dxil_debug_info::DxcPixDxilInstructionOffsets::GetCount()
  172. {
  173. return static_cast<DWORD>(m_offsets.size());
  174. }
  175. DWORD dxil_debug_info::DxcPixDxilInstructionOffsets::GetOffsetByIndex(DWORD Index)
  176. {
  177. if (Index < static_cast<DWORD>(m_offsets.size()))
  178. {
  179. return m_offsets[Index];
  180. }
  181. return static_cast<DWORD>(-1);
  182. }