LLVM 23.0.0git
DebugInfoMetadata.cpp
Go to the documentation of this file.
1//===- DebugInfoMetadata.cpp - Implement debug info metadata --------------===//
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// This file implements the debug info Metadata classes.
10//
11//===----------------------------------------------------------------------===//
12
14#include "LLVMContextImpl.h"
15#include "MetadataImpl.h"
16#include "llvm/ADT/SetVector.h"
20#include "llvm/IR/Function.h"
22#include "llvm/IR/Type.h"
23#include "llvm/IR/Value.h"
26
27#include <numeric>
28#include <optional>
29
30using namespace llvm;
31
32namespace llvm {
33// Use FS-AFDO discriminator.
35 "enable-fs-discriminator", cl::Hidden,
36 cl::desc("Enable adding flow sensitive discriminators"));
37
38// When true, preserves line and column number by picking one of the merged
39// location info in a deterministic manner to assist sample based PGO.
41 "pick-merged-source-locations", cl::init(false), cl::Hidden,
42 cl::desc("Preserve line and column number when merging locations."));
43} // namespace llvm
44
46 return (getTag() == dwarf::DW_TAG_LLVM_ptrauth_type ? 0 : SubclassData32);
47}
48
49const DIExpression::FragmentInfo DebugVariable::DefaultFragment = {
50 std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()};
51
53 : Variable(DVR->getVariable()),
54 Fragment(DVR->getExpression()->getFragmentInfo()),
55 InlinedAt(DVR->getDebugLoc().getInlinedAt()) {}
56
60
61DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
62 unsigned Column, uint64_t AtomGroup, uint8_t AtomRank,
63 ArrayRef<Metadata *> MDs, bool ImplicitCode)
64 : MDNode(C, DILocationKind, Storage, MDs), AtomGroup(AtomGroup),
65 AtomRank(AtomRank) {
66 assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
67 if (AtomGroup)
68 C.updateDILocationAtomGroupWaterline(AtomGroup + 1);
69
70 assert((MDs.size() == 1 || MDs.size() == 2) &&
71 "Expected a scope and optional inlined-at");
72 // Set line and column.
73 assert(Column < (1u << 16) && "Expected 16-bit column");
74
75 SubclassData32 = Line;
76 SubclassData16 = Column;
77
78 setImplicitCode(ImplicitCode);
79}
80
81static void adjustColumn(unsigned &Column) {
82 // Set to unknown on overflow. We only have 16 bits to play with here.
83 if (Column >= (1u << 16))
84 Column = 0;
85}
86
87DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
88 unsigned Column, Metadata *Scope,
89 Metadata *InlinedAt, bool ImplicitCode,
90 uint64_t AtomGroup, uint8_t AtomRank,
91 StorageType Storage, bool ShouldCreate) {
92 // Fixup column.
94
95 if (Storage == Uniqued) {
96 if (auto *N = getUniqued(Context.pImpl->DILocations,
97 DILocationInfo::KeyTy(Line, Column, Scope,
99 AtomGroup, AtomRank)))
100 return N;
101 if (!ShouldCreate)
102 return nullptr;
103 } else {
104 assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
105 }
106
108 Ops.push_back(Scope);
109 if (InlinedAt)
110 Ops.push_back(InlinedAt);
111 return storeImpl(new (Ops.size(), Storage)
112 DILocation(Context, Storage, Line, Column, AtomGroup,
113 AtomRank, Ops, ImplicitCode),
114 Storage, Context.pImpl->DILocations);
115}
116
118 if (Locs.empty())
119 return nullptr;
120 if (Locs.size() == 1)
121 return Locs[0];
122 auto *Merged = Locs[0];
123 for (DILocation *L : llvm::drop_begin(Locs)) {
124 Merged = getMergedLocation(Merged, L);
125 if (Merged == nullptr)
126 break;
127 }
128 return Merged;
129}
130
132 DIScope *NewParent) {
133 TempMDNode ClonedScope = LBB->clone();
134 cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent);
136 MDNode::replaceWithUniqued(std::move(ClonedScope)));
137}
138
139using LineColumn = std::pair<unsigned /* Line */, unsigned /* Column */>;
140
141/// Returns the location of DILocalScope, if present, or a default value.
143 assert(isa<DILocalScope>(S) && "Expected DILocalScope.");
144
146 return Default;
147 if (auto *LB = dyn_cast<DILexicalBlock>(S))
148 return {LB->getLine(), LB->getColumn()};
149 if (auto *SP = dyn_cast<DISubprogram>(S))
150 return {SP->getLine(), 0u};
151
152 llvm_unreachable("Unhandled type of DILocalScope.");
153}
154
155// Returns the nearest matching scope inside a subprogram.
156template <typename MatcherT>
157static std::pair<DIScope *, LineColumn>
159 MatcherT Matcher;
160
161 DIScope *S1 = L1->getScope();
162 DIScope *S2 = L2->getScope();
163
164 LineColumn Loc1(L1->getLine(), L1->getColumn());
165 for (; S1; S1 = S1->getScope()) {
166 Loc1 = getLocalScopeLocationOr(S1, Loc1);
167 Matcher.insert(S1, Loc1);
169 break;
170 }
171
172 LineColumn Loc2(L2->getLine(), L2->getColumn());
173 for (; S2; S2 = S2->getScope()) {
174 Loc2 = getLocalScopeLocationOr(S2, Loc2);
175
176 if (DIScope *S = Matcher.match(S2, Loc2))
177 return std::make_pair(S, Loc2);
178
179 if (isa<DISubprogram>(S2))
180 break;
181 }
182 return std::make_pair(nullptr, LineColumn(L2->getLine(), L2->getColumn()));
183}
184
185// Matches equal scopes.
188
189 void insert(DIScope *S, LineColumn Loc) { Scopes.insert(S); }
190
192 return Scopes.contains(S) ? S : nullptr;
193 }
194};
195
196// Matches scopes with the same location.
199 8>
201
203 Scopes[{S->getFile(), Loc}].insert(S);
204 }
205
207 auto ScopesAtLoc = Scopes.find({S->getFile(), Loc});
208 // No scope found with the given location.
209 if (ScopesAtLoc == Scopes.end())
210 return nullptr;
211
212 // Prefer S over other scopes with the same location.
213 if (ScopesAtLoc->second.contains(S))
214 return S;
215
216 if (!ScopesAtLoc->second.empty())
217 return *ScopesAtLoc->second.begin();
218
219 llvm_unreachable("Scopes must not have empty entries.");
220 }
221};
222
223DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
224 if (LocA == LocB)
225 return LocA;
226
227 // For some use cases (SamplePGO), it is important to retain distinct source
228 // locations. When this flag is set, we choose arbitrarily between A and B,
229 // rather than computing a merged location using line 0, which is typically
230 // not useful for PGO. If one of them is null, then try to return one which is
231 // valid.
233 if (!LocA || !LocB)
234 return LocA ? LocA : LocB;
235
236 auto A = std::make_tuple(LocA->getLine(), LocA->getColumn(),
237 LocA->getDiscriminator(), LocA->getFilename(),
238 LocA->getDirectory());
239 auto B = std::make_tuple(LocB->getLine(), LocB->getColumn(),
240 LocB->getDiscriminator(), LocB->getFilename(),
241 LocB->getDirectory());
242 return A < B ? LocA : LocB;
243 }
244
245 if (!LocA || !LocB)
246 return nullptr;
247
248 LLVMContext &C = LocA->getContext();
249
250 using LocVec = SmallVector<const DILocation *>;
251 LocVec ALocs;
252 LocVec BLocs;
254 4>
255 ALookup;
256
257 // Walk through LocA and its inlined-at locations, populate them in ALocs and
258 // save the index for the subprogram and inlined-at pair, which we use to find
259 // a matching starting location in LocB's chain.
260 for (auto [L, I] = std::make_pair(LocA, 0U); L; L = L->getInlinedAt(), I++) {
261 ALocs.push_back(L);
262 auto Res = ALookup.try_emplace(
263 {L->getScope()->getSubprogram(), L->getInlinedAt()}, I);
264 assert(Res.second && "Multiple <SP, InlinedAt> pairs in a location chain?");
265 (void)Res;
266 }
267
268 LocVec::reverse_iterator ARIt = ALocs.rend();
269 LocVec::reverse_iterator BRIt = BLocs.rend();
270
271 // Populate BLocs and look for a matching starting location, the first
272 // location with the same subprogram and inlined-at location as in LocA's
273 // chain. Since the two locations have the same inlined-at location we do
274 // not need to look at those parts of the chains.
275 for (auto [L, I] = std::make_pair(LocB, 0U); L; L = L->getInlinedAt(), I++) {
276 BLocs.push_back(L);
277
278 if (ARIt != ALocs.rend())
279 // We have already found a matching starting location.
280 continue;
281
282 auto IT = ALookup.find({L->getScope()->getSubprogram(), L->getInlinedAt()});
283 if (IT == ALookup.end())
284 continue;
285
286 // The + 1 is to account for the &*rev_it = &(it - 1) relationship.
287 ARIt = LocVec::reverse_iterator(ALocs.begin() + IT->second + 1);
288 BRIt = LocVec::reverse_iterator(BLocs.begin() + I + 1);
289
290 // If we have found a matching starting location we do not need to add more
291 // locations to BLocs, since we will only look at location pairs preceding
292 // the matching starting location, and adding more elements to BLocs could
293 // invalidate the iterator that we initialized here.
294 break;
295 }
296
297 // Merge the two locations if possible, using the supplied
298 // inlined-at location for the created location.
299 auto *LocAIA = LocA->getInlinedAt();
300 auto *LocBIA = LocB->getInlinedAt();
301 auto MergeLocPair = [&C, LocAIA,
302 LocBIA](const DILocation *L1, const DILocation *L2,
303 DILocation *InlinedAt) -> DILocation * {
304 if (L1 == L2)
305 return DILocation::get(C, L1->getLine(), L1->getColumn(), L1->getScope(),
306 InlinedAt, L1->isImplicitCode(),
307 L1->getAtomGroup(), L1->getAtomRank());
308
309 // If the locations originate from different subprograms we can't produce
310 // a common location.
311 if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())
312 return nullptr;
313
314 // Find nearest common scope inside subprogram.
316 assert(Scope && "No common scope in the same subprogram?");
317
318 // Try using the nearest scope with common location if files are different.
319 if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile()) {
320 auto [CommonLocScope, CommonLoc] =
322
323 // If CommonLocScope is a DILexicalBlockBase, clone it and locate
324 // a new scope inside the nearest common scope to preserve
325 // lexical blocks structure.
326 if (auto *LBB = dyn_cast<DILexicalBlockBase>(CommonLocScope);
327 LBB && LBB != Scope)
328 CommonLocScope = cloneAndReplaceParentScope(LBB, Scope);
329
330 Scope = CommonLocScope;
331
332 // If files are still different, assume that L1 and L2 were "included"
333 // from CommonLoc. Use it as merged location.
334 if (Scope->getFile() != L1->getFile() || L1->getFile() != L2->getFile())
335 return DILocation::get(C, CommonLoc.first, CommonLoc.second,
336 CommonLocScope, InlinedAt);
337 }
338
339 bool SameLine = L1->getLine() == L2->getLine();
340 bool SameCol = L1->getColumn() == L2->getColumn();
341 unsigned Line = SameLine ? L1->getLine() : 0;
342 unsigned Col = SameLine && SameCol ? L1->getColumn() : 0;
343 bool IsImplicitCode = L1->isImplicitCode() && L2->isImplicitCode();
344
345 // Discard source location atom if the line becomes 0. And there's nothing
346 // further to do if neither location has an atom number.
347 if (!SameLine || !(L1->getAtomGroup() || L2->getAtomGroup()))
348 return DILocation::get(C, Line, Col, Scope, InlinedAt, IsImplicitCode,
349 /*AtomGroup*/ 0, /*AtomRank*/ 0);
350
351 uint64_t Group = 0;
352 uint64_t Rank = 0;
353 // If we're preserving the same matching inlined-at field we can
354 // preserve the atom.
355 if (LocBIA == LocAIA && InlinedAt == LocBIA) {
356 // Deterministically keep the lowest non-zero ranking atom group
357 // number.
358 // FIXME: It would be nice if we could track that an instruction
359 // belongs to two source atoms.
360 bool UseL1Atom = [L1, L2]() {
361 if (L1->getAtomRank() == L2->getAtomRank()) {
362 // Arbitrarily choose the lowest non-zero group number.
363 if (!L1->getAtomGroup() || !L2->getAtomGroup())
364 return !L2->getAtomGroup();
365 return L1->getAtomGroup() < L2->getAtomGroup();
366 }
367 // Choose the lowest non-zero rank.
368 if (!L1->getAtomRank() || !L2->getAtomRank())
369 return !L2->getAtomRank();
370 return L1->getAtomRank() < L2->getAtomRank();
371 }();
372 Group = UseL1Atom ? L1->getAtomGroup() : L2->getAtomGroup();
373 Rank = UseL1Atom ? L1->getAtomRank() : L2->getAtomRank();
374 } else {
375 // If either instruction is part of a source atom, reassign it a new
376 // atom group. This essentially regresses to non-key-instructions
377 // behaviour (now that it's the only instruction in its group it'll
378 // probably get is_stmt applied).
379 Group = C.incNextDILocationAtomGroup();
380 Rank = 1;
381 }
382 return DILocation::get(C, Line, Col, Scope, InlinedAt, IsImplicitCode,
383 Group, Rank);
384 };
385
386 DILocation *Result = ARIt != ALocs.rend() ? (*ARIt)->getInlinedAt() : nullptr;
387
388 // If we have found a common starting location, walk up the inlined-at chains
389 // and try to produce common locations.
390 for (; ARIt != ALocs.rend() && BRIt != BLocs.rend(); ++ARIt, ++BRIt) {
391 DILocation *Tmp = MergeLocPair(*ARIt, *BRIt, Result);
392
393 if (!Tmp)
394 // We have walked up to a point in the chains where the two locations
395 // are irreconsilable. At this point Result contains the nearest common
396 // location in the inlined-at chains of LocA and LocB, so we break here.
397 break;
398
399 Result = Tmp;
400 }
401
402 if (Result)
403 return Result;
404
405 // We ended up with LocA and LocB as irreconsilable locations. Produce a
406 // location at 0:0 with one of the locations' scope. The function has
407 // historically picked A's scope, and a nullptr inlined-at location, so that
408 // behavior is mimicked here but I am not sure if this is always the correct
409 // way to handle this.
410 // Key Instructions: it's fine to drop atom group and rank here, as line 0
411 // is a nonsensical is_stmt location.
412 return DILocation::get(C, 0, 0, LocA->getScope(), nullptr, false,
413 /*AtomGroup*/ 0, /*AtomRank*/ 0);
414}
415
416std::optional<unsigned>
417DILocation::encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI) {
418 std::array<unsigned, 3> Components = {BD, DF, CI};
419 uint64_t RemainingWork = 0U;
420 // We use RemainingWork to figure out if we have no remaining components to
421 // encode. For example: if BD != 0 but DF == 0 && CI == 0, we don't need to
422 // encode anything for the latter 2.
423 // Since any of the input components is at most 32 bits, their sum will be
424 // less than 34 bits, and thus RemainingWork won't overflow.
425 RemainingWork =
426 std::accumulate(Components.begin(), Components.end(), RemainingWork);
427
428 int I = 0;
429 unsigned Ret = 0;
430 unsigned NextBitInsertionIndex = 0;
431 while (RemainingWork > 0) {
432 unsigned C = Components[I++];
433 RemainingWork -= C;
434 unsigned EC = encodeComponent(C);
435 Ret |= (EC << NextBitInsertionIndex);
436 NextBitInsertionIndex += encodingBits(C);
437 }
438
439 // Encoding may be unsuccessful because of overflow. We determine success by
440 // checking equivalence of components before & after encoding. Alternatively,
441 // we could determine Success during encoding, but the current alternative is
442 // simpler.
443 unsigned TBD, TDF, TCI = 0;
444 decodeDiscriminator(Ret, TBD, TDF, TCI);
445 if (TBD == BD && TDF == DF && TCI == CI)
446 return Ret;
447 return std::nullopt;
448}
449
458
460 return StringSwitch<DIFlags>(Flag)
461#define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME)
462#include "llvm/IR/DebugInfoFlags.def"
463 .Default(DINode::FlagZero);
464}
465
467 switch (Flag) {
468#define HANDLE_DI_FLAG(ID, NAME) \
469 case Flag##NAME: \
470 return "DIFlag" #NAME;
471#include "llvm/IR/DebugInfoFlags.def"
472 }
473 return "";
474}
475
477 SmallVectorImpl<DIFlags> &SplitFlags) {
478 // Flags that are packed together need to be specially handled, so
479 // that, for example, we emit "DIFlagPublic" and not
480 // "DIFlagPrivate | DIFlagProtected".
481 if (DIFlags A = Flags & FlagAccessibility) {
482 if (A == FlagPrivate)
483 SplitFlags.push_back(FlagPrivate);
484 else if (A == FlagProtected)
485 SplitFlags.push_back(FlagProtected);
486 else
487 SplitFlags.push_back(FlagPublic);
488 Flags &= ~A;
489 }
490 if (DIFlags R = Flags & FlagPtrToMemberRep) {
491 if (R == FlagSingleInheritance)
492 SplitFlags.push_back(FlagSingleInheritance);
493 else if (R == FlagMultipleInheritance)
494 SplitFlags.push_back(FlagMultipleInheritance);
495 else
496 SplitFlags.push_back(FlagVirtualInheritance);
497 Flags &= ~R;
498 }
499 if ((Flags & FlagIndirectVirtualBase) == FlagIndirectVirtualBase) {
500 Flags &= ~FlagIndirectVirtualBase;
501 SplitFlags.push_back(FlagIndirectVirtualBase);
502 }
503
504#define HANDLE_DI_FLAG(ID, NAME) \
505 if (DIFlags Bit = Flags & Flag##NAME) { \
506 SplitFlags.push_back(Bit); \
507 Flags &= ~Bit; \
508 }
509#include "llvm/IR/DebugInfoFlags.def"
510 return Flags;
511}
512
514 if (auto *T = dyn_cast<DIType>(this))
515 return T->getScope();
516
517 if (auto *SP = dyn_cast<DISubprogram>(this))
518 return SP->getScope();
519
520 if (auto *LB = dyn_cast<DILexicalBlockBase>(this))
521 return LB->getScope();
522
523 if (auto *NS = dyn_cast<DINamespace>(this))
524 return NS->getScope();
525
526 if (auto *CB = dyn_cast<DICommonBlock>(this))
527 return CB->getScope();
528
529 if (auto *M = dyn_cast<DIModule>(this))
530 return M->getScope();
531
532 assert((isa<DIFile>(this) || isa<DICompileUnit>(this)) &&
533 "Unhandled type of scope.");
534 return nullptr;
535}
536
538 if (auto *T = dyn_cast<DIType>(this))
539 return T->getName();
540 if (auto *SP = dyn_cast<DISubprogram>(this))
541 return SP->getName();
542 if (auto *NS = dyn_cast<DINamespace>(this))
543 return NS->getName();
544 if (auto *CB = dyn_cast<DICommonBlock>(this))
545 return CB->getName();
546 if (auto *M = dyn_cast<DIModule>(this))
547 return M->getName();
549 isa<DICompileUnit>(this)) &&
550 "Unhandled type of scope.");
551 return "";
552}
553
554#ifndef NDEBUG
555static bool isCanonical(const MDString *S) {
556 return !S || !S->getString().empty();
557}
558#endif
559
561GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag,
562 MDString *Header,
563 ArrayRef<Metadata *> DwarfOps,
564 StorageType Storage, bool ShouldCreate) {
565 unsigned Hash = 0;
566 if (Storage == Uniqued) {
567 GenericDINodeInfo::KeyTy Key(Tag, Header, DwarfOps);
568 if (auto *N = getUniqued(Context.pImpl->GenericDINodes, Key))
569 return N;
570 if (!ShouldCreate)
571 return nullptr;
572 Hash = Key.getHash();
573 } else {
574 assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
575 }
576
577 // Use a nullptr for empty headers.
578 assert(isCanonical(Header) && "Expected canonical MDString");
579 Metadata *PreOps[] = {Header};
580 return storeImpl(new (DwarfOps.size() + 1, Storage) GenericDINode(
581 Context, Storage, Hash, Tag, PreOps, DwarfOps),
582 Storage, Context.pImpl->GenericDINodes);
583}
584
585void GenericDINode::recalculateHash() {
586 setHash(GenericDINodeInfo::KeyTy::calculateHash(this));
587}
588
589#define UNWRAP_ARGS_IMPL(...) __VA_ARGS__
590#define UNWRAP_ARGS(ARGS) UNWRAP_ARGS_IMPL ARGS
591#define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS) \
592 do { \
593 if (Storage == Uniqued) { \
594 if (auto *N = getUniqued(Context.pImpl->CLASS##s, \
595 CLASS##Info::KeyTy(UNWRAP_ARGS(ARGS)))) \
596 return N; \
597 if (!ShouldCreate) \
598 return nullptr; \
599 } else { \
600 assert(ShouldCreate && \
601 "Expected non-uniqued nodes to always be created"); \
602 } \
603 } while (false)
604#define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS) \
605 return storeImpl(new (std::size(OPS), Storage) \
606 CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
607 Storage, Context.pImpl->CLASS##s)
608#define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS) \
609 return storeImpl(new (0u, Storage) \
610 CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \
611 Storage, Context.pImpl->CLASS##s)
612#define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS) \
613 return storeImpl(new (std::size(OPS), Storage) CLASS(Context, Storage, OPS), \
614 Storage, Context.pImpl->CLASS##s)
615#define DEFINE_GETIMPL_STORE_N(CLASS, ARGS, OPS, NUM_OPS) \
616 return storeImpl(new (NUM_OPS, Storage) \
617 CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
618 Storage, Context.pImpl->CLASS##s)
619
620DISubrange::DISubrange(LLVMContext &C, StorageType Storage,
622 : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {}
623DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
624 StorageType Storage, bool ShouldCreate) {
627 auto *LB = ConstantAsMetadata::get(
629 return getImpl(Context, CountNode, LB, nullptr, nullptr, Storage,
630 ShouldCreate);
631}
632
633DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
634 int64_t Lo, StorageType Storage,
635 bool ShouldCreate) {
636 auto *LB = ConstantAsMetadata::get(
638 return getImpl(Context, CountNode, LB, nullptr, nullptr, Storage,
639 ShouldCreate);
640}
641
642DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
643 Metadata *LB, Metadata *UB, Metadata *Stride,
644 StorageType Storage, bool ShouldCreate) {
645 DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, LB, UB, Stride));
646 Metadata *Ops[] = {CountNode, LB, UB, Stride};
648}
649
650DISubrange::BoundType DISubrange::getCount() const {
651 Metadata *CB = getRawCountNode();
652 if (!CB)
653 return BoundType();
654
656 isa<DIExpression>(CB)) &&
657 "Count must be signed constant or DIVariable or DIExpression");
658
659 if (auto *MD = dyn_cast<ConstantAsMetadata>(CB))
660 return BoundType(cast<ConstantInt>(MD->getValue()));
661
662 if (auto *MD = dyn_cast<DIVariable>(CB))
663 return BoundType(MD);
664
665 if (auto *MD = dyn_cast<DIExpression>(CB))
666 return BoundType(MD);
667
668 return BoundType();
669}
670
671DISubrange::BoundType DISubrange::getLowerBound() const {
672 Metadata *LB = getRawLowerBound();
673 if (!LB)
674 return BoundType();
675
677 isa<DIExpression>(LB)) &&
678 "LowerBound must be signed constant or DIVariable or DIExpression");
679
680 if (auto *MD = dyn_cast<ConstantAsMetadata>(LB))
681 return BoundType(cast<ConstantInt>(MD->getValue()));
682
683 if (auto *MD = dyn_cast<DIVariable>(LB))
684 return BoundType(MD);
685
686 if (auto *MD = dyn_cast<DIExpression>(LB))
687 return BoundType(MD);
688
689 return BoundType();
690}
691
692DISubrange::BoundType DISubrange::getUpperBound() const {
693 Metadata *UB = getRawUpperBound();
694 if (!UB)
695 return BoundType();
696
698 isa<DIExpression>(UB)) &&
699 "UpperBound must be signed constant or DIVariable or DIExpression");
700
701 if (auto *MD = dyn_cast<ConstantAsMetadata>(UB))
702 return BoundType(cast<ConstantInt>(MD->getValue()));
703
704 if (auto *MD = dyn_cast<DIVariable>(UB))
705 return BoundType(MD);
706
707 if (auto *MD = dyn_cast<DIExpression>(UB))
708 return BoundType(MD);
709
710 return BoundType();
711}
712
713DISubrange::BoundType DISubrange::getStride() const {
714 Metadata *ST = getRawStride();
715 if (!ST)
716 return BoundType();
717
719 isa<DIExpression>(ST)) &&
720 "Stride must be signed constant or DIVariable or DIExpression");
721
722 if (auto *MD = dyn_cast<ConstantAsMetadata>(ST))
723 return BoundType(cast<ConstantInt>(MD->getValue()));
724
725 if (auto *MD = dyn_cast<DIVariable>(ST))
726 return BoundType(MD);
727
728 if (auto *MD = dyn_cast<DIExpression>(ST))
729 return BoundType(MD);
730
731 return BoundType();
732}
733DIGenericSubrange::DIGenericSubrange(LLVMContext &C, StorageType Storage,
735 : DINode(C, DIGenericSubrangeKind, Storage, dwarf::DW_TAG_generic_subrange,
736 Ops) {}
737
738DIGenericSubrange *DIGenericSubrange::getImpl(LLVMContext &Context,
739 Metadata *CountNode, Metadata *LB,
740 Metadata *UB, Metadata *Stride,
741 StorageType Storage,
742 bool ShouldCreate) {
743 DEFINE_GETIMPL_LOOKUP(DIGenericSubrange, (CountNode, LB, UB, Stride));
744 Metadata *Ops[] = {CountNode, LB, UB, Stride};
746}
747
750 if (!CB)
751 return BoundType();
752
754 "Count must be signed constant or DIVariable or DIExpression");
755
756 if (auto *MD = dyn_cast<DIVariable>(CB))
757 return BoundType(MD);
758
759 if (auto *MD = dyn_cast<DIExpression>(CB))
760 return BoundType(MD);
761
762 return BoundType();
763}
764
767 if (!LB)
768 return BoundType();
769
771 "LowerBound must be signed constant or DIVariable or DIExpression");
772
773 if (auto *MD = dyn_cast<DIVariable>(LB))
774 return BoundType(MD);
775
776 if (auto *MD = dyn_cast<DIExpression>(LB))
777 return BoundType(MD);
778
779 return BoundType();
780}
781
784 if (!UB)
785 return BoundType();
786
788 "UpperBound must be signed constant or DIVariable or DIExpression");
789
790 if (auto *MD = dyn_cast<DIVariable>(UB))
791 return BoundType(MD);
792
793 if (auto *MD = dyn_cast<DIExpression>(UB))
794 return BoundType(MD);
795
796 return BoundType();
797}
798
800 Metadata *ST = getRawStride();
801 if (!ST)
802 return BoundType();
803
805 "Stride must be signed constant or DIVariable or DIExpression");
806
807 if (auto *MD = dyn_cast<DIVariable>(ST))
808 return BoundType(MD);
809
810 if (auto *MD = dyn_cast<DIExpression>(ST))
811 return BoundType(MD);
812
813 return BoundType();
814}
815
816DISubrangeType::DISubrangeType(LLVMContext &C, StorageType Storage,
817 unsigned Line, uint32_t AlignInBits,
818 DIFlags Flags, ArrayRef<Metadata *> Ops)
819 : DIType(C, DISubrangeTypeKind, Storage, dwarf::DW_TAG_subrange_type, Line,
820 AlignInBits, 0, Flags, Ops) {}
821
822DISubrangeType *DISubrangeType::getImpl(
823 LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
824 Metadata *Scope, Metadata *SizeInBits, uint32_t AlignInBits, DIFlags Flags,
825 Metadata *BaseType, Metadata *LowerBound, Metadata *UpperBound,
826 Metadata *Stride, Metadata *Bias, StorageType Storage, bool ShouldCreate) {
827 assert(isCanonical(Name) && "Expected canonical MDString");
829 AlignInBits, Flags, BaseType,
831 Metadata *Ops[] = {File, Scope, Name, SizeInBits, nullptr,
833 DEFINE_GETIMPL_STORE(DISubrangeType, (Line, AlignInBits, Flags), Ops);
834}
835
837DISubrangeType::convertRawToBound(Metadata *IN) const {
838 if (!IN)
839 return BoundType();
840
843
844 if (auto *MD = dyn_cast<ConstantAsMetadata>(IN))
845 return BoundType(cast<ConstantInt>(MD->getValue()));
846
847 if (auto *MD = dyn_cast<DIVariable>(IN))
848 return BoundType(MD);
849
850 if (auto *MD = dyn_cast<DIExpression>(IN))
851 return BoundType(MD);
852
853 if (auto *DT = dyn_cast<DIDerivedType>(IN))
854 return BoundType(DT);
855
856 return BoundType();
857}
858
859DIEnumerator::DIEnumerator(LLVMContext &C, StorageType Storage,
860 const APInt &Value, bool IsUnsigned,
862 : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
863 Value(Value) {
864 SubclassData32 = IsUnsigned;
865}
866DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,
867 bool IsUnsigned, MDString *Name,
868 StorageType Storage, bool ShouldCreate) {
869 assert(isCanonical(Name) && "Expected canonical MDString");
870 DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));
871 Metadata *Ops[] = {Name};
872 DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);
873}
874
877 uint32_t AlignInBits, unsigned Encoding,
879 uint32_t DataSizeInBits, DIFlags Flags,
880 StorageType Storage, bool ShouldCreate) {
881 assert(isCanonical(Name) && "Expected canonical MDString");
883 (Tag, Name, SizeInBits, AlignInBits, Encoding,
884 NumExtraInhabitants, DataSizeInBits, Flags));
885 Metadata *Ops[] = {nullptr, nullptr, Name, SizeInBits, nullptr};
888 (Tag, AlignInBits, Encoding, NumExtraInhabitants, DataSizeInBits, Flags),
889 Ops);
890}
891
892std::optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {
893 switch (getEncoding()) {
894 case dwarf::DW_ATE_signed:
895 case dwarf::DW_ATE_signed_char:
896 case dwarf::DW_ATE_signed_fixed:
897 return Signedness::Signed;
898 case dwarf::DW_ATE_unsigned:
899 case dwarf::DW_ATE_unsigned_char:
900 case dwarf::DW_ATE_unsigned_fixed:
902 default:
903 return std::nullopt;
904 }
905}
906
908DIFixedPointType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,
909 Metadata *SizeInBits, uint32_t AlignInBits,
910 unsigned Encoding, DIFlags Flags, unsigned Kind,
911 int Factor, APInt Numerator, APInt Denominator,
912 StorageType Storage, bool ShouldCreate) {
915 Kind, Factor, Numerator, Denominator));
916 Metadata *Ops[] = {nullptr, nullptr, Name, SizeInBits, nullptr};
919 (Tag, AlignInBits, Encoding, Flags, Kind, Factor, Numerator, Denominator),
920 Ops);
921}
922
924 return getEncoding() == dwarf::DW_ATE_signed_fixed;
925}
926
927std::optional<DIFixedPointType::FixedPointKind>
930 .Case("Binary", FixedPointBinary)
931 .Case("Decimal", FixedPointDecimal)
932 .Case("Rational", FixedPointRational)
933 .Default(std::nullopt);
934}
935
937 switch (V) {
938 case FixedPointBinary:
939 return "Binary";
941 return "Decimal";
943 return "Rational";
944 }
945 return nullptr;
946}
947
948DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag,
949 MDString *Name, Metadata *StringLength,
950 Metadata *StringLengthExp,
951 Metadata *StringLocationExp,
952 Metadata *SizeInBits, uint32_t AlignInBits,
953 unsigned Encoding, StorageType Storage,
954 bool ShouldCreate) {
955 assert(isCanonical(Name) && "Expected canonical MDString");
959 Metadata *Ops[] = {nullptr, nullptr, Name,
960 SizeInBits, nullptr, StringLength,
963}
965 assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
967}
968
969// Helper function to extract ConstantAsMetadata from ExtraData,
970// handling extra data MDTuple unwrapping if needed.
972 Metadata *ED = ExtraData;
973 if (auto *Tuple = dyn_cast_or_null<MDTuple>(ED)) {
974 if (Tuple->getNumOperands() != 1)
975 return nullptr;
976 ED = Tuple->getOperand(0);
977 }
979}
980
982 assert(getTag() == dwarf::DW_TAG_inheritance);
983 if (auto *CM = extractConstantMetadata(getExtraData()))
984 if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))
985 return static_cast<uint32_t>(CI->getZExtValue());
986 return 0;
987}
989 assert(getTag() == dwarf::DW_TAG_member && isBitField());
991 return C->getValue();
992 return nullptr;
993}
994
996 assert((getTag() == dwarf::DW_TAG_member ||
997 getTag() == dwarf::DW_TAG_variable) &&
1000 return C->getValue();
1001 return nullptr;
1002}
1004 assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
1005 if (auto *C = extractConstantMetadata(getExtraData()))
1006 return C->getValue();
1007 return nullptr;
1008}
1009
1010DIDerivedType *DIDerivedType::getImpl(
1011 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
1012 unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,
1013 uint32_t AlignInBits, Metadata *OffsetInBits,
1014 std::optional<unsigned> DWARFAddressSpace,
1015 std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData,
1016 Metadata *Annotations, StorageType Storage, bool ShouldCreate) {
1017 assert(isCanonical(Name) && "Expected canonical MDString");
1019 (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1021 PtrAuthData, Flags, ExtraData, Annotations));
1022 Metadata *Ops[] = {File, Scope, Name, SizeInBits,
1023 OffsetInBits, BaseType, ExtraData, Annotations};
1026 (Tag, Line, AlignInBits, DWARFAddressSpace, PtrAuthData, Flags), Ops);
1027}
1028
1029std::optional<DIDerivedType::PtrAuthData>
1030DIDerivedType::getPtrAuthData() const {
1031 return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type
1032 ? std::make_optional<PtrAuthData>(SubclassData32)
1033 : std::nullopt;
1034}
1035
1036DICompositeType *DICompositeType::getImpl(
1037 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
1038 unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,
1039 uint32_t AlignInBits, Metadata *OffsetInBits, DIFlags Flags,
1040 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1041 Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier,
1042 Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,
1043 Metadata *Allocated, Metadata *Rank, Metadata *Annotations,
1044 Metadata *Specification, uint32_t NumExtraInhabitants, Metadata *BitStride,
1045 StorageType Storage, bool ShouldCreate) {
1046 assert(isCanonical(Name) && "Expected canonical MDString");
1047
1048 // Keep this in sync with buildODRType.
1050 DICompositeType,
1060 DEFINE_GETIMPL_STORE(DICompositeType,
1061 (Tag, Line, RuntimeLang, AlignInBits,
1062 NumExtraInhabitants, EnumKind, Flags),
1063 Ops);
1064}
1065
1067 LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
1071 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1075 assert(!Identifier.getString().empty() && "Expected valid identifier");
1076 if (!Context.isODRUniquingDebugTypes())
1077 return nullptr;
1078 auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];
1079 if (!CT)
1080 return CT = DICompositeType::getDistinct(
1081 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1082 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
1086 if (CT->getTag() != Tag)
1087 return nullptr;
1088
1089 // Only mutate CT if it's a forward declaration and the new operands aren't.
1090 assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
1091 if (!CT->isForwardDecl() || (Flags & DINode::FlagFwdDecl))
1092 return CT;
1093
1094 // Mutate CT in place. Keep this in sync with getImpl.
1095 CT->mutate(Tag, Line, RuntimeLang, AlignInBits, NumExtraInhabitants, EnumKind,
1096 Flags);
1102 assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
1103 "Mismatched number of operands");
1104 for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
1105 if (Ops[I] != CT->getOperand(I))
1106 CT->setOperand(I, Ops[I]);
1107 return CT;
1108}
1109
1110DICompositeType *DICompositeType::getODRType(
1111 LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
1112 Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
1113 Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits,
1114 Metadata *Specification, uint32_t NumExtraInhabitants, DIFlags Flags,
1115 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
1116 Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
1117 Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
1118 Metadata *Rank, Metadata *Annotations, Metadata *BitStride) {
1119 assert(!Identifier.getString().empty() && "Expected valid identifier");
1120 if (!Context.isODRUniquingDebugTypes())
1121 return nullptr;
1122 auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];
1123 if (!CT) {
1125 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
1130 } else {
1131 if (CT->getTag() != Tag)
1132 return nullptr;
1133 }
1134 return CT;
1135}
1136
1139 assert(!Identifier.getString().empty() && "Expected valid identifier");
1140 if (!Context.isODRUniquingDebugTypes())
1141 return nullptr;
1142 return Context.pImpl->DITypeMap->lookup(&Identifier);
1143}
1144DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage,
1145 DIFlags Flags, uint8_t CC,
1147 : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0,
1148 0, 0, Flags, Ops),
1149 CC(CC) {}
1150
1151DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
1152 uint8_t CC, Metadata *TypeArray,
1153 StorageType Storage,
1154 bool ShouldCreate) {
1156 Metadata *Ops[] = {nullptr, nullptr, nullptr, nullptr, nullptr, TypeArray};
1157 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
1158}
1159
1160DIFile::DIFile(LLVMContext &C, StorageType Storage,
1161 std::optional<ChecksumInfo<MDString *>> CS, MDString *Src,
1163 : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
1164 Checksum(CS), Source(Src) {}
1165
1166// FIXME: Implement this string-enum correspondence with a .def file and macros,
1167// so that the association is explicit rather than implied.
1168static const char *ChecksumKindName[DIFile::CSK_Last] = {
1169 "CSK_MD5",
1170 "CSK_SHA1",
1171 "CSK_SHA256",
1172};
1173
1174StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {
1175 assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
1176 // The first space was originally the CSK_None variant, which is now
1177 // obsolete, but the space is still reserved in ChecksumKind, so we account
1178 // for it here.
1179 return ChecksumKindName[CSKind - 1];
1180}
1181
1182std::optional<DIFile::ChecksumKind>
1185 .Case("CSK_MD5", DIFile::CSK_MD5)
1186 .Case("CSK_SHA1", DIFile::CSK_SHA1)
1187 .Case("CSK_SHA256", DIFile::CSK_SHA256)
1188 .Default(std::nullopt);
1189}
1190
1191DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
1192 MDString *Directory,
1193 std::optional<DIFile::ChecksumInfo<MDString *>> CS,
1194 MDString *Source, StorageType Storage,
1195 bool ShouldCreate) {
1196 assert(isCanonical(Filename) && "Expected canonical MDString");
1197 assert(isCanonical(Directory) && "Expected canonical MDString");
1198 assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
1199 // We do *NOT* expect Source to be a canonical MDString because nullptr
1200 // means none, so we need something to represent the empty file.
1202 Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, Source};
1204}
1205DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage,
1207 bool IsOptimized, unsigned RuntimeVersion,
1208 unsigned EmissionKind, uint64_t DWOId,
1209 bool SplitDebugInlining,
1210 bool DebugInfoForProfiling, unsigned NameTableKind,
1211 bool RangesBaseAddress, ArrayRef<Metadata *> Ops)
1212 : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
1213 SourceLanguage(SourceLanguage), RuntimeVersion(RuntimeVersion),
1215 IsOptimized(IsOptimized), SplitDebugInlining(SplitDebugInlining),
1216 DebugInfoForProfiling(DebugInfoForProfiling),
1217 RangesBaseAddress(RangesBaseAddress) {
1219}
1220
1221DICompileUnit *DICompileUnit::getImpl(
1223 MDString *Producer, bool IsOptimized, MDString *Flags,
1224 unsigned RuntimeVersion, MDString *SplitDebugFilename,
1225 unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
1226 Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,
1227 uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,
1228 unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,
1229 MDString *SDK, StorageType Storage, bool ShouldCreate) {
1230 assert(Storage != Uniqued && "Cannot unique DICompileUnit");
1231 assert(isCanonical(Producer) && "Expected canonical MDString");
1232 assert(isCanonical(Flags) && "Expected canonical MDString");
1233 assert(isCanonical(SplitDebugFilename) && "Expected canonical MDString");
1234
1235 Metadata *Ops[] = {File,
1236 Producer,
1237 Flags,
1239 EnumTypes,
1243 Macros,
1244 SysRoot,
1245 SDK};
1246 return storeImpl(new (std::size(Ops), Storage) DICompileUnit(
1247 Context, Storage, SourceLanguage, IsOptimized,
1248 RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining,
1249 DebugInfoForProfiling, NameTableKind, RangesBaseAddress,
1250 Ops),
1251 Storage);
1252}
1253
1254std::optional<DICompileUnit::DebugEmissionKind>
1257 .Case("NoDebug", NoDebug)
1258 .Case("FullDebug", FullDebug)
1259 .Case("LineTablesOnly", LineTablesOnly)
1260 .Case("DebugDirectivesOnly", DebugDirectivesOnly)
1261 .Default(std::nullopt);
1262}
1263
1264std::optional<DICompileUnit::DebugNameTableKind>
1273
1275 switch (EK) {
1276 case NoDebug:
1277 return "NoDebug";
1278 case FullDebug:
1279 return "FullDebug";
1280 case LineTablesOnly:
1281 return "LineTablesOnly";
1283 return "DebugDirectivesOnly";
1284 }
1285 return nullptr;
1286}
1287
1289 switch (NTK) {
1291 return nullptr;
1293 return "GNU";
1295 return "Apple";
1297 return "None";
1298 }
1299 return nullptr;
1300}
1301DISubprogram::DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
1302 unsigned ScopeLine, unsigned VirtualIndex,
1303 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags,
1304 bool UsesKeyInstructions, ArrayRef<Metadata *> Ops)
1305 : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops),
1306 Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),
1307 ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) {
1308 static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range");
1309 SubclassData1 = UsesKeyInstructions;
1310}
1312DISubprogram::toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized,
1313 unsigned Virtuality, bool IsMainSubprogram) {
1314 // We're assuming virtuality is the low-order field.
1315 static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) &&
1316 int(SPFlagPureVirtual) ==
1317 int(dwarf::DW_VIRTUALITY_pure_virtual),
1318 "Virtuality constant mismatch");
1319 return static_cast<DISPFlags>(
1320 (Virtuality & SPFlagVirtuality) |
1321 (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) |
1322 (IsDefinition ? SPFlagDefinition : SPFlagZero) |
1323 (IsOptimized ? SPFlagOptimized : SPFlagZero) |
1324 (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero));
1325}
1326
1328 if (auto *Block = dyn_cast<DILexicalBlockBase>(this))
1329 return Block->getScope()->getSubprogram();
1330 return const_cast<DISubprogram *>(cast<DISubprogram>(this));
1331}
1332
1334 if (auto *File = dyn_cast<DILexicalBlockFile>(this))
1335 return File->getScope()->getNonLexicalBlockFileScope();
1336 return const_cast<DILocalScope *>(this);
1337}
1338
1340 DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx,
1342 SmallVector<DIScope *> ScopeChain;
1343 DIScope *CachedResult = nullptr;
1344
1345 for (DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);
1346 Scope = Scope->getScope()) {
1347 if (auto It = Cache.find(Scope); It != Cache.end()) {
1348 CachedResult = cast<DIScope>(It->second);
1349 break;
1350 }
1351 ScopeChain.push_back(Scope);
1352 }
1353
1354 // Recreate the scope chain, bottom-up, starting at the new subprogram (or a
1355 // cached result).
1356 DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
1357 for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
1358 UpdatedScope = cloneAndReplaceParentScope(
1359 cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);
1360 Cache[ScopeToUpdate] = UpdatedScope;
1361 }
1362
1363 return cast<DILocalScope>(UpdatedScope);
1364}
1365
1367 return StringSwitch<DISPFlags>(Flag)
1368#define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)
1369#include "llvm/IR/DebugInfoFlags.def"
1370 .Default(SPFlagZero);
1371}
1372
1374 switch (Flag) {
1375 // Appease a warning.
1376 case SPFlagVirtuality:
1377 return "";
1378#define HANDLE_DISP_FLAG(ID, NAME) \
1379 case SPFlag##NAME: \
1380 return "DISPFlag" #NAME;
1381#include "llvm/IR/DebugInfoFlags.def"
1382 }
1383 return "";
1384}
1385
1388 SmallVectorImpl<DISPFlags> &SplitFlags) {
1389 // Multi-bit fields can require special handling. In our case, however, the
1390 // only multi-bit field is virtuality, and all its values happen to be
1391 // single-bit values, so the right behavior just falls out.
1392#define HANDLE_DISP_FLAG(ID, NAME) \
1393 if (DISPFlags Bit = Flags & SPFlag##NAME) { \
1394 SplitFlags.push_back(Bit); \
1395 Flags &= ~Bit; \
1396 }
1397#include "llvm/IR/DebugInfoFlags.def"
1398 return Flags;
1399}
1400
1401DISubprogram *DISubprogram::getImpl(
1402 LLVMContext &Context, Metadata *Scope, MDString *Name,
1403 MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
1404 unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex,
1405 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit,
1406 Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
1407 Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName,
1408 bool UsesKeyInstructions, StorageType Storage, bool ShouldCreate) {
1409 assert(isCanonical(Name) && "Expected canonical MDString");
1410 assert(isCanonical(LinkageName) && "Expected canonical MDString");
1411 assert(isCanonical(TargetFuncName) && "Expected canonical MDString");
1413 (Scope, Name, LinkageName, File, Line, Type, ScopeLine,
1419 File, Scope, Name, LinkageName,
1423 if (!TargetFuncName) {
1424 Ops.pop_back();
1425 if (!Annotations) {
1426 Ops.pop_back();
1427 if (!ThrownTypes) {
1428 Ops.pop_back();
1429 if (!TemplateParams) {
1430 Ops.pop_back();
1431 if (!ContainingType)
1432 Ops.pop_back();
1433 }
1434 }
1435 }
1436 }
1437 DEFINE_GETIMPL_STORE_N(DISubprogram,
1438 (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags,
1439 SPFlags, UsesKeyInstructions),
1440 Ops, Ops.size());
1441}
1442
1444 assert(F && "Invalid function");
1445 return F->getSubprogram() == this;
1446}
1447
1448template <typename ScopeT, typename NodeT>
1449static ScopeT getRawRetainedNodeScopeInternal(NodeT *N) {
1450 auto getScope = [](auto *N) { return N->getScope(); };
1451
1452 return DISubprogram::visitRetainedNode<ScopeT>(
1453 N, getScope, getScope, getScope, getScope,
1454 [](auto *N) { return nullptr; });
1455}
1456
1460
1464
1468
1471}
1472
1474 // Checks if a metadata node from retainedTypes is a type not belonging to
1475 // this subprogram.
1476 auto IsAlienType = [this](DINode *N) {
1477 auto *T = dyn_cast_or_null<DIType>(N);
1478 if (!T)
1479 return false;
1480
1481 DISubprogram *TypeSP = nullptr;
1482 // The type might have been global in the previously loaded IR modules.
1483 if (auto *LS = dyn_cast_or_null<DILocalScope>(T->getScope()))
1484 TypeSP = LS->getSubprogram();
1485
1486 return this != TypeSP;
1487 };
1488
1489 // As this is expected to be called during module loading, before
1490 // stripping old or incorrect debug info, perform minimal sanity check.
1491 if (!isa_and_present<MDTuple>(getRawRetainedNodes()))
1492 return;
1493
1494 MDTuple *RetainedNodes = cast<MDTuple>(getRawRetainedNodes());
1496 MDs.reserve(RetainedNodes->getNumOperands());
1497 for (const MDOperand &Node : RetainedNodes->operands()) {
1498 // Ignore malformed retainedNodes.
1499 if (Node && !isa<DINode>(Node))
1500 return;
1501
1502 auto *N = cast_or_null<DINode>(Node);
1503 if (!IsAlienType(N))
1504 MDs.push_back(N);
1505 }
1506
1507 if (MDs.size() != RetainedNodes->getNumOperands())
1508 replaceRetainedNodes(MDNode::get(getContext(), MDs));
1509}
1510
1515
1516DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope,
1517 Metadata *File, unsigned Line,
1518 unsigned Column, StorageType Storage,
1519 bool ShouldCreate) {
1520 // Fixup column.
1522
1523 assert(Scope && "Expected scope");
1525 Metadata *Ops[] = {File, Scope};
1527}
1528
1529DILexicalBlockFile *DILexicalBlockFile::getImpl(LLVMContext &Context,
1530 Metadata *Scope, Metadata *File,
1531 unsigned Discriminator,
1532 StorageType Storage,
1533 bool ShouldCreate) {
1534 assert(Scope && "Expected scope");
1535 DEFINE_GETIMPL_LOOKUP(DILexicalBlockFile, (Scope, File, Discriminator));
1536 Metadata *Ops[] = {File, Scope};
1537 DEFINE_GETIMPL_STORE(DILexicalBlockFile, (Discriminator), Ops);
1538}
1539
1540DINamespace::DINamespace(LLVMContext &Context, StorageType Storage,
1541 bool ExportSymbols, ArrayRef<Metadata *> Ops)
1542 : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops) {
1543 SubclassData1 = ExportSymbols;
1544}
1545DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope,
1546 MDString *Name, bool ExportSymbols,
1547 StorageType Storage, bool ShouldCreate) {
1548 assert(isCanonical(Name) && "Expected canonical MDString");
1550 // The nullptr is for DIScope's File operand. This should be refactored.
1551 Metadata *Ops[] = {nullptr, Scope, Name};
1552 DEFINE_GETIMPL_STORE(DINamespace, (ExportSymbols), Ops);
1553}
1554
1555DICommonBlock::DICommonBlock(LLVMContext &Context, StorageType Storage,
1556 unsigned LineNo, ArrayRef<Metadata *> Ops)
1557 : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block,
1558 Ops) {
1559 SubclassData32 = LineNo;
1560}
1561DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope,
1562 Metadata *Decl, MDString *Name,
1563 Metadata *File, unsigned LineNo,
1564 StorageType Storage, bool ShouldCreate) {
1565 assert(isCanonical(Name) && "Expected canonical MDString");
1566 DEFINE_GETIMPL_LOOKUP(DICommonBlock, (Scope, Decl, Name, File, LineNo));
1567 // The nullptr is for DIScope's File operand. This should be refactored.
1568 Metadata *Ops[] = {Scope, Decl, Name, File};
1569 DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo), Ops);
1570}
1571
1572DIModule::DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,
1573 bool IsDecl, ArrayRef<Metadata *> Ops)
1574 : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {
1575 SubclassData1 = IsDecl;
1576 SubclassData32 = LineNo;
1577}
1578DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File,
1579 Metadata *Scope, MDString *Name,
1580 MDString *ConfigurationMacros,
1581 MDString *IncludePath, MDString *APINotesFile,
1582 unsigned LineNo, bool IsDecl, StorageType Storage,
1583 bool ShouldCreate) {
1584 assert(isCanonical(Name) && "Expected canonical MDString");
1586 IncludePath, APINotesFile, LineNo, IsDecl));
1589 DEFINE_GETIMPL_STORE(DIModule, (LineNo, IsDecl), Ops);
1590}
1591DITemplateTypeParameter::DITemplateTypeParameter(LLVMContext &Context,
1592 StorageType Storage,
1593 bool IsDefault,
1595 : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,
1596 dwarf::DW_TAG_template_type_parameter, IsDefault,
1597 Ops) {}
1598
1600DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name,
1601 Metadata *Type, bool isDefault,
1602 StorageType Storage, bool ShouldCreate) {
1603 assert(isCanonical(Name) && "Expected canonical MDString");
1604 DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type, isDefault));
1605 Metadata *Ops[] = {Name, Type};
1606 DEFINE_GETIMPL_STORE(DITemplateTypeParameter, (isDefault), Ops);
1607}
1608
1609DITemplateValueParameter *DITemplateValueParameter::getImpl(
1610 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type,
1611 bool isDefault, Metadata *Value, StorageType Storage, bool ShouldCreate) {
1612 assert(isCanonical(Name) && "Expected canonical MDString");
1613 DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter,
1614 (Tag, Name, Type, isDefault, Value));
1615 Metadata *Ops[] = {Name, Type, Value};
1616 DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag, isDefault), Ops);
1617}
1618
1620DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
1621 MDString *LinkageName, Metadata *File, unsigned Line,
1622 Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
1623 Metadata *StaticDataMemberDeclaration,
1624 Metadata *TemplateParams, uint32_t AlignInBits,
1625 Metadata *Annotations, StorageType Storage,
1626 bool ShouldCreate) {
1627 assert(isCanonical(Name) && "Expected canonical MDString");
1628 assert(isCanonical(LinkageName) && "Expected canonical MDString");
1630 DIGlobalVariable,
1631 (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
1633 Metadata *Ops[] = {Scope,
1634 Name,
1635 File,
1636 Type,
1637 Name,
1641 Annotations};
1642 DEFINE_GETIMPL_STORE(DIGlobalVariable,
1643 (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops);
1644}
1645
1647DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
1648 Metadata *File, unsigned Line, Metadata *Type,
1649 unsigned Arg, DIFlags Flags, uint32_t AlignInBits,
1650 Metadata *Annotations, StorageType Storage,
1651 bool ShouldCreate) {
1652 // 64K ought to be enough for any frontend.
1653 assert(Arg <= UINT16_MAX && "Expected argument number to fit in 16-bits");
1654
1655 assert(Scope && "Expected scope");
1656 assert(isCanonical(Name) && "Expected canonical MDString");
1657 DEFINE_GETIMPL_LOOKUP(DILocalVariable, (Scope, Name, File, Line, Type, Arg,
1658 Flags, AlignInBits, Annotations));
1660 DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops);
1661}
1662
1664 signed Line, ArrayRef<Metadata *> Ops,
1665 uint32_t AlignInBits)
1666 : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {
1667 SubclassData32 = AlignInBits;
1668}
1669std::optional<uint64_t> DIVariable::getSizeInBits() const {
1670 // This is used by the Verifier so be mindful of broken types.
1671 const Metadata *RawType = getRawType();
1672 while (RawType) {
1673 // Try to get the size directly.
1674 if (auto *T = dyn_cast<DIType>(RawType))
1675 if (uint64_t Size = T->getSizeInBits())
1676 return Size;
1677
1678 if (auto *DT = dyn_cast<DIDerivedType>(RawType)) {
1679 // Look at the base type.
1680 RawType = DT->getRawBaseType();
1681 continue;
1682 }
1683
1684 // Missing type or size.
1685 break;
1686 }
1687
1688 // Fail gracefully.
1689 return std::nullopt;
1690}
1691
1692DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line,
1693 unsigned Column, bool IsArtificial,
1694 std::optional<unsigned> CoroSuspendIdx,
1696 : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) {
1697 this->SubclassData32 = Line;
1698 this->Column = Column;
1699 this->IsArtificial = IsArtificial;
1700 this->CoroSuspendIdx = CoroSuspendIdx;
1701}
1702DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
1703 Metadata *File, unsigned Line, unsigned Column,
1704 bool IsArtificial,
1705 std::optional<unsigned> CoroSuspendIdx,
1706 StorageType Storage, bool ShouldCreate) {
1707 assert(Scope && "Expected scope");
1708 assert(isCanonical(Name) && "Expected canonical MDString");
1710 DILabel, (Scope, Name, File, Line, Column, IsArtificial, CoroSuspendIdx));
1711 Metadata *Ops[] = {Scope, Name, File};
1712 DEFINE_GETIMPL_STORE(DILabel, (Line, Column, IsArtificial, CoroSuspendIdx),
1713 Ops);
1714}
1715
1716DIExpression *DIExpression::getImpl(LLVMContext &Context,
1717 ArrayRef<uint64_t> Elements,
1718 StorageType Storage, bool ShouldCreate) {
1719 DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements));
1720 DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));
1721}
1723 if (auto singleLocElts = getSingleLocationExpressionElements()) {
1724 return singleLocElts->size() > 0 &&
1725 (*singleLocElts)[0] == dwarf::DW_OP_LLVM_entry_value;
1726 }
1727 return false;
1728}
1730 if (auto singleLocElts = getSingleLocationExpressionElements())
1731 return singleLocElts->size() > 0 &&
1732 (*singleLocElts)[0] == dwarf::DW_OP_deref;
1733 return false;
1734}
1736 if (auto singleLocElts = getSingleLocationExpressionElements())
1737 return singleLocElts->size() == 1 &&
1738 (*singleLocElts)[0] == dwarf::DW_OP_deref;
1739 return false;
1740}
1741
1742DIAssignID *DIAssignID::getImpl(LLVMContext &Context, StorageType Storage,
1743 bool ShouldCreate) {
1744 // Uniqued DIAssignID are not supported as the instance address *is* the ID.
1745 assert(Storage != StorageType::Uniqued && "uniqued DIAssignID unsupported");
1746 return storeImpl(new (0u, Storage) DIAssignID(Context, Storage), Storage);
1747}
1748
1750 uint64_t Op = getOp();
1751
1752 if (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31)
1753 return 2;
1754
1755 switch (Op) {
1760 case dwarf::DW_OP_bregx:
1761 return 3;
1762 case dwarf::DW_OP_constu:
1763 case dwarf::DW_OP_consts:
1764 case dwarf::DW_OP_deref_size:
1765 case dwarf::DW_OP_plus_uconst:
1769 case dwarf::DW_OP_regx:
1770 return 2;
1771 default:
1772 return 1;
1773 }
1774}
1775
1777 for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) {
1778 // Check that there's space for the operand.
1779 if (I->get() + I->getSize() > E->get())
1780 return false;
1781
1782 uint64_t Op = I->getOp();
1783 if ((Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31) ||
1784 (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31))
1785 return true;
1786
1787 // Check that the operand is valid.
1788 switch (Op) {
1789 default:
1790 return false;
1792 // A fragment operator must appear at the end.
1793 return I->get() + I->getSize() == E->get();
1794 case dwarf::DW_OP_stack_value: {
1795 // Must be the last one or followed by a DW_OP_LLVM_fragment.
1796 if (I->get() + I->getSize() == E->get())
1797 break;
1798 auto J = I;
1799 if ((++J)->getOp() != dwarf::DW_OP_LLVM_fragment)
1800 return false;
1801 break;
1802 }
1803 case dwarf::DW_OP_swap: {
1804 // Must be more than one implicit element on the stack.
1805
1806 // FIXME: A better way to implement this would be to add a local variable
1807 // that keeps track of the stack depth and introduce something like a
1808 // DW_LLVM_OP_implicit_location as a placeholder for the location this
1809 // DIExpression is attached to, or else pass the number of implicit stack
1810 // elements into isValid.
1811 if (getNumElements() == 1)
1812 return false;
1813 break;
1814 }
1816 // An entry value operator must appear at the beginning or immediately
1817 // following `DW_OP_LLVM_arg 0`, and the number of operations it cover can
1818 // currently only be 1, because we support only entry values of a simple
1819 // register location. One reason for this is that we currently can't
1820 // calculate the size of the resulting DWARF block for other expressions.
1821 auto FirstOp = expr_op_begin();
1822 if (FirstOp->getOp() == dwarf::DW_OP_LLVM_arg && FirstOp->getArg(0) == 0)
1823 ++FirstOp;
1824 return I->get() == FirstOp->get() && I->getArg(0) == 1;
1825 }
1832 case dwarf::DW_OP_constu:
1833 case dwarf::DW_OP_plus_uconst:
1834 case dwarf::DW_OP_plus:
1835 case dwarf::DW_OP_minus:
1836 case dwarf::DW_OP_mul:
1837 case dwarf::DW_OP_div:
1838 case dwarf::DW_OP_mod:
1839 case dwarf::DW_OP_or:
1840 case dwarf::DW_OP_and:
1841 case dwarf::DW_OP_xor:
1842 case dwarf::DW_OP_shl:
1843 case dwarf::DW_OP_shr:
1844 case dwarf::DW_OP_shra:
1845 case dwarf::DW_OP_deref:
1846 case dwarf::DW_OP_deref_size:
1847 case dwarf::DW_OP_xderef:
1848 case dwarf::DW_OP_lit0:
1849 case dwarf::DW_OP_not:
1850 case dwarf::DW_OP_dup:
1851 case dwarf::DW_OP_regx:
1852 case dwarf::DW_OP_bregx:
1853 case dwarf::DW_OP_push_object_address:
1854 case dwarf::DW_OP_over:
1855 case dwarf::DW_OP_rot:
1856 case dwarf::DW_OP_consts:
1857 case dwarf::DW_OP_eq:
1858 case dwarf::DW_OP_ne:
1859 case dwarf::DW_OP_gt:
1860 case dwarf::DW_OP_ge:
1861 case dwarf::DW_OP_lt:
1862 case dwarf::DW_OP_le:
1863 case dwarf::DW_OP_neg:
1864 case dwarf::DW_OP_abs:
1865 break;
1866 }
1867 }
1868 return true;
1869}
1870
1872 if (!isValid())
1873 return false;
1874
1875 if (getNumElements() == 0)
1876 return false;
1877
1878 for (const auto &It : expr_ops()) {
1879 switch (It.getOp()) {
1880 default:
1881 break;
1882 case dwarf::DW_OP_stack_value:
1883 return true;
1884 }
1885 }
1886
1887 return false;
1888}
1889
1891 if (!isValid())
1892 return false;
1893
1894 if (getNumElements() == 0)
1895 return false;
1896
1897 // If there are any elements other than fragment or tag_offset, then some
1898 // kind of complex computation occurs.
1899 for (const auto &It : expr_ops()) {
1900 switch (It.getOp()) {
1904 continue;
1905 default:
1906 return true;
1907 }
1908 }
1909
1910 return false;
1911}
1912
1914 if (!isValid())
1915 return false;
1916
1917 if (getNumElements() == 0)
1918 return true;
1919
1920 auto ExprOpBegin = expr_ops().begin();
1921 auto ExprOpEnd = expr_ops().end();
1922 if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg) {
1923 if (ExprOpBegin->getArg(0) != 0)
1924 return false;
1925 ++ExprOpBegin;
1926 }
1927
1928 return !std::any_of(ExprOpBegin, ExprOpEnd, [](auto Op) {
1929 return Op.getOp() == dwarf::DW_OP_LLVM_arg;
1930 });
1931}
1932
1933std::optional<ArrayRef<uint64_t>>
1935 // Check for `isValid` covered by `isSingleLocationExpression`.
1937 return std::nullopt;
1938
1939 // An empty expression is already non-variadic.
1940 if (!getNumElements())
1941 return ArrayRef<uint64_t>();
1942
1943 // If Expr does not have a leading DW_OP_LLVM_arg then we don't need to do
1944 // anything.
1946 return getElements().drop_front(2);
1947 return getElements();
1948}
1949
1950const DIExpression *
1952 SmallVector<uint64_t, 3> UndefOps;
1953 if (auto FragmentInfo = Expr->getFragmentInfo()) {
1954 UndefOps.append({dwarf::DW_OP_LLVM_fragment, FragmentInfo->OffsetInBits,
1955 FragmentInfo->SizeInBits});
1956 }
1957 return DIExpression::get(Expr->getContext(), UndefOps);
1958}
1959
1960const DIExpression *
1962 if (any_of(Expr->expr_ops(), [](auto ExprOp) {
1963 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1964 }))
1965 return Expr;
1966 SmallVector<uint64_t> NewOps;
1967 NewOps.reserve(Expr->getNumElements() + 2);
1968 NewOps.append({dwarf::DW_OP_LLVM_arg, 0});
1969 NewOps.append(Expr->elements_begin(), Expr->elements_end());
1970 return DIExpression::get(Expr->getContext(), NewOps);
1971}
1972
1973std::optional<const DIExpression *>
1975 if (!Expr)
1976 return std::nullopt;
1977
1978 if (auto Elts = Expr->getSingleLocationExpressionElements())
1979 return DIExpression::get(Expr->getContext(), *Elts);
1980
1981 return std::nullopt;
1982}
1983
1985 const DIExpression *Expr,
1986 bool IsIndirect) {
1987 // If Expr is not already variadic, insert the implied `DW_OP_LLVM_arg 0`
1988 // to the existing expression ops.
1989 if (none_of(Expr->expr_ops(), [](auto ExprOp) {
1990 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1991 }))
1992 Ops.append({dwarf::DW_OP_LLVM_arg, 0});
1993 // If Expr is not indirect, we only need to insert the expression elements and
1994 // we're done.
1995 if (!IsIndirect) {
1996 Ops.append(Expr->elements_begin(), Expr->elements_end());
1997 return;
1998 }
1999 // If Expr is indirect, insert the implied DW_OP_deref at the end of the
2000 // expression but before DW_OP_{stack_value, LLVM_fragment} if they are
2001 // present.
2002 for (auto Op : Expr->expr_ops()) {
2003 if (Op.getOp() == dwarf::DW_OP_stack_value ||
2004 Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
2005 Ops.push_back(dwarf::DW_OP_deref);
2006 IsIndirect = false;
2007 }
2008 Op.appendToVector(Ops);
2009 }
2010 if (IsIndirect)
2011 Ops.push_back(dwarf::DW_OP_deref);
2012}
2013
2014bool DIExpression::isEqualExpression(const DIExpression *FirstExpr,
2015 bool FirstIndirect,
2016 const DIExpression *SecondExpr,
2017 bool SecondIndirect) {
2018 SmallVector<uint64_t> FirstOps;
2019 DIExpression::canonicalizeExpressionOps(FirstOps, FirstExpr, FirstIndirect);
2020 SmallVector<uint64_t> SecondOps;
2021 DIExpression::canonicalizeExpressionOps(SecondOps, SecondExpr,
2022 SecondIndirect);
2023 return FirstOps == SecondOps;
2024}
2025
2026std::optional<DIExpression::FragmentInfo>
2028 for (auto I = Start; I != End; ++I)
2029 if (I->getOp() == dwarf::DW_OP_LLVM_fragment) {
2030 DIExpression::FragmentInfo Info = {I->getArg(1), I->getArg(0)};
2031 return Info;
2032 }
2033 return std::nullopt;
2034}
2035
2036std::optional<uint64_t> DIExpression::getActiveBits(DIVariable *Var) {
2037 std::optional<uint64_t> InitialActiveBits = Var->getSizeInBits();
2038 std::optional<uint64_t> ActiveBits = InitialActiveBits;
2039 for (auto Op : expr_ops()) {
2040 switch (Op.getOp()) {
2041 default:
2042 // We assume the worst case for anything we don't currently handle and
2043 // revert to the initial active bits.
2044 ActiveBits = InitialActiveBits;
2045 break;
2048 // We can't handle an extract whose sign doesn't match that of the
2049 // variable.
2050 std::optional<DIBasicType::Signedness> VarSign = Var->getSignedness();
2051 bool VarSigned = (VarSign == DIBasicType::Signedness::Signed);
2052 bool OpSigned = (Op.getOp() == dwarf::DW_OP_LLVM_extract_bits_sext);
2053 if (!VarSign || VarSigned != OpSigned) {
2054 ActiveBits = InitialActiveBits;
2055 break;
2056 }
2057 [[fallthrough]];
2058 }
2060 // Extract or fragment narrows the active bits
2061 if (ActiveBits)
2062 ActiveBits = std::min(*ActiveBits, Op.getArg(1));
2063 else
2064 ActiveBits = Op.getArg(1);
2065 break;
2066 }
2067 }
2068 return ActiveBits;
2069}
2070
2072 int64_t Offset) {
2073 if (Offset > 0) {
2074 Ops.push_back(dwarf::DW_OP_plus_uconst);
2075 Ops.push_back(Offset);
2076 } else if (Offset < 0) {
2077 Ops.push_back(dwarf::DW_OP_constu);
2078 // Avoid UB when encountering LLONG_MIN, because in 2's complement
2079 // abs(LLONG_MIN) is LLONG_MAX+1.
2080 uint64_t AbsMinusOne = -(Offset+1);
2081 Ops.push_back(AbsMinusOne + 1);
2082 Ops.push_back(dwarf::DW_OP_minus);
2083 }
2084}
2085
2087 auto SingleLocEltsOpt = getSingleLocationExpressionElements();
2088 if (!SingleLocEltsOpt)
2089 return false;
2090 auto SingleLocElts = *SingleLocEltsOpt;
2091
2092 if (SingleLocElts.size() == 0) {
2093 Offset = 0;
2094 return true;
2095 }
2096
2097 if (SingleLocElts.size() == 2 &&
2098 SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {
2099 Offset = SingleLocElts[1];
2100 return true;
2101 }
2102
2103 if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {
2104 if (SingleLocElts[2] == dwarf::DW_OP_plus) {
2105 Offset = SingleLocElts[1];
2106 return true;
2107 }
2108 if (SingleLocElts[2] == dwarf::DW_OP_minus) {
2109 Offset = -SingleLocElts[1];
2110 return true;
2111 }
2112 }
2113
2114 return false;
2115}
2116
2118 ArrayRef<uint64_t> Ops, int64_t &OffsetInBytes,
2119 SmallVectorImpl<uint64_t> &RemainingOps) {
2120 OffsetInBytes = 0;
2121 RemainingOps.clear();
2122
2123 auto ExprOpEnd = expr_op_iterator(Ops.end());
2124 auto ExprOpIt = expr_op_iterator(Ops.begin());
2125 while (ExprOpIt != ExprOpEnd) {
2126 uint64_t Op = ExprOpIt->getOp();
2127 if (Op == dwarf::DW_OP_deref || Op == dwarf::DW_OP_deref_size ||
2128 Op == dwarf::DW_OP_deref_type || Op == dwarf::DW_OP_LLVM_fragment ||
2131 break;
2132 } else if (Op == dwarf::DW_OP_plus_uconst) {
2133 OffsetInBytes += ExprOpIt->getArg(0);
2134 } else if (Op == dwarf::DW_OP_constu) {
2135 uint64_t Value = ExprOpIt->getArg(0);
2136 ++ExprOpIt;
2137 if (ExprOpIt->getOp() == dwarf::DW_OP_plus)
2138 OffsetInBytes += Value;
2139 else if (ExprOpIt->getOp() == dwarf::DW_OP_minus)
2140 OffsetInBytes -= Value;
2141 else
2142 return false;
2143 } else {
2144 // Not a const plus/minus operation or deref.
2145 return false;
2146 }
2147 ++ExprOpIt;
2148 }
2149 RemainingOps.append(ExprOpIt.getBase(), ExprOpEnd.getBase());
2150 return true;
2151}
2152
2154 int64_t &OffsetInBytes, SmallVectorImpl<uint64_t> &RemainingOps) const {
2155 auto SingleLocEltsOpt = getSingleLocationExpressionElements();
2156 if (!SingleLocEltsOpt) {
2157 OffsetInBytes = 0;
2158 RemainingOps.clear();
2159 return false;
2160 }
2161
2162 return extractLeadingOffset(*SingleLocEltsOpt, OffsetInBytes, RemainingOps);
2163}
2164
2167 for (auto ExprOp : expr_ops())
2168 if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)
2169 SeenOps.insert(ExprOp.getArg(0));
2170 for (uint64_t Idx = 0; Idx < N; ++Idx)
2171 if (!SeenOps.contains(Idx))
2172 return false;
2173 return true;
2174}
2175
2176const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,
2177 unsigned &AddrClass) {
2178 // FIXME: This seems fragile. Nothing that verifies that these elements
2179 // actually map to ops and not operands.
2180 auto SingleLocEltsOpt = Expr->getSingleLocationExpressionElements();
2181 if (!SingleLocEltsOpt)
2182 return nullptr;
2183 auto SingleLocElts = *SingleLocEltsOpt;
2184
2185 const unsigned PatternSize = 4;
2186 if (SingleLocElts.size() >= PatternSize &&
2187 SingleLocElts[PatternSize - 4] == dwarf::DW_OP_constu &&
2188 SingleLocElts[PatternSize - 2] == dwarf::DW_OP_swap &&
2189 SingleLocElts[PatternSize - 1] == dwarf::DW_OP_xderef) {
2190 AddrClass = SingleLocElts[PatternSize - 3];
2191
2192 if (SingleLocElts.size() == PatternSize)
2193 return nullptr;
2194 return DIExpression::get(
2195 Expr->getContext(),
2196 ArrayRef(&*SingleLocElts.begin(), SingleLocElts.size() - PatternSize));
2197 }
2198 return Expr;
2199}
2200
2201DIExpression *DIExpression::prepend(const DIExpression *Expr, uint8_t Flags,
2202 int64_t Offset) {
2204 if (Flags & DIExpression::DerefBefore)
2205 Ops.push_back(dwarf::DW_OP_deref);
2206
2208 if (Flags & DIExpression::DerefAfter)
2209 Ops.push_back(dwarf::DW_OP_deref);
2210
2211 bool StackValue = Flags & DIExpression::StackValue;
2212 bool EntryValue = Flags & DIExpression::EntryValue;
2213
2214 return prependOpcodes(Expr, Ops, StackValue, EntryValue);
2215}
2216
2217DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,
2219 unsigned ArgNo, bool StackValue) {
2220 assert(Expr && "Can't add ops to this expression");
2221
2222 // Handle non-variadic intrinsics by prepending the opcodes.
2223 if (!any_of(Expr->expr_ops(),
2224 [](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {
2225 assert(ArgNo == 0 &&
2226 "Location Index must be 0 for a non-variadic expression.");
2228 return DIExpression::prependOpcodes(Expr, NewOps, StackValue);
2229 }
2230
2232 for (auto Op : Expr->expr_ops()) {
2233 // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
2234 if (StackValue) {
2235 if (Op.getOp() == dwarf::DW_OP_stack_value)
2236 StackValue = false;
2237 else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
2238 NewOps.push_back(dwarf::DW_OP_stack_value);
2239 StackValue = false;
2240 }
2241 }
2242 Op.appendToVector(NewOps);
2243 if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo)
2244 llvm::append_range(NewOps, Ops);
2245 }
2246 if (StackValue)
2247 NewOps.push_back(dwarf::DW_OP_stack_value);
2248
2249 return DIExpression::get(Expr->getContext(), NewOps);
2250}
2251
2252DIExpression *DIExpression::replaceArg(const DIExpression *Expr,
2253 uint64_t OldArg, uint64_t NewArg) {
2254 assert(Expr && "Can't replace args in this expression");
2255
2257
2258 for (auto Op : Expr->expr_ops()) {
2259 if (Op.getOp() != dwarf::DW_OP_LLVM_arg || Op.getArg(0) < OldArg) {
2260 Op.appendToVector(NewOps);
2261 continue;
2262 }
2264 uint64_t Arg = Op.getArg(0) == OldArg ? NewArg : Op.getArg(0);
2265 // OldArg has been deleted from the Op list, so decrement all indices
2266 // greater than it.
2267 if (Arg > OldArg)
2268 --Arg;
2269 NewOps.push_back(Arg);
2270 }
2271 return DIExpression::get(Expr->getContext(), NewOps);
2272}
2273
2274DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
2276 bool StackValue, bool EntryValue) {
2277 assert(Expr && "Can't prepend ops to this expression");
2278
2279 if (EntryValue) {
2281 // Use a block size of 1 for the target register operand. The
2282 // DWARF backend currently cannot emit entry values with a block
2283 // size > 1.
2284 Ops.push_back(1);
2285 }
2286
2287 // If there are no ops to prepend, do not even add the DW_OP_stack_value.
2288 if (Ops.empty())
2289 StackValue = false;
2290 for (auto Op : Expr->expr_ops()) {
2291 // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
2292 if (StackValue) {
2293 if (Op.getOp() == dwarf::DW_OP_stack_value)
2294 StackValue = false;
2295 else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
2296 Ops.push_back(dwarf::DW_OP_stack_value);
2297 StackValue = false;
2298 }
2299 }
2300 Op.appendToVector(Ops);
2301 }
2302 if (StackValue)
2303 Ops.push_back(dwarf::DW_OP_stack_value);
2304 return DIExpression::get(Expr->getContext(), Ops);
2305}
2306
2307DIExpression *DIExpression::append(const DIExpression *Expr,
2309 assert(Expr && !Ops.empty() && "Can't append ops to this expression");
2310
2311 // Copy Expr's current op list.
2313 for (auto Op : Expr->expr_ops()) {
2314 // Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.
2315 if (Op.getOp() == dwarf::DW_OP_stack_value ||
2316 Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
2317 NewOps.append(Ops.begin(), Ops.end());
2318
2319 // Ensure that the new opcodes are only appended once.
2320 Ops = {};
2321 }
2322 Op.appendToVector(NewOps);
2323 }
2324 NewOps.append(Ops.begin(), Ops.end());
2325 auto *result =
2326 DIExpression::get(Expr->getContext(), NewOps)->foldConstantMath();
2327 assert(result->isValid() && "concatenated expression is not valid");
2328 return result;
2329}
2330
2331DIExpression *DIExpression::appendToStack(const DIExpression *Expr,
2333 assert(Expr && !Ops.empty() && "Can't append ops to this expression");
2334 assert(std::none_of(expr_op_iterator(Ops.begin()),
2335 expr_op_iterator(Ops.end()),
2336 [](auto Op) {
2337 return Op.getOp() == dwarf::DW_OP_stack_value ||
2338 Op.getOp() == dwarf::DW_OP_LLVM_fragment;
2339 }) &&
2340 "Can't append this op");
2341
2342 // Append a DW_OP_deref after Expr's current op list if it's non-empty and
2343 // has no DW_OP_stack_value.
2344 //
2345 // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?.
2346 std::optional<FragmentInfo> FI = Expr->getFragmentInfo();
2347 unsigned DropUntilStackValue = FI ? 3 : 0;
2348 ArrayRef<uint64_t> ExprOpsBeforeFragment =
2349 Expr->getElements().drop_back(DropUntilStackValue);
2350 bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) &&
2351 (ExprOpsBeforeFragment.back() != dwarf::DW_OP_stack_value);
2352 bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.empty();
2353
2354 // Append a DW_OP_deref after Expr's current op list if needed, then append
2355 // the new ops, and finally ensure that a single DW_OP_stack_value is present.
2357 if (NeedsDeref)
2358 NewOps.push_back(dwarf::DW_OP_deref);
2359 NewOps.append(Ops.begin(), Ops.end());
2360 if (NeedsStackValue)
2361 NewOps.push_back(dwarf::DW_OP_stack_value);
2362 return DIExpression::append(Expr, NewOps);
2363}
2364
2365std::optional<DIExpression *> DIExpression::createFragmentExpression(
2366 const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) {
2368 // Track whether it's safe to split the value at the top of the DWARF stack,
2369 // assuming that it'll be used as an implicit location value.
2370 bool CanSplitValue = true;
2371 // Track whether we need to add a fragment expression to the end of Expr.
2372 bool EmitFragment = true;
2373 // Copy over the expression, but leave off any trailing DW_OP_LLVM_fragment.
2374 if (Expr) {
2375 for (auto Op : Expr->expr_ops()) {
2376 switch (Op.getOp()) {
2377 default:
2378 break;
2379 case dwarf::DW_OP_shr:
2380 case dwarf::DW_OP_shra:
2381 case dwarf::DW_OP_shl:
2382 case dwarf::DW_OP_plus:
2383 case dwarf::DW_OP_plus_uconst:
2384 case dwarf::DW_OP_minus:
2385 // We can't safely split arithmetic or shift operations into multiple
2386 // fragments because we can't express carry-over between fragments.
2387 //
2388 // FIXME: We *could* preserve the lowest fragment of a constant offset
2389 // operation if the offset fits into SizeInBits.
2390 CanSplitValue = false;
2391 break;
2392 case dwarf::DW_OP_deref:
2393 case dwarf::DW_OP_deref_size:
2394 case dwarf::DW_OP_deref_type:
2395 case dwarf::DW_OP_xderef:
2396 case dwarf::DW_OP_xderef_size:
2397 case dwarf::DW_OP_xderef_type:
2398 // Preceeding arithmetic operations have been applied to compute an
2399 // address. It's okay to split the value loaded from that address.
2400 CanSplitValue = true;
2401 break;
2402 case dwarf::DW_OP_stack_value:
2403 // Bail if this expression computes a value that cannot be split.
2404 if (!CanSplitValue)
2405 return std::nullopt;
2406 break;
2408 // If we've decided we don't need a fragment then give up if we see that
2409 // there's already a fragment expression.
2410 // FIXME: We could probably do better here
2411 if (!EmitFragment)
2412 return std::nullopt;
2413 // Make the new offset point into the existing fragment.
2414 uint64_t FragmentOffsetInBits = Op.getArg(0);
2415 uint64_t FragmentSizeInBits = Op.getArg(1);
2416 (void)FragmentSizeInBits;
2417 assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
2418 "new fragment outside of original fragment");
2419 OffsetInBits += FragmentOffsetInBits;
2420 continue;
2421 }
2424 // If we're extracting bits from inside of the fragment that we're
2425 // creating then we don't have a fragment after all, and just need to
2426 // adjust the offset that we're extracting from.
2427 uint64_t ExtractOffsetInBits = Op.getArg(0);
2428 uint64_t ExtractSizeInBits = Op.getArg(1);
2429 if (ExtractOffsetInBits >= OffsetInBits &&
2430 ExtractOffsetInBits + ExtractSizeInBits <=
2431 OffsetInBits + SizeInBits) {
2432 Ops.push_back(Op.getOp());
2433 Ops.push_back(ExtractOffsetInBits - OffsetInBits);
2434 Ops.push_back(ExtractSizeInBits);
2435 EmitFragment = false;
2436 continue;
2437 }
2438 // If the extracted bits aren't fully contained within the fragment then
2439 // give up.
2440 // FIXME: We could probably do better here
2441 return std::nullopt;
2442 }
2443 }
2444 Op.appendToVector(Ops);
2445 }
2446 }
2447 assert((!Expr->isImplicit() || CanSplitValue) && "Expr can't be split");
2448 assert(Expr && "Unknown DIExpression");
2449 if (EmitFragment) {
2451 Ops.push_back(OffsetInBits);
2452 Ops.push_back(SizeInBits);
2453 }
2454 return DIExpression::get(Expr->getContext(), Ops);
2455}
2456
2457/// See declaration for more info.
2459 const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits,
2460 uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits,
2461 int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag,
2462 std::optional<DIExpression::FragmentInfo> &Result,
2463 int64_t &OffsetFromLocationInBits) {
2464
2465 if (VarFrag.SizeInBits == 0)
2466 return false; // Variable size is unknown.
2467
2468 // Difference between mem slice start and the dbg location start.
2469 // 0 4 8 12 16 ...
2470 // | |
2471 // dbg location start
2472 // |
2473 // mem slice start
2474 // Here MemStartRelToDbgStartInBits is 8. Note this can be negative.
2475 int64_t MemStartRelToDbgStartInBits;
2476 {
2477 auto MemOffsetFromDbgInBytes = SliceStart->getPointerOffsetFrom(DbgPtr, DL);
2478 if (!MemOffsetFromDbgInBytes)
2479 return false; // Can't calculate difference in addresses.
2480 // Difference between the pointers.
2481 MemStartRelToDbgStartInBits = *MemOffsetFromDbgInBytes * 8;
2482 // Add the difference of the offsets.
2483 MemStartRelToDbgStartInBits +=
2484 SliceOffsetInBits - (DbgPtrOffsetInBits + DbgExtractOffsetInBits);
2485 }
2486
2487 // Out-param. Invert offset to get offset from debug location.
2488 OffsetFromLocationInBits = -MemStartRelToDbgStartInBits;
2489
2490 // Check if the variable fragment sits outside (before) this memory slice.
2491 int64_t MemEndRelToDbgStart = MemStartRelToDbgStartInBits + SliceSizeInBits;
2492 if (MemEndRelToDbgStart < 0) {
2493 Result = {0, 0}; // Out-param.
2494 return true;
2495 }
2496
2497 // Work towards creating SliceOfVariable which is the bits of the variable
2498 // that the memory region covers.
2499 // 0 4 8 12 16 ...
2500 // | |
2501 // dbg location start with VarFrag offset=32
2502 // |
2503 // mem slice start: SliceOfVariable offset=40
2504 int64_t MemStartRelToVarInBits =
2505 MemStartRelToDbgStartInBits + VarFrag.OffsetInBits;
2506 int64_t MemEndRelToVarInBits = MemStartRelToVarInBits + SliceSizeInBits;
2507 // If the memory region starts before the debug location the fragment
2508 // offset would be negative, which we can't encode. Limit those to 0. This
2509 // is fine because those bits necessarily don't overlap with the existing
2510 // variable fragment.
2511 int64_t MemFragStart = std::max<int64_t>(0, MemStartRelToVarInBits);
2512 int64_t MemFragSize =
2513 std::max<int64_t>(0, MemEndRelToVarInBits - MemFragStart);
2514 DIExpression::FragmentInfo SliceOfVariable(MemFragSize, MemFragStart);
2515
2516 // Intersect the memory region fragment with the variable location fragment.
2517 DIExpression::FragmentInfo TrimmedSliceOfVariable =
2518 DIExpression::FragmentInfo::intersect(SliceOfVariable, VarFrag);
2519 if (TrimmedSliceOfVariable == VarFrag)
2520 Result = std::nullopt; // Out-param.
2521 else
2522 Result = TrimmedSliceOfVariable; // Out-param.
2523 return true;
2524}
2525
2526std::pair<DIExpression *, const ConstantInt *>
2528 // Copy the APInt so we can modify it.
2529 APInt NewInt = CI->getValue();
2531
2532 // Fold operators only at the beginning of the expression.
2533 bool First = true;
2534 bool Changed = false;
2535 for (auto Op : expr_ops()) {
2536 switch (Op.getOp()) {
2537 default:
2538 // We fold only the leading part of the expression; if we get to a part
2539 // that we're going to copy unchanged, and haven't done any folding,
2540 // then the entire expression is unchanged and we can return early.
2541 if (!Changed)
2542 return {this, CI};
2543 First = false;
2544 break;
2546 if (!First)
2547 break;
2548 Changed = true;
2549 if (Op.getArg(1) == dwarf::DW_ATE_signed)
2550 NewInt = NewInt.sextOrTrunc(Op.getArg(0));
2551 else {
2552 assert(Op.getArg(1) == dwarf::DW_ATE_unsigned && "Unexpected operand");
2553 NewInt = NewInt.zextOrTrunc(Op.getArg(0));
2554 }
2555 continue;
2556 }
2557 Op.appendToVector(Ops);
2558 }
2559 if (!Changed)
2560 return {this, CI};
2561 return {DIExpression::get(getContext(), Ops),
2562 ConstantInt::get(getContext(), NewInt)};
2563}
2564
2566 uint64_t Result = 0;
2567 for (auto ExprOp : expr_ops())
2568 if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)
2569 Result = std::max(Result, ExprOp.getArg(0) + 1);
2570 assert(hasAllLocationOps(Result) &&
2571 "Expression is missing one or more location operands.");
2572 return Result;
2573}
2574
2575std::optional<DIExpression::SignedOrUnsignedConstant>
2577
2578 // Recognize signed and unsigned constants.
2579 // An signed constants can be represented as DW_OP_consts C DW_OP_stack_value
2580 // (DW_OP_LLVM_fragment of Len).
2581 // An unsigned constant can be represented as
2582 // DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment of Len).
2583
2584 if ((getNumElements() != 2 && getNumElements() != 3 &&
2585 getNumElements() != 6) ||
2586 (getElement(0) != dwarf::DW_OP_consts &&
2587 getElement(0) != dwarf::DW_OP_constu))
2588 return std::nullopt;
2589
2590 if (getNumElements() == 2 && getElement(0) == dwarf::DW_OP_consts)
2592
2593 if ((getNumElements() == 3 && getElement(2) != dwarf::DW_OP_stack_value) ||
2594 (getNumElements() == 6 && (getElement(2) != dwarf::DW_OP_stack_value ||
2596 return std::nullopt;
2597 return getElement(0) == dwarf::DW_OP_constu
2600}
2601
2602DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize,
2603 bool Signed) {
2604 dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned;
2606 dwarf::DW_OP_LLVM_convert, ToSize, TK}};
2607 return Ops;
2608}
2609
2610DIExpression *DIExpression::appendExt(const DIExpression *Expr,
2611 unsigned FromSize, unsigned ToSize,
2612 bool Signed) {
2613 return appendToStack(Expr, getExtOps(FromSize, ToSize, Signed));
2614}
2615
2617DIGlobalVariableExpression::getImpl(LLVMContext &Context, Metadata *Variable,
2619 bool ShouldCreate) {
2621 Metadata *Ops[] = {Variable, Expression};
2623}
2624DIObjCProperty::DIObjCProperty(LLVMContext &C, StorageType Storage,
2625 unsigned Line, unsigned Attributes,
2627 : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops),
2629
2630DIObjCProperty *DIObjCProperty::getImpl(
2631 LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
2632 MDString *GetterName, MDString *SetterName, unsigned Attributes,
2633 Metadata *Type, StorageType Storage, bool ShouldCreate) {
2634 assert(isCanonical(Name) && "Expected canonical MDString");
2635 assert(isCanonical(GetterName) && "Expected canonical MDString");
2636 assert(isCanonical(SetterName) && "Expected canonical MDString");
2637 DEFINE_GETIMPL_LOOKUP(DIObjCProperty, (Name, File, Line, GetterName,
2638 SetterName, Attributes, Type));
2640 DEFINE_GETIMPL_STORE(DIObjCProperty, (Line, Attributes), Ops);
2641}
2642
2643DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,
2644 Metadata *Scope, Metadata *Entity,
2645 Metadata *File, unsigned Line,
2646 MDString *Name, Metadata *Elements,
2647 StorageType Storage,
2648 bool ShouldCreate) {
2649 assert(isCanonical(Name) && "Expected canonical MDString");
2650 DEFINE_GETIMPL_LOOKUP(DIImportedEntity,
2651 (Tag, Scope, Entity, File, Line, Name, Elements));
2653 DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops);
2654}
2655
2656DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,
2657 MDString *Name, MDString *Value, StorageType Storage,
2658 bool ShouldCreate) {
2659 assert(isCanonical(Name) && "Expected canonical MDString");
2661 Metadata *Ops[] = {Name, Value};
2662 DEFINE_GETIMPL_STORE(DIMacro, (MIType, Line), Ops);
2663}
2664
2665DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
2666 unsigned Line, Metadata *File,
2667 Metadata *Elements, StorageType Storage,
2668 bool ShouldCreate) {
2669 DEFINE_GETIMPL_LOOKUP(DIMacroFile, (MIType, Line, File, Elements));
2670 Metadata *Ops[] = {File, Elements};
2671 DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);
2672}
2673
2674DIArgList *DIArgList::get(LLVMContext &Context,
2676 auto ExistingIt = Context.pImpl->DIArgLists.find_as(DIArgListKeyInfo(Args));
2677 if (ExistingIt != Context.pImpl->DIArgLists.end())
2678 return *ExistingIt;
2679 DIArgList *NewArgList = new DIArgList(Context, Args);
2680 Context.pImpl->DIArgLists.insert(NewArgList);
2681 return NewArgList;
2682}
2683
2685 ValueAsMetadata **OldVMPtr = static_cast<ValueAsMetadata **>(Ref);
2686 assert((!New || isa<ValueAsMetadata>(New)) &&
2687 "DIArgList must be passed a ValueAsMetadata");
2688 untrack();
2689 // We need to update the set storage once the Args are updated since they
2690 // form the key to the DIArgLists store.
2691 getContext().pImpl->DIArgLists.erase(this);
2693 for (ValueAsMetadata *&VM : Args) {
2694 if (&VM == OldVMPtr) {
2695 if (NewVM)
2696 VM = NewVM;
2697 else
2698 VM = ValueAsMetadata::get(PoisonValue::get(VM->getValue()->getType()));
2699 }
2700 }
2701 // We've changed the contents of this DIArgList, and the set storage may
2702 // already contain a DIArgList with our new set of args; if it does, then we
2703 // must RAUW this with the existing DIArgList, otherwise we simply insert this
2704 // back into the set storage.
2705 DIArgList *ExistingArgList = getUniqued(getContext().pImpl->DIArgLists, this);
2706 if (ExistingArgList) {
2707 replaceAllUsesWith(ExistingArgList);
2708 // Clear this here so we don't try to untrack in the destructor.
2709 Args.clear();
2710 delete this;
2711 return;
2712 }
2713 getContext().pImpl->DIArgLists.insert(this);
2714 track();
2715}
2716void DIArgList::track() {
2717 for (ValueAsMetadata *&VAM : Args)
2718 if (VAM)
2719 MetadataTracking::track(&VAM, *VAM, *this);
2720}
2721void DIArgList::untrack() {
2722 for (ValueAsMetadata *&VAM : Args)
2723 if (VAM)
2724 MetadataTracking::untrack(&VAM, *VAM);
2725}
2726void DIArgList::dropAllReferences(bool Untrack) {
2727 if (Untrack)
2728 untrack();
2729 Args.clear();
2730 ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
2731}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
constexpr LLT S1
AMDGPU Kernel Attributes
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
static ConstantAsMetadata * extractConstantMetadata(Metadata *ExtraData)
static const char * ChecksumKindName[DIFile::CSK_Last]
#define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS)
static void adjustColumn(unsigned &Column)
#define DEFINE_GETIMPL_STORE_N(CLASS, ARGS, OPS, NUM_OPS)
static std::pair< DIScope *, LineColumn > getNearestMatchingScope(const DILocation *L1, const DILocation *L2)
static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default)
Returns the location of DILocalScope, if present, or a default value.
std::pair< unsigned, unsigned > LineColumn
static ScopeT getRawRetainedNodeScopeInternal(NodeT *N)
static bool isCanonical(const MDString *S)
#define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS)
#define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS)
#define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS)
static DILexicalBlockBase * cloneAndReplaceParentScope(DILexicalBlockBase *LBB, DIScope *NewParent)
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
static unsigned encodingBits(unsigned C)
static unsigned encodeComponent(unsigned C)
static unsigned getNextComponentInDiscriminator(unsigned D)
Returns the next component stored in discriminator.
static unsigned getUnsignedFromPrefixEncoding(unsigned U)
Reverse transformation as getPrefixEncodingFromUnsigned.
@ Default
This file contains constants used for implementing Dwarf debug support.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
#define T
static constexpr StringLiteral Filename
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file implements a set that has insertion order iteration characteristics.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
Definition APInt.cpp:1064
LLVM_ABI APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition APInt.cpp:1072
Annotations lets you mark points and ranges inside source code, for tests:
Definition Annotations.h:53
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
back - Get the last element.
Definition ArrayRef.h:151
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:195
size_t size() const
size - Get the array size.
Definition ArrayRef.h:142
ArrayRef< T > drop_back(size_t N=1) const
Drop the last N elements of the array.
Definition ArrayRef.h:201
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:137
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI void handleChangedOperand(void *Ref, Metadata *New)
static LLVM_ABI DIArgList * get(LLVMContext &Context, ArrayRef< ValueAsMetadata * > Args)
static DIBasicType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, uint32_t NumExtraInhabitants, uint32_t DataSizeInBits, DIFlags Flags, StorageType Storage, bool ShouldCreate=true)
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t unsigned DIFlags Flags
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, uint32_t AlignInBits, unsigned Encoding, uint32_t NumExtraInhabitants, uint32_t DataSizeInBits, DIFlags Flags, ArrayRef< Metadata * > Ops)
unsigned StringRef uint64_t SizeInBits
LLVM_ABI std::optional< Signedness > getSignedness() const
Return the signedness of this type, or std::nullopt if this type is neither signed nor unsigned.
unsigned getEncoding() const
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t unsigned DIFlags Flags unsigned StringRef uint64_t uint32_t unsigned uint32_t NumExtraInhabitants
unsigned StringRef Name
unsigned StringRef uint64_t FlagZero unsigned StringRef uint64_t uint32_t AlignInBits
Debug common block.
Metadata Metadata * Decl
Metadata Metadata MDString Metadata unsigned LineNo
Metadata Metadata MDString * Name
Metadata Metadata MDString Metadata * File
static LLVM_ABI const char * nameTableKindString(DebugNameTableKind PK)
static LLVM_ABI const char * emissionKindString(DebugEmissionKind EK)
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata uint64_t bool bool unsigned bool MDString * SysRoot
DISourceLanguageName Metadata MDString bool MDString * Flags
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata uint64_t bool bool unsigned bool MDString MDString * SDK
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata * GlobalVariables
DebugEmissionKind getEmissionKind() const
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata * EnumTypes
DISourceLanguageName Metadata MDString * Producer
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata * RetainedTypes
DISourceLanguageName Metadata MDString bool MDString unsigned MDString * SplitDebugFilename
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata * ImportedEntities
DISourceLanguageName Metadata MDString bool MDString unsigned MDString unsigned Metadata Metadata Metadata Metadata Metadata * Macros
DebugNameTableKind getNameTableKind() const
DISourceLanguageName Metadata * File
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t AlignInBits
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > EnumKind
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata * DataLocation
static LLVM_ABI DICompositeType * buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, Metadata *Specification, uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, std::optional< uint32_t > EnumKind, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, Metadata *Rank, Metadata *Annotations, Metadata *BitStride)
Build a DICompositeType with the given ODR identifier.
unsigned MDString Metadata unsigned Line
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata * Elements
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned RuntimeLang
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata * Annotations
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString * Identifier
static LLVM_ABI DICompositeType * getODRTypeIfExists(LLVMContext &Context, MDString &Identifier)
unsigned MDString * Name
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata * Discriminator
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata * TemplateParams
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t OffsetInBits
unsigned MDString Metadata unsigned Metadata * Scope
unsigned MDString Metadata * File
unsigned MDString Metadata unsigned Metadata Metadata * BaseType
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Flags
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata * Allocated
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata * Specification
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata * VTableHolder
unsigned MDString Metadata unsigned Metadata Metadata uint64_t SizeInBits
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata * Associated
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata uint32_t NumExtraInhabitants
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata * Rank
unsigned MDString Metadata unsigned Metadata Metadata uint64_t uint32_t uint64_t DIFlags Metadata unsigned std::optional< uint32_t > Metadata Metadata MDString Metadata Metadata Metadata Metadata Metadata Metadata Metadata uint32_t Metadata * BitStride
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata * OffsetInBits
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t AlignInBits
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata std::optional< unsigned > std::optional< PtrAuthData > PtrAuthData
Metadata * getExtraData() const
Get extra data associated with this derived type.
unsigned StringRef DIFile * File
unsigned StringRef DIFile unsigned DIScope DIType Metadata uint32_t Metadata std::optional< unsigned > DWARFAddressSpace
LLVM_ABI DIType * getClassType() const
Get casted version of extra data.
LLVM_ABI Constant * getConstant() const
unsigned StringRef DIFile unsigned DIScope DIType Metadata * SizeInBits
LLVM_ABI Constant * getStorageOffsetInBits() const
LLVM_ABI Constant * getDiscriminantValue() const
unsigned StringRef Name
LLVM_ABI uint32_t getVBPtrOffset() const
Enumeration value.
int64_t bool MDString * Name
LLVM_ABI unsigned getSize() const
Return the size of the operand.
uint64_t getOp() const
Get the operand code.
An iterator for expression operands.
DWARF expression.
element_iterator elements_end() const
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
iterator_range< expr_op_iterator > expr_ops() const
static LLVM_ABI DIExpression * append(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Append the opcodes Ops to DIExpr.
std::array< uint64_t, 6 > ExtOps
unsigned getNumElements() const
static LLVM_ABI ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed)
Returns the ops for a zero- or sign-extension in a DIExpression.
expr_op_iterator expr_op_begin() const
Visit the elements via ExprOperand wrappers.
LLVM_ABI bool extractIfOffset(int64_t &Offset) const
If this is a constant offset, extract it.
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
DbgVariableFragmentInfo FragmentInfo
LLVM_ABI bool startsWithDeref() const
Return whether the first element a DW_OP_deref.
static LLVM_ABI bool isEqualExpression(const DIExpression *FirstExpr, bool FirstIndirect, const DIExpression *SecondExpr, bool SecondIndirect)
Determines whether two debug values should produce equivalent DWARF expressions, using their DIExpres...
expr_op_iterator expr_op_end() const
LLVM_ABI bool isImplicit() const
Return whether this is an implicit location description.
static LLVM_ABI bool calculateFragmentIntersect(const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits, uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits, int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag, std::optional< DIExpression::FragmentInfo > &Result, int64_t &OffsetFromLocationInBits)
Computes a fragment, bit-extract operation if needed, and new constant offset to describe a part of a...
element_iterator elements_begin() const
LLVM_ABI bool hasAllLocationOps(unsigned N) const
Returns true iff this DIExpression contains at least one instance of DW_OP_LLVM_arg,...
std::optional< FragmentInfo > getFragmentInfo() const
Retrieve the details of this fragment expression.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
LLVM_ABI bool isComplex() const
Return whether the location is computed on the expression stack, meaning it cannot be a simple regist...
static LLVM_ABI std::optional< FragmentInfo > getFragmentInfo(expr_op_iterator Start, expr_op_iterator End)
Retrieve the details of this fragment expression.
static LLVM_ABI std::optional< const DIExpression * > convertToNonVariadicExpression(const DIExpression *Expr)
If Expr is a valid single-location expression, i.e.
LLVM_ABI std::pair< DIExpression *, const ConstantInt * > constantFold(const ConstantInt *CI)
Try to shorten an expression with an initial constant operand.
LLVM_ABI bool isDeref() const
Return whether there is exactly one operator and it is a DW_OP_deref;.
static LLVM_ABI const DIExpression * convertToVariadicExpression(const DIExpression *Expr)
If Expr is a non-variadic expression (i.e.
LLVM_ABI uint64_t getNumLocationOperands() const
Return the number of unique location operands referred to (via DW_OP_LLVM_arg) in this expression; th...
ArrayRef< uint64_t > getElements() const
static LLVM_ABI DIExpression * replaceArg(const DIExpression *Expr, uint64_t OldArg, uint64_t NewArg)
Create a copy of Expr with each instance of DW_OP_LLVM_arg, \p OldArg replaced with DW_OP_LLVM_arg,...
LLVM_ABI std::optional< uint64_t > getActiveBits(DIVariable *Var)
Return the number of bits that have an active value, i.e.
static LLVM_ABI void canonicalizeExpressionOps(SmallVectorImpl< uint64_t > &Ops, const DIExpression *Expr, bool IsIndirect)
Inserts the elements of Expr into Ops modified to a canonical form, which uses DW_OP_LLVM_arg (i....
uint64_t getElement(unsigned I) const
static LLVM_ABI bool extractLeadingOffset(ArrayRef< uint64_t > Ops, int64_t &OffsetInBytes, SmallVectorImpl< uint64_t > &RemainingOps)
static LLVM_ABI std::optional< DIExpression * > createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits)
Create a DIExpression to describe one part of an aggregate variable that is fragmented across multipl...
static LLVM_ABI const DIExpression * convertToUndefExpression(const DIExpression *Expr)
Removes all elements from Expr that do not apply to an undef debug value, which includes every operat...
static LLVM_ABI DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
static LLVM_ABI DIExpression * appendToStack(const DIExpression *Expr, ArrayRef< uint64_t > Ops)
Convert DIExpr into a stack value if it isn't one already by appending DW_OP_deref if needed,...
static LLVM_ABI DIExpression * appendExt(const DIExpression *Expr, unsigned FromSize, unsigned ToSize, bool Signed)
Append a zero- or sign-extension to Expr.
LLVM_ABI std::optional< ArrayRef< uint64_t > > getSingleLocationExpressionElements() const
Returns a reference to the elements contained in this expression, skipping past the leading DW_OP_LLV...
LLVM_ABI bool isSingleLocationExpression() const
Return whether the evaluated expression makes use of a single location at the start of the expression...
LLVM_ABI std::optional< SignedOrUnsignedConstant > isConstant() const
Determine whether this represents a constant value, if so.
LLVM_ABI bool isValid() const
static LLVM_ABI const DIExpression * extractAddressClass(const DIExpression *Expr, unsigned &AddrClass)
Checks if the last 4 elements of the expression are DW_OP_constu <DWARFAddress Space> DW_OP_swap DW_O...
static LLVM_ABI DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
MDString MDString * Directory
MDString MDString std::optional< ChecksumInfo< MDString * > > MDString * Source
static LLVM_ABI std::optional< ChecksumKind > getChecksumKind(StringRef CSKindStr)
MDString MDString std::optional< ChecksumInfo< MDString * > > CS
unsigned StringRef uint64_t uint32_t unsigned DIFlags unsigned int Factor
static LLVM_ABI std::optional< FixedPointKind > getFixedPointKind(StringRef Str)
static LLVM_ABI const char * fixedPointKindString(FixedPointKind)
unsigned StringRef uint64_t uint32_t unsigned Encoding
unsigned StringRef uint64_t uint32_t AlignInBits
LLVM_ABI bool isSigned() const
@ FixedPointBinary
Scale factor 2^Factor.
@ FixedPointDecimal
Scale factor 10^Factor.
@ FixedPointRational
Arbitrary rational scale factor.
unsigned StringRef uint64_t uint32_t unsigned DIFlags unsigned int APInt Numerator
unsigned StringRef uint64_t uint32_t unsigned DIFlags unsigned int APInt APInt Denominator
unsigned StringRef uint64_t SizeInBits
Metadata * getRawLowerBound() const
Metadata * getRawCountNode() const
Metadata * getRawStride() const
LLVM_ABI BoundType getLowerBound() const
Metadata * getRawUpperBound() const
LLVM_ABI BoundType getCount() const
LLVM_ABI BoundType getUpperBound() const
PointerUnion< DIVariable *, DIExpression * > BoundType
LLVM_ABI BoundType getStride() const
A pair of DIGlobalVariable and DIExpression.
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata Metadata * TemplateParams
Metadata MDString MDString Metadata unsigned Line
Metadata MDString MDString Metadata unsigned Metadata * Type
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata Metadata uint32_t Metadata * Annotations
Metadata MDString * Name
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata * StaticDataMemberDeclaration
Metadata MDString MDString * LinkageName
Metadata MDString MDString Metadata * File
Metadata MDString MDString Metadata unsigned Metadata bool bool Metadata Metadata uint32_t AlignInBits
An imported module (C++ using directive or similar).
unsigned Metadata Metadata * Entity
unsigned Metadata Metadata Metadata unsigned Line
unsigned Metadata Metadata Metadata unsigned MDString * Name
unsigned Metadata Metadata Metadata * File
unsigned Metadata * Scope
Metadata MDString Metadata unsigned unsigned bool std::optional< unsigned > CoroSuspendIdx
Metadata MDString Metadata unsigned unsigned Column
Metadata MDString Metadata unsigned unsigned bool IsArtificial
Metadata MDString Metadata unsigned Line
Metadata MDString * Name
Metadata MDString Metadata * File
LLVM_ABI DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef< Metadata * > Ops)
Metadata Metadata unsigned Discriminator
Debug lexical block.
Metadata Metadata unsigned unsigned Column
Metadata Metadata * File
A scope for locals.
LLVM_ABI DISubprogram * getSubprogram() const
Get the subprogram for this scope.
LLVM_ABI DILocalScope * getNonLexicalBlockFileScope() const
Get the first non DILexicalBlockFile scope of this scope.
DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef< Metadata * > Ops)
static LLVM_ABI DILocalScope * cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx, DenseMap< const MDNode *, MDNode * > &Cache)
Traverses the scope chain rooted at RootScope until it hits a Subprogram, recreating the chain with "...
Metadata MDString Metadata unsigned Metadata * Type
Metadata MDString Metadata * File
Metadata MDString * Name
Metadata MDString Metadata unsigned Line
Metadata MDString Metadata unsigned Metadata unsigned DIFlags uint32_t Metadata * Annotations
Metadata MDString Metadata unsigned Metadata unsigned DIFlags uint32_t AlignInBits
unsigned unsigned DILocalScope * Scope
static LLVM_ABI DILocation * getMergedLocations(ArrayRef< DILocation * > Locs)
Try to combine the vector of locations passed as input in a single one.
static LLVM_ABI std::optional< unsigned > encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI)
Raw encoding of the discriminator.
unsigned unsigned DILocalScope DILocation bool ImplicitCode
static LLVM_ABI void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, unsigned &CI)
Raw decoder for values in an encoded discriminator D.
static LLVM_ABI DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
Attempts to merge LocA and LocB into a single location; see DebugLoc::getMergedLocation for more deta...
unsigned unsigned Column
unsigned unsigned DILocalScope DILocation * InlinedAt
unsigned unsigned Metadata * File
unsigned unsigned Line
unsigned unsigned Metadata Metadata * Elements
unsigned unsigned MDString MDString * Value
unsigned unsigned MDString * Name
unsigned unsigned Line
Represents a module in the programming language, for example, a Clang module, or a Fortran module.
Metadata Metadata * Scope
Metadata Metadata MDString * Name
Metadata Metadata MDString MDString MDString MDString * APINotesFile
Metadata Metadata MDString MDString MDString * IncludePath
Metadata Metadata MDString MDString * ConfigurationMacros
Metadata Metadata MDString MDString MDString MDString unsigned LineNo
Debug lexical block.
Metadata MDString bool ExportSymbols
Metadata MDString * Name
Tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
static LLVM_ABI DIFlags getFlag(StringRef Flag)
static LLVM_ABI DIFlags splitFlags(DIFlags Flags, SmallVectorImpl< DIFlags > &SplitFlags)
Split up a flags bitfield.
DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef< Metadata * > Ops1, ArrayRef< Metadata * > Ops2={})
static LLVM_ABI StringRef getFlagString(DIFlags Flag)
DIFlags
Debug info flags.
MDString Metadata * File
MDString Metadata unsigned MDString MDString unsigned Metadata * Type
MDString Metadata unsigned MDString * GetterName
MDString Metadata unsigned MDString MDString * SetterName
Base class for scope-like contexts.
LLVM_ABI StringRef getName() const
DIFile * getFile() const
LLVM_ABI DIScope * getScope() const
DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef< Metadata * > Ops)
Wrapper structure that holds a language name and its version.
String type, Fortran CHARACTER(n)
unsigned MDString * Name
unsigned MDString Metadata Metadata Metadata uint64_t SizeInBits
unsigned MDString Metadata Metadata Metadata uint64_t uint32_t AlignInBits
unsigned MDString Metadata Metadata Metadata * StringLocationExp
unsigned MDString Metadata Metadata * StringLengthExp
unsigned MDString Metadata Metadata Metadata uint64_t uint32_t unsigned Encoding
unsigned MDString Metadata * StringLength
Subprogram description. Uses SubclassData1.
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata Metadata MDString bool UsesKeyInstructions
void cleanupRetainedNodes()
When IR modules are merged, typically during LTO, the merged module may contain several types having ...
Metadata MDString MDString Metadata unsigned Metadata unsigned ScopeLine
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags SPFlags
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata * ContainingType
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata * TemplateParams
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata * Declaration
static DILocalScope * getRetainedNodeScope(MDNode *N)
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata Metadata MDString * TargetFuncName
static LLVM_ABI DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, unsigned Virtuality=SPFlagNonvirtual, bool IsMainSubprogram=false)
static const DIScope * getRawRetainedNodeScope(const MDNode *N)
Metadata MDString * Name
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata Metadata * ThrownTypes
static LLVM_ABI DISPFlags getFlag(StringRef Flag)
Metadata MDString MDString Metadata * File
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned VirtualIndex
static LLVM_ABI DISPFlags splitFlags(DISPFlags Flags, SmallVectorImpl< DISPFlags > &SplitFlags)
Split up a flags bitfield for easier printing.
static LLVM_ABI StringRef getFlagString(DISPFlags Flag)
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int DIFlags DISPFlags Metadata Metadata Metadata Metadata * RetainedNodes
DISPFlags
Debug info subprogram flags.
Metadata MDString MDString Metadata unsigned Metadata unsigned Metadata unsigned int ThisAdjustment
LLVM_ABI bool describes(const Function *F) const
Check if this subprogram describes the given function.
StringRef DIFile unsigned Line
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata * UpperBound
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata Metadata Metadata * Bias
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata Metadata Metadata * Stride
StringRef DIFile unsigned DIScope uint64_t SizeInBits
StringRef DIFile * File
PointerUnion< ConstantInt *, DIVariable *, DIExpression *, DIDerivedType * > BoundType
StringRef DIFile unsigned DIScope uint64_t uint32_t AlignInBits
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags DIType Metadata * LowerBound
StringRef DIFile unsigned DIScope uint64_t uint32_t DIFlags Flags
Array subrange.
LLVM_ABI BoundType getUpperBound() const
LLVM_ABI BoundType getStride() const
LLVM_ABI BoundType getLowerBound() const
LLVM_ABI BoundType getCount() const
Type array for a subprogram.
DIFlags uint8_t Metadata * TypeArray
Base class for template parameters.
unsigned MDString Metadata * Type
unsigned MDString Metadata bool Metadata * Value
Base class for types.
bool isBitField() const
bool isStaticMember() const
DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, uint32_t AlignInBits, uint32_t NumExtraInhabitants, DIFlags Flags, ArrayRef< Metadata * > Ops)
LLVM_ABI uint32_t getAlignInBits() const
Base class for variables.
std::optional< DIBasicType::Signedness > getSignedness() const
Return the signedness of this variable's type, or std::nullopt if this type is neither signed nor uns...
LLVM_ABI std::optional< uint64_t > getSizeInBits() const
Determines the size of the variable's type.
Metadata * getRawType() const
LLVM_ABI DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, signed Line, ArrayRef< Metadata * > Ops, uint32_t AlignInBits=0)
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI DebugVariableAggregate(const DbgVariableRecord *DVR)
const DILocation * getInlinedAt() const
const DILocalVariable * getVariable() const
LLVM_ABI DebugVariable(const DbgVariableRecord *DVR)
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:256
iterator end()
Definition DenseMap.h:81
Class representing an expression and its matching format.
Generic tagged DWARF-like metadata node.
LLVM_ABI dwarf::Tag getTag() const
unsigned MDString * Header
unsigned MDString ArrayRef< Metadata * > DwarfOps
DenseSet< DIArgList *, DIArgListInfo > DIArgLists
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVMContextImpl *const pImpl
Definition LLVMContext.h:70
Metadata node.
Definition Metadata.h:1080
friend class DIAssignID
Definition Metadata.h:1083
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1580
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
LLVM_ABI TempMDNode clone() const
Create a (temporary) clone of this.
Definition Metadata.cpp:683
static T * storeImpl(T *N, StorageType Storage, StoreT &Store)
LLVMContext & getContext() const
Definition Metadata.h:1244
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
Definition Metadata.h:1319
Tracking metadata reference owned by Metadata.
Definition Metadata.h:902
A single uniqued string.
Definition Metadata.h:722
LLVM_ABI StringRef getString() const
Definition Metadata.cpp:632
Tuple of metadata.
Definition Metadata.h:1500
static void untrack(Metadata *&MD)
Stop tracking a reference to metadata.
Definition Metadata.h:358
static bool track(Metadata *&MD)
Track the reference to metadata.
Definition Metadata.h:324
Root of the metadata hierarchy.
Definition Metadata.h:64
StorageType
Active type of storage.
Definition Metadata.h:72
unsigned short SubclassData16
Definition Metadata.h:78
unsigned SubclassData32
Definition Metadata.h:79
unsigned char Storage
Storage flag for non-uniqued, otherwise unowned, metadata.
Definition Metadata.h:75
unsigned char SubclassData1
Definition Metadata.h:77
Metadata(unsigned ID, StorageType Storage)
Definition Metadata.h:88
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
LLVM_ABI void replaceAllUsesWith(Metadata *MD)
Replace all uses of this with MD.
Definition Metadata.cpp:375
LLVMContext & getContext() const
Definition Metadata.h:409
LLVM_ABI void resolveAllUses(bool ResolveUsers=true)
Resolve all uses of this.
Definition Metadata.cpp:428
Implements a dense probed hash-table based set with some number of buckets stored inline.
Definition DenseSet.h:291
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:339
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:314
Value wrapper in the Metadata hierarchy.
Definition Metadata.h:459
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:509
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI std::optional< int64_t > getPointerOffsetFrom(const Value *Other, const DataLayout &DL) const
If this ptr is provably equal to Other plus a constant offset, return that offset in bytes.
Definition Value.cpp:1060
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:175
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.h:35
@ DW_OP_LLVM_entry_value
Only used in LLVM metadata.
Definition Dwarf.h:147
@ DW_OP_LLVM_implicit_pointer
Only used in LLVM metadata.
Definition Dwarf.h:148
@ DW_OP_LLVM_extract_bits_zext
Only used in LLVM metadata.
Definition Dwarf.h:151
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
Definition Dwarf.h:146
@ DW_OP_LLVM_fragment
Only used in LLVM metadata.
Definition Dwarf.h:144
@ DW_OP_LLVM_arg
Only used in LLVM metadata.
Definition Dwarf.h:149
@ DW_OP_LLVM_convert
Only used in LLVM metadata.
Definition Dwarf.h:145
@ DW_OP_LLVM_extract_bits_sext
Only used in LLVM metadata.
Definition Dwarf.h:150
@ DW_VIRTUALITY_max
Definition Dwarf.h:200
@ NameTableKind
Definition LLToken.h:517
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:532
static T * getUniqued(DenseSet< T *, InfoT > &Store, const typename InfoT::KeyTy &Key)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI cl::opt< bool > EnableFSDiscriminator
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
auto cast_or_null(const Y &Val)
Definition Casting.h:714
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
bool isa_and_present(const Y &Val)
isa_and_present<X> - Functionally identical to isa, except that a null value is accepted.
Definition Casting.h:669
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI cl::opt< bool > PickMergedSourceLocations("pick-merged-source-locations", cl::init(false), cl::Hidden, cl::desc("Preserve line and column number when merging locations."))
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
#define N
SmallPtrSet< DIScope *, 8 > Scopes
void insert(DIScope *S, LineColumn Loc)
DIScope * match(DIScope *S, LineColumn Loc)
void insert(DIScope *S, LineColumn Loc)
DIScope * match(DIScope *S, LineColumn Loc)
SmallMapVector< std::pair< DIFile *, LineColumn >, SmallSetVector< DIScope *, 8 >, 8 > Scopes
A single checksum, represented by a Kind and a Value (a string).
static DbgVariableFragmentInfo intersect(DbgVariableFragmentInfo A, DbgVariableFragmentInfo B)
Returns a zero-sized fragment if A and B don't intersect.
A MapVector that performs no allocations if smaller than a certain size.
Definition MapVector.h:276