1//===--- DXILDebugInfo.cpp - analysis&lowering for Debug info -*- C++ -*- ---=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DXILDebugInfo.h"
10#include "../DirectX.h"
11#include "DXILAttributes.h"
12#include "llvm/ADT/DenseSet.h"
13#include "llvm/BinaryFormat/Dwarf.h"
14#include "llvm/IR/AttributeMask.h"
15#include "llvm/IR/Attributes.h"
16#include "llvm/IR/DebugInfo.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/Module.h"
19#include "llvm/Pass.h"
20#include "llvm/Support/Casting.h"
21#include "llvm/Transforms/Utils/BasicBlockUtils.h"
22
23#define DEBUG_TYPE "dx-debug-info"
24
25using namespace llvm;
26using namespace llvm::dxil;
27
28static bool lowerDXILDebugInfo(Module &M) {
29 // Convert debug markers back to dbg.value intrinsics. Record whether any
30 // changes were made.
31 bool Modified = M.convertFromNewDbgValues();
32 DebugInfoFinder DIF;
33 DIF.processModule(M);
34
35 {
36 Function *DVDecl = nullptr;
37
38 // Logically these should be variables in the
39 // for (BasicBlock &BB : F) loop.
40 // They are defined here and cleared at the start of the loop body to avoid
41 // the cost of deconstruction and reconstruction.
42 DenseMap<DILocalVariable *, std::pair<Instruction *, DbgValueInst *>>
43 DbgValues;
44 DenseMap<std::pair<DILocalVariable *, DIExpression *>,
45 std::pair<Instruction *, DbgValueInst *>>
46 DbgValueFragments;
47 // Likewise, logically, this should be a variable in the
48 // for (Function &F : M) loop.
49 DenseSet<DILocalVariable *> DbgVariablesSeen;
50
51 const AttributeMask &AttrMask = getNonDXILAttributeMask();
52
53 for (Function &F : M) {
54 F.removeFnAttrs(Attrs: AttrMask);
55 F.removeRetAttrs(Attrs: AttrMask);
56 for (unsigned ArgNo = 0; ArgNo != F.arg_size(); ++ArgNo)
57 F.removeParamAttrs(ArgNo, Attrs: AttrMask);
58
59 bool IsEntryBlock = true;
60 DbgVariablesSeen.clear();
61 for (BasicBlock &BB : F) {
62 Instruction *NextNonDebugInst = nullptr;
63 DbgValues.clear();
64 DbgValueFragments.clear();
65 for (Instruction &I : make_early_inc_range(Range: reverse(C&: BB))) {
66 I.eraseMetadataIf(Pred: [](unsigned KindID, MDNode *) {
67 return KindID == LLVMContext::MD_DIAssignID;
68 });
69 if (!isa<DbgInfoIntrinsic>(Val: I)) {
70 NextNonDebugInst = &I;
71 continue;
72 }
73 if (auto *DL = dyn_cast<DbgLabelInst>(Val: &I)) {
74 DL->eraseFromParent();
75 Modified = true;
76 continue;
77 }
78 // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
79 // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
80 // and remove redundant llvm.dbg.values.
81 if (auto *DV = dyn_cast<DbgValueInst>(Val: &I)) {
82 // Keep track of the last location where we saw any debug value for
83 // a variable.
84 DILocalVariable *V = DV->getVariable();
85 DIExpression *E = DV->getExpression();
86 // If this is already an llvm.dbg.value instruction that we can
87 // keep, just do that, otherwise convert it.
88 auto *Val = cast<MetadataAsValue>(Val: DV->getArgOperand(i: 0));
89 auto *Var = cast<MetadataAsValue>(Val: DV->getArgOperand(i: 1));
90 auto *Expr = cast<MetadataAsValue>(Val: DV->getArgOperand(i: 2));
91 bool Replace = DV->getIntrinsicID() != Intrinsic::dbg_value;
92 if (!isa<ValueAsMetadata>(Val: Val->getMetadata())) {
93 // This may be a DIArgList which is not supported in LLVM 3.7. If
94 // it is, we cannot record the new value, but we still need to
95 // kill any old value. Do this by poison. We do not know the
96 // correct type to use here and arbitrarily use i1.
97 // This should never be anything other than ValueAsMetadata or
98 // DIArgList, but in manually constructed LLVM IR, it can be.
99 // Handle this gracefully by also replacing it with poison.
100 Val = MetadataAsValue::get(
101 Context&: M.getContext(), MD: ConstantAsMetadata::get(C: PoisonValue::get(
102 T: Type::getInt1Ty(C&: M.getContext()))));
103 E = DIExpression::get(Context&: M.getContext(), Elements: {});
104 Expr = MetadataAsValue::get(Context&: M.getContext(), MD: E);
105 Replace = true;
106 }
107 std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
108 std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
109 DbgValueFragments[{V, E}];
110 if (DbgValue.second) {
111 // If there is a later value of the same fragment at the same
112 // location, this value is redundant.
113 if (DbgValueFragment.first == NextNonDebugInst) {
114 DV->eraseFromParent();
115 Modified = true;
116 continue;
117 }
118 // If there is a later identical value of the same fragment at a
119 // later point, and there have been no intervening values of
120 // different possibly overlapping fragments, that later value is
121 // redundant.
122 if (DbgValueFragment.second &&
123 DbgValueFragment.second == DbgValue.second &&
124 DbgValueFragment.second->getValue() == DV->getValue()) {
125 DbgValue.second->eraseFromParent();
126 Modified = true;
127 }
128 }
129 DbgValueInst *NewDV;
130 if (Replace) {
131 if (!DVDecl) {
132 DVDecl =
133 Intrinsic::getOrInsertDeclaration(M: &M, id: Intrinsic::dbg_value);
134 AttributeMask AM;
135 for (Attribute A : DVDecl->getAttributes().getFnAttrs())
136 if (A.isStringAttribute() ||
137 (A.getKindAsEnum() != Attribute::NoUnwind &&
138 A.getKindAsEnum() != Attribute::Memory))
139 AM.addAttribute(A);
140 DVDecl->removeFnAttrs(Attrs: AM);
141 }
142 NewDV = cast<DbgValueInst>(
143 Val: CallInst::Create(Func: DVDecl, Args: {Val, Var, Expr}, Bundles: {}, NameStr: "",
144 InsertBefore: std::next(x: DV->getIterator())));
145 NewDV->setTailCall();
146 NewDV->setDebugLoc(DV->getDebugLoc());
147 DV->eraseFromParent();
148 Modified = true;
149 } else {
150 NewDV = DV;
151 }
152 DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
153 continue;
154 }
155 }
156 // If this is the entry block, if the first value we see for each debug
157 // value is undef, it is redundant.
158 if (IsEntryBlock) {
159 for (Instruction &I : make_early_inc_range(Range&: BB)) {
160 auto *DV = dyn_cast<DbgValueInst>(Val: &I);
161 if (!DV || DbgVariablesSeen.contains(V: DV->getVariable()))
162 continue;
163 if (isa<UndefValue>(Val: DV->getValue())) {
164 DV->eraseFromParent();
165 Modified = true;
166 continue;
167 }
168 DbgVariablesSeen.insert(V: DV->getVariable());
169 }
170 }
171 IsEntryBlock = false;
172 }
173 }
174 }
175
176 for (DISubprogram *SP : DIF.subprograms()) {
177 if (MDTuple *RN = cast_or_null<MDTuple>(Val: SP->getRawRetainedNodes())) {
178 SmallVector<Metadata *> MDs(RN->operands());
179 MDs.erase(CS: std::remove_if(first: MDs.begin(), last: MDs.end(),
180 pred: [](Metadata *M) { return isa<DILabel>(Val: M); }),
181 CE: MDs.end());
182 SP->replaceRetainedNodes(N: MDTuple::get(Context&: M.getContext(), MDs));
183 Modified = true;
184 }
185 }
186
187 return Modified;
188}
189
190PreservedAnalyses DXILDebugInfo::run(Module &M, ModuleAnalysisManager &) {
191 return lowerDXILDebugInfo(M) ? PreservedAnalyses::none()
192 : PreservedAnalyses::all();
193}
194
195namespace {
196class DXILDebugInfoLegacy : public ModulePass {
197public:
198 static char ID;
199
200 DXILDebugInfoLegacy() : ModulePass(ID) {}
201
202 bool runOnModule(Module &M) override { return lowerDXILDebugInfo(M); }
203
204 void getAnalysisUsage(AnalysisUsage &AU) const override {
205 AU.setPreservesAll();
206 }
207};
208} // namespace
209
210char DXILDebugInfoLegacy::ID = 0;
211
212INITIALIZE_PASS(DXILDebugInfoLegacy, DEBUG_TYPE, "DXIL Debug Info", false,
213 false)
214
215ModulePass *llvm::createDXILDebugInfoLegacyPass() {
216 return new DXILDebugInfoLegacy();
217}
218