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