DxilDbgValueToDbgDeclare.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilDbgValueToDbgDeclare.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. // Converts calls to llvm.dbg.value to llvm.dbg.declare + alloca + stores. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include <algorithm>
  12. #include <memory>
  13. #include <map>
  14. #include <unordered_map>
  15. #include <utility>
  16. #include "dxc/DXIL/DxilModule.h"
  17. #include "dxc/DxilPIXPasses/DxilPIXPasses.h"
  18. #include "llvm/IR/DebugInfo.h"
  19. #include "llvm/IR/DebugInfoMetadata.h"
  20. #include "llvm/IR/Instructions.h"
  21. #include "llvm/IR/IntrinsicInst.h"
  22. #include "llvm/IR/Intrinsics.h"
  23. #include "llvm/IR/IRBuilder.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/Pass.h"
  26. #define DEBUG_TYPE "dxil-dbg-value-to-dbg-declare"
  27. namespace {
  28. using OffsetInBits = unsigned;
  29. using SizeInBits = unsigned;
  30. // OffsetManager is used to map between "packed" and aligned offsets.
  31. //
  32. // For example, the aligned offsets for a struct [float, half, int, double]
  33. // will be {0, 32, 64, 128} (assuming 32 bit alignments for ints, and 64
  34. // bit for doubles), while the packed offsets will be {0, 32, 48, 80}.
  35. //
  36. // This mapping makes it easier to deal with llvm.dbg.values whose value
  37. // operand does not match exactly the Variable operand's type.
  38. class OffsetManager
  39. {
  40. public:
  41. OffsetManager() = default;
  42. // AlignTo aligns the current aligned offset to Ty's natural alignment.
  43. void AlignTo(
  44. llvm::DIType *Ty
  45. )
  46. {
  47. // This is some magic arithmetic. Here's an example:
  48. //
  49. // Assume the natural alignment for Ty is 16 bits. Then
  50. //
  51. // AlignMask = 0x0000000f(15)
  52. //
  53. // If the current aligned offset is
  54. //
  55. // CurrentAlignedOffset = 0x00000048(72)
  56. //
  57. // Then
  58. //
  59. // T = CurrentAlignOffset + AlignMask = 0x00000057(87)
  60. //
  61. // Which mean
  62. //
  63. // T & ~CurrentOffset = 0x00000050(80)
  64. //
  65. // is the aligned offset where Ty should be placed.
  66. const unsigned AlignMask = Ty->getAlignInBits() - 1;
  67. m_CurrentAlignedOffset =
  68. (m_CurrentAlignedOffset + AlignMask) & ~AlignMask;
  69. }
  70. // Add is used to "add" an aggregate element (struct field, array element)
  71. // at the current aligned/packed offsets, bumping them by Ty's size.
  72. OffsetInBits Add(
  73. llvm::DIBasicType *Ty
  74. )
  75. {
  76. m_PackedOffsetToAlignedOffset[m_CurrentPackedOffset] = m_CurrentAlignedOffset;
  77. m_AlignedOffsetToPackedOffset[m_CurrentAlignedOffset] = m_CurrentPackedOffset;
  78. const OffsetInBits Ret = m_CurrentAlignedOffset;
  79. m_CurrentPackedOffset += Ty->getSizeInBits();
  80. m_CurrentAlignedOffset += Ty->getSizeInBits();
  81. return Ret;
  82. }
  83. // AlignToAndAddUnhandledType is used for error handling when Ty
  84. // could not be handled by the transformation. This is a best-effort
  85. // way to continue the pass by ignoring the current type and hoping
  86. // that adding Ty as a blob other fields/elements added will land
  87. // in the proper offset.
  88. void AlignToAndAddUnhandledType(
  89. llvm::DIType *Ty
  90. )
  91. {
  92. AlignTo(Ty);
  93. m_CurrentPackedOffset += Ty->getSizeInBits();
  94. m_CurrentAlignedOffset += Ty->getSizeInBits();
  95. }
  96. bool GetAlignedOffsetFromPackedOffset(
  97. OffsetInBits PackedOffset,
  98. OffsetInBits *AlignedOffset
  99. ) const
  100. {
  101. return GetOffsetWithMap(
  102. m_PackedOffsetToAlignedOffset,
  103. PackedOffset,
  104. AlignedOffset);
  105. }
  106. OffsetInBits GetPackedOffsetFromAlignedOffset(
  107. OffsetInBits AlignedOffset,
  108. OffsetInBits *PackedOffset
  109. ) const
  110. {
  111. return GetOffsetWithMap(
  112. m_PackedOffsetToAlignedOffset,
  113. AlignedOffset,
  114. PackedOffset);
  115. }
  116. OffsetInBits GetCurrentPackedOffset() const
  117. {
  118. return m_CurrentPackedOffset;
  119. }
  120. OffsetInBits GetCurrentAlignedOffset() const
  121. {
  122. return m_CurrentAlignedOffset;
  123. }
  124. private:
  125. OffsetInBits m_CurrentPackedOffset = 0;
  126. OffsetInBits m_CurrentAlignedOffset = 0;
  127. using OffsetMap = std::unordered_map<OffsetInBits, OffsetInBits>;
  128. OffsetMap m_PackedOffsetToAlignedOffset;
  129. OffsetMap m_AlignedOffsetToPackedOffset;
  130. static bool GetOffsetWithMap(
  131. const OffsetMap &Map,
  132. OffsetInBits SrcOffset,
  133. OffsetInBits *DstOffset
  134. )
  135. {
  136. auto it = Map.find(SrcOffset);
  137. if (it == Map.end())
  138. {
  139. return false;
  140. }
  141. *DstOffset = it->second;
  142. return true;
  143. }
  144. };
  145. // VariableRegisters contains the logic for traversing a DIType T and
  146. // creating AllocaInsts that map back to a specific offset within T.
  147. class VariableRegisters
  148. {
  149. public:
  150. VariableRegisters(
  151. llvm::DIVariable *Variable,
  152. llvm::Module *M
  153. );
  154. llvm::AllocaInst *GetRegisterForAlignedOffset(
  155. OffsetInBits AlignedOffset
  156. ) const;
  157. const OffsetManager& GetOffsetManager() const
  158. {
  159. return m_Offsets;
  160. }
  161. private:
  162. void PopulateAllocaMap(
  163. llvm::DIType *Ty
  164. );
  165. void PopulateAllocaMap_BasicType(
  166. llvm::DIBasicType *Ty
  167. );
  168. void PopulateAllocaMap_ArrayType(
  169. llvm::DICompositeType *Ty
  170. );
  171. void PopulateAllocaMap_StructType(
  172. llvm::DICompositeType* Ty
  173. );
  174. llvm::DILocation *GetVariableLocation() const;
  175. llvm::Value *GetMetadataAsValue(
  176. llvm::Metadata *M
  177. ) const;
  178. llvm::DIExpression *GetDIExpression(
  179. llvm::DIType *Ty,
  180. OffsetInBits Offset
  181. ) const;
  182. llvm::DIVariable* m_Variable = nullptr;
  183. llvm::IRBuilder<> m_B;
  184. llvm::Function *m_DbgDeclareFn = nullptr;
  185. OffsetManager m_Offsets;
  186. std::unordered_map<OffsetInBits, llvm::AllocaInst *> m_AlignedOffsetToAlloca;
  187. };
  188. class DxilDbgValueToDbgDeclare : public llvm::ModulePass {
  189. public:
  190. static char ID;
  191. DxilDbgValueToDbgDeclare() : llvm::ModulePass(ID) {}
  192. bool runOnModule(
  193. llvm::Module &M
  194. ) override;
  195. private:
  196. void handleDbgValue(
  197. llvm::Module &M,
  198. llvm::DbgValueInst *DbgValue);
  199. std::unordered_map<llvm::DIVariable *, std::unique_ptr<VariableRegisters>> m_Registers;
  200. };
  201. } // namespace
  202. char DxilDbgValueToDbgDeclare::ID = 0;
  203. struct ValueAndOffset
  204. {
  205. llvm::Value *m_V;
  206. OffsetInBits m_PackedOffset;
  207. };
  208. // SplitValue splits an llvm::Value into possibly multiple
  209. // scalar Values. Those scalar values will later be "stored"
  210. // into their corresponding register.
  211. static OffsetInBits SplitValue(
  212. llvm::Value *V,
  213. OffsetInBits CurrentOffset,
  214. std::vector<ValueAndOffset> *Values,
  215. llvm::IRBuilder<>& B
  216. )
  217. {
  218. auto *VTy = V->getType();
  219. if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(VTy))
  220. {
  221. for (unsigned i = 0; i < ArrTy->getNumElements(); ++i)
  222. {
  223. CurrentOffset = SplitValue(
  224. B.CreateExtractValue(V, {i}),
  225. CurrentOffset,
  226. Values,
  227. B);
  228. }
  229. }
  230. else if (auto *StTy = llvm::dyn_cast<llvm::StructType>(VTy))
  231. {
  232. for (unsigned i = 0; i < StTy->getNumElements(); ++i)
  233. {
  234. CurrentOffset = SplitValue(
  235. B.CreateExtractValue(V, {i}),
  236. CurrentOffset,
  237. Values,
  238. B);
  239. }
  240. }
  241. else if (auto *VecTy = llvm::dyn_cast<llvm::VectorType>(VTy))
  242. {
  243. for (unsigned i = 0; i < VecTy->getNumElements(); ++i)
  244. {
  245. CurrentOffset = SplitValue(
  246. B.CreateExtractElement(V, i),
  247. CurrentOffset,
  248. Values,
  249. B);
  250. }
  251. }
  252. else
  253. {
  254. assert(VTy->isFloatTy() || VTy->isDoubleTy() || VTy->isHalfTy() ||
  255. VTy->isIntegerTy(32) || VTy->isIntegerTy(64) || VTy->isIntegerTy(16));
  256. Values->emplace_back(ValueAndOffset{V, CurrentOffset});
  257. CurrentOffset += VTy->getScalarSizeInBits();
  258. }
  259. return CurrentOffset;
  260. }
  261. // A more convenient version of SplitValue.
  262. static std::vector<ValueAndOffset> SplitValue(
  263. llvm::Value* V,
  264. OffsetInBits CurrentOffset,
  265. llvm::IRBuilder<>& B
  266. )
  267. {
  268. std::vector<ValueAndOffset> Ret;
  269. SplitValue(V, CurrentOffset, &Ret, B);
  270. return Ret;
  271. }
  272. // Convenient helper for parsing a DIExpression's offset.
  273. static OffsetInBits GetAlignedOffsetFromDIExpression(
  274. llvm::DIExpression *Exp
  275. )
  276. {
  277. if (!Exp->isBitPiece())
  278. {
  279. return 0;
  280. }
  281. return Exp->getBitPieceOffset();
  282. }
  283. bool DxilDbgValueToDbgDeclare::runOnModule(
  284. llvm::Module &M
  285. )
  286. {
  287. auto *DbgValueFn =
  288. llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::dbg_value);
  289. bool Changed = false;
  290. for (auto it = DbgValueFn->user_begin(); it != DbgValueFn->user_end(); )
  291. {
  292. llvm::User *User = *it++;
  293. if (auto *DbgValue = llvm::dyn_cast<llvm::DbgValueInst>(User))
  294. {
  295. Changed = true;
  296. handleDbgValue(M, DbgValue);
  297. DbgValue->eraseFromParent();
  298. }
  299. }
  300. return Changed;
  301. }
  302. void DxilDbgValueToDbgDeclare::handleDbgValue(
  303. llvm::Module& M,
  304. llvm::DbgValueInst* DbgValue)
  305. {
  306. llvm::IRBuilder<> B(M.getContext());
  307. auto* Zero = B.getInt32(0);
  308. llvm::DIVariable *Variable = DbgValue->getVariable();
  309. auto &Register = m_Registers[DbgValue->getVariable()];
  310. if (Register == nullptr)
  311. {
  312. Register.reset(new VariableRegisters(Variable, &M));
  313. }
  314. llvm::Value *V = DbgValue->getValue();
  315. if (V == nullptr)
  316. {
  317. // The metadata contained a null Value, so we ignore it. This
  318. // seems to be a dxcompiler bug.
  319. return;
  320. }
  321. // Convert the offset from DbgValue's expression to a packed
  322. // offset, which we'll need in order to determine the (packed)
  323. // offset of each scalar Value in DbgValue.
  324. const OffsetInBits AlignedOffsetFromVar =
  325. GetAlignedOffsetFromDIExpression(DbgValue->getExpression());
  326. OffsetInBits PackedOffsetFromVar;
  327. const OffsetManager& Offsets = Register->GetOffsetManager();
  328. if (!Offsets.GetPackedOffsetFromAlignedOffset(AlignedOffsetFromVar,
  329. &PackedOffsetFromVar))
  330. {
  331. assert(!"Failed to find packed offset");
  332. return;
  333. }
  334. const OffsetInBits InitialOffset = PackedOffsetFromVar;
  335. B.SetInsertPoint(DbgValue);
  336. B.SetCurrentDebugLocation(llvm::DebugLoc());
  337. // Now traverse a list of pairs {Scalar Value, InitialOffset + Offset}.
  338. // InitialOffset is the offset from DbgValue's expression (i.e., the
  339. // offset from the Variable's start), and Offset is the Scalar Value's
  340. // packed offset from DbgValue's value.
  341. for (const ValueAndOffset &VO : SplitValue(V, InitialOffset, B))
  342. {
  343. OffsetInBits AlignedOffset;
  344. if (!Offsets.GetAlignedOffsetFromPackedOffset(VO.m_PackedOffset,
  345. &AlignedOffset))
  346. {
  347. continue;
  348. }
  349. auto* AllocaInst = Register->GetRegisterForAlignedOffset(AlignedOffset);
  350. if (AllocaInst == nullptr)
  351. {
  352. assert(!"Failed to find alloca for var[offset]");
  353. continue;
  354. }
  355. auto *GEP = B.CreateGEP(AllocaInst, {Zero, Zero});
  356. B.CreateStore(VO.m_V, GEP);
  357. }
  358. }
  359. llvm::AllocaInst *VariableRegisters::GetRegisterForAlignedOffset(
  360. OffsetInBits Offset
  361. ) const
  362. {
  363. auto it = m_AlignedOffsetToAlloca.find(Offset);
  364. if (it == m_AlignedOffsetToAlloca.end())
  365. {
  366. return nullptr;
  367. }
  368. return it->second;
  369. }
  370. // DITypePeelConstAndTypedef peels const and typedef types off of Ty,
  371. // returning the unalised type.
  372. static llvm::DIType *DITypePeelConstAndTypedef(
  373. llvm::DIType* Ty
  374. )
  375. {
  376. if (auto *DerivedTy = llvm::dyn_cast<llvm::DIDerivedType>(Ty))
  377. {
  378. const llvm::DITypeIdentifierMap EmptyMap;
  379. switch (DerivedTy->getTag())
  380. {
  381. case llvm::dwarf::DW_TAG_const_type:
  382. case llvm::dwarf::DW_TAG_typedef:
  383. return DITypePeelConstAndTypedef(
  384. DerivedTy->getBaseType().resolve(EmptyMap));
  385. }
  386. }
  387. return Ty;
  388. }
  389. VariableRegisters::VariableRegisters(
  390. llvm::DIVariable *Variable,
  391. llvm::Module *M
  392. ) : m_Variable(Variable)
  393. , m_B(M->GetOrCreateDxilModule().GetEntryFunction()->getEntryBlock().begin())
  394. , m_DbgDeclareFn(llvm::Intrinsic::getDeclaration(
  395. M, llvm::Intrinsic::dbg_declare))
  396. {
  397. const llvm::DITypeIdentifierMap EmptyMap;
  398. llvm::DIType* Ty = m_Variable->getType().resolve(EmptyMap);
  399. PopulateAllocaMap(Ty);
  400. assert(m_Offsets.GetCurrentPackedOffset() ==
  401. DITypePeelConstAndTypedef(Ty)->getSizeInBits());
  402. }
  403. void VariableRegisters::PopulateAllocaMap(
  404. llvm::DIType *Ty
  405. )
  406. {
  407. if (auto *DerivedTy = llvm::dyn_cast<llvm::DIDerivedType>(Ty))
  408. {
  409. const llvm::DITypeIdentifierMap EmptyMap;
  410. switch (DerivedTy->getTag())
  411. {
  412. default:
  413. assert(!"Unhandled DIDerivedType");
  414. m_Offsets.AlignToAndAddUnhandledType(DerivedTy);
  415. return;
  416. case llvm::dwarf::DW_TAG_const_type:
  417. case llvm::dwarf::DW_TAG_typedef:
  418. PopulateAllocaMap(
  419. DerivedTy->getBaseType().resolve(EmptyMap));
  420. return;
  421. }
  422. }
  423. else if (auto *CompositeTy = llvm::dyn_cast<llvm::DICompositeType>(Ty))
  424. {
  425. switch (CompositeTy->getTag())
  426. {
  427. default:
  428. assert(!"Unhandled DICompositeType");
  429. m_Offsets.AlignToAndAddUnhandledType(CompositeTy);
  430. return;
  431. case llvm::dwarf::DW_TAG_array_type:
  432. PopulateAllocaMap_ArrayType(CompositeTy);
  433. return;
  434. case llvm::dwarf::DW_TAG_structure_type:
  435. case llvm::dwarf::DW_TAG_class_type:
  436. PopulateAllocaMap_StructType(CompositeTy);
  437. return;
  438. }
  439. }
  440. else if (auto *BasicTy = llvm::dyn_cast<llvm::DIBasicType>(Ty))
  441. {
  442. PopulateAllocaMap_BasicType(BasicTy);
  443. return;
  444. }
  445. assert(!"Unhandled DIType");
  446. m_Offsets.AlignToAndAddUnhandledType(Ty);
  447. }
  448. static llvm::Type* GetLLVMTypeFromDIBasicType(
  449. llvm::IRBuilder<> &B,
  450. llvm::DIBasicType* Ty
  451. )
  452. {
  453. const SizeInBits Size = Ty->getSizeInBits();
  454. switch (Ty->getEncoding())
  455. {
  456. default:
  457. break;
  458. case llvm::dwarf::DW_ATE_boolean:
  459. case llvm::dwarf::DW_ATE_signed:
  460. case llvm::dwarf::DW_ATE_unsigned:
  461. switch(Size)
  462. {
  463. case 16:
  464. return B.getInt16Ty();
  465. case 32:
  466. return B.getInt32Ty();
  467. case 64:
  468. return B.getInt64Ty();
  469. }
  470. break;
  471. case llvm::dwarf::DW_ATE_float:
  472. switch(Size)
  473. {
  474. case 16:
  475. return B.getHalfTy();
  476. case 32:
  477. return B.getFloatTy();
  478. case 64:
  479. return B.getDoubleTy();
  480. }
  481. break;
  482. }
  483. return nullptr;
  484. }
  485. void VariableRegisters::PopulateAllocaMap_BasicType(
  486. llvm::DIBasicType *Ty
  487. )
  488. {
  489. llvm::Type* AllocaElementTy = GetLLVMTypeFromDIBasicType(m_B, Ty);
  490. assert(AllocaElementTy != nullptr);
  491. if (AllocaElementTy == nullptr)
  492. {
  493. return;
  494. }
  495. const OffsetInBits AlignedOffset = m_Offsets.Add(Ty);
  496. llvm::Type *AllocaTy = llvm::ArrayType::get(AllocaElementTy, 1);
  497. llvm::AllocaInst *&Alloca = m_AlignedOffsetToAlloca[AlignedOffset];
  498. Alloca = m_B.CreateAlloca(AllocaTy, m_B.getInt32(0));
  499. Alloca->setDebugLoc(llvm::DebugLoc());
  500. auto *Storage = GetMetadataAsValue(llvm::ValueAsMetadata::get(Alloca));
  501. auto *Variable = GetMetadataAsValue(m_Variable);
  502. auto *Expression = GetMetadataAsValue(GetDIExpression(Ty, AlignedOffset));
  503. auto *DbgDeclare = m_B.CreateCall(
  504. m_DbgDeclareFn,
  505. {Storage, Variable, Expression});
  506. DbgDeclare->setDebugLoc(GetVariableLocation());
  507. }
  508. static unsigned NumArrayElements(
  509. llvm::DICompositeType *Array
  510. )
  511. {
  512. if (Array->getElements().size() == 0)
  513. {
  514. return 0;
  515. }
  516. unsigned NumElements = 1;
  517. for (llvm::DINode *N : Array->getElements())
  518. {
  519. if (auto* Subrange = llvm::dyn_cast<llvm::DISubrange>(N))
  520. {
  521. NumElements *= Subrange->getCount();
  522. }
  523. else
  524. {
  525. assert(!"Unhandled array element");
  526. return 0;
  527. }
  528. }
  529. return NumElements;
  530. }
  531. void VariableRegisters::PopulateAllocaMap_ArrayType(
  532. llvm::DICompositeType* Ty
  533. )
  534. {
  535. unsigned NumElements = NumArrayElements(Ty);
  536. if (NumElements == 0)
  537. {
  538. m_Offsets.AlignToAndAddUnhandledType(Ty);
  539. return;
  540. }
  541. const SizeInBits ArraySizeInBits = Ty->getSizeInBits();
  542. (void)ArraySizeInBits;
  543. const llvm::DITypeIdentifierMap EmptyMap;
  544. llvm::DIType *ElementTy = Ty->getBaseType().resolve(EmptyMap);
  545. assert(ArraySizeInBits % NumElements == 0 &&
  546. " invalid DIArrayType"
  547. " - Size is not a multiple of NumElements");
  548. // After aligning the current aligned offset to ElementTy's natural
  549. // alignment, the current aligned offset must match Ty's offset
  550. // in bits.
  551. m_Offsets.AlignTo(ElementTy);
  552. for (unsigned i = 0; i < NumElements; ++i)
  553. {
  554. // This is only needed if ElementTy's size is not a multiple of
  555. // its natural alignment.
  556. m_Offsets.AlignTo(ElementTy);
  557. PopulateAllocaMap(ElementTy);
  558. }
  559. }
  560. // SortMembers traverses all of Ty's members and returns them sorted
  561. // by their offset from Ty's start. Returns true if the function succeeds
  562. // and false otherwise.
  563. static bool SortMembers(
  564. llvm::DICompositeType* Ty,
  565. std::map<OffsetInBits, llvm::DIDerivedType*> *SortedMembers
  566. )
  567. {
  568. const llvm::DITypeIdentifierMap EmptyMap;
  569. for (auto *Element : Ty->getElements())
  570. {
  571. switch (Element->getTag())
  572. {
  573. case llvm::dwarf::DW_TAG_member: {
  574. if (auto *Member = llvm::dyn_cast<llvm::DIDerivedType>(Element))
  575. {
  576. auto it = SortedMembers->emplace(std::make_pair(Member->getOffsetInBits(), Member));
  577. (void)it;
  578. assert(it.second &&
  579. "Invalid DIStructType"
  580. " - members with the same offset -- are unions possible?");
  581. break;
  582. }
  583. // FALLTHROUGH
  584. }
  585. default:
  586. assert(!"Unhandled field type in DIStructType");
  587. return false;
  588. }
  589. }
  590. return true;
  591. }
  592. void VariableRegisters::PopulateAllocaMap_StructType(
  593. llvm::DICompositeType *Ty
  594. )
  595. {
  596. std::map<OffsetInBits, llvm::DIDerivedType*> SortedMembers;
  597. if (!SortMembers(Ty, &SortedMembers))
  598. {
  599. m_Offsets.AlignToAndAddUnhandledType(Ty);
  600. return;
  601. }
  602. m_Offsets.AlignTo(Ty);
  603. const OffsetInBits StructStart = m_Offsets.GetCurrentAlignedOffset();
  604. (void)StructStart;
  605. const llvm::DITypeIdentifierMap EmptyMap;
  606. for (auto OffsetAndMember : SortedMembers)
  607. {
  608. // Align the offsets to the member's type natural alignment. This
  609. // should always result in the current aligned offset being the
  610. // same as the member's offset.
  611. m_Offsets.AlignTo(OffsetAndMember.second);
  612. assert(m_Offsets.GetCurrentAlignedOffset() ==
  613. StructStart + OffsetAndMember.first &&
  614. "Offset mismatch in DIStructType");
  615. PopulateAllocaMap(
  616. OffsetAndMember.second->getBaseType().resolve(EmptyMap));
  617. }
  618. }
  619. llvm::DILocation *VariableRegisters::GetVariableLocation() const
  620. {
  621. const unsigned DefaultColumn = 1;
  622. return llvm::DILocation::get(
  623. m_B.getContext(),
  624. m_Variable->getLine(),
  625. DefaultColumn,
  626. m_Variable->getScope());
  627. }
  628. llvm::Value *VariableRegisters::GetMetadataAsValue(
  629. llvm::Metadata *M
  630. ) const
  631. {
  632. return llvm::MetadataAsValue::get(m_B.getContext(), M);
  633. }
  634. llvm::DIExpression *VariableRegisters::GetDIExpression(
  635. llvm::DIType *Ty,
  636. OffsetInBits Offset
  637. ) const
  638. {
  639. llvm::SmallVector<uint64_t, 3> ExpElements;
  640. if (Offset != 0)
  641. {
  642. ExpElements.emplace_back(llvm::dwarf::DW_OP_bit_piece);
  643. ExpElements.emplace_back(Offset);
  644. ExpElements.emplace_back(Ty->getSizeInBits());
  645. }
  646. return llvm::DIExpression::get(m_B.getContext(), ExpElements);
  647. }
  648. using namespace llvm;
  649. INITIALIZE_PASS(DxilDbgValueToDbgDeclare, DEBUG_TYPE,
  650. "Converts calls to dbg.value to dbg.declare + stores to new virtual registers",
  651. false, false)
  652. ModulePass *llvm::createDxilDbgValueToDbgDeclarePass() {
  653. return new DxilDbgValueToDbgDeclare();
  654. }