123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 |
- ///////////////////////////////////////////////////////////////////////////////
- // //
- // DxilDbgValueToDbgDeclare.cpp //
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- // This file is distributed under the University of Illinois Open Source //
- // License. See LICENSE.TXT for details. //
- // //
- // Converts calls to llvm.dbg.value to llvm.dbg.declare + alloca + stores. //
- // //
- ///////////////////////////////////////////////////////////////////////////////
- #include <algorithm>
- #include <memory>
- #include <map>
- #include <unordered_map>
- #include <utility>
- #include "dxc/DXIL/DxilConstants.h"
- #include "dxc/DXIL/DxilResourceBase.h"
- #include "dxc/DXIL/DxilModule.h"
- #include "dxc/DxilPIXPasses/DxilPIXPasses.h"
- #include "llvm/IR/DebugInfo.h"
- #include "llvm/IR/DebugInfoMetadata.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/IntrinsicInst.h"
- #include "llvm/IR/Intrinsics.h"
- #include "llvm/IR/IRBuilder.h"
- #include "llvm/IR/Module.h"
- #include "llvm/Pass.h"
- #define DEBUG_TYPE "dxil-dbg-value-to-dbg-declare"
- namespace {
- using OffsetInBits = unsigned;
- using SizeInBits = unsigned;
- // OffsetManager is used to map between "packed" and aligned offsets.
- //
- // For example, the aligned offsets for a struct [float, half, int, double]
- // will be {0, 32, 64, 128} (assuming 32 bit alignments for ints, and 64
- // bit for doubles), while the packed offsets will be {0, 32, 48, 80}.
- //
- // This mapping makes it easier to deal with llvm.dbg.values whose value
- // operand does not match exactly the Variable operand's type.
- class OffsetManager
- {
- public:
- OffsetManager() = default;
- // AlignTo aligns the current aligned offset to Ty's natural alignment.
- void AlignTo(
- llvm::DIType *Ty
- )
- {
- // This is some magic arithmetic. Here's an example:
- //
- // Assume the natural alignment for Ty is 16 bits. Then
- //
- // AlignMask = 0x0000000f(15)
- //
- // If the current aligned offset is
- //
- // CurrentAlignedOffset = 0x00000048(72)
- //
- // Then
- //
- // T = CurrentAlignOffset + AlignMask = 0x00000057(87)
- //
- // Which mean
- //
- // T & ~CurrentOffset = 0x00000050(80)
- //
- // is the aligned offset where Ty should be placed.
- unsigned AlignMask = Ty->getAlignInBits();
- if (AlignMask == 0)
- {
- if (auto *DerivedTy = llvm::dyn_cast<llvm::DIDerivedType>(Ty)) {
- const llvm::DITypeIdentifierMap EmptyMap;
- switch (DerivedTy->getTag()) {
- case llvm::dwarf::DW_TAG_restrict_type:
- case llvm::dwarf::DW_TAG_reference_type:
- case llvm::dwarf::DW_TAG_const_type:
- case llvm::dwarf::DW_TAG_typedef:
- AlignMask = DerivedTy->getBaseType().resolve(EmptyMap)->getAlignInBits();
- assert(AlignMask != 0);
- }
- }
- }
- AlignMask = AlignMask - 1;
- m_CurrentAlignedOffset =
- (m_CurrentAlignedOffset + AlignMask) & ~AlignMask;
- }
- // Add is used to "add" an aggregate element (struct field, array element)
- // at the current aligned/packed offsets, bumping them by Ty's size.
- OffsetInBits Add(
- llvm::DIBasicType *Ty
- )
- {
- m_PackedOffsetToAlignedOffset[m_CurrentPackedOffset] = m_CurrentAlignedOffset;
- m_AlignedOffsetToPackedOffset[m_CurrentAlignedOffset] = m_CurrentPackedOffset;
- const OffsetInBits Ret = m_CurrentAlignedOffset;
- m_CurrentPackedOffset += Ty->getSizeInBits();
- m_CurrentAlignedOffset += Ty->getSizeInBits();
- return Ret;
- }
- // AlignToAndAddUnhandledType is used for error handling when Ty
- // could not be handled by the transformation. This is a best-effort
- // way to continue the pass by ignoring the current type and hoping
- // that adding Ty as a blob other fields/elements added will land
- // in the proper offset.
- void AlignToAndAddUnhandledType(
- llvm::DIType *Ty
- )
- {
- AlignTo(Ty);
- m_CurrentPackedOffset += Ty->getSizeInBits();
- m_CurrentAlignedOffset += Ty->getSizeInBits();
- }
- void AddResourceType(llvm::DIType *Ty)
- {
- m_PackedOffsetToAlignedOffset[m_CurrentPackedOffset] =
- m_CurrentAlignedOffset;
- m_AlignedOffsetToPackedOffset[m_CurrentAlignedOffset] =
- m_CurrentPackedOffset;
- m_CurrentPackedOffset += Ty->getSizeInBits();
- m_CurrentAlignedOffset += Ty->getSizeInBits();
- }
- bool GetAlignedOffsetFromPackedOffset(
- OffsetInBits PackedOffset,
- OffsetInBits *AlignedOffset
- ) const
- {
- return GetOffsetWithMap(
- m_PackedOffsetToAlignedOffset,
- PackedOffset,
- AlignedOffset);
- }
- OffsetInBits GetPackedOffsetFromAlignedOffset(
- OffsetInBits AlignedOffset,
- OffsetInBits *PackedOffset
- ) const
- {
- return GetOffsetWithMap(
- m_PackedOffsetToAlignedOffset,
- AlignedOffset,
- PackedOffset);
- }
- OffsetInBits GetCurrentPackedOffset() const
- {
- return m_CurrentPackedOffset;
- }
- OffsetInBits GetCurrentAlignedOffset() const
- {
- return m_CurrentAlignedOffset;
- }
- private:
- OffsetInBits m_CurrentPackedOffset = 0;
- OffsetInBits m_CurrentAlignedOffset = 0;
- using OffsetMap = std::unordered_map<OffsetInBits, OffsetInBits>;
- OffsetMap m_PackedOffsetToAlignedOffset;
- OffsetMap m_AlignedOffsetToPackedOffset;
- static bool GetOffsetWithMap(
- const OffsetMap &Map,
- OffsetInBits SrcOffset,
- OffsetInBits *DstOffset
- )
- {
- auto it = Map.find(SrcOffset);
- if (it == Map.end())
- {
- return false;
- }
- *DstOffset = it->second;
- return true;
- }
- };
- // VariableRegisters contains the logic for traversing a DIType T and
- // creating AllocaInsts that map back to a specific offset within T.
- class VariableRegisters
- {
- public:
- VariableRegisters(
- llvm::DebugLoc const &,
- llvm::DIVariable *Variable,
- llvm::Module *M
- );
- llvm::AllocaInst *GetRegisterForAlignedOffset(
- OffsetInBits AlignedOffset
- ) const;
- const OffsetManager& GetOffsetManager() const
- {
- return m_Offsets;
- }
- private:
- void PopulateAllocaMap(
- llvm::DIType *Ty
- );
- void PopulateAllocaMap_BasicType(llvm::DIBasicType *Ty
- );
- void PopulateAllocaMap_ArrayType(llvm::DICompositeType *Ty
- );
- void PopulateAllocaMap_StructType(llvm::DICompositeType *Ty
- );
- llvm::DILocation *GetVariableLocation() const;
- llvm::Value *GetMetadataAsValue(
- llvm::Metadata *M
- ) const;
- llvm::DIExpression *GetDIExpression(
- llvm::DIType *Ty,
- OffsetInBits Offset
- ) const;
- llvm::DebugLoc const &m_dbgLoc;
- llvm::DIVariable *m_Variable = nullptr;
- llvm::IRBuilder<> m_B;
- llvm::Function *m_DbgDeclareFn = nullptr;
- OffsetManager m_Offsets;
- std::unordered_map<OffsetInBits, llvm::AllocaInst *> m_AlignedOffsetToAlloca;
- };
- class DxilDbgValueToDbgDeclare : public llvm::ModulePass {
- public:
- static char ID;
- DxilDbgValueToDbgDeclare() : llvm::ModulePass(ID)
- {
- }
- bool runOnModule(
- llvm::Module &M
- ) override;
- private:
- void handleDbgValue(
- llvm::Module &M,
- llvm::DbgValueInst *DbgValue);
- std::unordered_map<llvm::DIVariable *, std::unique_ptr<VariableRegisters>> m_Registers;
- };
- } // namespace
- char DxilDbgValueToDbgDeclare::ID = 0;
- struct ValueAndOffset
- {
- llvm::Value *m_V;
- OffsetInBits m_PackedOffset;
- };
- // SplitValue splits an llvm::Value into possibly multiple
- // scalar Values. Those scalar values will later be "stored"
- // into their corresponding register.
- static OffsetInBits SplitValue(
- llvm::Value *V,
- OffsetInBits CurrentOffset,
- std::vector<ValueAndOffset> *Values,
- llvm::IRBuilder<>& B
- )
- {
- auto *VTy = V->getType();
- if (auto *ArrTy = llvm::dyn_cast<llvm::ArrayType>(VTy))
- {
- for (unsigned i = 0; i < ArrTy->getNumElements(); ++i)
- {
- CurrentOffset = SplitValue(
- B.CreateExtractValue(V, {i}),
- CurrentOffset,
- Values,
- B);
- }
- }
- else if (auto *StTy = llvm::dyn_cast<llvm::StructType>(VTy))
- {
- for (unsigned i = 0; i < StTy->getNumElements(); ++i)
- {
- CurrentOffset = SplitValue(
- B.CreateExtractValue(V, {i}),
- CurrentOffset,
- Values,
- B);
- }
- }
- else if (auto *VecTy = llvm::dyn_cast<llvm::VectorType>(VTy))
- {
- for (unsigned i = 0; i < VecTy->getNumElements(); ++i)
- {
- CurrentOffset = SplitValue(
- B.CreateExtractElement(V, i),
- CurrentOffset,
- Values,
- B);
- }
- }
- else
- {
- assert(VTy->isFloatTy() || VTy->isDoubleTy() || VTy->isHalfTy() ||
- VTy->isIntegerTy(32) || VTy->isIntegerTy(64) || VTy->isIntegerTy(16));
- Values->emplace_back(ValueAndOffset{V, CurrentOffset});
- CurrentOffset += VTy->getScalarSizeInBits();
- }
- return CurrentOffset;
- }
- // A more convenient version of SplitValue.
- static std::vector<ValueAndOffset> SplitValue(
- llvm::Value* V,
- OffsetInBits CurrentOffset,
- llvm::IRBuilder<>& B
- )
- {
- std::vector<ValueAndOffset> Ret;
- SplitValue(V, CurrentOffset, &Ret, B);
- return Ret;
- }
- // Convenient helper for parsing a DIExpression's offset.
- static OffsetInBits GetAlignedOffsetFromDIExpression(
- llvm::DIExpression *Exp
- )
- {
- if (!Exp->isBitPiece())
- {
- return 0;
- }
- return Exp->getBitPieceOffset();
- }
- bool DxilDbgValueToDbgDeclare::runOnModule(
- llvm::Module &M
- )
- {
- auto *DbgValueFn =
- llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::dbg_value);
- bool Changed = false;
- for (auto it = DbgValueFn->user_begin(); it != DbgValueFn->user_end(); )
- {
- llvm::User *User = *it++;
- if (auto *DbgValue = llvm::dyn_cast<llvm::DbgValueInst>(User))
- {
- Changed = true;
- handleDbgValue(M, DbgValue);
- DbgValue->eraseFromParent();
- }
- }
- return Changed;
- }
- void DxilDbgValueToDbgDeclare::handleDbgValue(
- llvm::Module& M,
- llvm::DbgValueInst* DbgValue)
- {
- llvm::Value *V = DbgValue->getValue();
- if (V == nullptr) {
- // The metadata contained a null Value, so we ignore it. This
- // seems to be a dxcompiler bug.
- return;
- }
- if (auto *PtrTy = llvm::dyn_cast<llvm::PointerType>(V->getType())) {
- return;
- }
-
- llvm::DIVariable *Variable = DbgValue->getVariable();
- auto &Register = m_Registers[Variable];
- if (Register == nullptr)
- {
- Register.reset(new VariableRegisters(DbgValue->getDebugLoc(), Variable, &M));
- }
- // Convert the offset from DbgValue's expression to a packed
- // offset, which we'll need in order to determine the (packed)
- // offset of each scalar Value in DbgValue.
- llvm::DIExpression* expression = DbgValue->getExpression();
- const OffsetInBits AlignedOffsetFromVar =
- GetAlignedOffsetFromDIExpression(expression);
- OffsetInBits PackedOffsetFromVar;
- const OffsetManager& Offsets = Register->GetOffsetManager();
- if (!Offsets.GetPackedOffsetFromAlignedOffset(AlignedOffsetFromVar,
- &PackedOffsetFromVar))
- {
- // todo: output geometry for GS
- return;
- }
- const OffsetInBits InitialOffset = PackedOffsetFromVar;
- llvm::IRBuilder<> B(DbgValue->getCalledFunction()->getContext());
- B.SetInsertPoint(DbgValue);
- B.SetCurrentDebugLocation(llvm::DebugLoc());
- auto *Zero = B.getInt32(0);
- // Now traverse a list of pairs {Scalar Value, InitialOffset + Offset}.
- // InitialOffset is the offset from DbgValue's expression (i.e., the
- // offset from the Variable's start), and Offset is the Scalar Value's
- // packed offset from DbgValue's value.
- for (const ValueAndOffset &VO : SplitValue(V, InitialOffset, B))
- {
- OffsetInBits AlignedOffset;
- if (!Offsets.GetAlignedOffsetFromPackedOffset(VO.m_PackedOffset,
- &AlignedOffset))
- {
- continue;
- }
- auto* AllocaInst = Register->GetRegisterForAlignedOffset(AlignedOffset);
- if (AllocaInst == nullptr)
- {
- assert(!"Failed to find alloca for var[offset]");
- continue;
- }
- if (AllocaInst->getAllocatedType()->getArrayElementType() == VO.m_V->getType())
- {
- auto* GEP = B.CreateGEP(AllocaInst, { Zero, Zero });
- B.CreateStore(VO.m_V, GEP);
- }
- }
- }
- llvm::AllocaInst *VariableRegisters::GetRegisterForAlignedOffset(
- OffsetInBits Offset
- ) const
- {
- auto it = m_AlignedOffsetToAlloca.find(Offset);
- if (it == m_AlignedOffsetToAlloca.end())
- {
- return nullptr;
- }
- return it->second;
- }
- #ifndef NDEBUG
- // DITypePeelTypeAlias peels const, typedef, and other alias types off of Ty,
- // returning the unalised type.
- static llvm::DIType *DITypePeelTypeAlias(
- llvm::DIType* Ty
- )
- {
- if (auto *DerivedTy = llvm::dyn_cast<llvm::DIDerivedType>(Ty))
- {
- const llvm::DITypeIdentifierMap EmptyMap;
- switch (DerivedTy->getTag())
- {
- case llvm::dwarf::DW_TAG_restrict_type:
- case llvm::dwarf::DW_TAG_reference_type:
- case llvm::dwarf::DW_TAG_const_type:
- case llvm::dwarf::DW_TAG_typedef:
- case llvm::dwarf::DW_TAG_pointer_type:
- case llvm::dwarf::DW_TAG_member:
- return DITypePeelTypeAlias(
- DerivedTy->getBaseType().resolve(EmptyMap));
- }
- }
- return Ty;
- }
- #endif // NDEBUG
- VariableRegisters::VariableRegisters(
- llvm::DebugLoc const & dbgLoc,
- llvm::DIVariable *Variable,
- llvm::Module *M)
- : m_dbgLoc(dbgLoc)
- ,m_Variable(Variable)
- , m_B(M->GetOrCreateDxilModule().GetEntryFunction()->getEntryBlock().begin())
- , m_DbgDeclareFn(llvm::Intrinsic::getDeclaration(
- M, llvm::Intrinsic::dbg_declare))
- {
- const llvm::DITypeIdentifierMap EmptyMap;
- llvm::DIType* Ty = m_Variable->getType().resolve(EmptyMap);
- PopulateAllocaMap(Ty);
- assert(m_Offsets.GetCurrentPackedOffset() ==
- DITypePeelTypeAlias(Ty)->getSizeInBits());
- }
- void VariableRegisters::PopulateAllocaMap(
- llvm::DIType *Ty
- )
- {
- if (auto *DerivedTy = llvm::dyn_cast<llvm::DIDerivedType>(Ty))
- {
- const llvm::DITypeIdentifierMap EmptyMap;
- switch (DerivedTy->getTag())
- {
- default:
- assert(!"Unhandled DIDerivedType");
- m_Offsets.AlignToAndAddUnhandledType(DerivedTy);
- return;
- case llvm::dwarf::DW_TAG_arg_variable: // "this" pointer
- case llvm::dwarf::DW_TAG_pointer_type: // "this" pointer
- case llvm::dwarf::DW_TAG_restrict_type:
- case llvm::dwarf::DW_TAG_reference_type:
- case llvm::dwarf::DW_TAG_const_type:
- case llvm::dwarf::DW_TAG_typedef:
- case llvm::dwarf::DW_TAG_member:
- PopulateAllocaMap(
- DerivedTy->getBaseType().resolve(EmptyMap));
- return;
- case llvm::dwarf::DW_TAG_subroutine_type:
- //ignore member functions.
- return;
- }
- }
- else if (auto *CompositeTy = llvm::dyn_cast<llvm::DICompositeType>(Ty))
- {
- switch (CompositeTy->getTag())
- {
- default:
- assert(!"Unhandled DICompositeType");
- m_Offsets.AlignToAndAddUnhandledType(CompositeTy);
- return;
- case llvm::dwarf::DW_TAG_array_type:
- PopulateAllocaMap_ArrayType(CompositeTy);
- return;
- case llvm::dwarf::DW_TAG_structure_type:
- case llvm::dwarf::DW_TAG_class_type:
- PopulateAllocaMap_StructType(CompositeTy);
- return;
- }
- }
- else if (auto *BasicTy = llvm::dyn_cast<llvm::DIBasicType>(Ty))
- {
- PopulateAllocaMap_BasicType(BasicTy);
- return;
- }
- assert(!"Unhandled DIType");
- m_Offsets.AlignToAndAddUnhandledType(Ty);
- }
- static llvm::Type* GetLLVMTypeFromDIBasicType(
- llvm::IRBuilder<> &B,
- llvm::DIBasicType* Ty
- )
- {
- const SizeInBits Size = Ty->getSizeInBits();
- switch (Ty->getEncoding())
- {
- default:
- break;
- case llvm::dwarf::DW_ATE_boolean:
- case llvm::dwarf::DW_ATE_signed:
- case llvm::dwarf::DW_ATE_unsigned:
- switch(Size)
- {
- case 16:
- return B.getInt16Ty();
- case 32:
- return B.getInt32Ty();
- case 64:
- return B.getInt64Ty();
- }
- break;
- case llvm::dwarf::DW_ATE_float:
- switch(Size)
- {
- case 16:
- return B.getHalfTy();
- case 32:
- return B.getFloatTy();
- case 64:
- return B.getDoubleTy();
- }
- break;
- }
- return nullptr;
- }
- void VariableRegisters::PopulateAllocaMap_BasicType(
- llvm::DIBasicType *Ty
- )
- {
- llvm::Type* AllocaElementTy = GetLLVMTypeFromDIBasicType(m_B, Ty);
- assert(AllocaElementTy != nullptr);
- if (AllocaElementTy == nullptr)
- {
- return;
- }
- const OffsetInBits AlignedOffset = m_Offsets.Add(Ty);
- llvm::Type *AllocaTy = llvm::ArrayType::get(AllocaElementTy, 1);
- llvm::AllocaInst *&Alloca = m_AlignedOffsetToAlloca[AlignedOffset];
- Alloca = m_B.CreateAlloca(AllocaTy, m_B.getInt32(0));
- Alloca->setDebugLoc(llvm::DebugLoc());
- auto *Storage = GetMetadataAsValue(llvm::ValueAsMetadata::get(Alloca));
- auto *Variable = GetMetadataAsValue(m_Variable);
- auto *Expression = GetMetadataAsValue(GetDIExpression(Ty, AlignedOffset));
- auto *DbgDeclare = m_B.CreateCall(
- m_DbgDeclareFn,
- {Storage, Variable, Expression});
- DbgDeclare->setDebugLoc(m_dbgLoc);
- }
- static unsigned NumArrayElements(
- llvm::DICompositeType *Array
- )
- {
- if (Array->getElements().size() == 0)
- {
- return 0;
- }
- unsigned NumElements = 1;
- for (llvm::DINode *N : Array->getElements())
- {
- if (auto* Subrange = llvm::dyn_cast<llvm::DISubrange>(N))
- {
- NumElements *= Subrange->getCount();
- }
- else
- {
- assert(!"Unhandled array element");
- return 0;
- }
- }
- return NumElements;
- }
- void VariableRegisters::PopulateAllocaMap_ArrayType(
- llvm::DICompositeType* Ty
- )
- {
- unsigned NumElements = NumArrayElements(Ty);
- if (NumElements == 0)
- {
- m_Offsets.AlignToAndAddUnhandledType(Ty);
- return;
- }
- const SizeInBits ArraySizeInBits = Ty->getSizeInBits();
- (void)ArraySizeInBits;
- const llvm::DITypeIdentifierMap EmptyMap;
- llvm::DIType *ElementTy = Ty->getBaseType().resolve(EmptyMap);
- assert(ArraySizeInBits % NumElements == 0 &&
- " invalid DIArrayType"
- " - Size is not a multiple of NumElements");
- // After aligning the current aligned offset to ElementTy's natural
- // alignment, the current aligned offset must match Ty's offset
- // in bits.
- m_Offsets.AlignTo(ElementTy);
- for (unsigned i = 0; i < NumElements; ++i)
- {
- // This is only needed if ElementTy's size is not a multiple of
- // its natural alignment.
- m_Offsets.AlignTo(ElementTy);
- PopulateAllocaMap(ElementTy);
- }
- }
- // SortMembers traverses all of Ty's members and returns them sorted
- // by their offset from Ty's start. Returns true if the function succeeds
- // and false otherwise.
- static bool SortMembers(
- llvm::DICompositeType* Ty,
- std::map<OffsetInBits, llvm::DIDerivedType*> *SortedMembers
- )
- {
- auto Elements = Ty->getElements();
- if (Elements.begin() == Elements.end())
- {
- return false;
- }
- for (auto* Element : Elements)
- {
- switch (Element->getTag())
- {
- case llvm::dwarf::DW_TAG_member: {
- if (auto* Member = llvm::dyn_cast<llvm::DIDerivedType>(Element))
- {
- if (Member->getSizeInBits()) {
- auto it = SortedMembers->emplace(std::make_pair(Member->getOffsetInBits(), Member));
- (void)it;
- assert(it.second &&
- "Invalid DIStructType"
- " - members with the same offset -- are unions possible?");
- }
- break;
- }
- assert(!"member is not a Member");
- return false;
- }
- case llvm::dwarf::DW_TAG_subprogram: {
- if (auto* SubProgram = llvm::dyn_cast<llvm::DISubprogram>(Element)) {
- continue;
- }
- assert(!"DISubprogram not understood");
- return false;
- }
- case llvm::dwarf::DW_TAG_inheritance: {
- if (auto* Member = llvm::dyn_cast<llvm::DIDerivedType>(Element))
- {
- auto it = SortedMembers->emplace(
- std::make_pair(Member->getOffsetInBits(), Member));
- (void)it;
- assert(it.second &&
- "Invalid DIStructType"
- " - members with the same offset -- are unions possible?");
- }
- continue;
- }
- default:
- assert(!"Unhandled field type in DIStructType");
- return false;
- }
- }
- return true;
- }
- static bool IsResourceObject(llvm::DIDerivedType *DT) {
- const llvm::DITypeIdentifierMap EmptyMap;
- auto *BT = DT->getBaseType().resolve(EmptyMap);
- if (auto *CompositeTy = llvm::dyn_cast<llvm::DICompositeType>(BT)) {
- // Resource variables (e.g. TextureCube) are composite types but have no elements:
- if (CompositeTy->getElements().begin() ==
- CompositeTy->getElements().end()) {
- auto name = CompositeTy->getName();
- auto openTemplateListMarker = name.find_first_of('<');
- if (openTemplateListMarker != llvm::StringRef::npos) {
- auto hlslType = name.substr(0, openTemplateListMarker);
- for (int i = static_cast<int>(hlsl::DXIL::ResourceKind::Invalid) + 1;
- i < static_cast<int>(hlsl::DXIL::ResourceKind::NumEntries);
- ++i) {
- if (hlslType == hlsl::GetResourceKindName(static_cast<hlsl::DXIL::ResourceKind>(i))) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
- void VariableRegisters::PopulateAllocaMap_StructType(
- llvm::DICompositeType *Ty
- )
- {
- std::map<OffsetInBits, llvm::DIDerivedType*> SortedMembers;
- if (!SortMembers(Ty, &SortedMembers))
- {
- m_Offsets.AlignToAndAddUnhandledType(Ty);
- return;
- }
- m_Offsets.AlignTo(Ty);
- const OffsetInBits StructStart = m_Offsets.GetCurrentAlignedOffset();
- (void)StructStart;
- const llvm::DITypeIdentifierMap EmptyMap;
- for (auto OffsetAndMember : SortedMembers)
- {
- // Align the offsets to the member's type natural alignment. This
- // should always result in the current aligned offset being the
- // same as the member's offset.
- m_Offsets.AlignTo(OffsetAndMember.second);
- assert(m_Offsets.GetCurrentAlignedOffset() ==
- StructStart + OffsetAndMember.first &&
- "Offset mismatch in DIStructType");
- if (IsResourceObject(OffsetAndMember.second)) {
- m_Offsets.AddResourceType(OffsetAndMember.second);
- } else {
- PopulateAllocaMap(
- OffsetAndMember.second->getBaseType().resolve(EmptyMap));
- }
- }
- }
- llvm::DILocation *VariableRegisters::GetVariableLocation() const
- {
- const unsigned DefaultColumn = 1;
- return llvm::DILocation::get(
- m_B.getContext(),
- m_Variable->getLine(),
- DefaultColumn,
- m_Variable->getScope());
- }
- llvm::Value *VariableRegisters::GetMetadataAsValue(
- llvm::Metadata *M
- ) const
- {
- return llvm::MetadataAsValue::get(m_B.getContext(), M);
- }
- llvm::DIExpression *VariableRegisters::GetDIExpression(
- llvm::DIType *Ty,
- OffsetInBits Offset
- ) const
- {
- llvm::SmallVector<uint64_t, 3> ExpElements;
- if (Offset != 0)
- {
- ExpElements.emplace_back(llvm::dwarf::DW_OP_bit_piece);
- ExpElements.emplace_back(Offset);
- ExpElements.emplace_back(Ty->getSizeInBits());
- }
- return llvm::DIExpression::get(m_B.getContext(), ExpElements);
- }
- using namespace llvm;
- INITIALIZE_PASS(DxilDbgValueToDbgDeclare, DEBUG_TYPE,
- "Converts calls to dbg.value to dbg.declare + stores to new virtual registers",
- false, false)
- ModulePass *llvm::createDxilDbgValueToDbgDeclarePass() {
- return new DxilDbgValueToDbgDeclare();
- }
|