1 | //=====-- DebugProgramInstruction.cpp - Implement DbgRecords/DbgMarkers --====// |
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 "llvm/IR/DebugInfoMetadata.h" |
10 | #include "llvm/IR/DebugProgramInstruction.h" |
11 | #include "llvm/IR/DIBuilder.h" |
12 | #include "llvm/IR/IntrinsicInst.h" |
13 | |
14 | namespace llvm { |
15 | |
16 | template <typename T> |
17 | DbgRecordParamRef<T>::DbgRecordParamRef(const T *Param) |
18 | : Ref(const_cast<T *>(Param)) {} |
19 | template <typename T> |
20 | DbgRecordParamRef<T>::DbgRecordParamRef(const MDNode *Param) |
21 | : Ref(const_cast<MDNode *>(Param)) {} |
22 | |
23 | template <typename T> T *DbgRecordParamRef<T>::get() const { |
24 | return cast<T>(Ref); |
25 | } |
26 | |
27 | template class DbgRecordParamRef<DIExpression>; |
28 | template class DbgRecordParamRef<DILabel>; |
29 | template class DbgRecordParamRef<DILocalVariable>; |
30 | |
31 | DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI) |
32 | : DbgRecord(ValueKind, DVI->getDebugLoc()), |
33 | DebugValueUser({DVI->getRawLocation(), nullptr, nullptr}), |
34 | Variable(DVI->getVariable()), Expression(DVI->getExpression()), |
35 | AddressExpression() { |
36 | switch (DVI->getIntrinsicID()) { |
37 | case Intrinsic::dbg_value: |
38 | Type = LocationType::Value; |
39 | break; |
40 | case Intrinsic::dbg_declare: |
41 | Type = LocationType::Declare; |
42 | break; |
43 | case Intrinsic::dbg_assign: { |
44 | Type = LocationType::Assign; |
45 | const DbgAssignIntrinsic *Assign = |
46 | static_cast<const DbgAssignIntrinsic *>(DVI); |
47 | resetDebugValue(Idx: 1, DebugValue: Assign->getRawAddress()); |
48 | AddressExpression = Assign->getAddressExpression(); |
49 | setAssignId(Assign->getAssignID()); |
50 | break; |
51 | } |
52 | default: |
53 | llvm_unreachable( |
54 | "Trying to create a DbgVariableRecord with an invalid intrinsic type!" ); |
55 | } |
56 | } |
57 | |
58 | DbgVariableRecord::DbgVariableRecord(const DbgVariableRecord &DVR) |
59 | : DbgRecord(ValueKind, DVR.getDebugLoc()), DebugValueUser(DVR.DebugValues), |
60 | Type(DVR.getType()), Variable(DVR.getVariable()), |
61 | Expression(DVR.getExpression()), |
62 | AddressExpression(DVR.AddressExpression) {} |
63 | |
64 | DbgVariableRecord::DbgVariableRecord(Metadata *Location, DILocalVariable *DV, |
65 | DIExpression *Expr, const DILocation *DI, |
66 | LocationType Type) |
67 | : DbgRecord(ValueKind, DI), DebugValueUser({Location, nullptr, nullptr}), |
68 | Type(Type), Variable(DV), Expression(Expr) {} |
69 | |
70 | DbgVariableRecord::DbgVariableRecord(Metadata *Value, DILocalVariable *Variable, |
71 | DIExpression *Expression, |
72 | DIAssignID *AssignID, Metadata *Address, |
73 | DIExpression *AddressExpression, |
74 | const DILocation *DI) |
75 | : DbgRecord(ValueKind, DI), DebugValueUser({Value, Address, AssignID}), |
76 | Type(LocationType::Assign), Variable(Variable), Expression(Expression), |
77 | AddressExpression(AddressExpression) {} |
78 | |
79 | void DbgRecord::deleteRecord() { |
80 | switch (RecordKind) { |
81 | case ValueKind: |
82 | delete cast<DbgVariableRecord>(Val: this); |
83 | return; |
84 | case LabelKind: |
85 | delete cast<DbgLabelRecord>(Val: this); |
86 | return; |
87 | } |
88 | llvm_unreachable("unsupported DbgRecord kind" ); |
89 | } |
90 | |
91 | void DbgRecord::print(raw_ostream &O, bool IsForDebug) const { |
92 | switch (RecordKind) { |
93 | case ValueKind: |
94 | cast<DbgVariableRecord>(Val: this)->print(O, IsForDebug); |
95 | return; |
96 | case LabelKind: |
97 | cast<DbgLabelRecord>(Val: this)->print(O, IsForDebug); |
98 | return; |
99 | }; |
100 | llvm_unreachable("unsupported DbgRecord kind" ); |
101 | } |
102 | |
103 | void DbgRecord::print(raw_ostream &O, ModuleSlotTracker &MST, |
104 | bool IsForDebug) const { |
105 | switch (RecordKind) { |
106 | case ValueKind: |
107 | cast<DbgVariableRecord>(Val: this)->print(ROS&: O, MST, IsForDebug); |
108 | return; |
109 | case LabelKind: |
110 | cast<DbgLabelRecord>(Val: this)->print(ROS&: O, MST, IsForDebug); |
111 | return; |
112 | }; |
113 | llvm_unreachable("unsupported DbgRecord kind" ); |
114 | } |
115 | |
116 | bool DbgRecord::isIdenticalToWhenDefined(const DbgRecord &R) const { |
117 | if (RecordKind != R.RecordKind) |
118 | return false; |
119 | switch (RecordKind) { |
120 | case ValueKind: |
121 | return cast<DbgVariableRecord>(Val: this)->isIdenticalToWhenDefined( |
122 | Other: *cast<DbgVariableRecord>(Val: &R)); |
123 | case LabelKind: |
124 | return cast<DbgLabelRecord>(Val: this)->getLabel() == |
125 | cast<DbgLabelRecord>(Val: R).getLabel(); |
126 | }; |
127 | llvm_unreachable("unsupported DbgRecord kind" ); |
128 | } |
129 | |
130 | bool DbgRecord::isEquivalentTo(const DbgRecord &R) const { |
131 | return getDebugLoc() == R.getDebugLoc() && isIdenticalToWhenDefined(R); |
132 | } |
133 | |
134 | DbgInfoIntrinsic * |
135 | DbgRecord::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { |
136 | switch (RecordKind) { |
137 | case ValueKind: |
138 | return cast<DbgVariableRecord>(Val: this)->createDebugIntrinsic(M, InsertBefore); |
139 | case LabelKind: |
140 | return cast<DbgLabelRecord>(Val: this)->createDebugIntrinsic(M, InsertBefore); |
141 | }; |
142 | llvm_unreachable("unsupported DbgRecord kind" ); |
143 | } |
144 | |
145 | DbgLabelRecord::DbgLabelRecord(MDNode *Label, MDNode *DL) |
146 | : DbgRecord(LabelKind, DebugLoc(DL)), Label(Label) { |
147 | assert(Label && "Unexpected nullptr" ); |
148 | assert((isa<DILabel>(Label) || Label->isTemporary()) && |
149 | "Label type must be or resolve to a DILabel" ); |
150 | } |
151 | DbgLabelRecord::DbgLabelRecord(DILabel *Label, DebugLoc DL) |
152 | : DbgRecord(LabelKind, DL), Label(Label) { |
153 | assert(Label && "Unexpected nullptr" ); |
154 | } |
155 | |
156 | DbgLabelRecord *DbgLabelRecord::createUnresolvedDbgLabelRecord(MDNode *Label, |
157 | MDNode *DL) { |
158 | return new DbgLabelRecord(Label, DL); |
159 | } |
160 | |
161 | DbgVariableRecord::DbgVariableRecord(DbgVariableRecord::LocationType Type, |
162 | Metadata *Val, MDNode *Variable, |
163 | MDNode *Expression, MDNode *AssignID, |
164 | Metadata *Address, |
165 | MDNode *AddressExpression, MDNode *DI) |
166 | : DbgRecord(ValueKind, DebugLoc(DI)), |
167 | DebugValueUser({Val, Address, AssignID}), Type(Type), Variable(Variable), |
168 | Expression(Expression), AddressExpression(AddressExpression) {} |
169 | |
170 | DbgVariableRecord *DbgVariableRecord::createUnresolvedDbgVariableRecord( |
171 | DbgVariableRecord::LocationType Type, Metadata *Val, MDNode *Variable, |
172 | MDNode *Expression, MDNode *AssignID, Metadata *Address, |
173 | MDNode *AddressExpression, MDNode *DI) { |
174 | return new DbgVariableRecord(Type, Val, Variable, Expression, AssignID, |
175 | Address, AddressExpression, DI); |
176 | } |
177 | |
178 | DbgVariableRecord * |
179 | DbgVariableRecord::createDbgVariableRecord(Value *Location, DILocalVariable *DV, |
180 | DIExpression *Expr, |
181 | const DILocation *DI) { |
182 | return new DbgVariableRecord(ValueAsMetadata::get(V: Location), DV, Expr, DI, |
183 | LocationType::Value); |
184 | } |
185 | |
186 | DbgVariableRecord *DbgVariableRecord::createDbgVariableRecord( |
187 | Value *Location, DILocalVariable *DV, DIExpression *Expr, |
188 | const DILocation *DI, DbgVariableRecord &InsertBefore) { |
189 | auto *NewDbgVariableRecord = createDbgVariableRecord(Location, DV, Expr, DI); |
190 | NewDbgVariableRecord->insertBefore(InsertBefore: &InsertBefore); |
191 | return NewDbgVariableRecord; |
192 | } |
193 | |
194 | DbgVariableRecord *DbgVariableRecord::createDVRDeclare(Value *Address, |
195 | DILocalVariable *DV, |
196 | DIExpression *Expr, |
197 | const DILocation *DI) { |
198 | return new DbgVariableRecord(ValueAsMetadata::get(V: Address), DV, Expr, DI, |
199 | LocationType::Declare); |
200 | } |
201 | |
202 | DbgVariableRecord * |
203 | DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV, |
204 | DIExpression *Expr, const DILocation *DI, |
205 | DbgVariableRecord &InsertBefore) { |
206 | auto *NewDVRDeclare = createDVRDeclare(Address, DV, Expr, DI); |
207 | NewDVRDeclare->insertBefore(InsertBefore: &InsertBefore); |
208 | return NewDVRDeclare; |
209 | } |
210 | |
211 | DbgVariableRecord *DbgVariableRecord::createDVRAssign( |
212 | Value *Val, DILocalVariable *Variable, DIExpression *Expression, |
213 | DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression, |
214 | const DILocation *DI) { |
215 | return new DbgVariableRecord(ValueAsMetadata::get(V: Val), Variable, Expression, |
216 | AssignID, ValueAsMetadata::get(V: Address), |
217 | AddressExpression, DI); |
218 | } |
219 | |
220 | DbgVariableRecord *DbgVariableRecord::createLinkedDVRAssign( |
221 | Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, |
222 | DIExpression *Expression, Value *Address, DIExpression *AddressExpression, |
223 | const DILocation *DI) { |
224 | auto *Link = LinkedInstr->getMetadata(KindID: LLVMContext::MD_DIAssignID); |
225 | assert(Link && "Linked instruction must have DIAssign metadata attached" ); |
226 | auto *NewDVRAssign = DbgVariableRecord::createDVRAssign( |
227 | Val, Variable, Expression, AssignID: cast<DIAssignID>(Val: Link), Address, |
228 | AddressExpression, DI); |
229 | LinkedInstr->getParent()->insertDbgRecordAfter(DR: NewDVRAssign, I: LinkedInstr); |
230 | return NewDVRAssign; |
231 | } |
232 | |
233 | iterator_range<DbgVariableRecord::location_op_iterator> |
234 | DbgVariableRecord::location_ops() const { |
235 | auto *MD = getRawLocation(); |
236 | // If a Value has been deleted, the "location" for this DbgVariableRecord will |
237 | // be replaced by nullptr. Return an empty range. |
238 | if (!MD) |
239 | return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), |
240 | location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; |
241 | |
242 | // If operand is ValueAsMetadata, return a range over just that operand. |
243 | if (auto *VAM = dyn_cast<ValueAsMetadata>(Val: MD)) |
244 | return {location_op_iterator(VAM), location_op_iterator(VAM + 1)}; |
245 | |
246 | // If operand is DIArgList, return a range over its args. |
247 | if (auto *AL = dyn_cast<DIArgList>(Val: MD)) |
248 | return {location_op_iterator(AL->args_begin()), |
249 | location_op_iterator(AL->args_end())}; |
250 | |
251 | // Operand is an empty metadata tuple, so return empty iterator. |
252 | assert(cast<MDNode>(MD)->getNumOperands() == 0); |
253 | return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), |
254 | location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; |
255 | } |
256 | |
257 | unsigned DbgVariableRecord::getNumVariableLocationOps() const { |
258 | if (hasArgList()) |
259 | return cast<DIArgList>(Val: getRawLocation())->getArgs().size(); |
260 | return 1; |
261 | } |
262 | |
263 | Value *DbgVariableRecord::getVariableLocationOp(unsigned OpIdx) const { |
264 | auto *MD = getRawLocation(); |
265 | if (!MD) |
266 | return nullptr; |
267 | |
268 | if (auto *AL = dyn_cast<DIArgList>(Val: MD)) |
269 | return AL->getArgs()[OpIdx]->getValue(); |
270 | if (isa<MDNode>(Val: MD)) |
271 | return nullptr; |
272 | assert(isa<ValueAsMetadata>(MD) && |
273 | "Attempted to get location operand from DbgVariableRecord with none." ); |
274 | auto *V = cast<ValueAsMetadata>(Val: MD); |
275 | assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a " |
276 | "single location operand." ); |
277 | return V->getValue(); |
278 | } |
279 | |
280 | static ValueAsMetadata *getAsMetadata(Value *V) { |
281 | return isa<MetadataAsValue>(Val: V) ? dyn_cast<ValueAsMetadata>( |
282 | Val: cast<MetadataAsValue>(Val: V)->getMetadata()) |
283 | : ValueAsMetadata::get(V); |
284 | } |
285 | |
286 | void DbgVariableRecord::replaceVariableLocationOp(Value *OldValue, |
287 | Value *NewValue, |
288 | bool AllowEmpty) { |
289 | assert(NewValue && "Values must be non-null" ); |
290 | |
291 | bool DbgAssignAddrReplaced = isDbgAssign() && OldValue == getAddress(); |
292 | if (DbgAssignAddrReplaced) |
293 | setAddress(NewValue); |
294 | |
295 | auto Locations = location_ops(); |
296 | auto OldIt = find(Range&: Locations, Val: OldValue); |
297 | if (OldIt == Locations.end()) { |
298 | if (AllowEmpty || DbgAssignAddrReplaced) |
299 | return; |
300 | llvm_unreachable("OldValue must be a current location" ); |
301 | } |
302 | |
303 | if (!hasArgList()) { |
304 | // Set our location to be the MAV wrapping the new Value. |
305 | setRawLocation(isa<MetadataAsValue>(Val: NewValue) |
306 | ? cast<MetadataAsValue>(Val: NewValue)->getMetadata() |
307 | : ValueAsMetadata::get(V: NewValue)); |
308 | return; |
309 | } |
310 | |
311 | // We must be referring to a DIArgList, produce a new operands vector with the |
312 | // old value replaced, generate a new DIArgList and set it as our location. |
313 | SmallVector<ValueAsMetadata *, 4> MDs; |
314 | ValueAsMetadata *NewOperand = getAsMetadata(V: NewValue); |
315 | for (auto *VMD : Locations) |
316 | MDs.push_back(Elt: VMD == *OldIt ? NewOperand : getAsMetadata(V: VMD)); |
317 | setRawLocation(DIArgList::get(Context&: getVariableLocationOp(OpIdx: 0)->getContext(), Args: MDs)); |
318 | } |
319 | |
320 | void DbgVariableRecord::replaceVariableLocationOp(unsigned OpIdx, |
321 | Value *NewValue) { |
322 | assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index" ); |
323 | |
324 | if (!hasArgList()) { |
325 | setRawLocation(isa<MetadataAsValue>(Val: NewValue) |
326 | ? cast<MetadataAsValue>(Val: NewValue)->getMetadata() |
327 | : ValueAsMetadata::get(V: NewValue)); |
328 | return; |
329 | } |
330 | |
331 | SmallVector<ValueAsMetadata *, 4> MDs; |
332 | ValueAsMetadata *NewOperand = getAsMetadata(V: NewValue); |
333 | for (unsigned Idx = 0; Idx < getNumVariableLocationOps(); ++Idx) |
334 | MDs.push_back(Elt: Idx == OpIdx ? NewOperand |
335 | : getAsMetadata(V: getVariableLocationOp(OpIdx: Idx))); |
336 | |
337 | setRawLocation(DIArgList::get(Context&: getVariableLocationOp(OpIdx: 0)->getContext(), Args: MDs)); |
338 | } |
339 | |
340 | void DbgVariableRecord::addVariableLocationOps(ArrayRef<Value *> NewValues, |
341 | DIExpression *NewExpr) { |
342 | assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + |
343 | NewValues.size()) && |
344 | "NewExpr for debug variable intrinsic does not reference every " |
345 | "location operand." ); |
346 | assert(!is_contained(NewValues, nullptr) && "New values must be non-null" ); |
347 | setExpression(NewExpr); |
348 | SmallVector<ValueAsMetadata *, 4> MDs; |
349 | for (auto *VMD : location_ops()) |
350 | MDs.push_back(Elt: getAsMetadata(V: VMD)); |
351 | for (auto *VMD : NewValues) |
352 | MDs.push_back(Elt: getAsMetadata(V: VMD)); |
353 | setRawLocation(DIArgList::get(Context&: getVariableLocationOp(OpIdx: 0)->getContext(), Args: MDs)); |
354 | } |
355 | |
356 | void DbgVariableRecord::setKillLocation() { |
357 | // TODO: When/if we remove duplicate values from DIArgLists, we don't need |
358 | // this set anymore. |
359 | SmallPtrSet<Value *, 4> RemovedValues; |
360 | for (Value *OldValue : location_ops()) { |
361 | if (!RemovedValues.insert(Ptr: OldValue).second) |
362 | continue; |
363 | Value *Poison = PoisonValue::get(T: OldValue->getType()); |
364 | replaceVariableLocationOp(OldValue, NewValue: Poison); |
365 | } |
366 | } |
367 | |
368 | bool DbgVariableRecord::isKillLocation() const { |
369 | return (getNumVariableLocationOps() == 0 && |
370 | !getExpression()->isComplex()) || |
371 | any_of(Range: location_ops(), P: [](Value *V) { return isa<UndefValue>(Val: V); }); |
372 | } |
373 | |
374 | std::optional<uint64_t> DbgVariableRecord::getFragmentSizeInBits() const { |
375 | if (auto Fragment = getExpression()->getFragmentInfo()) |
376 | return Fragment->SizeInBits; |
377 | return getVariable()->getSizeInBits(); |
378 | } |
379 | |
380 | DbgRecord *DbgRecord::clone() const { |
381 | switch (RecordKind) { |
382 | case ValueKind: |
383 | return cast<DbgVariableRecord>(Val: this)->clone(); |
384 | case LabelKind: |
385 | return cast<DbgLabelRecord>(Val: this)->clone(); |
386 | }; |
387 | llvm_unreachable("unsupported DbgRecord kind" ); |
388 | } |
389 | |
390 | DbgVariableRecord *DbgVariableRecord::clone() const { |
391 | return new DbgVariableRecord(*this); |
392 | } |
393 | |
394 | DbgLabelRecord *DbgLabelRecord::clone() const { |
395 | return new DbgLabelRecord(getLabel(), getDebugLoc()); |
396 | } |
397 | |
398 | DbgVariableIntrinsic * |
399 | DbgVariableRecord::createDebugIntrinsic(Module *M, |
400 | Instruction *InsertBefore) const { |
401 | [[maybe_unused]] DICompileUnit *Unit = |
402 | getDebugLoc().get()->getScope()->getSubprogram()->getUnit(); |
403 | assert(M && Unit && |
404 | "Cannot clone from BasicBlock that is not part of a Module or " |
405 | "DICompileUnit!" ); |
406 | LLVMContext &Context = getDebugLoc()->getContext(); |
407 | Function *IntrinsicFn; |
408 | |
409 | // Work out what sort of intrinsic we're going to produce. |
410 | switch (getType()) { |
411 | case DbgVariableRecord::LocationType::Declare: |
412 | IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::id: dbg_declare); |
413 | break; |
414 | case DbgVariableRecord::LocationType::Value: |
415 | IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::id: dbg_value); |
416 | break; |
417 | case DbgVariableRecord::LocationType::Assign: |
418 | IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::id: dbg_assign); |
419 | break; |
420 | case DbgVariableRecord::LocationType::End: |
421 | case DbgVariableRecord::LocationType::Any: |
422 | llvm_unreachable("Invalid LocationType" ); |
423 | } |
424 | |
425 | // Create the intrinsic from this DbgVariableRecord's information, optionally |
426 | // insert into the target location. |
427 | DbgVariableIntrinsic *DVI; |
428 | assert(getRawLocation() && |
429 | "DbgVariableRecord's RawLocation should be non-null." ); |
430 | if (isDbgAssign()) { |
431 | Value *AssignArgs[] = { |
432 | MetadataAsValue::get(Context, MD: getRawLocation()), |
433 | MetadataAsValue::get(Context, MD: getVariable()), |
434 | MetadataAsValue::get(Context, MD: getExpression()), |
435 | MetadataAsValue::get(Context, MD: getAssignID()), |
436 | MetadataAsValue::get(Context, MD: getRawAddress()), |
437 | MetadataAsValue::get(Context, MD: getAddressExpression())}; |
438 | DVI = cast<DbgVariableIntrinsic>(Val: CallInst::Create( |
439 | Ty: IntrinsicFn->getFunctionType(), Func: IntrinsicFn, Args: AssignArgs)); |
440 | } else { |
441 | Value *Args[] = {MetadataAsValue::get(Context, MD: getRawLocation()), |
442 | MetadataAsValue::get(Context, MD: getVariable()), |
443 | MetadataAsValue::get(Context, MD: getExpression())}; |
444 | DVI = cast<DbgVariableIntrinsic>( |
445 | Val: CallInst::Create(Ty: IntrinsicFn->getFunctionType(), Func: IntrinsicFn, Args)); |
446 | } |
447 | DVI->setTailCall(); |
448 | DVI->setDebugLoc(getDebugLoc()); |
449 | if (InsertBefore) |
450 | DVI->insertBefore(InsertPos: InsertBefore); |
451 | |
452 | return DVI; |
453 | } |
454 | |
455 | DbgLabelInst * |
456 | DbgLabelRecord::createDebugIntrinsic(Module *M, |
457 | Instruction *InsertBefore) const { |
458 | auto *LabelFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_label); |
459 | Value *Args[] = { |
460 | MetadataAsValue::get(Context&: getDebugLoc()->getContext(), MD: getLabel())}; |
461 | DbgLabelInst *DbgLabel = cast<DbgLabelInst>( |
462 | CallInst::Create(LabelFn->getFunctionType(), LabelFn, Args)); |
463 | DbgLabel->setTailCall(); |
464 | DbgLabel->setDebugLoc(getDebugLoc()); |
465 | if (InsertBefore) |
466 | DbgLabel->insertBefore(InsertPos: InsertBefore); |
467 | return DbgLabel; |
468 | } |
469 | |
470 | Value *DbgVariableRecord::getAddress() const { |
471 | auto *MD = getRawAddress(); |
472 | if (auto *V = dyn_cast<ValueAsMetadata>(Val: MD)) |
473 | return V->getValue(); |
474 | |
475 | // When the value goes to null, it gets replaced by an empty MDNode. |
476 | assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode" ); |
477 | return nullptr; |
478 | } |
479 | |
480 | DIAssignID *DbgVariableRecord::getAssignID() const { |
481 | return cast<DIAssignID>(Val: DebugValues[2]); |
482 | } |
483 | |
484 | void DbgVariableRecord::setAssignId(DIAssignID *New) { |
485 | resetDebugValue(Idx: 2, DebugValue: New); |
486 | } |
487 | |
488 | void DbgVariableRecord::setKillAddress() { |
489 | resetDebugValue( |
490 | Idx: 1, DebugValue: ValueAsMetadata::get(V: UndefValue::get(T: getAddress()->getType()))); |
491 | } |
492 | |
493 | bool DbgVariableRecord::isKillAddress() const { |
494 | Value *Addr = getAddress(); |
495 | return !Addr || isa<UndefValue>(Val: Addr); |
496 | } |
497 | |
498 | const Instruction *DbgRecord::getInstruction() const { |
499 | return Marker->MarkedInstr; |
500 | } |
501 | |
502 | const BasicBlock *DbgRecord::getParent() const { |
503 | return Marker->MarkedInstr->getParent(); |
504 | } |
505 | |
506 | BasicBlock *DbgRecord::getParent() { return Marker->MarkedInstr->getParent(); } |
507 | |
508 | BasicBlock *DbgRecord::getBlock() { return Marker->getParent(); } |
509 | |
510 | const BasicBlock *DbgRecord::getBlock() const { return Marker->getParent(); } |
511 | |
512 | Function *DbgRecord::getFunction() { return getBlock()->getParent(); } |
513 | |
514 | const Function *DbgRecord::getFunction() const { |
515 | return getBlock()->getParent(); |
516 | } |
517 | |
518 | Module *DbgRecord::getModule() { return getFunction()->getParent(); } |
519 | |
520 | const Module *DbgRecord::getModule() const { |
521 | return getFunction()->getParent(); |
522 | } |
523 | |
524 | LLVMContext &DbgRecord::getContext() { return getBlock()->getContext(); } |
525 | |
526 | const LLVMContext &DbgRecord::getContext() const { |
527 | return getBlock()->getContext(); |
528 | } |
529 | |
530 | void DbgRecord::insertBefore(DbgRecord *InsertBefore) { |
531 | assert(!getMarker() && |
532 | "Cannot insert a DbgRecord that is already has a DbgMarker!" ); |
533 | assert(InsertBefore->getMarker() && |
534 | "Cannot insert a DbgRecord before a DbgRecord that does not have a " |
535 | "DbgMarker!" ); |
536 | InsertBefore->getMarker()->insertDbgRecord(New: this, InsertBefore); |
537 | } |
538 | void DbgRecord::insertAfter(DbgRecord *InsertAfter) { |
539 | assert(!getMarker() && |
540 | "Cannot insert a DbgRecord that is already has a DbgMarker!" ); |
541 | assert(InsertAfter->getMarker() && |
542 | "Cannot insert a DbgRecord after a DbgRecord that does not have a " |
543 | "DbgMarker!" ); |
544 | InsertAfter->getMarker()->insertDbgRecordAfter(New: this, InsertAfter); |
545 | } |
546 | void DbgRecord::moveBefore(DbgRecord *MoveBefore) { |
547 | assert(getMarker() && |
548 | "Canot move a DbgRecord that does not currently have a DbgMarker!" ); |
549 | removeFromParent(); |
550 | insertBefore(InsertBefore: MoveBefore); |
551 | } |
552 | void DbgRecord::moveAfter(DbgRecord *MoveAfter) { |
553 | assert(getMarker() && |
554 | "Canot move a DbgRecord that does not currently have a DbgMarker!" ); |
555 | removeFromParent(); |
556 | insertAfter(InsertAfter: MoveAfter); |
557 | } |
558 | |
559 | /////////////////////////////////////////////////////////////////////////////// |
560 | |
561 | // An empty, global, DbgMarker for the purpose of describing empty ranges of |
562 | // DbgRecords. |
563 | DbgMarker DbgMarker::EmptyDbgMarker; |
564 | |
565 | void DbgMarker::dropDbgRecords() { |
566 | while (!StoredDbgRecords.empty()) { |
567 | auto It = StoredDbgRecords.begin(); |
568 | DbgRecord *DR = &*It; |
569 | StoredDbgRecords.erase(I: It); |
570 | DR->deleteRecord(); |
571 | } |
572 | } |
573 | |
574 | void DbgMarker::dropOneDbgRecord(DbgRecord *DR) { |
575 | assert(DR->getMarker() == this); |
576 | StoredDbgRecords.erase(I: DR->getIterator()); |
577 | DR->deleteRecord(); |
578 | } |
579 | |
580 | const BasicBlock *DbgMarker::getParent() const { |
581 | return MarkedInstr->getParent(); |
582 | } |
583 | |
584 | BasicBlock *DbgMarker::getParent() { return MarkedInstr->getParent(); } |
585 | |
586 | void DbgMarker::removeMarker() { |
587 | // Are there any DbgRecords in this DbgMarker? If not, nothing to preserve. |
588 | Instruction *Owner = MarkedInstr; |
589 | if (StoredDbgRecords.empty()) { |
590 | eraseFromParent(); |
591 | Owner->DebugMarker = nullptr; |
592 | return; |
593 | } |
594 | |
595 | // The attached DbgRecords need to be preserved; attach them to the next |
596 | // instruction. If there isn't a next instruction, put them on the |
597 | // "trailing" list. |
598 | DbgMarker *NextMarker = Owner->getParent()->getNextMarker(I: Owner); |
599 | if (NextMarker) { |
600 | NextMarker->absorbDebugValues(Src&: *this, InsertAtHead: true); |
601 | eraseFromParent(); |
602 | } else { |
603 | // We can avoid a deallocation -- just store this marker onto the next |
604 | // instruction. Unless we're at the end of the block, in which case this |
605 | // marker becomes the trailing marker of a degenerate block. |
606 | BasicBlock::iterator NextIt = std::next(x: Owner->getIterator()); |
607 | if (NextIt == getParent()->end()) { |
608 | getParent()->setTrailingDbgRecords(this); |
609 | MarkedInstr = nullptr; |
610 | } else { |
611 | NextIt->DebugMarker = this; |
612 | MarkedInstr = &*NextIt; |
613 | } |
614 | } |
615 | Owner->DebugMarker = nullptr; |
616 | } |
617 | |
618 | void DbgMarker::removeFromParent() { |
619 | MarkedInstr->DebugMarker = nullptr; |
620 | MarkedInstr = nullptr; |
621 | } |
622 | |
623 | void DbgMarker::eraseFromParent() { |
624 | if (MarkedInstr) |
625 | removeFromParent(); |
626 | dropDbgRecords(); |
627 | delete this; |
628 | } |
629 | |
630 | iterator_range<DbgRecord::self_iterator> DbgMarker::getDbgRecordRange() { |
631 | return make_range(x: StoredDbgRecords.begin(), y: StoredDbgRecords.end()); |
632 | } |
633 | iterator_range<DbgRecord::const_self_iterator> |
634 | DbgMarker::getDbgRecordRange() const { |
635 | return make_range(x: StoredDbgRecords.begin(), y: StoredDbgRecords.end()); |
636 | } |
637 | |
638 | void DbgRecord::removeFromParent() { |
639 | getMarker()->StoredDbgRecords.erase(I: getIterator()); |
640 | Marker = nullptr; |
641 | } |
642 | |
643 | void DbgRecord::eraseFromParent() { |
644 | removeFromParent(); |
645 | deleteRecord(); |
646 | } |
647 | |
648 | void DbgMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { |
649 | auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); |
650 | StoredDbgRecords.insert(I: It, Node&: *New); |
651 | New->setMarker(this); |
652 | } |
653 | void DbgMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { |
654 | assert(InsertBefore->getMarker() == this && |
655 | "DbgRecord 'InsertBefore' must be contained in this DbgMarker!" ); |
656 | StoredDbgRecords.insert(I: InsertBefore->getIterator(), Node&: *New); |
657 | New->setMarker(this); |
658 | } |
659 | void DbgMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { |
660 | assert(InsertAfter->getMarker() == this && |
661 | "DbgRecord 'InsertAfter' must be contained in this DbgMarker!" ); |
662 | StoredDbgRecords.insert(I: ++(InsertAfter->getIterator()), Node&: *New); |
663 | New->setMarker(this); |
664 | } |
665 | |
666 | void DbgMarker::absorbDebugValues(DbgMarker &Src, bool InsertAtHead) { |
667 | auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); |
668 | for (DbgRecord &DVR : Src.StoredDbgRecords) |
669 | DVR.setMarker(this); |
670 | |
671 | StoredDbgRecords.splice(I: It, L2&: Src.StoredDbgRecords); |
672 | } |
673 | |
674 | void DbgMarker::absorbDebugValues( |
675 | iterator_range<DbgRecord::self_iterator> Range, DbgMarker &Src, |
676 | bool InsertAtHead) { |
677 | for (DbgRecord &DR : Range) |
678 | DR.setMarker(this); |
679 | |
680 | auto InsertPos = |
681 | (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); |
682 | |
683 | StoredDbgRecords.splice(I: InsertPos, Src.StoredDbgRecords, First: Range.begin(), |
684 | Last: Range.end()); |
685 | } |
686 | |
687 | iterator_range<simple_ilist<DbgRecord>::iterator> DbgMarker::cloneDebugInfoFrom( |
688 | DbgMarker *From, std::optional<simple_ilist<DbgRecord>::iterator> from_here, |
689 | bool InsertAtHead) { |
690 | DbgRecord *First = nullptr; |
691 | // Work out what range of DbgRecords to clone: normally all the contents of |
692 | // the "From" marker, optionally we can start from the from_here position down |
693 | // to end(). |
694 | auto Range = |
695 | make_range(x: From->StoredDbgRecords.begin(), y: From->StoredDbgRecords.end()); |
696 | if (from_here.has_value()) |
697 | Range = make_range(x: *from_here, y: From->StoredDbgRecords.end()); |
698 | |
699 | // Clone each DbgVariableRecord and insert into StoreDbgVariableRecords; |
700 | // optionally place them at the start or the end of the list. |
701 | auto Pos = (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); |
702 | for (DbgRecord &DR : Range) { |
703 | DbgRecord *New = DR.clone(); |
704 | New->setMarker(this); |
705 | StoredDbgRecords.insert(I: Pos, Node&: *New); |
706 | if (!First) |
707 | First = New; |
708 | } |
709 | |
710 | if (!First) |
711 | return {StoredDbgRecords.end(), StoredDbgRecords.end()}; |
712 | |
713 | if (InsertAtHead) |
714 | // If InsertAtHead is set, we cloned a range onto the front of of the |
715 | // StoredDbgRecords collection, return that range. |
716 | return {StoredDbgRecords.begin(), Pos}; |
717 | else |
718 | // We inserted a block at the end, return that range. |
719 | return {First->getIterator(), StoredDbgRecords.end()}; |
720 | } |
721 | |
722 | } // end namespace llvm |
723 | |