/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- 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 | | // Common functionality for different debug information format backends. |
10 | | // LLVM currently supports DWARF and CodeView. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/CodeGen/DebugHandlerBase.h" |
15 | | #include "llvm/ADT/Optional.h" |
16 | | #include "llvm/ADT/Twine.h" |
17 | | #include "llvm/CodeGen/AsmPrinter.h" |
18 | | #include "llvm/CodeGen/MachineFunction.h" |
19 | | #include "llvm/CodeGen/MachineInstr.h" |
20 | | #include "llvm/CodeGen/MachineModuleInfo.h" |
21 | | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
22 | | #include "llvm/IR/DebugInfo.h" |
23 | | #include "llvm/MC/MCStreamer.h" |
24 | | |
25 | | using namespace llvm; |
26 | | |
27 | | #define DEBUG_TYPE "dwarfdebug" |
28 | | |
29 | | Optional<DbgVariableLocation> |
30 | | DbgVariableLocation::extractFromMachineInstruction( |
31 | 163 | const MachineInstr &Instruction) { |
32 | 163 | DbgVariableLocation Location; |
33 | 163 | if (!Instruction.isDebugValue()) |
34 | 0 | return None; |
35 | 163 | if (!Instruction.getOperand(0).isReg()) |
36 | 22 | return None; |
37 | 141 | Location.Register = Instruction.getOperand(0).getReg(); |
38 | 141 | Location.FragmentInfo.reset(); |
39 | 141 | // We only handle expressions generated by DIExpression::appendOffset, |
40 | 141 | // which doesn't require a full stack machine. |
41 | 141 | int64_t Offset = 0; |
42 | 141 | const DIExpression *DIExpr = Instruction.getDebugExpression(); |
43 | 141 | auto Op = DIExpr->expr_op_begin(); |
44 | 195 | while (Op != DIExpr->expr_op_end()) { |
45 | 59 | switch (Op->getOp()) { |
46 | 59 | case dwarf::DW_OP_constu: { |
47 | 1 | int Value = Op->getArg(0); |
48 | 1 | ++Op; |
49 | 1 | if (Op != DIExpr->expr_op_end()) { |
50 | 1 | switch (Op->getOp()) { |
51 | 1 | case dwarf::DW_OP_minus: |
52 | 1 | Offset -= Value; |
53 | 1 | break; |
54 | 1 | case dwarf::DW_OP_plus: |
55 | 0 | Offset += Value; |
56 | 0 | break; |
57 | 1 | default: |
58 | 0 | continue; |
59 | 1 | } |
60 | 1 | } |
61 | 1 | } break; |
62 | 26 | case dwarf::DW_OP_plus_uconst: |
63 | 26 | Offset += Op->getArg(0); |
64 | 26 | break; |
65 | 16 | case dwarf::DW_OP_LLVM_fragment: |
66 | 16 | Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)}; |
67 | 16 | break; |
68 | 11 | case dwarf::DW_OP_deref: |
69 | 11 | Location.LoadChain.push_back(Offset); |
70 | 11 | Offset = 0; |
71 | 11 | break; |
72 | 5 | default: |
73 | 5 | return None; |
74 | 54 | } |
75 | 54 | ++Op; |
76 | 54 | } |
77 | 141 | |
78 | 141 | // Do one final implicit DW_OP_deref if this was an indirect DBG_VALUE |
79 | 141 | // instruction. |
80 | 141 | // FIXME: Replace these with DIExpression. |
81 | 141 | if (136 Instruction.isIndirectDebugValue()136 ) |
82 | 32 | Location.LoadChain.push_back(Offset); |
83 | 136 | |
84 | 136 | return Location; |
85 | 141 | } |
86 | | |
87 | 36.1k | DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} |
88 | | |
89 | | // Each LexicalScope has first instruction and last instruction to mark |
90 | | // beginning and end of a scope respectively. Create an inverse map that list |
91 | | // scopes starts (and ends) with an instruction. One instruction may start (or |
92 | | // end) multiple scopes. Ignore scopes that are not reachable. |
93 | 35.7k | void DebugHandlerBase::identifyScopeMarkers() { |
94 | 35.7k | SmallVector<LexicalScope *, 4> WorkList; |
95 | 35.7k | WorkList.push_back(LScopes.getCurrentFunctionScope()); |
96 | 351k | while (!WorkList.empty()) { |
97 | 315k | LexicalScope *S = WorkList.pop_back_val(); |
98 | 315k | |
99 | 315k | const SmallVectorImpl<LexicalScope *> &Children = S->getChildren(); |
100 | 315k | if (!Children.empty()) |
101 | 162k | WorkList.append(Children.begin(), Children.end()); |
102 | 315k | |
103 | 315k | if (S->isAbstractScope()) |
104 | 0 | continue; |
105 | 315k | |
106 | 397k | for (const InsnRange &R : S->getRanges())315k { |
107 | 397k | assert(R.first && "InsnRange does not have first instruction!"); |
108 | 397k | assert(R.second && "InsnRange does not have second instruction!"); |
109 | 397k | requestLabelBeforeInsn(R.first); |
110 | 397k | requestLabelAfterInsn(R.second); |
111 | 397k | } |
112 | 315k | } |
113 | 35.7k | } |
114 | | |
115 | | // Return Label preceding the instruction. |
116 | 372k | MCSymbol *DebugHandlerBase::getLabelBeforeInsn(const MachineInstr *MI) { |
117 | 372k | MCSymbol *Label = LabelsBeforeInsn.lookup(MI); |
118 | 372k | assert(Label && "Didn't insert label before instruction"); |
119 | 372k | return Label; |
120 | 372k | } |
121 | | |
122 | | // Return Label immediately following the instruction. |
123 | 364k | MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) { |
124 | 364k | return LabelsAfterInsn.lookup(MI); |
125 | 364k | } |
126 | | |
127 | | // Return the function-local offset of an instruction. |
128 | | const MCExpr * |
129 | 8 | DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) { |
130 | 8 | MCContext &MC = Asm->OutContext; |
131 | 8 | |
132 | 8 | MCSymbol *Start = Asm->getFunctionBegin(); |
133 | 8 | const auto *StartRef = MCSymbolRefExpr::create(Start, MC); |
134 | 8 | |
135 | 8 | MCSymbol *AfterInsn = getLabelAfterInsn(MI); |
136 | 8 | assert(AfterInsn && "Expected label after instruction"); |
137 | 8 | const auto *AfterRef = MCSymbolRefExpr::create(AfterInsn, MC); |
138 | 8 | |
139 | 8 | return MCBinaryExpr::createSub(AfterRef, StartRef, MC); |
140 | 8 | } |
141 | | |
142 | | /// If this type is derived from a base type then return base type size. |
143 | 1.34k | uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) { |
144 | 1.34k | assert(Ty); |
145 | 1.34k | const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty); |
146 | 1.34k | if (!DDTy) |
147 | 521 | return Ty->getSizeInBits(); |
148 | 826 | |
149 | 826 | unsigned Tag = DDTy->getTag(); |
150 | 826 | |
151 | 826 | if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef202 && |
152 | 826 | Tag != dwarf::DW_TAG_const_type162 && Tag != dwarf::DW_TAG_volatile_type153 && |
153 | 826 | Tag != dwarf::DW_TAG_restrict_type151 && Tag != dwarf::DW_TAG_atomic_type151 ) |
154 | 151 | return DDTy->getSizeInBits(); |
155 | 675 | |
156 | 675 | DIType *BaseType = DDTy->getBaseType(); |
157 | 675 | |
158 | 675 | if (!BaseType) |
159 | 1 | return 0; |
160 | 674 | |
161 | 674 | // If this is a derived type, go ahead and get the base type, unless it's a |
162 | 674 | // reference then it's just the size of the field. Pointer types have no need |
163 | 674 | // of this since they're a different type of qualification on the type. |
164 | 674 | if (BaseType->getTag() == dwarf::DW_TAG_reference_type || |
165 | 674 | BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type673 ) |
166 | 1 | return Ty->getSizeInBits(); |
167 | 673 | |
168 | 673 | return getBaseTypeSize(BaseType); |
169 | 673 | } |
170 | | |
171 | | static bool hasDebugInfo(const MachineModuleInfo *MMI, |
172 | 996k | const MachineFunction *MF) { |
173 | 996k | if (!MMI->hasDebugInfo()) |
174 | 922k | return false; |
175 | 73.8k | auto *SP = MF->getFunction().getSubprogram(); |
176 | 73.8k | if (!SP) |
177 | 2.26k | return false; |
178 | 71.5k | assert(SP->getUnit()); |
179 | 71.5k | auto EK = SP->getUnit()->getEmissionKind(); |
180 | 71.5k | if (EK == DICompileUnit::NoDebug) |
181 | 6 | return false; |
182 | 71.5k | return true; |
183 | 71.5k | } |
184 | | |
185 | 498k | void DebugHandlerBase::beginFunction(const MachineFunction *MF) { |
186 | 498k | PrevInstBB = nullptr; |
187 | 498k | |
188 | 498k | if (!Asm498k || !hasDebugInfo(MMI, MF)) { |
189 | 462k | skippedNonDebugFunction(); |
190 | 462k | return; |
191 | 462k | } |
192 | 35.7k | |
193 | 35.7k | // Grab the lexical scopes for the function, if we don't have any of those |
194 | 35.7k | // then we're not going to be able to do anything. |
195 | 35.7k | LScopes.initialize(*MF); |
196 | 35.7k | if (LScopes.empty()) { |
197 | 65 | beginFunctionImpl(MF); |
198 | 65 | return; |
199 | 65 | } |
200 | 35.7k | |
201 | 35.7k | // Make sure that each lexical scope will have a begin/end label. |
202 | 35.7k | identifyScopeMarkers(); |
203 | 35.7k | |
204 | 35.7k | // Calculate history for local variables. |
205 | 35.7k | assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); |
206 | 35.7k | assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!"); |
207 | 35.7k | calculateDbgEntityHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), |
208 | 35.7k | DbgValues, DbgLabels); |
209 | 35.7k | LLVM_DEBUG(DbgValues.dump()); |
210 | 35.7k | |
211 | 35.7k | // Request labels for the full history. |
212 | 35.7k | for (const auto &I : DbgValues) { |
213 | 772 | const auto &Entries = I.second; |
214 | 772 | if (Entries.empty()) |
215 | 0 | continue; |
216 | 772 | |
217 | 4.37k | auto IsDescribedByReg = [](const MachineInstr *MI) 772 { |
218 | 4.37k | return MI->getOperand(0).isReg() && MI->getOperand(0).getReg()363 ; |
219 | 4.37k | }; |
220 | 772 | |
221 | 772 | // The first mention of a function argument gets the CurrentFnBegin label, |
222 | 772 | // so arguments are visible when breaking at function entry. |
223 | 772 | // |
224 | 772 | // We do not change the label for values that are described by registers, |
225 | 772 | // as that could place them above their defining instructions. We should |
226 | 772 | // ideally not change the labels for constant debug values either, since |
227 | 772 | // doing that violates the ranges that are calculated in the history map. |
228 | 772 | // However, we currently do not emit debug values for constant arguments |
229 | 772 | // directly at the start of the function, so this code is still useful. |
230 | 772 | const DILocalVariable *DIVar = |
231 | 772 | Entries.front().getInstr()->getDebugVariable(); |
232 | 772 | if (DIVar->isParameter() && |
233 | 772 | getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())421 ) { |
234 | 358 | if (!IsDescribedByReg(Entries.front().getInstr())) |
235 | 18 | LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin(); |
236 | 358 | if (Entries.front().getInstr()->getDebugExpression()->isFragment()) { |
237 | 22 | // Mark all non-overlapping initial fragments. |
238 | 4.02k | for (auto I = Entries.begin(); I != Entries.end(); ++I4.00k ) { |
239 | 4.02k | if (!I->isDbgValue()) |
240 | 0 | continue; |
241 | 4.02k | const DIExpression *Fragment = I->getInstr()->getDebugExpression(); |
242 | 4.02k | if (std::any_of(Entries.begin(), I, |
243 | 7.99M | [&](DbgValueHistoryMap::Entry Pred) { |
244 | 7.99M | return Pred.isDbgValue() && |
245 | 7.99M | Fragment->fragmentsOverlap( |
246 | 7.99M | Pred.getInstr()->getDebugExpression()); |
247 | 7.99M | })) |
248 | 0 | break; |
249 | 4.02k | // The code that generates location lists for DWARF assumes that the |
250 | 4.02k | // entries' start labels are monotonically increasing, and since we |
251 | 4.02k | // don't change the label for fragments that are described by |
252 | 4.02k | // registers, we must bail out when encountering such a fragment. |
253 | 4.02k | if (IsDescribedByReg(I->getInstr())) |
254 | 20 | break; |
255 | 4.00k | LabelsBeforeInsn[I->getInstr()] = Asm->getFunctionBegin(); |
256 | 4.00k | } |
257 | 22 | } |
258 | 358 | } |
259 | 772 | |
260 | 7.00k | for (const auto &Entry : Entries) { |
261 | 7.00k | if (Entry.isDbgValue()) |
262 | 5.81k | requestLabelBeforeInsn(Entry.getInstr()); |
263 | 1.18k | else |
264 | 1.18k | requestLabelAfterInsn(Entry.getInstr()); |
265 | 7.00k | } |
266 | 772 | } |
267 | 35.7k | |
268 | 35.7k | // Ensure there is a symbol before DBG_LABEL. |
269 | 35.7k | for (const auto &I : DbgLabels) { |
270 | 6 | const MachineInstr *MI = I.second; |
271 | 6 | requestLabelBeforeInsn(MI); |
272 | 6 | } |
273 | 35.7k | |
274 | 35.7k | PrevInstLoc = DebugLoc(); |
275 | 35.7k | PrevLabel = Asm->getFunctionBegin(); |
276 | 35.7k | beginFunctionImpl(MF); |
277 | 35.7k | } |
278 | | |
279 | 2.60M | void DebugHandlerBase::beginInstruction(const MachineInstr *MI) { |
280 | 2.60M | if (!MMI->hasDebugInfo()) |
281 | 0 | return; |
282 | 2.60M | |
283 | 2.60M | assert(CurMI == nullptr); |
284 | 2.60M | CurMI = MI; |
285 | 2.60M | |
286 | 2.60M | // Insert labels where requested. |
287 | 2.60M | DenseMap<const MachineInstr *, MCSymbol *>::iterator I = |
288 | 2.60M | LabelsBeforeInsn.find(MI); |
289 | 2.60M | |
290 | 2.60M | // No label needed. |
291 | 2.60M | if (I == LabelsBeforeInsn.end()) |
292 | 2.35M | return; |
293 | 248k | |
294 | 248k | // Label already assigned. |
295 | 248k | if (I->second) |
296 | 4.01k | return; |
297 | 244k | |
298 | 244k | if (!PrevLabel) { |
299 | 181k | PrevLabel = MMI->getContext().createTempSymbol(); |
300 | 181k | Asm->OutStreamer->EmitLabel(PrevLabel); |
301 | 181k | } |
302 | 244k | I->second = PrevLabel; |
303 | 244k | } |
304 | | |
305 | 2.60M | void DebugHandlerBase::endInstruction() { |
306 | 2.60M | if (!MMI->hasDebugInfo()) |
307 | 0 | return; |
308 | 2.60M | |
309 | 2.60M | assert(CurMI != nullptr); |
310 | 2.60M | // Don't create a new label after DBG_VALUE and other instructions that don't |
311 | 2.60M | // generate code. |
312 | 2.60M | if (!CurMI->isMetaInstruction()) { |
313 | 2.40M | PrevLabel = nullptr; |
314 | 2.40M | PrevInstBB = CurMI->getParent(); |
315 | 2.40M | } |
316 | 2.60M | |
317 | 2.60M | DenseMap<const MachineInstr *, MCSymbol *>::iterator I = |
318 | 2.60M | LabelsAfterInsn.find(CurMI); |
319 | 2.60M | CurMI = nullptr; |
320 | 2.60M | |
321 | 2.60M | // No label needed. |
322 | 2.60M | if (I == LabelsAfterInsn.end()) |
323 | 2.35M | return; |
324 | 256k | |
325 | 256k | // Label already assigned. |
326 | 256k | if (I->second) |
327 | 0 | return; |
328 | 256k | |
329 | 256k | // We need a label after this instruction. |
330 | 256k | if (!PrevLabel) { |
331 | 256k | PrevLabel = MMI->getContext().createTempSymbol(); |
332 | 256k | Asm->OutStreamer->EmitLabel(PrevLabel); |
333 | 256k | } |
334 | 256k | I->second = PrevLabel; |
335 | 256k | } |
336 | | |
337 | 498k | void DebugHandlerBase::endFunction(const MachineFunction *MF) { |
338 | 498k | if (hasDebugInfo(MMI, MF)) |
339 | 35.7k | endFunctionImpl(MF); |
340 | 498k | DbgValues.clear(); |
341 | 498k | DbgLabels.clear(); |
342 | 498k | LabelsBeforeInsn.clear(); |
343 | 498k | LabelsAfterInsn.clear(); |
344 | 498k | } |