2669 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the debug info Metadata classes.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/IR/DebugInfoMetadata.h"14#include "LLVMContextImpl.h"15#include "MetadataImpl.h"16#include "llvm/ADT/SetVector.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/BinaryFormat/Dwarf.h"19#include "llvm/IR/DebugProgramInstruction.h"20#include "llvm/IR/Function.h"21#include "llvm/IR/IntrinsicInst.h"22#include "llvm/IR/Type.h"23#include "llvm/IR/Value.h"24#include "llvm/Support/CommandLine.h"25#include "llvm/Support/Compiler.h"26 27#include <numeric>28#include <optional>29 30using namespace llvm;31 32namespace llvm {33// Use FS-AFDO discriminator.34cl::opt<bool> EnableFSDiscriminator(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 merged39// location info in a deterministic manner to assist sample based PGO.40LLVM_ABI cl::opt<bool> PickMergedSourceLocations(41 "pick-merged-source-locations", cl::init(false), cl::Hidden,42 cl::desc("Preserve line and column number when merging locations."));43} // namespace llvm44 45uint32_t DIType::getAlignInBits() const {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 52DebugVariable::DebugVariable(const DbgVariableRecord *DVR)53 : Variable(DVR->getVariable()),54 Fragment(DVR->getExpression()->getFragmentInfo()),55 InlinedAt(DVR->getDebugLoc().getInlinedAt()) {}56 57DebugVariableAggregate::DebugVariableAggregate(const DbgVariableRecord *DVR)58 : DebugVariable(DVR->getVariable(), std::nullopt,59 DVR->getDebugLoc()->getInlinedAt()) {}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.93 adjustColumn(Column);94 95 if (Storage == Uniqued) {96 if (auto *N = getUniqued(Context.pImpl->DILocations,97 DILocationInfo::KeyTy(Line, Column, Scope,98 InlinedAt, ImplicitCode,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 107 SmallVector<Metadata *, 2> Ops;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 117DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {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 131static DILexicalBlockBase *cloneAndReplaceParentScope(DILexicalBlockBase *LBB,132 DIScope *NewParent) {133 TempMDNode ClonedScope = LBB->clone();134 cast<DILexicalBlockBase>(*ClonedScope).replaceScope(NewParent);135 return cast<DILexicalBlockBase>(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.142static LineColumn getLocalScopeLocationOr(DIScope *S, LineColumn Default) {143 assert(isa<DILocalScope>(S) && "Expected DILocalScope.");144 145 if (isa<DILexicalBlockFile>(S))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>158getNearestMatchingScope(const DILocation *L1, const DILocation *L2) {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);168 if (isa<DISubprogram>(S1))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.186struct EqualScopesMatcher {187 SmallPtrSet<DIScope *, 8> Scopes;188 189 void insert(DIScope *S, LineColumn Loc) { Scopes.insert(S); }190 191 DIScope *match(DIScope *S, LineColumn Loc) {192 return Scopes.contains(S) ? S : nullptr;193 }194};195 196// Matches scopes with the same location.197struct ScopeLocationsMatcher {198 SmallMapVector<std::pair<DIFile *, LineColumn>, SmallSetVector<DIScope *, 8>,199 8>200 Scopes;201 202 void insert(DIScope *S, LineColumn Loc) {203 Scopes[{S->getFile(), Loc}].insert(S);204 }205 206 DIScope *match(DIScope *S, LineColumn Loc) {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 source228 // 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 typically230 // not useful for PGO. If one of them is null, then try to return one which is231 // valid.232 if (PickMergedSourceLocations) {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;253 SmallDenseMap<std::pair<const DISubprogram *, const DILocation *>, unsigned,254 4>255 ALookup;256 257 // Walk through LocA and its inlined-at locations, populate them in ALocs and258 // save the index for the subprogram and inlined-at pair, which we use to find259 // 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 first272 // location with the same subprogram and inlined-at location as in LocA's273 // chain. Since the two locations have the same inlined-at location we do274 // 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 more291 // locations to BLocs, since we will only look at location pairs preceding292 // the matching starting location, and adding more elements to BLocs could293 // invalidate the iterator that we initialized here.294 break;295 }296 297 // Merge the two locations if possible, using the supplied298 // 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 produce310 // a common location.311 if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())312 return nullptr;313 314 // Find nearest common scope inside subprogram.315 DIScope *Scope = getNearestMatchingScope<EqualScopesMatcher>(L1, L2).first;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] =321 getNearestMatchingScope<ScopeLocationsMatcher>(L1, L2);322 323 // If CommonLocScope is a DILexicalBlockBase, clone it and locate324 // a new scope inside the nearest common scope to preserve325 // 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 nothing346 // 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 can354 // preserve the atom.355 if (LocBIA == LocAIA && InlinedAt == LocBIA) {356 // Deterministically keep the lowest non-zero ranking atom group357 // number.358 // FIXME: It would be nice if we could track that an instruction359 // 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 new376 // atom group. This essentially regresses to non-key-instructions377 // behaviour (now that it's the only instruction in its group it'll378 // 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 chains389 // 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 locations395 // are irreconsilable. At this point Result contains the nearest common396 // 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 a406 // location at 0:0 with one of the locations' scope. The function has407 // historically picked A's scope, and a nullptr inlined-at location, so that408 // behavior is mimicked here but I am not sure if this is always the correct409 // way to handle this.410 // Key Instructions: it's fine to drop atom group and rank here, as line 0411 // 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 to421 // encode. For example: if BD != 0 but DF == 0 && CI == 0, we don't need to422 // encode anything for the latter 2.423 // Since any of the input components is at most 32 bits, their sum will be424 // 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 by440 // checking equivalence of components before & after encoding. Alternatively,441 // we could determine Success during encoding, but the current alternative is442 // 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 450void DILocation::decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF,451 unsigned &CI) {452 BD = getUnsignedFromPrefixEncoding(D);453 DF = getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator(D));454 CI = getUnsignedFromPrefixEncoding(455 getNextComponentInDiscriminator(getNextComponentInDiscriminator(D)));456}457dwarf::Tag DINode::getTag() const { return (dwarf::Tag)SubclassData16; }458 459DINode::DIFlags DINode::getFlag(StringRef Flag) {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 466StringRef DINode::getFlagString(DIFlags Flag) {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 476DINode::DIFlags DINode::splitFlags(DIFlags Flags,477 SmallVectorImpl<DIFlags> &SplitFlags) {478 // Flags that are packed together need to be specially handled, so479 // that, for example, we emit "DIFlagPublic" and not480 // "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 else487 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 else496 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 513DIScope *DIScope::getScope() const {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 537StringRef DIScope::getName() const {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();548 assert((isa<DILexicalBlockBase>(this) || isa<DIFile>(this) ||549 isa<DICompileUnit>(this)) &&550 "Unhandled type of scope.");551 return "";552}553 554#ifndef NDEBUG555static bool isCanonical(const MDString *S) {556 return !S || !S->getString().empty();557}558#endif559 560dwarf::Tag GenericDINode::getTag() const { return (dwarf::Tag)SubclassData16; }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 ARGS591#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,621 ArrayRef<Metadata *> Ops)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) {625 auto *CountNode = ConstantAsMetadata::get(626 ConstantInt::getSigned(Type::getInt64Ty(Context), Count));627 auto *LB = ConstantAsMetadata::get(628 ConstantInt::getSigned(Type::getInt64Ty(Context), Lo));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(637 ConstantInt::getSigned(Type::getInt64Ty(Context), Lo));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};647 DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DISubrange, Ops);648}649 650DISubrange::BoundType DISubrange::getCount() const {651 Metadata *CB = getRawCountNode();652 if (!CB)653 return BoundType();654 655 assert((isa<ConstantAsMetadata>(CB) || isa<DIVariable>(CB) ||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 676 assert((isa<ConstantAsMetadata>(LB) || isa<DIVariable>(LB) ||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 697 assert((isa<ConstantAsMetadata>(UB) || isa<DIVariable>(UB) ||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 718 assert((isa<ConstantAsMetadata>(ST) || isa<DIVariable>(ST) ||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,734 ArrayRef<Metadata *> Ops)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};745 DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGenericSubrange, Ops);746}747 748DIGenericSubrange::BoundType DIGenericSubrange::getCount() const {749 Metadata *CB = getRawCountNode();750 if (!CB)751 return BoundType();752 753 assert((isa<DIVariable>(CB) || isa<DIExpression>(CB)) &&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 765DIGenericSubrange::BoundType DIGenericSubrange::getLowerBound() const {766 Metadata *LB = getRawLowerBound();767 if (!LB)768 return BoundType();769 770 assert((isa<DIVariable>(LB) || isa<DIExpression>(LB)) &&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 782DIGenericSubrange::BoundType DIGenericSubrange::getUpperBound() const {783 Metadata *UB = getRawUpperBound();784 if (!UB)785 return BoundType();786 787 assert((isa<DIVariable>(UB) || isa<DIExpression>(UB)) &&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 799DIGenericSubrange::BoundType DIGenericSubrange::getStride() const {800 Metadata *ST = getRawStride();801 if (!ST)802 return BoundType();803 804 assert((isa<DIVariable>(ST) || isa<DIExpression>(ST)) &&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");828 DEFINE_GETIMPL_LOOKUP(DISubrangeType, (Name, File, Line, Scope, SizeInBits,829 AlignInBits, Flags, BaseType,830 LowerBound, UpperBound, Stride, Bias));831 Metadata *Ops[] = {File, Scope, Name, SizeInBits, nullptr,832 BaseType, LowerBound, UpperBound, Stride, Bias};833 DEFINE_GETIMPL_STORE(DISubrangeType, (Line, AlignInBits, Flags), Ops);834}835 836DISubrangeType::BoundType837DISubrangeType::convertRawToBound(Metadata *IN) const {838 if (!IN)839 return BoundType();840 841 assert(isa<ConstantAsMetadata>(IN) || isa<DIVariable>(IN) ||842 isa<DIExpression>(IN));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 return BoundType();854}855 856DIEnumerator::DIEnumerator(LLVMContext &C, StorageType Storage,857 const APInt &Value, bool IsUnsigned,858 ArrayRef<Metadata *> Ops)859 : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),860 Value(Value) {861 SubclassData32 = IsUnsigned;862}863DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,864 bool IsUnsigned, MDString *Name,865 StorageType Storage, bool ShouldCreate) {866 assert(isCanonical(Name) && "Expected canonical MDString");867 DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));868 Metadata *Ops[] = {Name};869 DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);870}871 872DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,873 MDString *Name, Metadata *SizeInBits,874 uint32_t AlignInBits, unsigned Encoding,875 uint32_t NumExtraInhabitants,876 uint32_t DataSizeInBits, DIFlags Flags,877 StorageType Storage, bool ShouldCreate) {878 assert(isCanonical(Name) && "Expected canonical MDString");879 DEFINE_GETIMPL_LOOKUP(DIBasicType,880 (Tag, Name, SizeInBits, AlignInBits, Encoding,881 NumExtraInhabitants, DataSizeInBits, Flags));882 Metadata *Ops[] = {nullptr, nullptr, Name, SizeInBits, nullptr};883 DEFINE_GETIMPL_STORE(884 DIBasicType,885 (Tag, AlignInBits, Encoding, NumExtraInhabitants, DataSizeInBits, Flags),886 Ops);887}888 889std::optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {890 switch (getEncoding()) {891 case dwarf::DW_ATE_signed:892 case dwarf::DW_ATE_signed_char:893 case dwarf::DW_ATE_signed_fixed:894 return Signedness::Signed;895 case dwarf::DW_ATE_unsigned:896 case dwarf::DW_ATE_unsigned_char:897 case dwarf::DW_ATE_unsigned_fixed:898 return Signedness::Unsigned;899 default:900 return std::nullopt;901 }902}903 904DIFixedPointType *905DIFixedPointType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,906 Metadata *SizeInBits, uint32_t AlignInBits,907 unsigned Encoding, DIFlags Flags, unsigned Kind,908 int Factor, APInt Numerator, APInt Denominator,909 StorageType Storage, bool ShouldCreate) {910 DEFINE_GETIMPL_LOOKUP(DIFixedPointType,911 (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,912 Kind, Factor, Numerator, Denominator));913 Metadata *Ops[] = {nullptr, nullptr, Name, SizeInBits, nullptr};914 DEFINE_GETIMPL_STORE(915 DIFixedPointType,916 (Tag, AlignInBits, Encoding, Flags, Kind, Factor, Numerator, Denominator),917 Ops);918}919 920bool DIFixedPointType::isSigned() const {921 return getEncoding() == dwarf::DW_ATE_signed_fixed;922}923 924std::optional<DIFixedPointType::FixedPointKind>925DIFixedPointType::getFixedPointKind(StringRef Str) {926 return StringSwitch<std::optional<FixedPointKind>>(Str)927 .Case("Binary", FixedPointBinary)928 .Case("Decimal", FixedPointDecimal)929 .Case("Rational", FixedPointRational)930 .Default(std::nullopt);931}932 933const char *DIFixedPointType::fixedPointKindString(FixedPointKind V) {934 switch (V) {935 case FixedPointBinary:936 return "Binary";937 case FixedPointDecimal:938 return "Decimal";939 case FixedPointRational:940 return "Rational";941 }942 return nullptr;943}944 945DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag,946 MDString *Name, Metadata *StringLength,947 Metadata *StringLengthExp,948 Metadata *StringLocationExp,949 Metadata *SizeInBits, uint32_t AlignInBits,950 unsigned Encoding, StorageType Storage,951 bool ShouldCreate) {952 assert(isCanonical(Name) && "Expected canonical MDString");953 DEFINE_GETIMPL_LOOKUP(DIStringType,954 (Tag, Name, StringLength, StringLengthExp,955 StringLocationExp, SizeInBits, AlignInBits, Encoding));956 Metadata *Ops[] = {nullptr, nullptr, Name,957 SizeInBits, nullptr, StringLength,958 StringLengthExp, StringLocationExp};959 DEFINE_GETIMPL_STORE(DIStringType, (Tag, AlignInBits, Encoding), Ops);960}961DIType *DIDerivedType::getClassType() const {962 assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);963 return cast_or_null<DIType>(getExtraData());964}965 966// Helper function to extract ConstantAsMetadata from ExtraData,967// handling extra data MDTuple unwrapping if needed.968static ConstantAsMetadata *extractConstantMetadata(Metadata *ExtraData) {969 Metadata *ED = ExtraData;970 if (auto *Tuple = dyn_cast_or_null<MDTuple>(ED)) {971 if (Tuple->getNumOperands() != 1)972 return nullptr;973 ED = Tuple->getOperand(0);974 }975 return cast_or_null<ConstantAsMetadata>(ED);976}977 978uint32_t DIDerivedType::getVBPtrOffset() const {979 assert(getTag() == dwarf::DW_TAG_inheritance);980 if (auto *CM = extractConstantMetadata(getExtraData()))981 if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))982 return static_cast<uint32_t>(CI->getZExtValue());983 return 0;984}985Constant *DIDerivedType::getStorageOffsetInBits() const {986 assert(getTag() == dwarf::DW_TAG_member && isBitField());987 if (auto *C = extractConstantMetadata(getExtraData()))988 return C->getValue();989 return nullptr;990}991 992Constant *DIDerivedType::getConstant() const {993 assert((getTag() == dwarf::DW_TAG_member ||994 getTag() == dwarf::DW_TAG_variable) &&995 isStaticMember());996 if (auto *C = extractConstantMetadata(getExtraData()))997 return C->getValue();998 return nullptr;999}1000Constant *DIDerivedType::getDiscriminantValue() const {1001 assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());1002 if (auto *C = extractConstantMetadata(getExtraData()))1003 return C->getValue();1004 return nullptr;1005}1006 1007DIDerivedType *DIDerivedType::getImpl(1008 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,1009 unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,1010 uint32_t AlignInBits, Metadata *OffsetInBits,1011 std::optional<unsigned> DWARFAddressSpace,1012 std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData,1013 Metadata *Annotations, StorageType Storage, bool ShouldCreate) {1014 assert(isCanonical(Name) && "Expected canonical MDString");1015 DEFINE_GETIMPL_LOOKUP(DIDerivedType,1016 (Tag, Name, File, Line, Scope, BaseType, SizeInBits,1017 AlignInBits, OffsetInBits, DWARFAddressSpace,1018 PtrAuthData, Flags, ExtraData, Annotations));1019 Metadata *Ops[] = {File, Scope, Name, SizeInBits,1020 OffsetInBits, BaseType, ExtraData, Annotations};1021 DEFINE_GETIMPL_STORE(1022 DIDerivedType,1023 (Tag, Line, AlignInBits, DWARFAddressSpace, PtrAuthData, Flags), Ops);1024}1025 1026std::optional<DIDerivedType::PtrAuthData>1027DIDerivedType::getPtrAuthData() const {1028 return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type1029 ? std::make_optional<PtrAuthData>(SubclassData32)1030 : std::nullopt;1031}1032 1033DICompositeType *DICompositeType::getImpl(1034 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,1035 unsigned Line, Metadata *Scope, Metadata *BaseType, Metadata *SizeInBits,1036 uint32_t AlignInBits, Metadata *OffsetInBits, DIFlags Flags,1037 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,1038 Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier,1039 Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,1040 Metadata *Allocated, Metadata *Rank, Metadata *Annotations,1041 Metadata *Specification, uint32_t NumExtraInhabitants, Metadata *BitStride,1042 StorageType Storage, bool ShouldCreate) {1043 assert(isCanonical(Name) && "Expected canonical MDString");1044 1045 // Keep this in sync with buildODRType.1046 DEFINE_GETIMPL_LOOKUP(1047 DICompositeType,1048 (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,1049 OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,1050 Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,1051 Annotations, Specification, NumExtraInhabitants, BitStride));1052 Metadata *Ops[] = {File, Scope, Name, SizeInBits,1053 OffsetInBits, BaseType, Elements, VTableHolder,1054 TemplateParams, Identifier, Discriminator, DataLocation,1055 Associated, Allocated, Rank, Annotations,1056 Specification, BitStride};1057 DEFINE_GETIMPL_STORE(DICompositeType,1058 (Tag, Line, RuntimeLang, AlignInBits,1059 NumExtraInhabitants, EnumKind, Flags),1060 Ops);1061}1062 1063DICompositeType *DICompositeType::buildODRType(1064 LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,1065 Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,1066 Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits,1067 Metadata *Specification, uint32_t NumExtraInhabitants, DIFlags Flags,1068 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,1069 Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,1070 Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,1071 Metadata *Rank, Metadata *Annotations, Metadata *BitStride) {1072 assert(!Identifier.getString().empty() && "Expected valid identifier");1073 if (!Context.isODRUniquingDebugTypes())1074 return nullptr;1075 auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];1076 if (!CT)1077 return CT = DICompositeType::getDistinct(1078 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,1079 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,1080 EnumKind, VTableHolder, TemplateParams, &Identifier,1081 Discriminator, DataLocation, Associated, Allocated, Rank,1082 Annotations, Specification, NumExtraInhabitants, BitStride);1083 if (CT->getTag() != Tag)1084 return nullptr;1085 1086 // Only mutate CT if it's a forward declaration and the new operands aren't.1087 assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");1088 if (!CT->isForwardDecl() || (Flags & DINode::FlagFwdDecl))1089 return CT;1090 1091 // Mutate CT in place. Keep this in sync with getImpl.1092 CT->mutate(Tag, Line, RuntimeLang, AlignInBits, NumExtraInhabitants, EnumKind,1093 Flags);1094 Metadata *Ops[] = {File, Scope, Name, SizeInBits,1095 OffsetInBits, BaseType, Elements, VTableHolder,1096 TemplateParams, &Identifier, Discriminator, DataLocation,1097 Associated, Allocated, Rank, Annotations,1098 Specification, BitStride};1099 assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&1100 "Mismatched number of operands");1101 for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)1102 if (Ops[I] != CT->getOperand(I))1103 CT->setOperand(I, Ops[I]);1104 return CT;1105}1106 1107DICompositeType *DICompositeType::getODRType(1108 LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,1109 Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,1110 Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits,1111 Metadata *Specification, uint32_t NumExtraInhabitants, DIFlags Flags,1112 Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,1113 Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,1114 Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,1115 Metadata *Rank, Metadata *Annotations, Metadata *BitStride) {1116 assert(!Identifier.getString().empty() && "Expected valid identifier");1117 if (!Context.isODRUniquingDebugTypes())1118 return nullptr;1119 auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];1120 if (!CT) {1121 CT = DICompositeType::getDistinct(1122 Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,1123 AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind,1124 VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation,1125 Associated, Allocated, Rank, Annotations, Specification,1126 NumExtraInhabitants, BitStride);1127 } else {1128 if (CT->getTag() != Tag)1129 return nullptr;1130 }1131 return CT;1132}1133 1134DICompositeType *DICompositeType::getODRTypeIfExists(LLVMContext &Context,1135 MDString &Identifier) {1136 assert(!Identifier.getString().empty() && "Expected valid identifier");1137 if (!Context.isODRUniquingDebugTypes())1138 return nullptr;1139 return Context.pImpl->DITypeMap->lookup(&Identifier);1140}1141DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage,1142 DIFlags Flags, uint8_t CC,1143 ArrayRef<Metadata *> Ops)1144 : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0,1145 0, 0, Flags, Ops),1146 CC(CC) {}1147 1148DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,1149 uint8_t CC, Metadata *TypeArray,1150 StorageType Storage,1151 bool ShouldCreate) {1152 DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));1153 Metadata *Ops[] = {nullptr, nullptr, nullptr, nullptr, nullptr, TypeArray};1154 DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);1155}1156 1157DIFile::DIFile(LLVMContext &C, StorageType Storage,1158 std::optional<ChecksumInfo<MDString *>> CS, MDString *Src,1159 ArrayRef<Metadata *> Ops)1160 : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),1161 Checksum(CS), Source(Src) {}1162 1163// FIXME: Implement this string-enum correspondence with a .def file and macros,1164// so that the association is explicit rather than implied.1165static const char *ChecksumKindName[DIFile::CSK_Last] = {1166 "CSK_MD5",1167 "CSK_SHA1",1168 "CSK_SHA256",1169};1170 1171StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {1172 assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");1173 // The first space was originally the CSK_None variant, which is now1174 // obsolete, but the space is still reserved in ChecksumKind, so we account1175 // for it here.1176 return ChecksumKindName[CSKind - 1];1177}1178 1179std::optional<DIFile::ChecksumKind>1180DIFile::getChecksumKind(StringRef CSKindStr) {1181 return StringSwitch<std::optional<DIFile::ChecksumKind>>(CSKindStr)1182 .Case("CSK_MD5", DIFile::CSK_MD5)1183 .Case("CSK_SHA1", DIFile::CSK_SHA1)1184 .Case("CSK_SHA256", DIFile::CSK_SHA256)1185 .Default(std::nullopt);1186}1187 1188DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,1189 MDString *Directory,1190 std::optional<DIFile::ChecksumInfo<MDString *>> CS,1191 MDString *Source, StorageType Storage,1192 bool ShouldCreate) {1193 assert(isCanonical(Filename) && "Expected canonical MDString");1194 assert(isCanonical(Directory) && "Expected canonical MDString");1195 assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");1196 // We do *NOT* expect Source to be a canonical MDString because nullptr1197 // means none, so we need something to represent the empty file.1198 DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));1199 Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, Source};1200 DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);1201}1202DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage,1203 DISourceLanguageName SourceLanguage,1204 bool IsOptimized, unsigned RuntimeVersion,1205 unsigned EmissionKind, uint64_t DWOId,1206 bool SplitDebugInlining,1207 bool DebugInfoForProfiling, unsigned NameTableKind,1208 bool RangesBaseAddress, ArrayRef<Metadata *> Ops)1209 : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),1210 SourceLanguage(SourceLanguage), RuntimeVersion(RuntimeVersion),1211 DWOId(DWOId), EmissionKind(EmissionKind), NameTableKind(NameTableKind),1212 IsOptimized(IsOptimized), SplitDebugInlining(SplitDebugInlining),1213 DebugInfoForProfiling(DebugInfoForProfiling),1214 RangesBaseAddress(RangesBaseAddress) {1215 assert(Storage != Uniqued);1216}1217 1218DICompileUnit *DICompileUnit::getImpl(1219 LLVMContext &Context, DISourceLanguageName SourceLanguage, Metadata *File,1220 MDString *Producer, bool IsOptimized, MDString *Flags,1221 unsigned RuntimeVersion, MDString *SplitDebugFilename,1222 unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,1223 Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,1224 uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,1225 unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,1226 MDString *SDK, StorageType Storage, bool ShouldCreate) {1227 assert(Storage != Uniqued && "Cannot unique DICompileUnit");1228 assert(isCanonical(Producer) && "Expected canonical MDString");1229 assert(isCanonical(Flags) && "Expected canonical MDString");1230 assert(isCanonical(SplitDebugFilename) && "Expected canonical MDString");1231 1232 Metadata *Ops[] = {File,1233 Producer,1234 Flags,1235 SplitDebugFilename,1236 EnumTypes,1237 RetainedTypes,1238 GlobalVariables,1239 ImportedEntities,1240 Macros,1241 SysRoot,1242 SDK};1243 return storeImpl(new (std::size(Ops), Storage) DICompileUnit(1244 Context, Storage, SourceLanguage, IsOptimized,1245 RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining,1246 DebugInfoForProfiling, NameTableKind, RangesBaseAddress,1247 Ops),1248 Storage);1249}1250 1251std::optional<DICompileUnit::DebugEmissionKind>1252DICompileUnit::getEmissionKind(StringRef Str) {1253 return StringSwitch<std::optional<DebugEmissionKind>>(Str)1254 .Case("NoDebug", NoDebug)1255 .Case("FullDebug", FullDebug)1256 .Case("LineTablesOnly", LineTablesOnly)1257 .Case("DebugDirectivesOnly", DebugDirectivesOnly)1258 .Default(std::nullopt);1259}1260 1261std::optional<DICompileUnit::DebugNameTableKind>1262DICompileUnit::getNameTableKind(StringRef Str) {1263 return StringSwitch<std::optional<DebugNameTableKind>>(Str)1264 .Case("Default", DebugNameTableKind::Default)1265 .Case("GNU", DebugNameTableKind::GNU)1266 .Case("Apple", DebugNameTableKind::Apple)1267 .Case("None", DebugNameTableKind::None)1268 .Default(std::nullopt);1269}1270 1271const char *DICompileUnit::emissionKindString(DebugEmissionKind EK) {1272 switch (EK) {1273 case NoDebug:1274 return "NoDebug";1275 case FullDebug:1276 return "FullDebug";1277 case LineTablesOnly:1278 return "LineTablesOnly";1279 case DebugDirectivesOnly:1280 return "DebugDirectivesOnly";1281 }1282 return nullptr;1283}1284 1285const char *DICompileUnit::nameTableKindString(DebugNameTableKind NTK) {1286 switch (NTK) {1287 case DebugNameTableKind::Default:1288 return nullptr;1289 case DebugNameTableKind::GNU:1290 return "GNU";1291 case DebugNameTableKind::Apple:1292 return "Apple";1293 case DebugNameTableKind::None:1294 return "None";1295 }1296 return nullptr;1297}1298DISubprogram::DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,1299 unsigned ScopeLine, unsigned VirtualIndex,1300 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags,1301 bool UsesKeyInstructions, ArrayRef<Metadata *> Ops)1302 : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops),1303 Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),1304 ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) {1305 static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range");1306 SubclassData1 = UsesKeyInstructions;1307}1308DISubprogram::DISPFlags1309DISubprogram::toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized,1310 unsigned Virtuality, bool IsMainSubprogram) {1311 // We're assuming virtuality is the low-order field.1312 static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) &&1313 int(SPFlagPureVirtual) ==1314 int(dwarf::DW_VIRTUALITY_pure_virtual),1315 "Virtuality constant mismatch");1316 return static_cast<DISPFlags>(1317 (Virtuality & SPFlagVirtuality) |1318 (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) |1319 (IsDefinition ? SPFlagDefinition : SPFlagZero) |1320 (IsOptimized ? SPFlagOptimized : SPFlagZero) |1321 (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero));1322}1323 1324DISubprogram *DILocalScope::getSubprogram() const {1325 if (auto *Block = dyn_cast<DILexicalBlockBase>(this))1326 return Block->getScope()->getSubprogram();1327 return const_cast<DISubprogram *>(cast<DISubprogram>(this));1328}1329 1330DILocalScope *DILocalScope::getNonLexicalBlockFileScope() const {1331 if (auto *File = dyn_cast<DILexicalBlockFile>(this))1332 return File->getScope()->getNonLexicalBlockFileScope();1333 return const_cast<DILocalScope *>(this);1334}1335 1336DILocalScope *DILocalScope::cloneScopeForSubprogram(1337 DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx,1338 DenseMap<const MDNode *, MDNode *> &Cache) {1339 SmallVector<DIScope *> ScopeChain;1340 DIScope *CachedResult = nullptr;1341 1342 for (DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);1343 Scope = Scope->getScope()) {1344 if (auto It = Cache.find(Scope); It != Cache.end()) {1345 CachedResult = cast<DIScope>(It->second);1346 break;1347 }1348 ScopeChain.push_back(Scope);1349 }1350 1351 // Recreate the scope chain, bottom-up, starting at the new subprogram (or a1352 // cached result).1353 DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;1354 for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {1355 UpdatedScope = cloneAndReplaceParentScope(1356 cast<DILexicalBlockBase>(ScopeToUpdate), UpdatedScope);1357 Cache[ScopeToUpdate] = UpdatedScope;1358 }1359 1360 return cast<DILocalScope>(UpdatedScope);1361}1362 1363DISubprogram::DISPFlags DISubprogram::getFlag(StringRef Flag) {1364 return StringSwitch<DISPFlags>(Flag)1365#define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)1366#include "llvm/IR/DebugInfoFlags.def"1367 .Default(SPFlagZero);1368}1369 1370StringRef DISubprogram::getFlagString(DISPFlags Flag) {1371 switch (Flag) {1372 // Appease a warning.1373 case SPFlagVirtuality:1374 return "";1375#define HANDLE_DISP_FLAG(ID, NAME) \1376 case SPFlag##NAME: \1377 return "DISPFlag" #NAME;1378#include "llvm/IR/DebugInfoFlags.def"1379 }1380 return "";1381}1382 1383DISubprogram::DISPFlags1384DISubprogram::splitFlags(DISPFlags Flags,1385 SmallVectorImpl<DISPFlags> &SplitFlags) {1386 // Multi-bit fields can require special handling. In our case, however, the1387 // only multi-bit field is virtuality, and all its values happen to be1388 // single-bit values, so the right behavior just falls out.1389#define HANDLE_DISP_FLAG(ID, NAME) \1390 if (DISPFlags Bit = Flags & SPFlag##NAME) { \1391 SplitFlags.push_back(Bit); \1392 Flags &= ~Bit; \1393 }1394#include "llvm/IR/DebugInfoFlags.def"1395 return Flags;1396}1397 1398DISubprogram *DISubprogram::getImpl(1399 LLVMContext &Context, Metadata *Scope, MDString *Name,1400 MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,1401 unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex,1402 int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit,1403 Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,1404 Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName,1405 bool UsesKeyInstructions, StorageType Storage, bool ShouldCreate) {1406 assert(isCanonical(Name) && "Expected canonical MDString");1407 assert(isCanonical(LinkageName) && "Expected canonical MDString");1408 assert(isCanonical(TargetFuncName) && "Expected canonical MDString");1409 DEFINE_GETIMPL_LOOKUP(DISubprogram,1410 (Scope, Name, LinkageName, File, Line, Type, ScopeLine,1411 ContainingType, VirtualIndex, ThisAdjustment, Flags,1412 SPFlags, Unit, TemplateParams, Declaration,1413 RetainedNodes, ThrownTypes, Annotations,1414 TargetFuncName, UsesKeyInstructions));1415 SmallVector<Metadata *, 13> Ops = {1416 File, Scope, Name, LinkageName,1417 Type, Unit, Declaration, RetainedNodes,1418 ContainingType, TemplateParams, ThrownTypes, Annotations,1419 TargetFuncName};1420 if (!TargetFuncName) {1421 Ops.pop_back();1422 if (!Annotations) {1423 Ops.pop_back();1424 if (!ThrownTypes) {1425 Ops.pop_back();1426 if (!TemplateParams) {1427 Ops.pop_back();1428 if (!ContainingType)1429 Ops.pop_back();1430 }1431 }1432 }1433 }1434 DEFINE_GETIMPL_STORE_N(DISubprogram,1435 (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags,1436 SPFlags, UsesKeyInstructions),1437 Ops, Ops.size());1438}1439 1440bool DISubprogram::describes(const Function *F) const {1441 assert(F && "Invalid function");1442 return F->getSubprogram() == this;1443}1444 1445const DIScope *DISubprogram::getRawRetainedNodeScope(const MDNode *N) {1446 return visitRetainedNode<DIScope *>(1447 N, [](const DILocalVariable *LV) { return LV->getScope(); },1448 [](const DILabel *L) { return L->getScope(); },1449 [](const DIImportedEntity *IE) { return IE->getScope(); },1450 [](const Metadata *N) { return nullptr; });1451}1452 1453const DILocalScope *DISubprogram::getRetainedNodeScope(const MDNode *N) {1454 return cast<DILocalScope>(getRawRetainedNodeScope(N));1455}1456 1457DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID,1458 StorageType Storage,1459 ArrayRef<Metadata *> Ops)1460 : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}1461 1462DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope,1463 Metadata *File, unsigned Line,1464 unsigned Column, StorageType Storage,1465 bool ShouldCreate) {1466 // Fixup column.1467 adjustColumn(Column);1468 1469 assert(Scope && "Expected scope");1470 DEFINE_GETIMPL_LOOKUP(DILexicalBlock, (Scope, File, Line, Column));1471 Metadata *Ops[] = {File, Scope};1472 DEFINE_GETIMPL_STORE(DILexicalBlock, (Line, Column), Ops);1473}1474 1475DILexicalBlockFile *DILexicalBlockFile::getImpl(LLVMContext &Context,1476 Metadata *Scope, Metadata *File,1477 unsigned Discriminator,1478 StorageType Storage,1479 bool ShouldCreate) {1480 assert(Scope && "Expected scope");1481 DEFINE_GETIMPL_LOOKUP(DILexicalBlockFile, (Scope, File, Discriminator));1482 Metadata *Ops[] = {File, Scope};1483 DEFINE_GETIMPL_STORE(DILexicalBlockFile, (Discriminator), Ops);1484}1485 1486DINamespace::DINamespace(LLVMContext &Context, StorageType Storage,1487 bool ExportSymbols, ArrayRef<Metadata *> Ops)1488 : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops) {1489 SubclassData1 = ExportSymbols;1490}1491DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope,1492 MDString *Name, bool ExportSymbols,1493 StorageType Storage, bool ShouldCreate) {1494 assert(isCanonical(Name) && "Expected canonical MDString");1495 DEFINE_GETIMPL_LOOKUP(DINamespace, (Scope, Name, ExportSymbols));1496 // The nullptr is for DIScope's File operand. This should be refactored.1497 Metadata *Ops[] = {nullptr, Scope, Name};1498 DEFINE_GETIMPL_STORE(DINamespace, (ExportSymbols), Ops);1499}1500 1501DICommonBlock::DICommonBlock(LLVMContext &Context, StorageType Storage,1502 unsigned LineNo, ArrayRef<Metadata *> Ops)1503 : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block,1504 Ops) {1505 SubclassData32 = LineNo;1506}1507DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope,1508 Metadata *Decl, MDString *Name,1509 Metadata *File, unsigned LineNo,1510 StorageType Storage, bool ShouldCreate) {1511 assert(isCanonical(Name) && "Expected canonical MDString");1512 DEFINE_GETIMPL_LOOKUP(DICommonBlock, (Scope, Decl, Name, File, LineNo));1513 // The nullptr is for DIScope's File operand. This should be refactored.1514 Metadata *Ops[] = {Scope, Decl, Name, File};1515 DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo), Ops);1516}1517 1518DIModule::DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,1519 bool IsDecl, ArrayRef<Metadata *> Ops)1520 : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {1521 SubclassData1 = IsDecl;1522 SubclassData32 = LineNo;1523}1524DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File,1525 Metadata *Scope, MDString *Name,1526 MDString *ConfigurationMacros,1527 MDString *IncludePath, MDString *APINotesFile,1528 unsigned LineNo, bool IsDecl, StorageType Storage,1529 bool ShouldCreate) {1530 assert(isCanonical(Name) && "Expected canonical MDString");1531 DEFINE_GETIMPL_LOOKUP(DIModule, (File, Scope, Name, ConfigurationMacros,1532 IncludePath, APINotesFile, LineNo, IsDecl));1533 Metadata *Ops[] = {File, Scope, Name, ConfigurationMacros,1534 IncludePath, APINotesFile};1535 DEFINE_GETIMPL_STORE(DIModule, (LineNo, IsDecl), Ops);1536}1537DITemplateTypeParameter::DITemplateTypeParameter(LLVMContext &Context,1538 StorageType Storage,1539 bool IsDefault,1540 ArrayRef<Metadata *> Ops)1541 : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,1542 dwarf::DW_TAG_template_type_parameter, IsDefault,1543 Ops) {}1544 1545DITemplateTypeParameter *1546DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name,1547 Metadata *Type, bool isDefault,1548 StorageType Storage, bool ShouldCreate) {1549 assert(isCanonical(Name) && "Expected canonical MDString");1550 DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type, isDefault));1551 Metadata *Ops[] = {Name, Type};1552 DEFINE_GETIMPL_STORE(DITemplateTypeParameter, (isDefault), Ops);1553}1554 1555DITemplateValueParameter *DITemplateValueParameter::getImpl(1556 LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type,1557 bool isDefault, Metadata *Value, StorageType Storage, bool ShouldCreate) {1558 assert(isCanonical(Name) && "Expected canonical MDString");1559 DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter,1560 (Tag, Name, Type, isDefault, Value));1561 Metadata *Ops[] = {Name, Type, Value};1562 DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag, isDefault), Ops);1563}1564 1565DIGlobalVariable *1566DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,1567 MDString *LinkageName, Metadata *File, unsigned Line,1568 Metadata *Type, bool IsLocalToUnit, bool IsDefinition,1569 Metadata *StaticDataMemberDeclaration,1570 Metadata *TemplateParams, uint32_t AlignInBits,1571 Metadata *Annotations, StorageType Storage,1572 bool ShouldCreate) {1573 assert(isCanonical(Name) && "Expected canonical MDString");1574 assert(isCanonical(LinkageName) && "Expected canonical MDString");1575 DEFINE_GETIMPL_LOOKUP(1576 DIGlobalVariable,1577 (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,1578 StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations));1579 Metadata *Ops[] = {Scope,1580 Name,1581 File,1582 Type,1583 Name,1584 LinkageName,1585 StaticDataMemberDeclaration,1586 TemplateParams,1587 Annotations};1588 DEFINE_GETIMPL_STORE(DIGlobalVariable,1589 (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops);1590}1591 1592DILocalVariable *1593DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,1594 Metadata *File, unsigned Line, Metadata *Type,1595 unsigned Arg, DIFlags Flags, uint32_t AlignInBits,1596 Metadata *Annotations, StorageType Storage,1597 bool ShouldCreate) {1598 // 64K ought to be enough for any frontend.1599 assert(Arg <= UINT16_MAX && "Expected argument number to fit in 16-bits");1600 1601 assert(Scope && "Expected scope");1602 assert(isCanonical(Name) && "Expected canonical MDString");1603 DEFINE_GETIMPL_LOOKUP(DILocalVariable, (Scope, Name, File, Line, Type, Arg,1604 Flags, AlignInBits, Annotations));1605 Metadata *Ops[] = {Scope, Name, File, Type, Annotations};1606 DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops);1607}1608 1609DIVariable::DIVariable(LLVMContext &C, unsigned ID, StorageType Storage,1610 signed Line, ArrayRef<Metadata *> Ops,1611 uint32_t AlignInBits)1612 : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {1613 SubclassData32 = AlignInBits;1614}1615std::optional<uint64_t> DIVariable::getSizeInBits() const {1616 // This is used by the Verifier so be mindful of broken types.1617 const Metadata *RawType = getRawType();1618 while (RawType) {1619 // Try to get the size directly.1620 if (auto *T = dyn_cast<DIType>(RawType))1621 if (uint64_t Size = T->getSizeInBits())1622 return Size;1623 1624 if (auto *DT = dyn_cast<DIDerivedType>(RawType)) {1625 // Look at the base type.1626 RawType = DT->getRawBaseType();1627 continue;1628 }1629 1630 // Missing type or size.1631 break;1632 }1633 1634 // Fail gracefully.1635 return std::nullopt;1636}1637 1638DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line,1639 unsigned Column, bool IsArtificial,1640 std::optional<unsigned> CoroSuspendIdx,1641 ArrayRef<Metadata *> Ops)1642 : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) {1643 this->SubclassData32 = Line;1644 this->Column = Column;1645 this->IsArtificial = IsArtificial;1646 this->CoroSuspendIdx = CoroSuspendIdx;1647}1648DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,1649 Metadata *File, unsigned Line, unsigned Column,1650 bool IsArtificial,1651 std::optional<unsigned> CoroSuspendIdx,1652 StorageType Storage, bool ShouldCreate) {1653 assert(Scope && "Expected scope");1654 assert(isCanonical(Name) && "Expected canonical MDString");1655 DEFINE_GETIMPL_LOOKUP(1656 DILabel, (Scope, Name, File, Line, Column, IsArtificial, CoroSuspendIdx));1657 Metadata *Ops[] = {Scope, Name, File};1658 DEFINE_GETIMPL_STORE(DILabel, (Line, Column, IsArtificial, CoroSuspendIdx),1659 Ops);1660}1661 1662DIExpression *DIExpression::getImpl(LLVMContext &Context,1663 ArrayRef<uint64_t> Elements,1664 StorageType Storage, bool ShouldCreate) {1665 DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements));1666 DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));1667}1668bool DIExpression::isEntryValue() const {1669 if (auto singleLocElts = getSingleLocationExpressionElements()) {1670 return singleLocElts->size() > 0 &&1671 (*singleLocElts)[0] == dwarf::DW_OP_LLVM_entry_value;1672 }1673 return false;1674}1675bool DIExpression::startsWithDeref() const {1676 if (auto singleLocElts = getSingleLocationExpressionElements())1677 return singleLocElts->size() > 0 &&1678 (*singleLocElts)[0] == dwarf::DW_OP_deref;1679 return false;1680}1681bool DIExpression::isDeref() const {1682 if (auto singleLocElts = getSingleLocationExpressionElements())1683 return singleLocElts->size() == 1 &&1684 (*singleLocElts)[0] == dwarf::DW_OP_deref;1685 return false;1686}1687 1688DIAssignID *DIAssignID::getImpl(LLVMContext &Context, StorageType Storage,1689 bool ShouldCreate) {1690 // Uniqued DIAssignID are not supported as the instance address *is* the ID.1691 assert(Storage != StorageType::Uniqued && "uniqued DIAssignID unsupported");1692 return storeImpl(new (0u, Storage) DIAssignID(Context, Storage), Storage);1693}1694 1695unsigned DIExpression::ExprOperand::getSize() const {1696 uint64_t Op = getOp();1697 1698 if (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31)1699 return 2;1700 1701 switch (Op) {1702 case dwarf::DW_OP_LLVM_convert:1703 case dwarf::DW_OP_LLVM_fragment:1704 case dwarf::DW_OP_LLVM_extract_bits_sext:1705 case dwarf::DW_OP_LLVM_extract_bits_zext:1706 case dwarf::DW_OP_bregx:1707 return 3;1708 case dwarf::DW_OP_constu:1709 case dwarf::DW_OP_consts:1710 case dwarf::DW_OP_deref_size:1711 case dwarf::DW_OP_plus_uconst:1712 case dwarf::DW_OP_LLVM_tag_offset:1713 case dwarf::DW_OP_LLVM_entry_value:1714 case dwarf::DW_OP_LLVM_arg:1715 case dwarf::DW_OP_regx:1716 return 2;1717 default:1718 return 1;1719 }1720}1721 1722bool DIExpression::isValid() const {1723 for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) {1724 // Check that there's space for the operand.1725 if (I->get() + I->getSize() > E->get())1726 return false;1727 1728 uint64_t Op = I->getOp();1729 if ((Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31) ||1730 (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31))1731 return true;1732 1733 // Check that the operand is valid.1734 switch (Op) {1735 default:1736 return false;1737 case dwarf::DW_OP_LLVM_fragment:1738 // A fragment operator must appear at the end.1739 return I->get() + I->getSize() == E->get();1740 case dwarf::DW_OP_stack_value: {1741 // Must be the last one or followed by a DW_OP_LLVM_fragment.1742 if (I->get() + I->getSize() == E->get())1743 break;1744 auto J = I;1745 if ((++J)->getOp() != dwarf::DW_OP_LLVM_fragment)1746 return false;1747 break;1748 }1749 case dwarf::DW_OP_swap: {1750 // Must be more than one implicit element on the stack.1751 1752 // FIXME: A better way to implement this would be to add a local variable1753 // that keeps track of the stack depth and introduce something like a1754 // DW_LLVM_OP_implicit_location as a placeholder for the location this1755 // DIExpression is attached to, or else pass the number of implicit stack1756 // elements into isValid.1757 if (getNumElements() == 1)1758 return false;1759 break;1760 }1761 case dwarf::DW_OP_LLVM_entry_value: {1762 // An entry value operator must appear at the beginning or immediately1763 // following `DW_OP_LLVM_arg 0`, and the number of operations it cover can1764 // currently only be 1, because we support only entry values of a simple1765 // register location. One reason for this is that we currently can't1766 // calculate the size of the resulting DWARF block for other expressions.1767 auto FirstOp = expr_op_begin();1768 if (FirstOp->getOp() == dwarf::DW_OP_LLVM_arg && FirstOp->getArg(0) == 0)1769 ++FirstOp;1770 return I->get() == FirstOp->get() && I->getArg(0) == 1;1771 }1772 case dwarf::DW_OP_LLVM_implicit_pointer:1773 case dwarf::DW_OP_LLVM_convert:1774 case dwarf::DW_OP_LLVM_arg:1775 case dwarf::DW_OP_LLVM_tag_offset:1776 case dwarf::DW_OP_LLVM_extract_bits_sext:1777 case dwarf::DW_OP_LLVM_extract_bits_zext:1778 case dwarf::DW_OP_constu:1779 case dwarf::DW_OP_plus_uconst:1780 case dwarf::DW_OP_plus:1781 case dwarf::DW_OP_minus:1782 case dwarf::DW_OP_mul:1783 case dwarf::DW_OP_div:1784 case dwarf::DW_OP_mod:1785 case dwarf::DW_OP_or:1786 case dwarf::DW_OP_and:1787 case dwarf::DW_OP_xor:1788 case dwarf::DW_OP_shl:1789 case dwarf::DW_OP_shr:1790 case dwarf::DW_OP_shra:1791 case dwarf::DW_OP_deref:1792 case dwarf::DW_OP_deref_size:1793 case dwarf::DW_OP_xderef:1794 case dwarf::DW_OP_lit0:1795 case dwarf::DW_OP_not:1796 case dwarf::DW_OP_dup:1797 case dwarf::DW_OP_regx:1798 case dwarf::DW_OP_bregx:1799 case dwarf::DW_OP_push_object_address:1800 case dwarf::DW_OP_over:1801 case dwarf::DW_OP_rot:1802 case dwarf::DW_OP_consts:1803 case dwarf::DW_OP_eq:1804 case dwarf::DW_OP_ne:1805 case dwarf::DW_OP_gt:1806 case dwarf::DW_OP_ge:1807 case dwarf::DW_OP_lt:1808 case dwarf::DW_OP_le:1809 case dwarf::DW_OP_neg:1810 case dwarf::DW_OP_abs:1811 break;1812 }1813 }1814 return true;1815}1816 1817bool DIExpression::isImplicit() const {1818 if (!isValid())1819 return false;1820 1821 if (getNumElements() == 0)1822 return false;1823 1824 for (const auto &It : expr_ops()) {1825 switch (It.getOp()) {1826 default:1827 break;1828 case dwarf::DW_OP_stack_value:1829 return true;1830 }1831 }1832 1833 return false;1834}1835 1836bool DIExpression::isComplex() const {1837 if (!isValid())1838 return false;1839 1840 if (getNumElements() == 0)1841 return false;1842 1843 // If there are any elements other than fragment or tag_offset, then some1844 // kind of complex computation occurs.1845 for (const auto &It : expr_ops()) {1846 switch (It.getOp()) {1847 case dwarf::DW_OP_LLVM_tag_offset:1848 case dwarf::DW_OP_LLVM_fragment:1849 case dwarf::DW_OP_LLVM_arg:1850 continue;1851 default:1852 return true;1853 }1854 }1855 1856 return false;1857}1858 1859bool DIExpression::isSingleLocationExpression() const {1860 if (!isValid())1861 return false;1862 1863 if (getNumElements() == 0)1864 return true;1865 1866 auto ExprOpBegin = expr_ops().begin();1867 auto ExprOpEnd = expr_ops().end();1868 if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg) {1869 if (ExprOpBegin->getArg(0) != 0)1870 return false;1871 ++ExprOpBegin;1872 }1873 1874 return !std::any_of(ExprOpBegin, ExprOpEnd, [](auto Op) {1875 return Op.getOp() == dwarf::DW_OP_LLVM_arg;1876 });1877}1878 1879std::optional<ArrayRef<uint64_t>>1880DIExpression::getSingleLocationExpressionElements() const {1881 // Check for `isValid` covered by `isSingleLocationExpression`.1882 if (!isSingleLocationExpression())1883 return std::nullopt;1884 1885 // An empty expression is already non-variadic.1886 if (!getNumElements())1887 return ArrayRef<uint64_t>();1888 1889 // If Expr does not have a leading DW_OP_LLVM_arg then we don't need to do1890 // anything.1891 if (getElements()[0] == dwarf::DW_OP_LLVM_arg)1892 return getElements().drop_front(2);1893 return getElements();1894}1895 1896const DIExpression *1897DIExpression::convertToUndefExpression(const DIExpression *Expr) {1898 SmallVector<uint64_t, 3> UndefOps;1899 if (auto FragmentInfo = Expr->getFragmentInfo()) {1900 UndefOps.append({dwarf::DW_OP_LLVM_fragment, FragmentInfo->OffsetInBits,1901 FragmentInfo->SizeInBits});1902 }1903 return DIExpression::get(Expr->getContext(), UndefOps);1904}1905 1906const DIExpression *1907DIExpression::convertToVariadicExpression(const DIExpression *Expr) {1908 if (any_of(Expr->expr_ops(), [](auto ExprOp) {1909 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;1910 }))1911 return Expr;1912 SmallVector<uint64_t> NewOps;1913 NewOps.reserve(Expr->getNumElements() + 2);1914 NewOps.append({dwarf::DW_OP_LLVM_arg, 0});1915 NewOps.append(Expr->elements_begin(), Expr->elements_end());1916 return DIExpression::get(Expr->getContext(), NewOps);1917}1918 1919std::optional<const DIExpression *>1920DIExpression::convertToNonVariadicExpression(const DIExpression *Expr) {1921 if (!Expr)1922 return std::nullopt;1923 1924 if (auto Elts = Expr->getSingleLocationExpressionElements())1925 return DIExpression::get(Expr->getContext(), *Elts);1926 1927 return std::nullopt;1928}1929 1930void DIExpression::canonicalizeExpressionOps(SmallVectorImpl<uint64_t> &Ops,1931 const DIExpression *Expr,1932 bool IsIndirect) {1933 // If Expr is not already variadic, insert the implied `DW_OP_LLVM_arg 0`1934 // to the existing expression ops.1935 if (none_of(Expr->expr_ops(), [](auto ExprOp) {1936 return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;1937 }))1938 Ops.append({dwarf::DW_OP_LLVM_arg, 0});1939 // If Expr is not indirect, we only need to insert the expression elements and1940 // we're done.1941 if (!IsIndirect) {1942 Ops.append(Expr->elements_begin(), Expr->elements_end());1943 return;1944 }1945 // If Expr is indirect, insert the implied DW_OP_deref at the end of the1946 // expression but before DW_OP_{stack_value, LLVM_fragment} if they are1947 // present.1948 for (auto Op : Expr->expr_ops()) {1949 if (Op.getOp() == dwarf::DW_OP_stack_value ||1950 Op.getOp() == dwarf::DW_OP_LLVM_fragment) {1951 Ops.push_back(dwarf::DW_OP_deref);1952 IsIndirect = false;1953 }1954 Op.appendToVector(Ops);1955 }1956 if (IsIndirect)1957 Ops.push_back(dwarf::DW_OP_deref);1958}1959 1960bool DIExpression::isEqualExpression(const DIExpression *FirstExpr,1961 bool FirstIndirect,1962 const DIExpression *SecondExpr,1963 bool SecondIndirect) {1964 SmallVector<uint64_t> FirstOps;1965 DIExpression::canonicalizeExpressionOps(FirstOps, FirstExpr, FirstIndirect);1966 SmallVector<uint64_t> SecondOps;1967 DIExpression::canonicalizeExpressionOps(SecondOps, SecondExpr,1968 SecondIndirect);1969 return FirstOps == SecondOps;1970}1971 1972std::optional<DIExpression::FragmentInfo>1973DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) {1974 for (auto I = Start; I != End; ++I)1975 if (I->getOp() == dwarf::DW_OP_LLVM_fragment) {1976 DIExpression::FragmentInfo Info = {I->getArg(1), I->getArg(0)};1977 return Info;1978 }1979 return std::nullopt;1980}1981 1982std::optional<uint64_t> DIExpression::getActiveBits(DIVariable *Var) {1983 std::optional<uint64_t> InitialActiveBits = Var->getSizeInBits();1984 std::optional<uint64_t> ActiveBits = InitialActiveBits;1985 for (auto Op : expr_ops()) {1986 switch (Op.getOp()) {1987 default:1988 // We assume the worst case for anything we don't currently handle and1989 // revert to the initial active bits.1990 ActiveBits = InitialActiveBits;1991 break;1992 case dwarf::DW_OP_LLVM_extract_bits_zext:1993 case dwarf::DW_OP_LLVM_extract_bits_sext: {1994 // We can't handle an extract whose sign doesn't match that of the1995 // variable.1996 std::optional<DIBasicType::Signedness> VarSign = Var->getSignedness();1997 bool VarSigned = (VarSign == DIBasicType::Signedness::Signed);1998 bool OpSigned = (Op.getOp() == dwarf::DW_OP_LLVM_extract_bits_sext);1999 if (!VarSign || VarSigned != OpSigned) {2000 ActiveBits = InitialActiveBits;2001 break;2002 }2003 [[fallthrough]];2004 }2005 case dwarf::DW_OP_LLVM_fragment:2006 // Extract or fragment narrows the active bits2007 if (ActiveBits)2008 ActiveBits = std::min(*ActiveBits, Op.getArg(1));2009 else2010 ActiveBits = Op.getArg(1);2011 break;2012 }2013 }2014 return ActiveBits;2015}2016 2017void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,2018 int64_t Offset) {2019 if (Offset > 0) {2020 Ops.push_back(dwarf::DW_OP_plus_uconst);2021 Ops.push_back(Offset);2022 } else if (Offset < 0) {2023 Ops.push_back(dwarf::DW_OP_constu);2024 // Avoid UB when encountering LLONG_MIN, because in 2's complement2025 // abs(LLONG_MIN) is LLONG_MAX+1.2026 uint64_t AbsMinusOne = -(Offset+1);2027 Ops.push_back(AbsMinusOne + 1);2028 Ops.push_back(dwarf::DW_OP_minus);2029 }2030}2031 2032bool DIExpression::extractIfOffset(int64_t &Offset) const {2033 auto SingleLocEltsOpt = getSingleLocationExpressionElements();2034 if (!SingleLocEltsOpt)2035 return false;2036 auto SingleLocElts = *SingleLocEltsOpt;2037 2038 if (SingleLocElts.size() == 0) {2039 Offset = 0;2040 return true;2041 }2042 2043 if (SingleLocElts.size() == 2 &&2044 SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {2045 Offset = SingleLocElts[1];2046 return true;2047 }2048 2049 if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {2050 if (SingleLocElts[2] == dwarf::DW_OP_plus) {2051 Offset = SingleLocElts[1];2052 return true;2053 }2054 if (SingleLocElts[2] == dwarf::DW_OP_minus) {2055 Offset = -SingleLocElts[1];2056 return true;2057 }2058 }2059 2060 return false;2061}2062 2063bool DIExpression::extractLeadingOffset(2064 int64_t &OffsetInBytes, SmallVectorImpl<uint64_t> &RemainingOps) const {2065 OffsetInBytes = 0;2066 RemainingOps.clear();2067 2068 auto SingleLocEltsOpt = getSingleLocationExpressionElements();2069 if (!SingleLocEltsOpt)2070 return false;2071 2072 auto ExprOpEnd = expr_op_iterator(SingleLocEltsOpt->end());2073 auto ExprOpIt = expr_op_iterator(SingleLocEltsOpt->begin());2074 while (ExprOpIt != ExprOpEnd) {2075 uint64_t Op = ExprOpIt->getOp();2076 if (Op == dwarf::DW_OP_deref || Op == dwarf::DW_OP_deref_size ||2077 Op == dwarf::DW_OP_deref_type || Op == dwarf::DW_OP_LLVM_fragment ||2078 Op == dwarf::DW_OP_LLVM_extract_bits_zext ||2079 Op == dwarf::DW_OP_LLVM_extract_bits_sext) {2080 break;2081 } else if (Op == dwarf::DW_OP_plus_uconst) {2082 OffsetInBytes += ExprOpIt->getArg(0);2083 } else if (Op == dwarf::DW_OP_constu) {2084 uint64_t Value = ExprOpIt->getArg(0);2085 ++ExprOpIt;2086 if (ExprOpIt->getOp() == dwarf::DW_OP_plus)2087 OffsetInBytes += Value;2088 else if (ExprOpIt->getOp() == dwarf::DW_OP_minus)2089 OffsetInBytes -= Value;2090 else2091 return false;2092 } else {2093 // Not a const plus/minus operation or deref.2094 return false;2095 }2096 ++ExprOpIt;2097 }2098 RemainingOps.append(ExprOpIt.getBase(), ExprOpEnd.getBase());2099 return true;2100}2101 2102bool DIExpression::hasAllLocationOps(unsigned N) const {2103 SmallDenseSet<uint64_t, 4> SeenOps;2104 for (auto ExprOp : expr_ops())2105 if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)2106 SeenOps.insert(ExprOp.getArg(0));2107 for (uint64_t Idx = 0; Idx < N; ++Idx)2108 if (!SeenOps.contains(Idx))2109 return false;2110 return true;2111}2112 2113const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,2114 unsigned &AddrClass) {2115 // FIXME: This seems fragile. Nothing that verifies that these elements2116 // actually map to ops and not operands.2117 auto SingleLocEltsOpt = Expr->getSingleLocationExpressionElements();2118 if (!SingleLocEltsOpt)2119 return nullptr;2120 auto SingleLocElts = *SingleLocEltsOpt;2121 2122 const unsigned PatternSize = 4;2123 if (SingleLocElts.size() >= PatternSize &&2124 SingleLocElts[PatternSize - 4] == dwarf::DW_OP_constu &&2125 SingleLocElts[PatternSize - 2] == dwarf::DW_OP_swap &&2126 SingleLocElts[PatternSize - 1] == dwarf::DW_OP_xderef) {2127 AddrClass = SingleLocElts[PatternSize - 3];2128 2129 if (SingleLocElts.size() == PatternSize)2130 return nullptr;2131 return DIExpression::get(2132 Expr->getContext(),2133 ArrayRef(&*SingleLocElts.begin(), SingleLocElts.size() - PatternSize));2134 }2135 return Expr;2136}2137 2138DIExpression *DIExpression::prepend(const DIExpression *Expr, uint8_t Flags,2139 int64_t Offset) {2140 SmallVector<uint64_t, 8> Ops;2141 if (Flags & DIExpression::DerefBefore)2142 Ops.push_back(dwarf::DW_OP_deref);2143 2144 appendOffset(Ops, Offset);2145 if (Flags & DIExpression::DerefAfter)2146 Ops.push_back(dwarf::DW_OP_deref);2147 2148 bool StackValue = Flags & DIExpression::StackValue;2149 bool EntryValue = Flags & DIExpression::EntryValue;2150 2151 return prependOpcodes(Expr, Ops, StackValue, EntryValue);2152}2153 2154DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,2155 ArrayRef<uint64_t> Ops,2156 unsigned ArgNo, bool StackValue) {2157 assert(Expr && "Can't add ops to this expression");2158 2159 // Handle non-variadic intrinsics by prepending the opcodes.2160 if (!any_of(Expr->expr_ops(),2161 [](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {2162 assert(ArgNo == 0 &&2163 "Location Index must be 0 for a non-variadic expression.");2164 SmallVector<uint64_t, 8> NewOps(Ops);2165 return DIExpression::prependOpcodes(Expr, NewOps, StackValue);2166 }2167 2168 SmallVector<uint64_t, 8> NewOps;2169 for (auto Op : Expr->expr_ops()) {2170 // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.2171 if (StackValue) {2172 if (Op.getOp() == dwarf::DW_OP_stack_value)2173 StackValue = false;2174 else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {2175 NewOps.push_back(dwarf::DW_OP_stack_value);2176 StackValue = false;2177 }2178 }2179 Op.appendToVector(NewOps);2180 if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo)2181 llvm::append_range(NewOps, Ops);2182 }2183 if (StackValue)2184 NewOps.push_back(dwarf::DW_OP_stack_value);2185 2186 return DIExpression::get(Expr->getContext(), NewOps);2187}2188 2189DIExpression *DIExpression::replaceArg(const DIExpression *Expr,2190 uint64_t OldArg, uint64_t NewArg) {2191 assert(Expr && "Can't replace args in this expression");2192 2193 SmallVector<uint64_t, 8> NewOps;2194 2195 for (auto Op : Expr->expr_ops()) {2196 if (Op.getOp() != dwarf::DW_OP_LLVM_arg || Op.getArg(0) < OldArg) {2197 Op.appendToVector(NewOps);2198 continue;2199 }2200 NewOps.push_back(dwarf::DW_OP_LLVM_arg);2201 uint64_t Arg = Op.getArg(0) == OldArg ? NewArg : Op.getArg(0);2202 // OldArg has been deleted from the Op list, so decrement all indices2203 // greater than it.2204 if (Arg > OldArg)2205 --Arg;2206 NewOps.push_back(Arg);2207 }2208 return DIExpression::get(Expr->getContext(), NewOps);2209}2210 2211DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,2212 SmallVectorImpl<uint64_t> &Ops,2213 bool StackValue, bool EntryValue) {2214 assert(Expr && "Can't prepend ops to this expression");2215 2216 if (EntryValue) {2217 Ops.push_back(dwarf::DW_OP_LLVM_entry_value);2218 // Use a block size of 1 for the target register operand. The2219 // DWARF backend currently cannot emit entry values with a block2220 // size > 1.2221 Ops.push_back(1);2222 }2223 2224 // If there are no ops to prepend, do not even add the DW_OP_stack_value.2225 if (Ops.empty())2226 StackValue = false;2227 for (auto Op : Expr->expr_ops()) {2228 // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.2229 if (StackValue) {2230 if (Op.getOp() == dwarf::DW_OP_stack_value)2231 StackValue = false;2232 else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {2233 Ops.push_back(dwarf::DW_OP_stack_value);2234 StackValue = false;2235 }2236 }2237 Op.appendToVector(Ops);2238 }2239 if (StackValue)2240 Ops.push_back(dwarf::DW_OP_stack_value);2241 return DIExpression::get(Expr->getContext(), Ops);2242}2243 2244DIExpression *DIExpression::append(const DIExpression *Expr,2245 ArrayRef<uint64_t> Ops) {2246 assert(Expr && !Ops.empty() && "Can't append ops to this expression");2247 2248 // Copy Expr's current op list.2249 SmallVector<uint64_t, 16> NewOps;2250 for (auto Op : Expr->expr_ops()) {2251 // Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.2252 if (Op.getOp() == dwarf::DW_OP_stack_value ||2253 Op.getOp() == dwarf::DW_OP_LLVM_fragment) {2254 NewOps.append(Ops.begin(), Ops.end());2255 2256 // Ensure that the new opcodes are only appended once.2257 Ops = {};2258 }2259 Op.appendToVector(NewOps);2260 }2261 NewOps.append(Ops.begin(), Ops.end());2262 auto *result =2263 DIExpression::get(Expr->getContext(), NewOps)->foldConstantMath();2264 assert(result->isValid() && "concatenated expression is not valid");2265 return result;2266}2267 2268DIExpression *DIExpression::appendToStack(const DIExpression *Expr,2269 ArrayRef<uint64_t> Ops) {2270 assert(Expr && !Ops.empty() && "Can't append ops to this expression");2271 assert(std::none_of(expr_op_iterator(Ops.begin()),2272 expr_op_iterator(Ops.end()),2273 [](auto Op) {2274 return Op.getOp() == dwarf::DW_OP_stack_value ||2275 Op.getOp() == dwarf::DW_OP_LLVM_fragment;2276 }) &&2277 "Can't append this op");2278 2279 // Append a DW_OP_deref after Expr's current op list if it's non-empty and2280 // has no DW_OP_stack_value.2281 //2282 // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?.2283 std::optional<FragmentInfo> FI = Expr->getFragmentInfo();2284 unsigned DropUntilStackValue = FI ? 3 : 0;2285 ArrayRef<uint64_t> ExprOpsBeforeFragment =2286 Expr->getElements().drop_back(DropUntilStackValue);2287 bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) &&2288 (ExprOpsBeforeFragment.back() != dwarf::DW_OP_stack_value);2289 bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.empty();2290 2291 // Append a DW_OP_deref after Expr's current op list if needed, then append2292 // the new ops, and finally ensure that a single DW_OP_stack_value is present.2293 SmallVector<uint64_t, 16> NewOps;2294 if (NeedsDeref)2295 NewOps.push_back(dwarf::DW_OP_deref);2296 NewOps.append(Ops.begin(), Ops.end());2297 if (NeedsStackValue)2298 NewOps.push_back(dwarf::DW_OP_stack_value);2299 return DIExpression::append(Expr, NewOps);2300}2301 2302std::optional<DIExpression *> DIExpression::createFragmentExpression(2303 const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) {2304 SmallVector<uint64_t, 8> Ops;2305 // Track whether it's safe to split the value at the top of the DWARF stack,2306 // assuming that it'll be used as an implicit location value.2307 bool CanSplitValue = true;2308 // Track whether we need to add a fragment expression to the end of Expr.2309 bool EmitFragment = true;2310 // Copy over the expression, but leave off any trailing DW_OP_LLVM_fragment.2311 if (Expr) {2312 for (auto Op : Expr->expr_ops()) {2313 switch (Op.getOp()) {2314 default:2315 break;2316 case dwarf::DW_OP_shr:2317 case dwarf::DW_OP_shra:2318 case dwarf::DW_OP_shl:2319 case dwarf::DW_OP_plus:2320 case dwarf::DW_OP_plus_uconst:2321 case dwarf::DW_OP_minus:2322 // We can't safely split arithmetic or shift operations into multiple2323 // fragments because we can't express carry-over between fragments.2324 //2325 // FIXME: We *could* preserve the lowest fragment of a constant offset2326 // operation if the offset fits into SizeInBits.2327 CanSplitValue = false;2328 break;2329 case dwarf::DW_OP_deref:2330 case dwarf::DW_OP_deref_size:2331 case dwarf::DW_OP_deref_type:2332 case dwarf::DW_OP_xderef:2333 case dwarf::DW_OP_xderef_size:2334 case dwarf::DW_OP_xderef_type:2335 // Preceeding arithmetic operations have been applied to compute an2336 // address. It's okay to split the value loaded from that address.2337 CanSplitValue = true;2338 break;2339 case dwarf::DW_OP_stack_value:2340 // Bail if this expression computes a value that cannot be split.2341 if (!CanSplitValue)2342 return std::nullopt;2343 break;2344 case dwarf::DW_OP_LLVM_fragment: {2345 // If we've decided we don't need a fragment then give up if we see that2346 // there's already a fragment expression.2347 // FIXME: We could probably do better here2348 if (!EmitFragment)2349 return std::nullopt;2350 // Make the new offset point into the existing fragment.2351 uint64_t FragmentOffsetInBits = Op.getArg(0);2352 uint64_t FragmentSizeInBits = Op.getArg(1);2353 (void)FragmentSizeInBits;2354 assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&2355 "new fragment outside of original fragment");2356 OffsetInBits += FragmentOffsetInBits;2357 continue;2358 }2359 case dwarf::DW_OP_LLVM_extract_bits_zext:2360 case dwarf::DW_OP_LLVM_extract_bits_sext: {2361 // If we're extracting bits from inside of the fragment that we're2362 // creating then we don't have a fragment after all, and just need to2363 // adjust the offset that we're extracting from.2364 uint64_t ExtractOffsetInBits = Op.getArg(0);2365 uint64_t ExtractSizeInBits = Op.getArg(1);2366 if (ExtractOffsetInBits >= OffsetInBits &&2367 ExtractOffsetInBits + ExtractSizeInBits <=2368 OffsetInBits + SizeInBits) {2369 Ops.push_back(Op.getOp());2370 Ops.push_back(ExtractOffsetInBits - OffsetInBits);2371 Ops.push_back(ExtractSizeInBits);2372 EmitFragment = false;2373 continue;2374 }2375 // If the extracted bits aren't fully contained within the fragment then2376 // give up.2377 // FIXME: We could probably do better here2378 return std::nullopt;2379 }2380 }2381 Op.appendToVector(Ops);2382 }2383 }2384 assert((!Expr->isImplicit() || CanSplitValue) && "Expr can't be split");2385 assert(Expr && "Unknown DIExpression");2386 if (EmitFragment) {2387 Ops.push_back(dwarf::DW_OP_LLVM_fragment);2388 Ops.push_back(OffsetInBits);2389 Ops.push_back(SizeInBits);2390 }2391 return DIExpression::get(Expr->getContext(), Ops);2392}2393 2394/// See declaration for more info.2395bool DIExpression::calculateFragmentIntersect(2396 const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits,2397 uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits,2398 int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag,2399 std::optional<DIExpression::FragmentInfo> &Result,2400 int64_t &OffsetFromLocationInBits) {2401 2402 if (VarFrag.SizeInBits == 0)2403 return false; // Variable size is unknown.2404 2405 // Difference between mem slice start and the dbg location start.2406 // 0 4 8 12 16 ...2407 // | |2408 // dbg location start2409 // |2410 // mem slice start2411 // Here MemStartRelToDbgStartInBits is 8. Note this can be negative.2412 int64_t MemStartRelToDbgStartInBits;2413 {2414 auto MemOffsetFromDbgInBytes = SliceStart->getPointerOffsetFrom(DbgPtr, DL);2415 if (!MemOffsetFromDbgInBytes)2416 return false; // Can't calculate difference in addresses.2417 // Difference between the pointers.2418 MemStartRelToDbgStartInBits = *MemOffsetFromDbgInBytes * 8;2419 // Add the difference of the offsets.2420 MemStartRelToDbgStartInBits +=2421 SliceOffsetInBits - (DbgPtrOffsetInBits + DbgExtractOffsetInBits);2422 }2423 2424 // Out-param. Invert offset to get offset from debug location.2425 OffsetFromLocationInBits = -MemStartRelToDbgStartInBits;2426 2427 // Check if the variable fragment sits outside (before) this memory slice.2428 int64_t MemEndRelToDbgStart = MemStartRelToDbgStartInBits + SliceSizeInBits;2429 if (MemEndRelToDbgStart < 0) {2430 Result = {0, 0}; // Out-param.2431 return true;2432 }2433 2434 // Work towards creating SliceOfVariable which is the bits of the variable2435 // that the memory region covers.2436 // 0 4 8 12 16 ...2437 // | |2438 // dbg location start with VarFrag offset=322439 // |2440 // mem slice start: SliceOfVariable offset=402441 int64_t MemStartRelToVarInBits =2442 MemStartRelToDbgStartInBits + VarFrag.OffsetInBits;2443 int64_t MemEndRelToVarInBits = MemStartRelToVarInBits + SliceSizeInBits;2444 // If the memory region starts before the debug location the fragment2445 // offset would be negative, which we can't encode. Limit those to 0. This2446 // is fine because those bits necessarily don't overlap with the existing2447 // variable fragment.2448 int64_t MemFragStart = std::max<int64_t>(0, MemStartRelToVarInBits);2449 int64_t MemFragSize =2450 std::max<int64_t>(0, MemEndRelToVarInBits - MemFragStart);2451 DIExpression::FragmentInfo SliceOfVariable(MemFragSize, MemFragStart);2452 2453 // Intersect the memory region fragment with the variable location fragment.2454 DIExpression::FragmentInfo TrimmedSliceOfVariable =2455 DIExpression::FragmentInfo::intersect(SliceOfVariable, VarFrag);2456 if (TrimmedSliceOfVariable == VarFrag)2457 Result = std::nullopt; // Out-param.2458 else2459 Result = TrimmedSliceOfVariable; // Out-param.2460 return true;2461}2462 2463std::pair<DIExpression *, const ConstantInt *>2464DIExpression::constantFold(const ConstantInt *CI) {2465 // Copy the APInt so we can modify it.2466 APInt NewInt = CI->getValue();2467 SmallVector<uint64_t, 8> Ops;2468 2469 // Fold operators only at the beginning of the expression.2470 bool First = true;2471 bool Changed = false;2472 for (auto Op : expr_ops()) {2473 switch (Op.getOp()) {2474 default:2475 // We fold only the leading part of the expression; if we get to a part2476 // that we're going to copy unchanged, and haven't done any folding,2477 // then the entire expression is unchanged and we can return early.2478 if (!Changed)2479 return {this, CI};2480 First = false;2481 break;2482 case dwarf::DW_OP_LLVM_convert:2483 if (!First)2484 break;2485 Changed = true;2486 if (Op.getArg(1) == dwarf::DW_ATE_signed)2487 NewInt = NewInt.sextOrTrunc(Op.getArg(0));2488 else {2489 assert(Op.getArg(1) == dwarf::DW_ATE_unsigned && "Unexpected operand");2490 NewInt = NewInt.zextOrTrunc(Op.getArg(0));2491 }2492 continue;2493 }2494 Op.appendToVector(Ops);2495 }2496 if (!Changed)2497 return {this, CI};2498 return {DIExpression::get(getContext(), Ops),2499 ConstantInt::get(getContext(), NewInt)};2500}2501 2502uint64_t DIExpression::getNumLocationOperands() const {2503 uint64_t Result = 0;2504 for (auto ExprOp : expr_ops())2505 if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)2506 Result = std::max(Result, ExprOp.getArg(0) + 1);2507 assert(hasAllLocationOps(Result) &&2508 "Expression is missing one or more location operands.");2509 return Result;2510}2511 2512std::optional<DIExpression::SignedOrUnsignedConstant>2513DIExpression::isConstant() const {2514 2515 // Recognize signed and unsigned constants.2516 // An signed constants can be represented as DW_OP_consts C DW_OP_stack_value2517 // (DW_OP_LLVM_fragment of Len).2518 // An unsigned constant can be represented as2519 // DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment of Len).2520 2521 if ((getNumElements() != 2 && getNumElements() != 3 &&2522 getNumElements() != 6) ||2523 (getElement(0) != dwarf::DW_OP_consts &&2524 getElement(0) != dwarf::DW_OP_constu))2525 return std::nullopt;2526 2527 if (getNumElements() == 2 && getElement(0) == dwarf::DW_OP_consts)2528 return SignedOrUnsignedConstant::SignedConstant;2529 2530 if ((getNumElements() == 3 && getElement(2) != dwarf::DW_OP_stack_value) ||2531 (getNumElements() == 6 && (getElement(2) != dwarf::DW_OP_stack_value ||2532 getElement(3) != dwarf::DW_OP_LLVM_fragment)))2533 return std::nullopt;2534 return getElement(0) == dwarf::DW_OP_constu2535 ? SignedOrUnsignedConstant::UnsignedConstant2536 : SignedOrUnsignedConstant::SignedConstant;2537}2538 2539DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize,2540 bool Signed) {2541 dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned;2542 DIExpression::ExtOps Ops{{dwarf::DW_OP_LLVM_convert, FromSize, TK,2543 dwarf::DW_OP_LLVM_convert, ToSize, TK}};2544 return Ops;2545}2546 2547DIExpression *DIExpression::appendExt(const DIExpression *Expr,2548 unsigned FromSize, unsigned ToSize,2549 bool Signed) {2550 return appendToStack(Expr, getExtOps(FromSize, ToSize, Signed));2551}2552 2553DIGlobalVariableExpression *2554DIGlobalVariableExpression::getImpl(LLVMContext &Context, Metadata *Variable,2555 Metadata *Expression, StorageType Storage,2556 bool ShouldCreate) {2557 DEFINE_GETIMPL_LOOKUP(DIGlobalVariableExpression, (Variable, Expression));2558 Metadata *Ops[] = {Variable, Expression};2559 DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGlobalVariableExpression, Ops);2560}2561DIObjCProperty::DIObjCProperty(LLVMContext &C, StorageType Storage,2562 unsigned Line, unsigned Attributes,2563 ArrayRef<Metadata *> Ops)2564 : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops),2565 Line(Line), Attributes(Attributes) {}2566 2567DIObjCProperty *DIObjCProperty::getImpl(2568 LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,2569 MDString *GetterName, MDString *SetterName, unsigned Attributes,2570 Metadata *Type, StorageType Storage, bool ShouldCreate) {2571 assert(isCanonical(Name) && "Expected canonical MDString");2572 assert(isCanonical(GetterName) && "Expected canonical MDString");2573 assert(isCanonical(SetterName) && "Expected canonical MDString");2574 DEFINE_GETIMPL_LOOKUP(DIObjCProperty, (Name, File, Line, GetterName,2575 SetterName, Attributes, Type));2576 Metadata *Ops[] = {Name, File, GetterName, SetterName, Type};2577 DEFINE_GETIMPL_STORE(DIObjCProperty, (Line, Attributes), Ops);2578}2579 2580DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,2581 Metadata *Scope, Metadata *Entity,2582 Metadata *File, unsigned Line,2583 MDString *Name, Metadata *Elements,2584 StorageType Storage,2585 bool ShouldCreate) {2586 assert(isCanonical(Name) && "Expected canonical MDString");2587 DEFINE_GETIMPL_LOOKUP(DIImportedEntity,2588 (Tag, Scope, Entity, File, Line, Name, Elements));2589 Metadata *Ops[] = {Scope, Entity, Name, File, Elements};2590 DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops);2591}2592 2593DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,2594 MDString *Name, MDString *Value, StorageType Storage,2595 bool ShouldCreate) {2596 assert(isCanonical(Name) && "Expected canonical MDString");2597 DEFINE_GETIMPL_LOOKUP(DIMacro, (MIType, Line, Name, Value));2598 Metadata *Ops[] = {Name, Value};2599 DEFINE_GETIMPL_STORE(DIMacro, (MIType, Line), Ops);2600}2601 2602DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,2603 unsigned Line, Metadata *File,2604 Metadata *Elements, StorageType Storage,2605 bool ShouldCreate) {2606 DEFINE_GETIMPL_LOOKUP(DIMacroFile, (MIType, Line, File, Elements));2607 Metadata *Ops[] = {File, Elements};2608 DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);2609}2610 2611DIArgList *DIArgList::get(LLVMContext &Context,2612 ArrayRef<ValueAsMetadata *> Args) {2613 auto ExistingIt = Context.pImpl->DIArgLists.find_as(DIArgListKeyInfo(Args));2614 if (ExistingIt != Context.pImpl->DIArgLists.end())2615 return *ExistingIt;2616 DIArgList *NewArgList = new DIArgList(Context, Args);2617 Context.pImpl->DIArgLists.insert(NewArgList);2618 return NewArgList;2619}2620 2621void DIArgList::handleChangedOperand(void *Ref, Metadata *New) {2622 ValueAsMetadata **OldVMPtr = static_cast<ValueAsMetadata **>(Ref);2623 assert((!New || isa<ValueAsMetadata>(New)) &&2624 "DIArgList must be passed a ValueAsMetadata");2625 untrack();2626 // We need to update the set storage once the Args are updated since they2627 // form the key to the DIArgLists store.2628 getContext().pImpl->DIArgLists.erase(this);2629 ValueAsMetadata *NewVM = cast_or_null<ValueAsMetadata>(New);2630 for (ValueAsMetadata *&VM : Args) {2631 if (&VM == OldVMPtr) {2632 if (NewVM)2633 VM = NewVM;2634 else2635 VM = ValueAsMetadata::get(PoisonValue::get(VM->getValue()->getType()));2636 }2637 }2638 // We've changed the contents of this DIArgList, and the set storage may2639 // already contain a DIArgList with our new set of args; if it does, then we2640 // must RAUW this with the existing DIArgList, otherwise we simply insert this2641 // back into the set storage.2642 DIArgList *ExistingArgList = getUniqued(getContext().pImpl->DIArgLists, this);2643 if (ExistingArgList) {2644 replaceAllUsesWith(ExistingArgList);2645 // Clear this here so we don't try to untrack in the destructor.2646 Args.clear();2647 delete this;2648 return;2649 }2650 getContext().pImpl->DIArgLists.insert(this);2651 track();2652}2653void DIArgList::track() {2654 for (ValueAsMetadata *&VAM : Args)2655 if (VAM)2656 MetadataTracking::track(&VAM, *VAM, *this);2657}2658void DIArgList::untrack() {2659 for (ValueAsMetadata *&VAM : Args)2660 if (VAM)2661 MetadataTracking::untrack(&VAM, *VAM);2662}2663void DIArgList::dropAllReferences(bool Untrack) {2664 if (Untrack)2665 untrack();2666 Args.clear();2667 ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);2668}2669