DxilAnnotateWithVirtualRegister.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilAnnotateWithVirtualRegister.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. // Annotates the llvm instructions with a virtual register number to be used //
  9. // during PIX debugging. //
  10. // //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "dxc/DxilPIXPasses/DxilPIXPasses.h"
  13. #include <memory>
  14. #include "dxc/DXIL/DxilModule.h"
  15. #include "dxc/Support/Global.h"
  16. #include "llvm/ADT/DenseMap.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/IR/Constant.h"
  19. #include "llvm/IR/Constants.h"
  20. #include "llvm/IR/InstIterator.h"
  21. #include "llvm/IR/Instruction.h"
  22. #include "llvm/IR/Instructions.h"
  23. #include "llvm/IR/IRBuilder.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/IR/Type.h"
  26. #include "llvm/Pass.h"
  27. #include "llvm/Support/Casting.h"
  28. #include "llvm/Support/raw_ostream.h"
  29. #include "DxilPIXVirtualRegisters.h"
  30. #define DEBUG_TYPE "dxil-annotate-with-virtual-regs"
  31. namespace {
  32. using namespace pix_dxil;
  33. class DxilAnnotateWithVirtualRegister : public llvm::ModulePass {
  34. public:
  35. static char ID;
  36. DxilAnnotateWithVirtualRegister() : llvm::ModulePass(ID) {}
  37. bool runOnModule(llvm::Module &M) override;
  38. private:
  39. void AnnotateValues(llvm::Instruction *pI);
  40. void AnnotateStore(llvm::Instruction *pI);
  41. bool IsAllocaRegisterWrite(llvm::Value *V, llvm::AllocaInst **pAI, llvm::Value **pIdx);
  42. void AnnotateAlloca(llvm::AllocaInst *pAlloca);
  43. void AnnotateGeneric(llvm::Instruction *pI);
  44. void AssignNewDxilRegister(llvm::Instruction *pI);
  45. void AssignNewAllocaRegister(llvm::AllocaInst *pAlloca, std::uint32_t C);
  46. hlsl::DxilModule *m_DM;
  47. std::uint32_t m_uVReg;
  48. void Init(llvm::Module &M) {
  49. m_DM = &M.GetOrCreateDxilModule();
  50. m_uVReg = 0;
  51. }
  52. };
  53. char DxilAnnotateWithVirtualRegister::ID = 0;
  54. bool DxilAnnotateWithVirtualRegister::runOnModule(llvm::Module &M) {
  55. Init(M);
  56. if (m_DM == nullptr) {
  57. return false;
  58. }
  59. if (OSOverride != nullptr) {
  60. *OSOverride << "\nBegin - dxil values to virtual register mapping\n";
  61. }
  62. std::uint32_t InstNum = 0;
  63. for (llvm::Instruction &I : llvm::inst_range(m_DM->GetEntryFunction())) {
  64. pix_dxil::PixDxilInstNum::AddMD(M.getContext(), &I, ++InstNum);
  65. }
  66. for (llvm::Instruction &I : llvm::inst_range(m_DM->GetEntryFunction())) {
  67. AnnotateValues(&I);
  68. }
  69. for (llvm::Instruction &I : llvm::inst_range(m_DM->GetEntryFunction())) {
  70. AnnotateStore(&I);
  71. }
  72. if (OSOverride != nullptr) {
  73. *OSOverride << "\nEnd - dxil values to virtual register mapping\n";
  74. }
  75. m_DM = nullptr;
  76. return m_uVReg > 0;
  77. }
  78. void DxilAnnotateWithVirtualRegister::AnnotateValues(llvm::Instruction *pI) {
  79. if (auto *pAlloca = llvm::dyn_cast<llvm::AllocaInst>(pI)) {
  80. AnnotateAlloca(pAlloca);
  81. } else if (!pI->getType()->isVoidTy()) {
  82. AnnotateGeneric(pI);
  83. }
  84. }
  85. void DxilAnnotateWithVirtualRegister::AnnotateStore(llvm::Instruction *pI) {
  86. auto *pSt = llvm::dyn_cast<llvm::StoreInst>(pI);
  87. if (pSt == nullptr) {
  88. return;
  89. }
  90. llvm::AllocaInst *Alloca;
  91. llvm::Value *Index;
  92. if (!IsAllocaRegisterWrite(pSt->getPointerOperand(), &Alloca, &Index)) {
  93. return;
  94. }
  95. llvm::MDNode *AllocaReg = Alloca->getMetadata(PixAllocaReg::MDName);
  96. if (AllocaReg == nullptr) {
  97. return;
  98. }
  99. PixAllocaRegWrite::AddMD(m_DM->GetCtx(), pSt, AllocaReg, Index);
  100. }
  101. bool DxilAnnotateWithVirtualRegister::IsAllocaRegisterWrite(llvm::Value *V, llvm::AllocaInst **pAI, llvm::Value **pIdx) {
  102. llvm::IRBuilder<> B(m_DM->GetCtx());
  103. *pAI = nullptr;
  104. *pIdx = nullptr;
  105. if (auto *pGEP = llvm::dyn_cast<llvm::GetElementPtrInst>(V)) {
  106. auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(pGEP->getPointerOperand());
  107. if (Alloca == nullptr) {
  108. return false;
  109. }
  110. llvm::SmallVector<llvm::Value *, 2> Indices(pGEP->idx_begin(), pGEP->idx_end());
  111. if (Indices.size() != 2) {
  112. return false;
  113. }
  114. auto *pIdx0 = llvm::dyn_cast<llvm::ConstantInt>(Indices[0]);
  115. if (pIdx0 == nullptr || pIdx0->getLimitedValue() != 0) {
  116. return false;
  117. }
  118. *pAI = Alloca;
  119. *pIdx = Indices[1];
  120. return true;
  121. }
  122. if (auto *pAlloca = llvm::dyn_cast<llvm::AllocaInst>(V)) {
  123. llvm::Type *pAllocaTy = pAlloca->getType()->getElementType();
  124. if (!pAllocaTy->isFloatTy() && !pAllocaTy->isIntegerTy()) {
  125. return false;
  126. }
  127. *pAI = pAlloca;
  128. *pIdx = B.getInt32(0);
  129. return true;
  130. }
  131. return false;
  132. }
  133. void DxilAnnotateWithVirtualRegister::AnnotateAlloca(llvm::AllocaInst *pAlloca) {
  134. llvm::Type *pAllocaTy = pAlloca->getType()->getElementType();
  135. if (pAllocaTy->isFloatTy() || pAllocaTy->isIntegerTy()) {
  136. AssignNewAllocaRegister(pAlloca, 1);
  137. } else if (auto *AT = llvm::dyn_cast<llvm::ArrayType>(pAllocaTy)) {
  138. AssignNewAllocaRegister(pAlloca, AT->getNumElements());
  139. } else {
  140. DXASSERT_ARGS(false, "Unhandled alloca kind: %d", pAllocaTy->getTypeID());
  141. }
  142. }
  143. void DxilAnnotateWithVirtualRegister::AnnotateGeneric(llvm::Instruction *pI) {
  144. if (!pI->getType()->isFloatTy() && !pI->getType()->isIntegerTy()) {
  145. return;
  146. }
  147. AssignNewDxilRegister(pI);
  148. }
  149. void DxilAnnotateWithVirtualRegister::AssignNewDxilRegister(llvm::Instruction *pI) {
  150. PixDxilReg::AddMD(m_DM->GetCtx(), pI, m_uVReg);
  151. if (OSOverride != nullptr) {
  152. static constexpr bool DontPrintType = false;
  153. pI->printAsOperand(*OSOverride, DontPrintType, m_DM->GetModule());
  154. *OSOverride << " dxil " << m_uVReg << "\n";
  155. }
  156. m_uVReg++;
  157. }
  158. void DxilAnnotateWithVirtualRegister::AssignNewAllocaRegister(llvm::AllocaInst *pAlloca, std::uint32_t C) {
  159. PixAllocaReg::AddMD(m_DM->GetCtx(), pAlloca, m_uVReg, C);
  160. if (OSOverride != nullptr) {
  161. static constexpr bool DontPrintType = false;
  162. pAlloca->printAsOperand(*OSOverride, DontPrintType, m_DM->GetModule());
  163. *OSOverride << " alloca " << m_uVReg << " " << C << "\n";
  164. }
  165. m_uVReg += C;
  166. }
  167. }
  168. using namespace llvm;
  169. INITIALIZE_PASS(DxilAnnotateWithVirtualRegister, DEBUG_TYPE, "Annotates each instruction in the DXIL module with a virtual register number", false, false)
  170. ModulePass *llvm::createDxilAnnotateWithVirtualRegisterPass() {
  171. return new DxilAnnotateWithVirtualRegister();
  172. }