15a5ac124SDimitry Andric //===- DebugInfoMetadata.cpp - Implement debug info metadata --------------===//
25a5ac124SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a5ac124SDimitry Andric //
75a5ac124SDimitry Andric //===----------------------------------------------------------------------===//
85a5ac124SDimitry Andric //
95a5ac124SDimitry Andric // This file implements the debug info Metadata classes.
105a5ac124SDimitry Andric //
115a5ac124SDimitry Andric //===----------------------------------------------------------------------===//
125a5ac124SDimitry Andric
135a5ac124SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
145a5ac124SDimitry Andric #include "LLVMContextImpl.h"
155a5ac124SDimitry Andric #include "MetadataImpl.h"
167fa27ce4SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
175a5ac124SDimitry Andric #include "llvm/ADT/StringSwitch.h"
18145449b1SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
19b1c73532SDimitry Andric #include "llvm/IR/DebugProgramInstruction.h"
205a5ac124SDimitry Andric #include "llvm/IR/Function.h"
21e3b55780SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
22ecbca9f5SDimitry Andric #include "llvm/IR/Type.h"
23ecbca9f5SDimitry Andric #include "llvm/IR/Value.h"
245a5ac124SDimitry Andric
25d8e91e46SDimitry Andric #include <numeric>
26e3b55780SDimitry Andric #include <optional>
27d8e91e46SDimitry Andric
285a5ac124SDimitry Andric using namespace llvm;
295a5ac124SDimitry Andric
30344a3780SDimitry Andric namespace llvm {
31344a3780SDimitry Andric // Use FS-AFDO discriminator.
32344a3780SDimitry Andric cl::opt<bool> EnableFSDiscriminator(
33145449b1SDimitry Andric "enable-fs-discriminator", cl::Hidden,
34344a3780SDimitry Andric cl::desc("Enable adding flow sensitive discriminators"));
35344a3780SDimitry Andric } // namespace llvm
36344a3780SDimitry Andric
getAlignInBits() const37ac9a064cSDimitry Andric uint32_t DIType::getAlignInBits() const {
38ac9a064cSDimitry Andric return (getTag() == dwarf::DW_TAG_LLVM_ptrauth_type ? 0 : SubclassData32);
39ac9a064cSDimitry Andric }
40ac9a064cSDimitry Andric
41706b4fc4SDimitry Andric const DIExpression::FragmentInfo DebugVariable::DefaultFragment = {
42706b4fc4SDimitry Andric std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()};
43706b4fc4SDimitry Andric
DebugVariable(const DbgVariableIntrinsic * DII)44e3b55780SDimitry Andric DebugVariable::DebugVariable(const DbgVariableIntrinsic *DII)
45e3b55780SDimitry Andric : Variable(DII->getVariable()),
46e3b55780SDimitry Andric Fragment(DII->getExpression()->getFragmentInfo()),
47e3b55780SDimitry Andric InlinedAt(DII->getDebugLoc().getInlinedAt()) {}
48e3b55780SDimitry Andric
DebugVariable(const DbgVariableRecord * DVR)49ac9a064cSDimitry Andric DebugVariable::DebugVariable(const DbgVariableRecord *DVR)
50ac9a064cSDimitry Andric : Variable(DVR->getVariable()),
51ac9a064cSDimitry Andric Fragment(DVR->getExpression()->getFragmentInfo()),
52ac9a064cSDimitry Andric InlinedAt(DVR->getDebugLoc().getInlinedAt()) {}
53b1c73532SDimitry Andric
DebugVariableAggregate(const DbgVariableIntrinsic * DVI)547fa27ce4SDimitry Andric DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI)
557fa27ce4SDimitry Andric : DebugVariable(DVI->getVariable(), std::nullopt,
567fa27ce4SDimitry Andric DVI->getDebugLoc()->getInlinedAt()) {}
577fa27ce4SDimitry Andric
DILocation(LLVMContext & C,StorageType Storage,unsigned Line,unsigned Column,ArrayRef<Metadata * > MDs,bool ImplicitCode)585a5ac124SDimitry Andric DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
59d8e91e46SDimitry Andric unsigned Column, ArrayRef<Metadata *> MDs,
60d8e91e46SDimitry Andric bool ImplicitCode)
615a5ac124SDimitry Andric : MDNode(C, DILocationKind, Storage, MDs) {
625a5ac124SDimitry Andric assert((MDs.size() == 1 || MDs.size() == 2) &&
635a5ac124SDimitry Andric "Expected a scope and optional inlined-at");
645a5ac124SDimitry Andric
655a5ac124SDimitry Andric // Set line and column.
665a5ac124SDimitry Andric assert(Column < (1u << 16) && "Expected 16-bit column");
675a5ac124SDimitry Andric
685a5ac124SDimitry Andric SubclassData32 = Line;
695a5ac124SDimitry Andric SubclassData16 = Column;
70d8e91e46SDimitry Andric
71d8e91e46SDimitry Andric setImplicitCode(ImplicitCode);
725a5ac124SDimitry Andric }
735a5ac124SDimitry Andric
adjustColumn(unsigned & Column)745a5ac124SDimitry Andric static void adjustColumn(unsigned &Column) {
755a5ac124SDimitry Andric // Set to unknown on overflow. We only have 16 bits to play with here.
765a5ac124SDimitry Andric if (Column >= (1u << 16))
775a5ac124SDimitry Andric Column = 0;
785a5ac124SDimitry Andric }
795a5ac124SDimitry Andric
getImpl(LLVMContext & Context,unsigned Line,unsigned Column,Metadata * Scope,Metadata * InlinedAt,bool ImplicitCode,StorageType Storage,bool ShouldCreate)805a5ac124SDimitry Andric DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
815a5ac124SDimitry Andric unsigned Column, Metadata *Scope,
82d8e91e46SDimitry Andric Metadata *InlinedAt, bool ImplicitCode,
83d8e91e46SDimitry Andric StorageType Storage, bool ShouldCreate) {
845a5ac124SDimitry Andric // Fixup column.
855a5ac124SDimitry Andric adjustColumn(Column);
865a5ac124SDimitry Andric
875a5ac124SDimitry Andric if (Storage == Uniqued) {
88d8e91e46SDimitry Andric if (auto *N = getUniqued(Context.pImpl->DILocations,
89d8e91e46SDimitry Andric DILocationInfo::KeyTy(Line, Column, Scope,
90d8e91e46SDimitry Andric InlinedAt, ImplicitCode)))
915a5ac124SDimitry Andric return N;
925a5ac124SDimitry Andric if (!ShouldCreate)
935a5ac124SDimitry Andric return nullptr;
945a5ac124SDimitry Andric } else {
955a5ac124SDimitry Andric assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
965a5ac124SDimitry Andric }
975a5ac124SDimitry Andric
985a5ac124SDimitry Andric SmallVector<Metadata *, 2> Ops;
995a5ac124SDimitry Andric Ops.push_back(Scope);
1005a5ac124SDimitry Andric if (InlinedAt)
1015a5ac124SDimitry Andric Ops.push_back(InlinedAt);
102145449b1SDimitry Andric return storeImpl(new (Ops.size(), Storage) DILocation(
103145449b1SDimitry Andric Context, Storage, Line, Column, Ops, ImplicitCode),
1045a5ac124SDimitry Andric Storage, Context.pImpl->DILocations);
1055a5ac124SDimitry Andric }
1065a5ac124SDimitry Andric
getMergedLocations(ArrayRef<DILocation * > Locs)1077fa27ce4SDimitry Andric DILocation *DILocation::getMergedLocations(ArrayRef<DILocation *> Locs) {
108cfca06d7SDimitry Andric if (Locs.empty())
109cfca06d7SDimitry Andric return nullptr;
110cfca06d7SDimitry Andric if (Locs.size() == 1)
111cfca06d7SDimitry Andric return Locs[0];
112cfca06d7SDimitry Andric auto *Merged = Locs[0];
1137fa27ce4SDimitry Andric for (DILocation *L : llvm::drop_begin(Locs)) {
114344a3780SDimitry Andric Merged = getMergedLocation(Merged, L);
115cfca06d7SDimitry Andric if (Merged == nullptr)
116cfca06d7SDimitry Andric break;
117cfca06d7SDimitry Andric }
118cfca06d7SDimitry Andric return Merged;
119cfca06d7SDimitry Andric }
120cfca06d7SDimitry Andric
getMergedLocation(DILocation * LocA,DILocation * LocB)1217fa27ce4SDimitry Andric DILocation *DILocation::getMergedLocation(DILocation *LocA, DILocation *LocB) {
122044eb2f6SDimitry Andric if (!LocA || !LocB)
123044eb2f6SDimitry Andric return nullptr;
124044eb2f6SDimitry Andric
125d8e91e46SDimitry Andric if (LocA == LocB)
126044eb2f6SDimitry Andric return LocA;
127044eb2f6SDimitry Andric
128e3b55780SDimitry Andric LLVMContext &C = LocA->getContext();
129e3b55780SDimitry Andric
1307fa27ce4SDimitry Andric using LocVec = SmallVector<const DILocation *>;
1317fa27ce4SDimitry Andric LocVec ALocs;
1327fa27ce4SDimitry Andric LocVec BLocs;
1337fa27ce4SDimitry Andric SmallDenseMap<std::pair<const DISubprogram *, const DILocation *>, unsigned,
1347fa27ce4SDimitry Andric 4>
1357fa27ce4SDimitry Andric ALookup;
136e3b55780SDimitry Andric
1377fa27ce4SDimitry Andric // Walk through LocA and its inlined-at locations, populate them in ALocs and
1387fa27ce4SDimitry Andric // save the index for the subprogram and inlined-at pair, which we use to find
1397fa27ce4SDimitry Andric // a matching starting location in LocB's chain.
1407fa27ce4SDimitry Andric for (auto [L, I] = std::make_pair(LocA, 0U); L; L = L->getInlinedAt(), I++) {
1417fa27ce4SDimitry Andric ALocs.push_back(L);
1427fa27ce4SDimitry Andric auto Res = ALookup.try_emplace(
1437fa27ce4SDimitry Andric {L->getScope()->getSubprogram(), L->getInlinedAt()}, I);
1447fa27ce4SDimitry Andric assert(Res.second && "Multiple <SP, InlinedAt> pairs in a location chain?");
1457fa27ce4SDimitry Andric (void)Res;
146d8e91e46SDimitry Andric }
147e3b55780SDimitry Andric
1487fa27ce4SDimitry Andric LocVec::reverse_iterator ARIt = ALocs.rend();
1497fa27ce4SDimitry Andric LocVec::reverse_iterator BRIt = BLocs.rend();
1507fa27ce4SDimitry Andric
1517fa27ce4SDimitry Andric // Populate BLocs and look for a matching starting location, the first
1527fa27ce4SDimitry Andric // location with the same subprogram and inlined-at location as in LocA's
1537fa27ce4SDimitry Andric // chain. Since the two locations have the same inlined-at location we do
1547fa27ce4SDimitry Andric // not need to look at those parts of the chains.
1557fa27ce4SDimitry Andric for (auto [L, I] = std::make_pair(LocB, 0U); L; L = L->getInlinedAt(), I++) {
1567fa27ce4SDimitry Andric BLocs.push_back(L);
1577fa27ce4SDimitry Andric
1587fa27ce4SDimitry Andric if (ARIt != ALocs.rend())
1597fa27ce4SDimitry Andric // We have already found a matching starting location.
1607fa27ce4SDimitry Andric continue;
1617fa27ce4SDimitry Andric
1627fa27ce4SDimitry Andric auto IT = ALookup.find({L->getScope()->getSubprogram(), L->getInlinedAt()});
1637fa27ce4SDimitry Andric if (IT == ALookup.end())
1647fa27ce4SDimitry Andric continue;
1657fa27ce4SDimitry Andric
1667fa27ce4SDimitry Andric // The + 1 is to account for the &*rev_it = &(it - 1) relationship.
1677fa27ce4SDimitry Andric ARIt = LocVec::reverse_iterator(ALocs.begin() + IT->second + 1);
1687fa27ce4SDimitry Andric BRIt = LocVec::reverse_iterator(BLocs.begin() + I + 1);
1697fa27ce4SDimitry Andric
1707fa27ce4SDimitry Andric // If we have found a matching starting location we do not need to add more
1717fa27ce4SDimitry Andric // locations to BLocs, since we will only look at location pairs preceding
1727fa27ce4SDimitry Andric // the matching starting location, and adding more elements to BLocs could
1737fa27ce4SDimitry Andric // invalidate the iterator that we initialized here.
174044eb2f6SDimitry Andric break;
175044eb2f6SDimitry Andric }
1767fa27ce4SDimitry Andric
1777fa27ce4SDimitry Andric // Merge the two locations if possible, using the supplied
1787fa27ce4SDimitry Andric // inlined-at location for the created location.
1797fa27ce4SDimitry Andric auto MergeLocPair = [&C](const DILocation *L1, const DILocation *L2,
1807fa27ce4SDimitry Andric DILocation *InlinedAt) -> DILocation * {
1817fa27ce4SDimitry Andric if (L1 == L2)
1827fa27ce4SDimitry Andric return DILocation::get(C, L1->getLine(), L1->getColumn(), L1->getScope(),
1837fa27ce4SDimitry Andric InlinedAt);
1847fa27ce4SDimitry Andric
1857fa27ce4SDimitry Andric // If the locations originate from different subprograms we can't produce
1867fa27ce4SDimitry Andric // a common location.
1877fa27ce4SDimitry Andric if (L1->getScope()->getSubprogram() != L2->getScope()->getSubprogram())
1887fa27ce4SDimitry Andric return nullptr;
1897fa27ce4SDimitry Andric
1907fa27ce4SDimitry Andric // Return the nearest common scope inside a subprogram.
1917fa27ce4SDimitry Andric auto GetNearestCommonScope = [](DIScope *S1, DIScope *S2) -> DIScope * {
1927fa27ce4SDimitry Andric SmallPtrSet<DIScope *, 8> Scopes;
1937fa27ce4SDimitry Andric for (; S1; S1 = S1->getScope()) {
1947fa27ce4SDimitry Andric Scopes.insert(S1);
1957fa27ce4SDimitry Andric if (isa<DISubprogram>(S1))
1967fa27ce4SDimitry Andric break;
197e3b55780SDimitry Andric }
198044eb2f6SDimitry Andric
1997fa27ce4SDimitry Andric for (; S2; S2 = S2->getScope()) {
2007fa27ce4SDimitry Andric if (Scopes.count(S2))
2017fa27ce4SDimitry Andric return S2;
2027fa27ce4SDimitry Andric if (isa<DISubprogram>(S2))
2037fa27ce4SDimitry Andric break;
204d8e91e46SDimitry Andric }
205d8e91e46SDimitry Andric
2067fa27ce4SDimitry Andric return nullptr;
2077fa27ce4SDimitry Andric };
2087fa27ce4SDimitry Andric
2097fa27ce4SDimitry Andric auto Scope = GetNearestCommonScope(L1->getScope(), L2->getScope());
2107fa27ce4SDimitry Andric assert(Scope && "No common scope in the same subprogram?");
2117fa27ce4SDimitry Andric
2127fa27ce4SDimitry Andric bool SameLine = L1->getLine() == L2->getLine();
2137fa27ce4SDimitry Andric bool SameCol = L1->getColumn() == L2->getColumn();
2147fa27ce4SDimitry Andric unsigned Line = SameLine ? L1->getLine() : 0;
2157fa27ce4SDimitry Andric unsigned Col = SameLine && SameCol ? L1->getColumn() : 0;
2167fa27ce4SDimitry Andric
2177fa27ce4SDimitry Andric return DILocation::get(C, Line, Col, Scope, InlinedAt);
2187fa27ce4SDimitry Andric };
2197fa27ce4SDimitry Andric
2207fa27ce4SDimitry Andric DILocation *Result = ARIt != ALocs.rend() ? (*ARIt)->getInlinedAt() : nullptr;
2217fa27ce4SDimitry Andric
2227fa27ce4SDimitry Andric // If we have found a common starting location, walk up the inlined-at chains
2237fa27ce4SDimitry Andric // and try to produce common locations.
2247fa27ce4SDimitry Andric for (; ARIt != ALocs.rend() && BRIt != BLocs.rend(); ++ARIt, ++BRIt) {
2257fa27ce4SDimitry Andric DILocation *Tmp = MergeLocPair(*ARIt, *BRIt, Result);
2267fa27ce4SDimitry Andric
2277fa27ce4SDimitry Andric if (!Tmp)
2287fa27ce4SDimitry Andric // We have walked up to a point in the chains where the two locations
2297fa27ce4SDimitry Andric // are irreconsilable. At this point Result contains the nearest common
2307fa27ce4SDimitry Andric // location in the inlined-at chains of LocA and LocB, so we break here.
2317fa27ce4SDimitry Andric break;
2327fa27ce4SDimitry Andric
2337fa27ce4SDimitry Andric Result = Tmp;
2347fa27ce4SDimitry Andric }
2357fa27ce4SDimitry Andric
2367fa27ce4SDimitry Andric if (Result)
2377fa27ce4SDimitry Andric return Result;
2387fa27ce4SDimitry Andric
2397fa27ce4SDimitry Andric // We ended up with LocA and LocB as irreconsilable locations. Produce a
2407fa27ce4SDimitry Andric // location at 0:0 with one of the locations' scope. The function has
2417fa27ce4SDimitry Andric // historically picked A's scope, and a nullptr inlined-at location, so that
2427fa27ce4SDimitry Andric // behavior is mimicked here but I am not sure if this is always the correct
2437fa27ce4SDimitry Andric // way to handle this.
2447fa27ce4SDimitry Andric return DILocation::get(C, 0, 0, LocA->getScope(), nullptr);
245e3b55780SDimitry Andric }
246e3b55780SDimitry Andric
247e3b55780SDimitry Andric std::optional<unsigned>
encodeDiscriminator(unsigned BD,unsigned DF,unsigned CI)248e3b55780SDimitry Andric DILocation::encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI) {
249b60736ecSDimitry Andric std::array<unsigned, 3> Components = {BD, DF, CI};
250d8e91e46SDimitry Andric uint64_t RemainingWork = 0U;
251d8e91e46SDimitry Andric // We use RemainingWork to figure out if we have no remaining components to
252d8e91e46SDimitry Andric // encode. For example: if BD != 0 but DF == 0 && CI == 0, we don't need to
253d8e91e46SDimitry Andric // encode anything for the latter 2.
254d8e91e46SDimitry Andric // Since any of the input components is at most 32 bits, their sum will be
255d8e91e46SDimitry Andric // less than 34 bits, and thus RemainingWork won't overflow.
256c0981da4SDimitry Andric RemainingWork =
257c0981da4SDimitry Andric std::accumulate(Components.begin(), Components.end(), RemainingWork);
258d8e91e46SDimitry Andric
259d8e91e46SDimitry Andric int I = 0;
260d8e91e46SDimitry Andric unsigned Ret = 0;
261d8e91e46SDimitry Andric unsigned NextBitInsertionIndex = 0;
262d8e91e46SDimitry Andric while (RemainingWork > 0) {
263d8e91e46SDimitry Andric unsigned C = Components[I++];
264d8e91e46SDimitry Andric RemainingWork -= C;
265d8e91e46SDimitry Andric unsigned EC = encodeComponent(C);
266d8e91e46SDimitry Andric Ret |= (EC << NextBitInsertionIndex);
267d8e91e46SDimitry Andric NextBitInsertionIndex += encodingBits(C);
268d8e91e46SDimitry Andric }
269d8e91e46SDimitry Andric
270d8e91e46SDimitry Andric // Encoding may be unsuccessful because of overflow. We determine success by
271d8e91e46SDimitry Andric // checking equivalence of components before & after encoding. Alternatively,
272d8e91e46SDimitry Andric // we could determine Success during encoding, but the current alternative is
273d8e91e46SDimitry Andric // simpler.
274d8e91e46SDimitry Andric unsigned TBD, TDF, TCI = 0;
275d8e91e46SDimitry Andric decodeDiscriminator(Ret, TBD, TDF, TCI);
276d8e91e46SDimitry Andric if (TBD == BD && TDF == DF && TCI == CI)
277d8e91e46SDimitry Andric return Ret;
278e3b55780SDimitry Andric return std::nullopt;
279d8e91e46SDimitry Andric }
280d8e91e46SDimitry Andric
decodeDiscriminator(unsigned D,unsigned & BD,unsigned & DF,unsigned & CI)281d8e91e46SDimitry Andric void DILocation::decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF,
282d8e91e46SDimitry Andric unsigned &CI) {
283d8e91e46SDimitry Andric BD = getUnsignedFromPrefixEncoding(D);
284d8e91e46SDimitry Andric DF = getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator(D));
285d8e91e46SDimitry Andric CI = getUnsignedFromPrefixEncoding(
286d8e91e46SDimitry Andric getNextComponentInDiscriminator(getNextComponentInDiscriminator(D)));
287d8e91e46SDimitry Andric }
getTag() const288145449b1SDimitry Andric dwarf::Tag DINode::getTag() const { return (dwarf::Tag)SubclassData16; }
289d8e91e46SDimitry Andric
getFlag(StringRef Flag)290b915e9e0SDimitry Andric DINode::DIFlags DINode::getFlag(StringRef Flag) {
291b915e9e0SDimitry Andric return StringSwitch<DIFlags>(Flag)
2925a5ac124SDimitry Andric #define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME)
2935a5ac124SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
294b915e9e0SDimitry Andric .Default(DINode::FlagZero);
2955a5ac124SDimitry Andric }
2965a5ac124SDimitry Andric
getFlagString(DIFlags Flag)297b915e9e0SDimitry Andric StringRef DINode::getFlagString(DIFlags Flag) {
2985a5ac124SDimitry Andric switch (Flag) {
2995a5ac124SDimitry Andric #define HANDLE_DI_FLAG(ID, NAME) \
3005a5ac124SDimitry Andric case Flag##NAME: \
3015a5ac124SDimitry Andric return "DIFlag" #NAME;
3025a5ac124SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
3035a5ac124SDimitry Andric }
304b915e9e0SDimitry Andric return "";
3055a5ac124SDimitry Andric }
3065a5ac124SDimitry Andric
splitFlags(DIFlags Flags,SmallVectorImpl<DIFlags> & SplitFlags)307b915e9e0SDimitry Andric DINode::DIFlags DINode::splitFlags(DIFlags Flags,
308b915e9e0SDimitry Andric SmallVectorImpl<DIFlags> &SplitFlags) {
309b915e9e0SDimitry Andric // Flags that are packed together need to be specially handled, so
310b915e9e0SDimitry Andric // that, for example, we emit "DIFlagPublic" and not
311b915e9e0SDimitry Andric // "DIFlagPrivate | DIFlagProtected".
312b915e9e0SDimitry Andric if (DIFlags A = Flags & FlagAccessibility) {
3135a5ac124SDimitry Andric if (A == FlagPrivate)
3145a5ac124SDimitry Andric SplitFlags.push_back(FlagPrivate);
3155a5ac124SDimitry Andric else if (A == FlagProtected)
3165a5ac124SDimitry Andric SplitFlags.push_back(FlagProtected);
3175a5ac124SDimitry Andric else
3185a5ac124SDimitry Andric SplitFlags.push_back(FlagPublic);
3195a5ac124SDimitry Andric Flags &= ~A;
3205a5ac124SDimitry Andric }
321b915e9e0SDimitry Andric if (DIFlags R = Flags & FlagPtrToMemberRep) {
32201095a5dSDimitry Andric if (R == FlagSingleInheritance)
32301095a5dSDimitry Andric SplitFlags.push_back(FlagSingleInheritance);
32401095a5dSDimitry Andric else if (R == FlagMultipleInheritance)
32501095a5dSDimitry Andric SplitFlags.push_back(FlagMultipleInheritance);
32601095a5dSDimitry Andric else
32701095a5dSDimitry Andric SplitFlags.push_back(FlagVirtualInheritance);
32801095a5dSDimitry Andric Flags &= ~R;
32901095a5dSDimitry Andric }
330b915e9e0SDimitry Andric if ((Flags & FlagIndirectVirtualBase) == FlagIndirectVirtualBase) {
331b915e9e0SDimitry Andric Flags &= ~FlagIndirectVirtualBase;
332b915e9e0SDimitry Andric SplitFlags.push_back(FlagIndirectVirtualBase);
333b915e9e0SDimitry Andric }
3345a5ac124SDimitry Andric
3355a5ac124SDimitry Andric #define HANDLE_DI_FLAG(ID, NAME) \
336b915e9e0SDimitry Andric if (DIFlags Bit = Flags & Flag##NAME) { \
3375a5ac124SDimitry Andric SplitFlags.push_back(Bit); \
3385a5ac124SDimitry Andric Flags &= ~Bit; \
3395a5ac124SDimitry Andric }
3405a5ac124SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
3415a5ac124SDimitry Andric return Flags;
3425a5ac124SDimitry Andric }
3435a5ac124SDimitry Andric
getScope() const344e6d15924SDimitry Andric DIScope *DIScope::getScope() const {
3455a5ac124SDimitry Andric if (auto *T = dyn_cast<DIType>(this))
3465a5ac124SDimitry Andric return T->getScope();
3475a5ac124SDimitry Andric
3485a5ac124SDimitry Andric if (auto *SP = dyn_cast<DISubprogram>(this))
3495a5ac124SDimitry Andric return SP->getScope();
3505a5ac124SDimitry Andric
3515a5ac124SDimitry Andric if (auto *LB = dyn_cast<DILexicalBlockBase>(this))
35201095a5dSDimitry Andric return LB->getScope();
3535a5ac124SDimitry Andric
3545a5ac124SDimitry Andric if (auto *NS = dyn_cast<DINamespace>(this))
35501095a5dSDimitry Andric return NS->getScope();
3565a5ac124SDimitry Andric
357e6d15924SDimitry Andric if (auto *CB = dyn_cast<DICommonBlock>(this))
358e6d15924SDimitry Andric return CB->getScope();
359e6d15924SDimitry Andric
3601a82d4c0SDimitry Andric if (auto *M = dyn_cast<DIModule>(this))
36101095a5dSDimitry Andric return M->getScope();
3621a82d4c0SDimitry Andric
3635a5ac124SDimitry Andric assert((isa<DIFile>(this) || isa<DICompileUnit>(this)) &&
3645a5ac124SDimitry Andric "Unhandled type of scope.");
3655a5ac124SDimitry Andric return nullptr;
3665a5ac124SDimitry Andric }
3675a5ac124SDimitry Andric
getName() const3685a5ac124SDimitry Andric StringRef DIScope::getName() const {
3695a5ac124SDimitry Andric if (auto *T = dyn_cast<DIType>(this))
3705a5ac124SDimitry Andric return T->getName();
3715a5ac124SDimitry Andric if (auto *SP = dyn_cast<DISubprogram>(this))
3725a5ac124SDimitry Andric return SP->getName();
3735a5ac124SDimitry Andric if (auto *NS = dyn_cast<DINamespace>(this))
3745a5ac124SDimitry Andric return NS->getName();
375e6d15924SDimitry Andric if (auto *CB = dyn_cast<DICommonBlock>(this))
376e6d15924SDimitry Andric return CB->getName();
3771a82d4c0SDimitry Andric if (auto *M = dyn_cast<DIModule>(this))
3781a82d4c0SDimitry Andric return M->getName();
3795a5ac124SDimitry Andric assert((isa<DILexicalBlockBase>(this) || isa<DIFile>(this) ||
3805a5ac124SDimitry Andric isa<DICompileUnit>(this)) &&
3815a5ac124SDimitry Andric "Unhandled type of scope.");
3825a5ac124SDimitry Andric return "";
3835a5ac124SDimitry Andric }
3845a5ac124SDimitry Andric
3855a5ac124SDimitry Andric #ifndef NDEBUG
isCanonical(const MDString * S)3865a5ac124SDimitry Andric static bool isCanonical(const MDString *S) {
3875a5ac124SDimitry Andric return !S || !S->getString().empty();
3885a5ac124SDimitry Andric }
3895a5ac124SDimitry Andric #endif
3905a5ac124SDimitry Andric
getTag() const391145449b1SDimitry Andric dwarf::Tag GenericDINode::getTag() const { return (dwarf::Tag)SubclassData16; }
getImpl(LLVMContext & Context,unsigned Tag,MDString * Header,ArrayRef<Metadata * > DwarfOps,StorageType Storage,bool ShouldCreate)3925a5ac124SDimitry Andric GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag,
3935a5ac124SDimitry Andric MDString *Header,
3945a5ac124SDimitry Andric ArrayRef<Metadata *> DwarfOps,
3955a5ac124SDimitry Andric StorageType Storage, bool ShouldCreate) {
3965a5ac124SDimitry Andric unsigned Hash = 0;
3975a5ac124SDimitry Andric if (Storage == Uniqued) {
39801095a5dSDimitry Andric GenericDINodeInfo::KeyTy Key(Tag, Header, DwarfOps);
3995a5ac124SDimitry Andric if (auto *N = getUniqued(Context.pImpl->GenericDINodes, Key))
4005a5ac124SDimitry Andric return N;
4015a5ac124SDimitry Andric if (!ShouldCreate)
4025a5ac124SDimitry Andric return nullptr;
4035a5ac124SDimitry Andric Hash = Key.getHash();
4045a5ac124SDimitry Andric } else {
4055a5ac124SDimitry Andric assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
4065a5ac124SDimitry Andric }
4075a5ac124SDimitry Andric
4085a5ac124SDimitry Andric // Use a nullptr for empty headers.
4095a5ac124SDimitry Andric assert(isCanonical(Header) && "Expected canonical MDString");
4105a5ac124SDimitry Andric Metadata *PreOps[] = {Header};
411145449b1SDimitry Andric return storeImpl(new (DwarfOps.size() + 1, Storage) GenericDINode(
4125a5ac124SDimitry Andric Context, Storage, Hash, Tag, PreOps, DwarfOps),
4135a5ac124SDimitry Andric Storage, Context.pImpl->GenericDINodes);
4145a5ac124SDimitry Andric }
4155a5ac124SDimitry Andric
recalculateHash()4165a5ac124SDimitry Andric void GenericDINode::recalculateHash() {
4175a5ac124SDimitry Andric setHash(GenericDINodeInfo::KeyTy::calculateHash(this));
4185a5ac124SDimitry Andric }
4195a5ac124SDimitry Andric
4205a5ac124SDimitry Andric #define UNWRAP_ARGS_IMPL(...) __VA_ARGS__
4215a5ac124SDimitry Andric #define UNWRAP_ARGS(ARGS) UNWRAP_ARGS_IMPL ARGS
4225a5ac124SDimitry Andric #define DEFINE_GETIMPL_LOOKUP(CLASS, ARGS) \
4235a5ac124SDimitry Andric do { \
4245a5ac124SDimitry Andric if (Storage == Uniqued) { \
4255a5ac124SDimitry Andric if (auto *N = getUniqued(Context.pImpl->CLASS##s, \
4265a5ac124SDimitry Andric CLASS##Info::KeyTy(UNWRAP_ARGS(ARGS)))) \
4275a5ac124SDimitry Andric return N; \
4285a5ac124SDimitry Andric if (!ShouldCreate) \
4295a5ac124SDimitry Andric return nullptr; \
4305a5ac124SDimitry Andric } else { \
4315a5ac124SDimitry Andric assert(ShouldCreate && \
4325a5ac124SDimitry Andric "Expected non-uniqued nodes to always be created"); \
4335a5ac124SDimitry Andric } \
4345a5ac124SDimitry Andric } while (false)
4355a5ac124SDimitry Andric #define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS) \
436e3b55780SDimitry Andric return storeImpl(new (std::size(OPS), Storage) \
4375a5ac124SDimitry Andric CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
4385a5ac124SDimitry Andric Storage, Context.pImpl->CLASS##s)
4395a5ac124SDimitry Andric #define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS) \
440145449b1SDimitry Andric return storeImpl(new (0u, Storage) \
441145449b1SDimitry Andric CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \
4425a5ac124SDimitry Andric Storage, Context.pImpl->CLASS##s)
4435a5ac124SDimitry Andric #define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS) \
444e3b55780SDimitry Andric return storeImpl(new (std::size(OPS), Storage) CLASS(Context, Storage, OPS), \
4455a5ac124SDimitry Andric Storage, Context.pImpl->CLASS##s)
446a303c417SDimitry Andric #define DEFINE_GETIMPL_STORE_N(CLASS, ARGS, OPS, NUM_OPS) \
447145449b1SDimitry Andric return storeImpl(new (NUM_OPS, Storage) \
448a303c417SDimitry Andric CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \
449a303c417SDimitry Andric Storage, Context.pImpl->CLASS##s)
4505a5ac124SDimitry Andric
DISubrange(LLVMContext & C,StorageType Storage,ArrayRef<Metadata * > Ops)451145449b1SDimitry Andric DISubrange::DISubrange(LLVMContext &C, StorageType Storage,
452145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
453145449b1SDimitry Andric : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {}
getImpl(LLVMContext & Context,int64_t Count,int64_t Lo,StorageType Storage,bool ShouldCreate)4545a5ac124SDimitry Andric DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
4555a5ac124SDimitry Andric StorageType Storage, bool ShouldCreate) {
456eb11fae6SDimitry Andric auto *CountNode = ConstantAsMetadata::get(
457eb11fae6SDimitry Andric ConstantInt::getSigned(Type::getInt64Ty(Context), Count));
458cfca06d7SDimitry Andric auto *LB = ConstantAsMetadata::get(
459cfca06d7SDimitry Andric ConstantInt::getSigned(Type::getInt64Ty(Context), Lo));
460cfca06d7SDimitry Andric return getImpl(Context, CountNode, LB, nullptr, nullptr, Storage,
461cfca06d7SDimitry Andric ShouldCreate);
462eb11fae6SDimitry Andric }
463eb11fae6SDimitry Andric
getImpl(LLVMContext & Context,Metadata * CountNode,int64_t Lo,StorageType Storage,bool ShouldCreate)464eb11fae6SDimitry Andric DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
465eb11fae6SDimitry Andric int64_t Lo, StorageType Storage,
466eb11fae6SDimitry Andric bool ShouldCreate) {
467cfca06d7SDimitry Andric auto *LB = ConstantAsMetadata::get(
468cfca06d7SDimitry Andric ConstantInt::getSigned(Type::getInt64Ty(Context), Lo));
469cfca06d7SDimitry Andric return getImpl(Context, CountNode, LB, nullptr, nullptr, Storage,
470cfca06d7SDimitry Andric ShouldCreate);
4715a5ac124SDimitry Andric }
4725a5ac124SDimitry Andric
getImpl(LLVMContext & Context,Metadata * CountNode,Metadata * LB,Metadata * UB,Metadata * Stride,StorageType Storage,bool ShouldCreate)473cfca06d7SDimitry Andric DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
474cfca06d7SDimitry Andric Metadata *LB, Metadata *UB, Metadata *Stride,
475cfca06d7SDimitry Andric StorageType Storage, bool ShouldCreate) {
476cfca06d7SDimitry Andric DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, LB, UB, Stride));
477cfca06d7SDimitry Andric Metadata *Ops[] = {CountNode, LB, UB, Stride};
478cfca06d7SDimitry Andric DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DISubrange, Ops);
479cfca06d7SDimitry Andric }
480cfca06d7SDimitry Andric
getCount() const481344a3780SDimitry Andric DISubrange::BoundType DISubrange::getCount() const {
482344a3780SDimitry Andric Metadata *CB = getRawCountNode();
483344a3780SDimitry Andric if (!CB)
484344a3780SDimitry Andric return BoundType();
485cfca06d7SDimitry Andric
486344a3780SDimitry Andric assert((isa<ConstantAsMetadata>(CB) || isa<DIVariable>(CB) ||
487344a3780SDimitry Andric isa<DIExpression>(CB)) &&
488344a3780SDimitry Andric "Count must be signed constant or DIVariable or DIExpression");
489cfca06d7SDimitry Andric
490344a3780SDimitry Andric if (auto *MD = dyn_cast<ConstantAsMetadata>(CB))
491344a3780SDimitry Andric return BoundType(cast<ConstantInt>(MD->getValue()));
492cfca06d7SDimitry Andric
493344a3780SDimitry Andric if (auto *MD = dyn_cast<DIVariable>(CB))
494344a3780SDimitry Andric return BoundType(MD);
495344a3780SDimitry Andric
496344a3780SDimitry Andric if (auto *MD = dyn_cast<DIExpression>(CB))
497344a3780SDimitry Andric return BoundType(MD);
498344a3780SDimitry Andric
499344a3780SDimitry Andric return BoundType();
500cfca06d7SDimitry Andric }
501cfca06d7SDimitry Andric
getLowerBound() const502cfca06d7SDimitry Andric DISubrange::BoundType DISubrange::getLowerBound() const {
503cfca06d7SDimitry Andric Metadata *LB = getRawLowerBound();
504cfca06d7SDimitry Andric if (!LB)
505cfca06d7SDimitry Andric return BoundType();
506cfca06d7SDimitry Andric
507cfca06d7SDimitry Andric assert((isa<ConstantAsMetadata>(LB) || isa<DIVariable>(LB) ||
508cfca06d7SDimitry Andric isa<DIExpression>(LB)) &&
509cfca06d7SDimitry Andric "LowerBound must be signed constant or DIVariable or DIExpression");
510cfca06d7SDimitry Andric
511cfca06d7SDimitry Andric if (auto *MD = dyn_cast<ConstantAsMetadata>(LB))
512cfca06d7SDimitry Andric return BoundType(cast<ConstantInt>(MD->getValue()));
513cfca06d7SDimitry Andric
514cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIVariable>(LB))
515cfca06d7SDimitry Andric return BoundType(MD);
516cfca06d7SDimitry Andric
517cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIExpression>(LB))
518cfca06d7SDimitry Andric return BoundType(MD);
519cfca06d7SDimitry Andric
520cfca06d7SDimitry Andric return BoundType();
521cfca06d7SDimitry Andric }
522cfca06d7SDimitry Andric
getUpperBound() const523cfca06d7SDimitry Andric DISubrange::BoundType DISubrange::getUpperBound() const {
524cfca06d7SDimitry Andric Metadata *UB = getRawUpperBound();
525cfca06d7SDimitry Andric if (!UB)
526cfca06d7SDimitry Andric return BoundType();
527cfca06d7SDimitry Andric
528cfca06d7SDimitry Andric assert((isa<ConstantAsMetadata>(UB) || isa<DIVariable>(UB) ||
529cfca06d7SDimitry Andric isa<DIExpression>(UB)) &&
530cfca06d7SDimitry Andric "UpperBound must be signed constant or DIVariable or DIExpression");
531cfca06d7SDimitry Andric
532cfca06d7SDimitry Andric if (auto *MD = dyn_cast<ConstantAsMetadata>(UB))
533cfca06d7SDimitry Andric return BoundType(cast<ConstantInt>(MD->getValue()));
534cfca06d7SDimitry Andric
535cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIVariable>(UB))
536cfca06d7SDimitry Andric return BoundType(MD);
537cfca06d7SDimitry Andric
538cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIExpression>(UB))
539cfca06d7SDimitry Andric return BoundType(MD);
540cfca06d7SDimitry Andric
541cfca06d7SDimitry Andric return BoundType();
542cfca06d7SDimitry Andric }
543cfca06d7SDimitry Andric
getStride() const544cfca06d7SDimitry Andric DISubrange::BoundType DISubrange::getStride() const {
545cfca06d7SDimitry Andric Metadata *ST = getRawStride();
546cfca06d7SDimitry Andric if (!ST)
547cfca06d7SDimitry Andric return BoundType();
548cfca06d7SDimitry Andric
549cfca06d7SDimitry Andric assert((isa<ConstantAsMetadata>(ST) || isa<DIVariable>(ST) ||
550cfca06d7SDimitry Andric isa<DIExpression>(ST)) &&
551cfca06d7SDimitry Andric "Stride must be signed constant or DIVariable or DIExpression");
552cfca06d7SDimitry Andric
553cfca06d7SDimitry Andric if (auto *MD = dyn_cast<ConstantAsMetadata>(ST))
554cfca06d7SDimitry Andric return BoundType(cast<ConstantInt>(MD->getValue()));
555cfca06d7SDimitry Andric
556cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIVariable>(ST))
557cfca06d7SDimitry Andric return BoundType(MD);
558cfca06d7SDimitry Andric
559cfca06d7SDimitry Andric if (auto *MD = dyn_cast<DIExpression>(ST))
560cfca06d7SDimitry Andric return BoundType(MD);
561cfca06d7SDimitry Andric
562cfca06d7SDimitry Andric return BoundType();
563cfca06d7SDimitry Andric }
DIGenericSubrange(LLVMContext & C,StorageType Storage,ArrayRef<Metadata * > Ops)564145449b1SDimitry Andric DIGenericSubrange::DIGenericSubrange(LLVMContext &C, StorageType Storage,
565145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
566145449b1SDimitry Andric : DINode(C, DIGenericSubrangeKind, Storage, dwarf::DW_TAG_generic_subrange,
567145449b1SDimitry Andric Ops) {}
568cfca06d7SDimitry Andric
getImpl(LLVMContext & Context,Metadata * CountNode,Metadata * LB,Metadata * UB,Metadata * Stride,StorageType Storage,bool ShouldCreate)569b60736ecSDimitry Andric DIGenericSubrange *DIGenericSubrange::getImpl(LLVMContext &Context,
570b60736ecSDimitry Andric Metadata *CountNode, Metadata *LB,
571b60736ecSDimitry Andric Metadata *UB, Metadata *Stride,
572b60736ecSDimitry Andric StorageType Storage,
573b60736ecSDimitry Andric bool ShouldCreate) {
574b60736ecSDimitry Andric DEFINE_GETIMPL_LOOKUP(DIGenericSubrange, (CountNode, LB, UB, Stride));
575b60736ecSDimitry Andric Metadata *Ops[] = {CountNode, LB, UB, Stride};
576b60736ecSDimitry Andric DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGenericSubrange, Ops);
577b60736ecSDimitry Andric }
578b60736ecSDimitry Andric
getCount() const579b60736ecSDimitry Andric DIGenericSubrange::BoundType DIGenericSubrange::getCount() const {
580b60736ecSDimitry Andric Metadata *CB = getRawCountNode();
581b60736ecSDimitry Andric if (!CB)
582b60736ecSDimitry Andric return BoundType();
583b60736ecSDimitry Andric
584b60736ecSDimitry Andric assert((isa<DIVariable>(CB) || isa<DIExpression>(CB)) &&
585b60736ecSDimitry Andric "Count must be signed constant or DIVariable or DIExpression");
586b60736ecSDimitry Andric
587b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIVariable>(CB))
588b60736ecSDimitry Andric return BoundType(MD);
589b60736ecSDimitry Andric
590b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIExpression>(CB))
591b60736ecSDimitry Andric return BoundType(MD);
592b60736ecSDimitry Andric
593b60736ecSDimitry Andric return BoundType();
594b60736ecSDimitry Andric }
595b60736ecSDimitry Andric
getLowerBound() const596b60736ecSDimitry Andric DIGenericSubrange::BoundType DIGenericSubrange::getLowerBound() const {
597b60736ecSDimitry Andric Metadata *LB = getRawLowerBound();
598b60736ecSDimitry Andric if (!LB)
599b60736ecSDimitry Andric return BoundType();
600b60736ecSDimitry Andric
601b60736ecSDimitry Andric assert((isa<DIVariable>(LB) || isa<DIExpression>(LB)) &&
602b60736ecSDimitry Andric "LowerBound must be signed constant or DIVariable or DIExpression");
603b60736ecSDimitry Andric
604b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIVariable>(LB))
605b60736ecSDimitry Andric return BoundType(MD);
606b60736ecSDimitry Andric
607b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIExpression>(LB))
608b60736ecSDimitry Andric return BoundType(MD);
609b60736ecSDimitry Andric
610b60736ecSDimitry Andric return BoundType();
611b60736ecSDimitry Andric }
612b60736ecSDimitry Andric
getUpperBound() const613b60736ecSDimitry Andric DIGenericSubrange::BoundType DIGenericSubrange::getUpperBound() const {
614b60736ecSDimitry Andric Metadata *UB = getRawUpperBound();
615b60736ecSDimitry Andric if (!UB)
616b60736ecSDimitry Andric return BoundType();
617b60736ecSDimitry Andric
618b60736ecSDimitry Andric assert((isa<DIVariable>(UB) || isa<DIExpression>(UB)) &&
619b60736ecSDimitry Andric "UpperBound must be signed constant or DIVariable or DIExpression");
620b60736ecSDimitry Andric
621b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIVariable>(UB))
622b60736ecSDimitry Andric return BoundType(MD);
623b60736ecSDimitry Andric
624b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIExpression>(UB))
625b60736ecSDimitry Andric return BoundType(MD);
626b60736ecSDimitry Andric
627b60736ecSDimitry Andric return BoundType();
628b60736ecSDimitry Andric }
629b60736ecSDimitry Andric
getStride() const630b60736ecSDimitry Andric DIGenericSubrange::BoundType DIGenericSubrange::getStride() const {
631b60736ecSDimitry Andric Metadata *ST = getRawStride();
632b60736ecSDimitry Andric if (!ST)
633b60736ecSDimitry Andric return BoundType();
634b60736ecSDimitry Andric
635b60736ecSDimitry Andric assert((isa<DIVariable>(ST) || isa<DIExpression>(ST)) &&
636b60736ecSDimitry Andric "Stride must be signed constant or DIVariable or DIExpression");
637b60736ecSDimitry Andric
638b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIVariable>(ST))
639b60736ecSDimitry Andric return BoundType(MD);
640b60736ecSDimitry Andric
641b60736ecSDimitry Andric if (auto *MD = dyn_cast<DIExpression>(ST))
642b60736ecSDimitry Andric return BoundType(MD);
643b60736ecSDimitry Andric
644b60736ecSDimitry Andric return BoundType();
645b60736ecSDimitry Andric }
646b60736ecSDimitry Andric
DIEnumerator(LLVMContext & C,StorageType Storage,const APInt & Value,bool IsUnsigned,ArrayRef<Metadata * > Ops)647145449b1SDimitry Andric DIEnumerator::DIEnumerator(LLVMContext &C, StorageType Storage,
648145449b1SDimitry Andric const APInt &Value, bool IsUnsigned,
649145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
650145449b1SDimitry Andric : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
651145449b1SDimitry Andric Value(Value) {
652145449b1SDimitry Andric SubclassData32 = IsUnsigned;
653145449b1SDimitry Andric }
getImpl(LLVMContext & Context,const APInt & Value,bool IsUnsigned,MDString * Name,StorageType Storage,bool ShouldCreate)654cfca06d7SDimitry Andric DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,
655eb11fae6SDimitry Andric bool IsUnsigned, MDString *Name,
656eb11fae6SDimitry Andric StorageType Storage, bool ShouldCreate) {
6575a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
658eb11fae6SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));
6595a5ac124SDimitry Andric Metadata *Ops[] = {Name};
660eb11fae6SDimitry Andric DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);
6615a5ac124SDimitry Andric }
6625a5ac124SDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,MDString * Name,uint64_t SizeInBits,uint32_t AlignInBits,unsigned Encoding,DIFlags Flags,StorageType Storage,bool ShouldCreate)6635a5ac124SDimitry Andric DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
6645a5ac124SDimitry Andric MDString *Name, uint64_t SizeInBits,
665b915e9e0SDimitry Andric uint32_t AlignInBits, unsigned Encoding,
666d8e91e46SDimitry Andric DIFlags Flags, StorageType Storage,
667d8e91e46SDimitry Andric bool ShouldCreate) {
6685a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
66901095a5dSDimitry Andric DEFINE_GETIMPL_LOOKUP(DIBasicType,
670d8e91e46SDimitry Andric (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags));
6715a5ac124SDimitry Andric Metadata *Ops[] = {nullptr, nullptr, Name};
672c0981da4SDimitry Andric DEFINE_GETIMPL_STORE(DIBasicType,
673c0981da4SDimitry Andric (Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops);
6745a5ac124SDimitry Andric }
6755a5ac124SDimitry Andric
getSignedness() const676e3b55780SDimitry Andric std::optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {
677eb11fae6SDimitry Andric switch (getEncoding()) {
678eb11fae6SDimitry Andric case dwarf::DW_ATE_signed:
679eb11fae6SDimitry Andric case dwarf::DW_ATE_signed_char:
680eb11fae6SDimitry Andric return Signedness::Signed;
681eb11fae6SDimitry Andric case dwarf::DW_ATE_unsigned:
682eb11fae6SDimitry Andric case dwarf::DW_ATE_unsigned_char:
683eb11fae6SDimitry Andric return Signedness::Unsigned;
684eb11fae6SDimitry Andric default:
685e3b55780SDimitry Andric return std::nullopt;
686eb11fae6SDimitry Andric }
687eb11fae6SDimitry Andric }
688eb11fae6SDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,MDString * Name,Metadata * StringLength,Metadata * StringLengthExp,Metadata * StringLocationExp,uint64_t SizeInBits,uint32_t AlignInBits,unsigned Encoding,StorageType Storage,bool ShouldCreate)689b60736ecSDimitry Andric DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag,
690b60736ecSDimitry Andric MDString *Name, Metadata *StringLength,
691b60736ecSDimitry Andric Metadata *StringLengthExp,
6926f8fc217SDimitry Andric Metadata *StringLocationExp,
693b60736ecSDimitry Andric uint64_t SizeInBits, uint32_t AlignInBits,
694b60736ecSDimitry Andric unsigned Encoding, StorageType Storage,
695b60736ecSDimitry Andric bool ShouldCreate) {
696b60736ecSDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
6976f8fc217SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIStringType,
6986f8fc217SDimitry Andric (Tag, Name, StringLength, StringLengthExp,
6996f8fc217SDimitry Andric StringLocationExp, SizeInBits, AlignInBits, Encoding));
7006f8fc217SDimitry Andric Metadata *Ops[] = {nullptr, nullptr, Name,
7016f8fc217SDimitry Andric StringLength, StringLengthExp, StringLocationExp};
702b60736ecSDimitry Andric DEFINE_GETIMPL_STORE(DIStringType, (Tag, SizeInBits, AlignInBits, Encoding),
703b60736ecSDimitry Andric Ops);
704b60736ecSDimitry Andric }
getClassType() const705145449b1SDimitry Andric DIType *DIDerivedType::getClassType() const {
706145449b1SDimitry Andric assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
707145449b1SDimitry Andric return cast_or_null<DIType>(getExtraData());
708145449b1SDimitry Andric }
getVBPtrOffset() const709145449b1SDimitry Andric uint32_t DIDerivedType::getVBPtrOffset() const {
710145449b1SDimitry Andric assert(getTag() == dwarf::DW_TAG_inheritance);
711145449b1SDimitry Andric if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData()))
712145449b1SDimitry Andric if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue()))
713145449b1SDimitry Andric return static_cast<uint32_t>(CI->getZExtValue());
714145449b1SDimitry Andric return 0;
715145449b1SDimitry Andric }
getStorageOffsetInBits() const716145449b1SDimitry Andric Constant *DIDerivedType::getStorageOffsetInBits() const {
717145449b1SDimitry Andric assert(getTag() == dwarf::DW_TAG_member && isBitField());
718145449b1SDimitry Andric if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
719145449b1SDimitry Andric return C->getValue();
720145449b1SDimitry Andric return nullptr;
721145449b1SDimitry Andric }
722145449b1SDimitry Andric
getConstant() const723145449b1SDimitry Andric Constant *DIDerivedType::getConstant() const {
724b1c73532SDimitry Andric assert((getTag() == dwarf::DW_TAG_member ||
725b1c73532SDimitry Andric getTag() == dwarf::DW_TAG_variable) &&
726b1c73532SDimitry Andric isStaticMember());
727145449b1SDimitry Andric if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
728145449b1SDimitry Andric return C->getValue();
729145449b1SDimitry Andric return nullptr;
730145449b1SDimitry Andric }
getDiscriminantValue() const731145449b1SDimitry Andric Constant *DIDerivedType::getDiscriminantValue() const {
732145449b1SDimitry Andric assert(getTag() == dwarf::DW_TAG_member && !isStaticMember());
733145449b1SDimitry Andric if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
734145449b1SDimitry Andric return C->getValue();
735145449b1SDimitry Andric return nullptr;
736145449b1SDimitry Andric }
737b60736ecSDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,MDString * Name,Metadata * File,unsigned Line,Metadata * Scope,Metadata * BaseType,uint64_t SizeInBits,uint32_t AlignInBits,uint64_t OffsetInBits,std::optional<unsigned> DWARFAddressSpace,std::optional<PtrAuthData> PtrAuthData,DIFlags Flags,Metadata * ExtraData,Metadata * Annotations,StorageType Storage,bool ShouldCreate)738ac9a064cSDimitry Andric DIDerivedType *DIDerivedType::getImpl(
739ac9a064cSDimitry Andric LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
740ac9a064cSDimitry Andric unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
74171d5a254SDimitry Andric uint32_t AlignInBits, uint64_t OffsetInBits,
742ac9a064cSDimitry Andric std::optional<unsigned> DWARFAddressSpace,
743ac9a064cSDimitry Andric std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData,
744ac9a064cSDimitry Andric Metadata *Annotations, StorageType Storage, bool ShouldCreate) {
7455a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
74601095a5dSDimitry Andric DEFINE_GETIMPL_LOOKUP(DIDerivedType,
74701095a5dSDimitry Andric (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
748ac9a064cSDimitry Andric AlignInBits, OffsetInBits, DWARFAddressSpace,
749ac9a064cSDimitry Andric PtrAuthData, Flags, ExtraData, Annotations));
750c0981da4SDimitry Andric Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData, Annotations};
751c0981da4SDimitry Andric DEFINE_GETIMPL_STORE(DIDerivedType,
752c0981da4SDimitry Andric (Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
753ac9a064cSDimitry Andric DWARFAddressSpace, PtrAuthData, Flags),
754c0981da4SDimitry Andric Ops);
7555a5ac124SDimitry Andric }
7565a5ac124SDimitry Andric
757ac9a064cSDimitry Andric std::optional<DIDerivedType::PtrAuthData>
getPtrAuthData() const758ac9a064cSDimitry Andric DIDerivedType::getPtrAuthData() const {
759ac9a064cSDimitry Andric return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type
760ac9a064cSDimitry Andric ? std::optional<PtrAuthData>(PtrAuthData(SubclassData32))
761ac9a064cSDimitry Andric : std::nullopt;
762ac9a064cSDimitry Andric }
763ac9a064cSDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,MDString * Name,Metadata * File,unsigned Line,Metadata * Scope,Metadata * BaseType,uint64_t SizeInBits,uint32_t AlignInBits,uint64_t OffsetInBits,DIFlags Flags,Metadata * Elements,unsigned RuntimeLang,Metadata * VTableHolder,Metadata * TemplateParams,MDString * Identifier,Metadata * Discriminator,Metadata * DataLocation,Metadata * Associated,Metadata * Allocated,Metadata * Rank,Metadata * Annotations,StorageType Storage,bool ShouldCreate)7645a5ac124SDimitry Andric DICompositeType *DICompositeType::getImpl(
7655a5ac124SDimitry Andric LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
7665a5ac124SDimitry Andric unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
767b915e9e0SDimitry Andric uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
7685a5ac124SDimitry Andric Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
769eb11fae6SDimitry Andric Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
770b60736ecSDimitry Andric Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
771c0981da4SDimitry Andric Metadata *Rank, Metadata *Annotations, StorageType Storage,
772c0981da4SDimitry Andric bool ShouldCreate) {
7735a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
77401095a5dSDimitry Andric
77501095a5dSDimitry Andric // Keep this in sync with buildODRType.
776c0981da4SDimitry Andric DEFINE_GETIMPL_LOOKUP(DICompositeType,
777c0981da4SDimitry Andric (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
778c0981da4SDimitry Andric AlignInBits, OffsetInBits, Flags, Elements,
779c0981da4SDimitry Andric RuntimeLang, VTableHolder, TemplateParams, Identifier,
780c0981da4SDimitry Andric Discriminator, DataLocation, Associated, Allocated,
781c0981da4SDimitry Andric Rank, Annotations));
7825a5ac124SDimitry Andric Metadata *Ops[] = {File, Scope, Name, BaseType,
783eb11fae6SDimitry Andric Elements, VTableHolder, TemplateParams, Identifier,
784b60736ecSDimitry Andric Discriminator, DataLocation, Associated, Allocated,
785c0981da4SDimitry Andric Rank, Annotations};
786c0981da4SDimitry Andric DEFINE_GETIMPL_STORE(
787c0981da4SDimitry Andric DICompositeType,
788c0981da4SDimitry Andric (Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags),
7895a5ac124SDimitry Andric Ops);
7905a5ac124SDimitry Andric }
7915a5ac124SDimitry Andric
buildODRType(LLVMContext & Context,MDString & Identifier,unsigned Tag,MDString * Name,Metadata * File,unsigned Line,Metadata * Scope,Metadata * BaseType,uint64_t SizeInBits,uint32_t AlignInBits,uint64_t OffsetInBits,DIFlags Flags,Metadata * Elements,unsigned RuntimeLang,Metadata * VTableHolder,Metadata * TemplateParams,Metadata * Discriminator,Metadata * DataLocation,Metadata * Associated,Metadata * Allocated,Metadata * Rank,Metadata * Annotations)79201095a5dSDimitry Andric DICompositeType *DICompositeType::buildODRType(
79301095a5dSDimitry Andric LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
79401095a5dSDimitry Andric Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
795b915e9e0SDimitry Andric uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
796b915e9e0SDimitry Andric DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
797cfca06d7SDimitry Andric Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
798b60736ecSDimitry Andric Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
799c0981da4SDimitry Andric Metadata *Rank, Metadata *Annotations) {
80001095a5dSDimitry Andric assert(!Identifier.getString().empty() && "Expected valid identifier");
80101095a5dSDimitry Andric if (!Context.isODRUniquingDebugTypes())
80201095a5dSDimitry Andric return nullptr;
80301095a5dSDimitry Andric auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];
80401095a5dSDimitry Andric if (!CT)
80501095a5dSDimitry Andric return CT = DICompositeType::getDistinct(
80601095a5dSDimitry Andric Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
80701095a5dSDimitry Andric AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
808cfca06d7SDimitry Andric VTableHolder, TemplateParams, &Identifier, Discriminator,
809c0981da4SDimitry Andric DataLocation, Associated, Allocated, Rank, Annotations);
810c0981da4SDimitry Andric
811c0981da4SDimitry Andric if (CT->getTag() != Tag)
812c0981da4SDimitry Andric return nullptr;
81301095a5dSDimitry Andric
81401095a5dSDimitry Andric // Only mutate CT if it's a forward declaration and the new operands aren't.
81501095a5dSDimitry Andric assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
81601095a5dSDimitry Andric if (!CT->isForwardDecl() || (Flags & DINode::FlagFwdDecl))
81701095a5dSDimitry Andric return CT;
81801095a5dSDimitry Andric
81901095a5dSDimitry Andric // Mutate CT in place. Keep this in sync with getImpl.
82001095a5dSDimitry Andric CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
82101095a5dSDimitry Andric Flags);
82201095a5dSDimitry Andric Metadata *Ops[] = {File, Scope, Name, BaseType,
823eb11fae6SDimitry Andric Elements, VTableHolder, TemplateParams, &Identifier,
824b60736ecSDimitry Andric Discriminator, DataLocation, Associated, Allocated,
825c0981da4SDimitry Andric Rank, Annotations};
82601095a5dSDimitry Andric assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
82701095a5dSDimitry Andric "Mismatched number of operands");
82801095a5dSDimitry Andric for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
82901095a5dSDimitry Andric if (Ops[I] != CT->getOperand(I))
83001095a5dSDimitry Andric CT->setOperand(I, Ops[I]);
83101095a5dSDimitry Andric return CT;
83201095a5dSDimitry Andric }
83301095a5dSDimitry Andric
getODRType(LLVMContext & Context,MDString & Identifier,unsigned Tag,MDString * Name,Metadata * File,unsigned Line,Metadata * Scope,Metadata * BaseType,uint64_t SizeInBits,uint32_t AlignInBits,uint64_t OffsetInBits,DIFlags Flags,Metadata * Elements,unsigned RuntimeLang,Metadata * VTableHolder,Metadata * TemplateParams,Metadata * Discriminator,Metadata * DataLocation,Metadata * Associated,Metadata * Allocated,Metadata * Rank,Metadata * Annotations)83401095a5dSDimitry Andric DICompositeType *DICompositeType::getODRType(
83501095a5dSDimitry Andric LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
83601095a5dSDimitry Andric Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
837b915e9e0SDimitry Andric uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
838b915e9e0SDimitry Andric DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
839cfca06d7SDimitry Andric Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
840b60736ecSDimitry Andric Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
841c0981da4SDimitry Andric Metadata *Rank, Metadata *Annotations) {
84201095a5dSDimitry Andric assert(!Identifier.getString().empty() && "Expected valid identifier");
84301095a5dSDimitry Andric if (!Context.isODRUniquingDebugTypes())
84401095a5dSDimitry Andric return nullptr;
84501095a5dSDimitry Andric auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier];
846c0981da4SDimitry Andric if (!CT) {
84701095a5dSDimitry Andric CT = DICompositeType::getDistinct(
84801095a5dSDimitry Andric Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
84901095a5dSDimitry Andric AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
850b60736ecSDimitry Andric TemplateParams, &Identifier, Discriminator, DataLocation, Associated,
851c0981da4SDimitry Andric Allocated, Rank, Annotations);
852c0981da4SDimitry Andric } else {
853c0981da4SDimitry Andric if (CT->getTag() != Tag)
854c0981da4SDimitry Andric return nullptr;
855c0981da4SDimitry Andric }
85601095a5dSDimitry Andric return CT;
85701095a5dSDimitry Andric }
85801095a5dSDimitry Andric
getODRTypeIfExists(LLVMContext & Context,MDString & Identifier)85901095a5dSDimitry Andric DICompositeType *DICompositeType::getODRTypeIfExists(LLVMContext &Context,
86001095a5dSDimitry Andric MDString &Identifier) {
86101095a5dSDimitry Andric assert(!Identifier.getString().empty() && "Expected valid identifier");
86201095a5dSDimitry Andric if (!Context.isODRUniquingDebugTypes())
86301095a5dSDimitry Andric return nullptr;
86401095a5dSDimitry Andric return Context.pImpl->DITypeMap->lookup(&Identifier);
86501095a5dSDimitry Andric }
DISubroutineType(LLVMContext & C,StorageType Storage,DIFlags Flags,uint8_t CC,ArrayRef<Metadata * > Ops)866145449b1SDimitry Andric DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage,
867145449b1SDimitry Andric DIFlags Flags, uint8_t CC,
868145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
869145449b1SDimitry Andric : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0,
870145449b1SDimitry Andric 0, 0, 0, Flags, Ops),
871145449b1SDimitry Andric CC(CC) {}
87201095a5dSDimitry Andric
getImpl(LLVMContext & Context,DIFlags Flags,uint8_t CC,Metadata * TypeArray,StorageType Storage,bool ShouldCreate)873b915e9e0SDimitry Andric DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
874b915e9e0SDimitry Andric uint8_t CC, Metadata *TypeArray,
8755a5ac124SDimitry Andric StorageType Storage,
8765a5ac124SDimitry Andric bool ShouldCreate) {
87701095a5dSDimitry Andric DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));
878dd58ef01SDimitry Andric Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray};
87901095a5dSDimitry Andric DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
8805a5ac124SDimitry Andric }
8815a5ac124SDimitry Andric
DIFile(LLVMContext & C,StorageType Storage,std::optional<ChecksumInfo<MDString * >> CS,MDString * Src,ArrayRef<Metadata * > Ops)882145449b1SDimitry Andric DIFile::DIFile(LLVMContext &C, StorageType Storage,
883e3b55780SDimitry Andric std::optional<ChecksumInfo<MDString *>> CS, MDString *Src,
884145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
885145449b1SDimitry Andric : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
886145449b1SDimitry Andric Checksum(CS), Source(Src) {}
887145449b1SDimitry Andric
888044eb2f6SDimitry Andric // FIXME: Implement this string-enum correspondence with a .def file and macros,
889044eb2f6SDimitry Andric // so that the association is explicit rather than implied.
890eb11fae6SDimitry Andric static const char *ChecksumKindName[DIFile::CSK_Last] = {
891b915e9e0SDimitry Andric "CSK_MD5",
892cfca06d7SDimitry Andric "CSK_SHA1",
893cfca06d7SDimitry Andric "CSK_SHA256",
894b915e9e0SDimitry Andric };
895b915e9e0SDimitry Andric
getChecksumKindAsString(ChecksumKind CSKind)896eb11fae6SDimitry Andric StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {
897eb11fae6SDimitry Andric assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
898eb11fae6SDimitry Andric // The first space was originally the CSK_None variant, which is now
899eb11fae6SDimitry Andric // obsolete, but the space is still reserved in ChecksumKind, so we account
900eb11fae6SDimitry Andric // for it here.
901eb11fae6SDimitry Andric return ChecksumKindName[CSKind - 1];
902b915e9e0SDimitry Andric }
903b915e9e0SDimitry Andric
904e3b55780SDimitry Andric std::optional<DIFile::ChecksumKind>
getChecksumKind(StringRef CSKindStr)905e3b55780SDimitry Andric DIFile::getChecksumKind(StringRef CSKindStr) {
906e3b55780SDimitry Andric return StringSwitch<std::optional<DIFile::ChecksumKind>>(CSKindStr)
907eb11fae6SDimitry Andric .Case("CSK_MD5", DIFile::CSK_MD5)
908eb11fae6SDimitry Andric .Case("CSK_SHA1", DIFile::CSK_SHA1)
909cfca06d7SDimitry Andric .Case("CSK_SHA256", DIFile::CSK_SHA256)
910e3b55780SDimitry Andric .Default(std::nullopt);
911b915e9e0SDimitry Andric }
912b915e9e0SDimitry Andric
getImpl(LLVMContext & Context,MDString * Filename,MDString * Directory,std::optional<DIFile::ChecksumInfo<MDString * >> CS,MDString * Source,StorageType Storage,bool ShouldCreate)9135a5ac124SDimitry Andric DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
914eb11fae6SDimitry Andric MDString *Directory,
915e3b55780SDimitry Andric std::optional<DIFile::ChecksumInfo<MDString *>> CS,
916e3b55780SDimitry Andric MDString *Source, StorageType Storage,
9175a5ac124SDimitry Andric bool ShouldCreate) {
9185a5ac124SDimitry Andric assert(isCanonical(Filename) && "Expected canonical MDString");
9195a5ac124SDimitry Andric assert(isCanonical(Directory) && "Expected canonical MDString");
920eb11fae6SDimitry Andric assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
921e3b55780SDimitry Andric // We do *NOT* expect Source to be a canonical MDString because nullptr
922e3b55780SDimitry Andric // means none, so we need something to represent the empty file.
923eb11fae6SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
924e3b55780SDimitry Andric Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, Source};
925eb11fae6SDimitry Andric DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
9265a5ac124SDimitry Andric }
DICompileUnit(LLVMContext & C,StorageType Storage,unsigned SourceLanguage,bool IsOptimized,unsigned RuntimeVersion,unsigned EmissionKind,uint64_t DWOId,bool SplitDebugInlining,bool DebugInfoForProfiling,unsigned NameTableKind,bool RangesBaseAddress,ArrayRef<Metadata * > Ops)927145449b1SDimitry Andric DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage,
928145449b1SDimitry Andric unsigned SourceLanguage, bool IsOptimized,
929145449b1SDimitry Andric unsigned RuntimeVersion, unsigned EmissionKind,
930145449b1SDimitry Andric uint64_t DWOId, bool SplitDebugInlining,
931145449b1SDimitry Andric bool DebugInfoForProfiling, unsigned NameTableKind,
932145449b1SDimitry Andric bool RangesBaseAddress, ArrayRef<Metadata *> Ops)
933145449b1SDimitry Andric : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
934b1c73532SDimitry Andric SourceLanguage(SourceLanguage), RuntimeVersion(RuntimeVersion),
935b1c73532SDimitry Andric DWOId(DWOId), EmissionKind(EmissionKind), NameTableKind(NameTableKind),
936b1c73532SDimitry Andric IsOptimized(IsOptimized), SplitDebugInlining(SplitDebugInlining),
937145449b1SDimitry Andric DebugInfoForProfiling(DebugInfoForProfiling),
938b1c73532SDimitry Andric RangesBaseAddress(RangesBaseAddress) {
939145449b1SDimitry Andric assert(Storage != Uniqued);
940145449b1SDimitry Andric }
9415a5ac124SDimitry Andric
getImpl(LLVMContext & Context,unsigned SourceLanguage,Metadata * File,MDString * Producer,bool IsOptimized,MDString * Flags,unsigned RuntimeVersion,MDString * SplitDebugFilename,unsigned EmissionKind,Metadata * EnumTypes,Metadata * RetainedTypes,Metadata * GlobalVariables,Metadata * ImportedEntities,Metadata * Macros,uint64_t DWOId,bool SplitDebugInlining,bool DebugInfoForProfiling,unsigned NameTableKind,bool RangesBaseAddress,MDString * SysRoot,MDString * SDK,StorageType Storage,bool ShouldCreate)9425a5ac124SDimitry Andric DICompileUnit *DICompileUnit::getImpl(
9435a5ac124SDimitry Andric LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
9445a5ac124SDimitry Andric MDString *Producer, bool IsOptimized, MDString *Flags,
9455a5ac124SDimitry Andric unsigned RuntimeVersion, MDString *SplitDebugFilename,
9465a5ac124SDimitry Andric unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
94701095a5dSDimitry Andric Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,
94871d5a254SDimitry Andric uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,
949cfca06d7SDimitry Andric unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,
950cfca06d7SDimitry Andric MDString *SDK, StorageType Storage, bool ShouldCreate) {
951dd58ef01SDimitry Andric assert(Storage != Uniqued && "Cannot unique DICompileUnit");
9525a5ac124SDimitry Andric assert(isCanonical(Producer) && "Expected canonical MDString");
9535a5ac124SDimitry Andric assert(isCanonical(Flags) && "Expected canonical MDString");
9545a5ac124SDimitry Andric assert(isCanonical(SplitDebugFilename) && "Expected canonical MDString");
955dd58ef01SDimitry Andric
956cfca06d7SDimitry Andric Metadata *Ops[] = {File,
957cfca06d7SDimitry Andric Producer,
958cfca06d7SDimitry Andric Flags,
959cfca06d7SDimitry Andric SplitDebugFilename,
960cfca06d7SDimitry Andric EnumTypes,
961cfca06d7SDimitry Andric RetainedTypes,
962cfca06d7SDimitry Andric GlobalVariables,
963cfca06d7SDimitry Andric ImportedEntities,
964cfca06d7SDimitry Andric Macros,
965cfca06d7SDimitry Andric SysRoot,
966cfca06d7SDimitry Andric SDK};
967e3b55780SDimitry Andric return storeImpl(new (std::size(Ops), Storage) DICompileUnit(
968044eb2f6SDimitry Andric Context, Storage, SourceLanguage, IsOptimized,
969044eb2f6SDimitry Andric RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining,
970d8e91e46SDimitry Andric DebugInfoForProfiling, NameTableKind, RangesBaseAddress,
971d8e91e46SDimitry Andric Ops),
972dd58ef01SDimitry Andric Storage);
9735a5ac124SDimitry Andric }
9745a5ac124SDimitry Andric
975e3b55780SDimitry Andric std::optional<DICompileUnit::DebugEmissionKind>
getEmissionKind(StringRef Str)97601095a5dSDimitry Andric DICompileUnit::getEmissionKind(StringRef Str) {
977e3b55780SDimitry Andric return StringSwitch<std::optional<DebugEmissionKind>>(Str)
97801095a5dSDimitry Andric .Case("NoDebug", NoDebug)
97901095a5dSDimitry Andric .Case("FullDebug", FullDebug)
98001095a5dSDimitry Andric .Case("LineTablesOnly", LineTablesOnly)
981d8e91e46SDimitry Andric .Case("DebugDirectivesOnly", DebugDirectivesOnly)
982e3b55780SDimitry Andric .Default(std::nullopt);
983d8e91e46SDimitry Andric }
984d8e91e46SDimitry Andric
985e3b55780SDimitry Andric std::optional<DICompileUnit::DebugNameTableKind>
getNameTableKind(StringRef Str)986d8e91e46SDimitry Andric DICompileUnit::getNameTableKind(StringRef Str) {
987e3b55780SDimitry Andric return StringSwitch<std::optional<DebugNameTableKind>>(Str)
988d8e91e46SDimitry Andric .Case("Default", DebugNameTableKind::Default)
989d8e91e46SDimitry Andric .Case("GNU", DebugNameTableKind::GNU)
9907fa27ce4SDimitry Andric .Case("Apple", DebugNameTableKind::Apple)
991d8e91e46SDimitry Andric .Case("None", DebugNameTableKind::None)
992e3b55780SDimitry Andric .Default(std::nullopt);
99301095a5dSDimitry Andric }
99401095a5dSDimitry Andric
emissionKindString(DebugEmissionKind EK)995eb11fae6SDimitry Andric const char *DICompileUnit::emissionKindString(DebugEmissionKind EK) {
99601095a5dSDimitry Andric switch (EK) {
997c0981da4SDimitry Andric case NoDebug:
998c0981da4SDimitry Andric return "NoDebug";
999c0981da4SDimitry Andric case FullDebug:
1000c0981da4SDimitry Andric return "FullDebug";
1001c0981da4SDimitry Andric case LineTablesOnly:
1002c0981da4SDimitry Andric return "LineTablesOnly";
1003c0981da4SDimitry Andric case DebugDirectivesOnly:
1004c0981da4SDimitry Andric return "DebugDirectivesOnly";
1005d8e91e46SDimitry Andric }
1006d8e91e46SDimitry Andric return nullptr;
1007d8e91e46SDimitry Andric }
1008d8e91e46SDimitry Andric
nameTableKindString(DebugNameTableKind NTK)1009d8e91e46SDimitry Andric const char *DICompileUnit::nameTableKindString(DebugNameTableKind NTK) {
1010d8e91e46SDimitry Andric switch (NTK) {
1011d8e91e46SDimitry Andric case DebugNameTableKind::Default:
1012d8e91e46SDimitry Andric return nullptr;
1013d8e91e46SDimitry Andric case DebugNameTableKind::GNU:
1014d8e91e46SDimitry Andric return "GNU";
10157fa27ce4SDimitry Andric case DebugNameTableKind::Apple:
10167fa27ce4SDimitry Andric return "Apple";
1017d8e91e46SDimitry Andric case DebugNameTableKind::None:
1018d8e91e46SDimitry Andric return "None";
101901095a5dSDimitry Andric }
102001095a5dSDimitry Andric return nullptr;
102101095a5dSDimitry Andric }
DISubprogram(LLVMContext & C,StorageType Storage,unsigned Line,unsigned ScopeLine,unsigned VirtualIndex,int ThisAdjustment,DIFlags Flags,DISPFlags SPFlags,ArrayRef<Metadata * > Ops)1022145449b1SDimitry Andric DISubprogram::DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line,
1023145449b1SDimitry Andric unsigned ScopeLine, unsigned VirtualIndex,
1024145449b1SDimitry Andric int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags,
1025145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
1026145449b1SDimitry Andric : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops),
1027145449b1SDimitry Andric Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex),
1028145449b1SDimitry Andric ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) {
1029145449b1SDimitry Andric static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range");
1030145449b1SDimitry Andric }
1031145449b1SDimitry Andric DISubprogram::DISPFlags
toSPFlags(bool IsLocalToUnit,bool IsDefinition,bool IsOptimized,unsigned Virtuality,bool IsMainSubprogram)1032145449b1SDimitry Andric DISubprogram::toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized,
1033145449b1SDimitry Andric unsigned Virtuality, bool IsMainSubprogram) {
1034145449b1SDimitry Andric // We're assuming virtuality is the low-order field.
1035145449b1SDimitry Andric static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) &&
1036145449b1SDimitry Andric int(SPFlagPureVirtual) ==
1037145449b1SDimitry Andric int(dwarf::DW_VIRTUALITY_pure_virtual),
1038145449b1SDimitry Andric "Virtuality constant mismatch");
1039145449b1SDimitry Andric return static_cast<DISPFlags>(
1040145449b1SDimitry Andric (Virtuality & SPFlagVirtuality) |
1041145449b1SDimitry Andric (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) |
1042145449b1SDimitry Andric (IsDefinition ? SPFlagDefinition : SPFlagZero) |
1043145449b1SDimitry Andric (IsOptimized ? SPFlagOptimized : SPFlagZero) |
1044145449b1SDimitry Andric (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero));
1045145449b1SDimitry Andric }
104601095a5dSDimitry Andric
getSubprogram() const10475a5ac124SDimitry Andric DISubprogram *DILocalScope::getSubprogram() const {
10485a5ac124SDimitry Andric if (auto *Block = dyn_cast<DILexicalBlockBase>(this))
10495a5ac124SDimitry Andric return Block->getScope()->getSubprogram();
10505a5ac124SDimitry Andric return const_cast<DISubprogram *>(cast<DISubprogram>(this));
10515a5ac124SDimitry Andric }
10525a5ac124SDimitry Andric
getNonLexicalBlockFileScope() const105301095a5dSDimitry Andric DILocalScope *DILocalScope::getNonLexicalBlockFileScope() const {
105401095a5dSDimitry Andric if (auto *File = dyn_cast<DILexicalBlockFile>(this))
105501095a5dSDimitry Andric return File->getScope()->getNonLexicalBlockFileScope();
105601095a5dSDimitry Andric return const_cast<DILocalScope *>(this);
105701095a5dSDimitry Andric }
105801095a5dSDimitry Andric
cloneScopeForSubprogram(DILocalScope & RootScope,DISubprogram & NewSP,LLVMContext & Ctx,DenseMap<const MDNode *,MDNode * > & Cache)1059e3b55780SDimitry Andric DILocalScope *DILocalScope::cloneScopeForSubprogram(
1060e3b55780SDimitry Andric DILocalScope &RootScope, DISubprogram &NewSP, LLVMContext &Ctx,
1061e3b55780SDimitry Andric DenseMap<const MDNode *, MDNode *> &Cache) {
1062e3b55780SDimitry Andric SmallVector<DIScope *> ScopeChain;
1063e3b55780SDimitry Andric DIScope *CachedResult = nullptr;
1064e3b55780SDimitry Andric
1065e3b55780SDimitry Andric for (DIScope *Scope = &RootScope; !isa<DISubprogram>(Scope);
1066e3b55780SDimitry Andric Scope = Scope->getScope()) {
1067e3b55780SDimitry Andric if (auto It = Cache.find(Scope); It != Cache.end()) {
1068e3b55780SDimitry Andric CachedResult = cast<DIScope>(It->second);
1069e3b55780SDimitry Andric break;
1070e3b55780SDimitry Andric }
1071e3b55780SDimitry Andric ScopeChain.push_back(Scope);
1072e3b55780SDimitry Andric }
1073e3b55780SDimitry Andric
1074e3b55780SDimitry Andric // Recreate the scope chain, bottom-up, starting at the new subprogram (or a
1075e3b55780SDimitry Andric // cached result).
1076e3b55780SDimitry Andric DIScope *UpdatedScope = CachedResult ? CachedResult : &NewSP;
1077e3b55780SDimitry Andric for (DIScope *ScopeToUpdate : reverse(ScopeChain)) {
1078e3b55780SDimitry Andric TempMDNode ClonedScope = ScopeToUpdate->clone();
1079e3b55780SDimitry Andric cast<DILexicalBlockBase>(*ClonedScope).replaceScope(UpdatedScope);
1080e3b55780SDimitry Andric UpdatedScope =
1081e3b55780SDimitry Andric cast<DIScope>(MDNode::replaceWithUniqued(std::move(ClonedScope)));
1082e3b55780SDimitry Andric Cache[ScopeToUpdate] = UpdatedScope;
1083e3b55780SDimitry Andric }
1084e3b55780SDimitry Andric
1085e3b55780SDimitry Andric return cast<DILocalScope>(UpdatedScope);
1086e3b55780SDimitry Andric }
1087e3b55780SDimitry Andric
getFlag(StringRef Flag)1088d8e91e46SDimitry Andric DISubprogram::DISPFlags DISubprogram::getFlag(StringRef Flag) {
1089d8e91e46SDimitry Andric return StringSwitch<DISPFlags>(Flag)
1090d8e91e46SDimitry Andric #define HANDLE_DISP_FLAG(ID, NAME) .Case("DISPFlag" #NAME, SPFlag##NAME)
1091d8e91e46SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
1092d8e91e46SDimitry Andric .Default(SPFlagZero);
1093d8e91e46SDimitry Andric }
1094d8e91e46SDimitry Andric
getFlagString(DISPFlags Flag)1095d8e91e46SDimitry Andric StringRef DISubprogram::getFlagString(DISPFlags Flag) {
1096d8e91e46SDimitry Andric switch (Flag) {
1097d8e91e46SDimitry Andric // Appease a warning.
1098d8e91e46SDimitry Andric case SPFlagVirtuality:
1099d8e91e46SDimitry Andric return "";
1100d8e91e46SDimitry Andric #define HANDLE_DISP_FLAG(ID, NAME) \
1101d8e91e46SDimitry Andric case SPFlag##NAME: \
1102d8e91e46SDimitry Andric return "DISPFlag" #NAME;
1103d8e91e46SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
1104d8e91e46SDimitry Andric }
1105d8e91e46SDimitry Andric return "";
1106d8e91e46SDimitry Andric }
1107d8e91e46SDimitry Andric
1108d8e91e46SDimitry Andric DISubprogram::DISPFlags
splitFlags(DISPFlags Flags,SmallVectorImpl<DISPFlags> & SplitFlags)1109d8e91e46SDimitry Andric DISubprogram::splitFlags(DISPFlags Flags,
1110d8e91e46SDimitry Andric SmallVectorImpl<DISPFlags> &SplitFlags) {
1111d8e91e46SDimitry Andric // Multi-bit fields can require special handling. In our case, however, the
1112d8e91e46SDimitry Andric // only multi-bit field is virtuality, and all its values happen to be
1113d8e91e46SDimitry Andric // single-bit values, so the right behavior just falls out.
1114d8e91e46SDimitry Andric #define HANDLE_DISP_FLAG(ID, NAME) \
1115d8e91e46SDimitry Andric if (DISPFlags Bit = Flags & SPFlag##NAME) { \
1116d8e91e46SDimitry Andric SplitFlags.push_back(Bit); \
1117d8e91e46SDimitry Andric Flags &= ~Bit; \
1118d8e91e46SDimitry Andric }
1119d8e91e46SDimitry Andric #include "llvm/IR/DebugInfoFlags.def"
1120d8e91e46SDimitry Andric return Flags;
1121d8e91e46SDimitry Andric }
1122d8e91e46SDimitry Andric
getImpl(LLVMContext & Context,Metadata * Scope,MDString * Name,MDString * LinkageName,Metadata * File,unsigned Line,Metadata * Type,unsigned ScopeLine,Metadata * ContainingType,unsigned VirtualIndex,int ThisAdjustment,DIFlags Flags,DISPFlags SPFlags,Metadata * Unit,Metadata * TemplateParams,Metadata * Declaration,Metadata * RetainedNodes,Metadata * ThrownTypes,Metadata * Annotations,MDString * TargetFuncName,StorageType Storage,bool ShouldCreate)11235a5ac124SDimitry Andric DISubprogram *DISubprogram::getImpl(
11245a5ac124SDimitry Andric LLVMContext &Context, Metadata *Scope, MDString *Name,
11255a5ac124SDimitry Andric MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
1126d8e91e46SDimitry Andric unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex,
1127d8e91e46SDimitry Andric int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit,
1128eb11fae6SDimitry Andric Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
1129145449b1SDimitry Andric Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName,
1130145449b1SDimitry Andric StorageType Storage, bool ShouldCreate) {
11315a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
11325a5ac124SDimitry Andric assert(isCanonical(LinkageName) && "Expected canonical MDString");
1133145449b1SDimitry Andric assert(isCanonical(TargetFuncName) && "Expected canonical MDString");
1134d8e91e46SDimitry Andric DEFINE_GETIMPL_LOOKUP(DISubprogram,
1135d8e91e46SDimitry Andric (Scope, Name, LinkageName, File, Line, Type, ScopeLine,
1136d8e91e46SDimitry Andric ContainingType, VirtualIndex, ThisAdjustment, Flags,
1137d8e91e46SDimitry Andric SPFlags, Unit, TemplateParams, Declaration,
1138145449b1SDimitry Andric RetainedNodes, ThrownTypes, Annotations,
1139145449b1SDimitry Andric TargetFuncName));
1140145449b1SDimitry Andric SmallVector<Metadata *, 13> Ops = {
1141c0981da4SDimitry Andric File, Scope, Name, LinkageName,
1142c0981da4SDimitry Andric Type, Unit, Declaration, RetainedNodes,
1143145449b1SDimitry Andric ContainingType, TemplateParams, ThrownTypes, Annotations,
1144145449b1SDimitry Andric TargetFuncName};
1145145449b1SDimitry Andric if (!TargetFuncName) {
1146145449b1SDimitry Andric Ops.pop_back();
1147c0981da4SDimitry Andric if (!Annotations) {
1148c0981da4SDimitry Andric Ops.pop_back();
1149a303c417SDimitry Andric if (!ThrownTypes) {
1150a303c417SDimitry Andric Ops.pop_back();
1151a303c417SDimitry Andric if (!TemplateParams) {
1152a303c417SDimitry Andric Ops.pop_back();
1153a303c417SDimitry Andric if (!ContainingType)
1154a303c417SDimitry Andric Ops.pop_back();
1155a303c417SDimitry Andric }
1156a303c417SDimitry Andric }
1157c0981da4SDimitry Andric }
1158145449b1SDimitry Andric }
1159d8e91e46SDimitry Andric DEFINE_GETIMPL_STORE_N(
1160d8e91e46SDimitry Andric DISubprogram,
1161d8e91e46SDimitry Andric (Line, ScopeLine, VirtualIndex, ThisAdjustment, Flags, SPFlags), Ops,
1162d8e91e46SDimitry Andric Ops.size());
11635a5ac124SDimitry Andric }
11645a5ac124SDimitry Andric
describes(const Function * F) const11655a5ac124SDimitry Andric bool DISubprogram::describes(const Function *F) const {
11665a5ac124SDimitry Andric assert(F && "Invalid function");
1167cfca06d7SDimitry Andric return F->getSubprogram() == this;
11685a5ac124SDimitry Andric }
DILexicalBlockBase(LLVMContext & C,unsigned ID,StorageType Storage,ArrayRef<Metadata * > Ops)1169145449b1SDimitry Andric DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID,
1170145449b1SDimitry Andric StorageType Storage,
1171145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
1172145449b1SDimitry Andric : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}
11735a5ac124SDimitry Andric
getImpl(LLVMContext & Context,Metadata * Scope,Metadata * File,unsigned Line,unsigned Column,StorageType Storage,bool ShouldCreate)11745a5ac124SDimitry Andric DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope,
11755a5ac124SDimitry Andric Metadata *File, unsigned Line,
11765a5ac124SDimitry Andric unsigned Column, StorageType Storage,
11775a5ac124SDimitry Andric bool ShouldCreate) {
1178dd58ef01SDimitry Andric // Fixup column.
1179dd58ef01SDimitry Andric adjustColumn(Column);
1180dd58ef01SDimitry Andric
11815a5ac124SDimitry Andric assert(Scope && "Expected scope");
11825a5ac124SDimitry Andric DEFINE_GETIMPL_LOOKUP(DILexicalBlock, (Scope, File, Line, Column));
11835a5ac124SDimitry Andric Metadata *Ops[] = {File, Scope};
11845a5ac124SDimitry Andric DEFINE_GETIMPL_STORE(DILexicalBlock, (Line, Column), Ops);
11855a5ac124SDimitry Andric }
11865a5ac124SDimitry Andric
getImpl(LLVMContext & Context,Metadata * Scope,Metadata * File,unsigned Discriminator,StorageType Storage,bool ShouldCreate)11875a5ac124SDimitry Andric DILexicalBlockFile *DILexicalBlockFile::getImpl(LLVMContext &Context,
11885a5ac124SDimitry Andric Metadata *Scope, Metadata *File,
11895a5ac124SDimitry Andric unsigned Discriminator,
11905a5ac124SDimitry Andric StorageType Storage,
11915a5ac124SDimitry Andric bool ShouldCreate) {
11925a5ac124SDimitry Andric assert(Scope && "Expected scope");
11935a5ac124SDimitry Andric DEFINE_GETIMPL_LOOKUP(DILexicalBlockFile, (Scope, File, Discriminator));
11945a5ac124SDimitry Andric Metadata *Ops[] = {File, Scope};
11955a5ac124SDimitry Andric DEFINE_GETIMPL_STORE(DILexicalBlockFile, (Discriminator), Ops);
11965a5ac124SDimitry Andric }
11975a5ac124SDimitry Andric
DINamespace(LLVMContext & Context,StorageType Storage,bool ExportSymbols,ArrayRef<Metadata * > Ops)1198145449b1SDimitry Andric DINamespace::DINamespace(LLVMContext &Context, StorageType Storage,
1199145449b1SDimitry Andric bool ExportSymbols, ArrayRef<Metadata *> Ops)
1200b1c73532SDimitry Andric : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops) {
1201b1c73532SDimitry Andric SubclassData1 = ExportSymbols;
1202b1c73532SDimitry Andric }
getImpl(LLVMContext & Context,Metadata * Scope,MDString * Name,bool ExportSymbols,StorageType Storage,bool ShouldCreate)12035a5ac124SDimitry Andric DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope,
1204a303c417SDimitry Andric MDString *Name, bool ExportSymbols,
1205a303c417SDimitry Andric StorageType Storage, bool ShouldCreate) {
12065a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1207a303c417SDimitry Andric DEFINE_GETIMPL_LOOKUP(DINamespace, (Scope, Name, ExportSymbols));
1208a303c417SDimitry Andric // The nullptr is for DIScope's File operand. This should be refactored.
1209a303c417SDimitry Andric Metadata *Ops[] = {nullptr, Scope, Name};
1210a303c417SDimitry Andric DEFINE_GETIMPL_STORE(DINamespace, (ExportSymbols), Ops);
12115a5ac124SDimitry Andric }
12125a5ac124SDimitry Andric
DICommonBlock(LLVMContext & Context,StorageType Storage,unsigned LineNo,ArrayRef<Metadata * > Ops)1213145449b1SDimitry Andric DICommonBlock::DICommonBlock(LLVMContext &Context, StorageType Storage,
1214145449b1SDimitry Andric unsigned LineNo, ArrayRef<Metadata *> Ops)
1215145449b1SDimitry Andric : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block,
1216b1c73532SDimitry Andric Ops) {
1217b1c73532SDimitry Andric SubclassData32 = LineNo;
1218b1c73532SDimitry Andric }
getImpl(LLVMContext & Context,Metadata * Scope,Metadata * Decl,MDString * Name,Metadata * File,unsigned LineNo,StorageType Storage,bool ShouldCreate)1219e6d15924SDimitry Andric DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope,
1220e6d15924SDimitry Andric Metadata *Decl, MDString *Name,
1221e6d15924SDimitry Andric Metadata *File, unsigned LineNo,
1222e6d15924SDimitry Andric StorageType Storage, bool ShouldCreate) {
1223e6d15924SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1224e6d15924SDimitry Andric DEFINE_GETIMPL_LOOKUP(DICommonBlock, (Scope, Decl, Name, File, LineNo));
1225e6d15924SDimitry Andric // The nullptr is for DIScope's File operand. This should be refactored.
1226e6d15924SDimitry Andric Metadata *Ops[] = {Scope, Decl, Name, File};
1227e6d15924SDimitry Andric DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo), Ops);
1228e6d15924SDimitry Andric }
1229e6d15924SDimitry Andric
DIModule(LLVMContext & Context,StorageType Storage,unsigned LineNo,bool IsDecl,ArrayRef<Metadata * > Ops)1230145449b1SDimitry Andric DIModule::DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo,
1231145449b1SDimitry Andric bool IsDecl, ArrayRef<Metadata *> Ops)
1232b1c73532SDimitry Andric : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {
1233b1c73532SDimitry Andric SubclassData1 = IsDecl;
1234b1c73532SDimitry Andric SubclassData32 = LineNo;
1235b1c73532SDimitry Andric }
getImpl(LLVMContext & Context,Metadata * File,Metadata * Scope,MDString * Name,MDString * ConfigurationMacros,MDString * IncludePath,MDString * APINotesFile,unsigned LineNo,bool IsDecl,StorageType Storage,bool ShouldCreate)1236cfca06d7SDimitry Andric DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File,
1237cfca06d7SDimitry Andric Metadata *Scope, MDString *Name,
1238cfca06d7SDimitry Andric MDString *ConfigurationMacros,
1239cfca06d7SDimitry Andric MDString *IncludePath, MDString *APINotesFile,
1240b60736ecSDimitry Andric unsigned LineNo, bool IsDecl, StorageType Storage,
12415a5ac124SDimitry Andric bool ShouldCreate) {
12425a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1243cfca06d7SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIModule, (File, Scope, Name, ConfigurationMacros,
1244b60736ecSDimitry Andric IncludePath, APINotesFile, LineNo, IsDecl));
1245cfca06d7SDimitry Andric Metadata *Ops[] = {File, Scope, Name, ConfigurationMacros,
1246cfca06d7SDimitry Andric IncludePath, APINotesFile};
1247b60736ecSDimitry Andric DEFINE_GETIMPL_STORE(DIModule, (LineNo, IsDecl), Ops);
1248cfca06d7SDimitry Andric }
DITemplateTypeParameter(LLVMContext & Context,StorageType Storage,bool IsDefault,ArrayRef<Metadata * > Ops)1249145449b1SDimitry Andric DITemplateTypeParameter::DITemplateTypeParameter(LLVMContext &Context,
1250145449b1SDimitry Andric StorageType Storage,
1251145449b1SDimitry Andric bool IsDefault,
1252145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
1253145449b1SDimitry Andric : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,
1254145449b1SDimitry Andric dwarf::DW_TAG_template_type_parameter, IsDefault,
1255145449b1SDimitry Andric Ops) {}
1256cfca06d7SDimitry Andric
1257cfca06d7SDimitry Andric DITemplateTypeParameter *
getImpl(LLVMContext & Context,MDString * Name,Metadata * Type,bool isDefault,StorageType Storage,bool ShouldCreate)1258cfca06d7SDimitry Andric DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name,
1259cfca06d7SDimitry Andric Metadata *Type, bool isDefault,
1260cfca06d7SDimitry Andric StorageType Storage, bool ShouldCreate) {
1261cfca06d7SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1262cfca06d7SDimitry Andric DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type, isDefault));
12635a5ac124SDimitry Andric Metadata *Ops[] = {Name, Type};
1264cfca06d7SDimitry Andric DEFINE_GETIMPL_STORE(DITemplateTypeParameter, (isDefault), Ops);
12655a5ac124SDimitry Andric }
12665a5ac124SDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,MDString * Name,Metadata * Type,bool isDefault,Metadata * Value,StorageType Storage,bool ShouldCreate)12675a5ac124SDimitry Andric DITemplateValueParameter *DITemplateValueParameter::getImpl(
12685a5ac124SDimitry Andric LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type,
1269cfca06d7SDimitry Andric bool isDefault, Metadata *Value, StorageType Storage, bool ShouldCreate) {
12705a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1271cfca06d7SDimitry Andric DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter,
1272cfca06d7SDimitry Andric (Tag, Name, Type, isDefault, Value));
12735a5ac124SDimitry Andric Metadata *Ops[] = {Name, Type, Value};
1274cfca06d7SDimitry Andric DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag, isDefault), Ops);
12755a5ac124SDimitry Andric }
12765a5ac124SDimitry Andric
12775a5ac124SDimitry Andric DIGlobalVariable *
getImpl(LLVMContext & Context,Metadata * Scope,MDString * Name,MDString * LinkageName,Metadata * File,unsigned Line,Metadata * Type,bool IsLocalToUnit,bool IsDefinition,Metadata * StaticDataMemberDeclaration,Metadata * TemplateParams,uint32_t AlignInBits,Metadata * Annotations,StorageType Storage,bool ShouldCreate)12785a5ac124SDimitry Andric DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
12795a5ac124SDimitry Andric MDString *LinkageName, Metadata *File, unsigned Line,
12805a5ac124SDimitry Andric Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
12815a5ac124SDimitry Andric Metadata *StaticDataMemberDeclaration,
1282d8e91e46SDimitry Andric Metadata *TemplateParams, uint32_t AlignInBits,
1283c0981da4SDimitry Andric Metadata *Annotations, StorageType Storage,
1284c0981da4SDimitry Andric bool ShouldCreate) {
12855a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
12865a5ac124SDimitry Andric assert(isCanonical(LinkageName) && "Expected canonical MDString");
1287c0981da4SDimitry Andric DEFINE_GETIMPL_LOOKUP(
1288c0981da4SDimitry Andric DIGlobalVariable,
1289c0981da4SDimitry Andric (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition,
1290c0981da4SDimitry Andric StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations));
1291d8e91e46SDimitry Andric Metadata *Ops[] = {Scope,
1292d8e91e46SDimitry Andric Name,
1293d8e91e46SDimitry Andric File,
1294d8e91e46SDimitry Andric Type,
1295d8e91e46SDimitry Andric Name,
1296d8e91e46SDimitry Andric LinkageName,
1297d8e91e46SDimitry Andric StaticDataMemberDeclaration,
1298c0981da4SDimitry Andric TemplateParams,
1299c0981da4SDimitry Andric Annotations};
1300b915e9e0SDimitry Andric DEFINE_GETIMPL_STORE(DIGlobalVariable,
1301d8e91e46SDimitry Andric (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops);
13025a5ac124SDimitry Andric }
13035a5ac124SDimitry Andric
1304c0981da4SDimitry Andric DILocalVariable *
getImpl(LLVMContext & Context,Metadata * Scope,MDString * Name,Metadata * File,unsigned Line,Metadata * Type,unsigned Arg,DIFlags Flags,uint32_t AlignInBits,Metadata * Annotations,StorageType Storage,bool ShouldCreate)1305c0981da4SDimitry Andric DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
1306c0981da4SDimitry Andric Metadata *File, unsigned Line, Metadata *Type,
1307c0981da4SDimitry Andric unsigned Arg, DIFlags Flags, uint32_t AlignInBits,
1308c0981da4SDimitry Andric Metadata *Annotations, StorageType Storage,
13095a5ac124SDimitry Andric bool ShouldCreate) {
13105a5ac124SDimitry Andric // 64K ought to be enough for any frontend.
13115a5ac124SDimitry Andric assert(Arg <= UINT16_MAX && "Expected argument number to fit in 16-bits");
13125a5ac124SDimitry Andric
13135a5ac124SDimitry Andric assert(Scope && "Expected scope");
13145a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1315c0981da4SDimitry Andric DEFINE_GETIMPL_LOOKUP(DILocalVariable, (Scope, Name, File, Line, Type, Arg,
1316c0981da4SDimitry Andric Flags, AlignInBits, Annotations));
1317c0981da4SDimitry Andric Metadata *Ops[] = {Scope, Name, File, Type, Annotations};
1318b915e9e0SDimitry Andric DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops);
13195a5ac124SDimitry Andric }
13205a5ac124SDimitry Andric
DIVariable(LLVMContext & C,unsigned ID,StorageType Storage,signed Line,ArrayRef<Metadata * > Ops,uint32_t AlignInBits)1321145449b1SDimitry Andric DIVariable::DIVariable(LLVMContext &C, unsigned ID, StorageType Storage,
1322145449b1SDimitry Andric signed Line, ArrayRef<Metadata *> Ops,
1323145449b1SDimitry Andric uint32_t AlignInBits)
1324b1c73532SDimitry Andric : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line) {
1325b1c73532SDimitry Andric SubclassData32 = AlignInBits;
1326b1c73532SDimitry Andric }
getSizeInBits() const1327e3b55780SDimitry Andric std::optional<uint64_t> DIVariable::getSizeInBits() const {
1328044eb2f6SDimitry Andric // This is used by the Verifier so be mindful of broken types.
1329044eb2f6SDimitry Andric const Metadata *RawType = getRawType();
1330044eb2f6SDimitry Andric while (RawType) {
1331044eb2f6SDimitry Andric // Try to get the size directly.
1332044eb2f6SDimitry Andric if (auto *T = dyn_cast<DIType>(RawType))
1333044eb2f6SDimitry Andric if (uint64_t Size = T->getSizeInBits())
1334044eb2f6SDimitry Andric return Size;
1335044eb2f6SDimitry Andric
1336044eb2f6SDimitry Andric if (auto *DT = dyn_cast<DIDerivedType>(RawType)) {
1337044eb2f6SDimitry Andric // Look at the base type.
1338044eb2f6SDimitry Andric RawType = DT->getRawBaseType();
1339044eb2f6SDimitry Andric continue;
1340044eb2f6SDimitry Andric }
1341044eb2f6SDimitry Andric
1342044eb2f6SDimitry Andric // Missing type or size.
1343044eb2f6SDimitry Andric break;
1344044eb2f6SDimitry Andric }
1345044eb2f6SDimitry Andric
1346044eb2f6SDimitry Andric // Fail gracefully.
1347e3b55780SDimitry Andric return std::nullopt;
1348044eb2f6SDimitry Andric }
1349044eb2f6SDimitry Andric
DILabel(LLVMContext & C,StorageType Storage,unsigned Line,ArrayRef<Metadata * > Ops)1350145449b1SDimitry Andric DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line,
1351145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
1352b1c73532SDimitry Andric : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops) {
1353b1c73532SDimitry Andric SubclassData32 = Line;
1354b1c73532SDimitry Andric }
getImpl(LLVMContext & Context,Metadata * Scope,MDString * Name,Metadata * File,unsigned Line,StorageType Storage,bool ShouldCreate)1355c0981da4SDimitry Andric DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
1356c0981da4SDimitry Andric Metadata *File, unsigned Line, StorageType Storage,
1357eb11fae6SDimitry Andric bool ShouldCreate) {
1358eb11fae6SDimitry Andric assert(Scope && "Expected scope");
1359eb11fae6SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
1360c0981da4SDimitry Andric DEFINE_GETIMPL_LOOKUP(DILabel, (Scope, Name, File, Line));
1361eb11fae6SDimitry Andric Metadata *Ops[] = {Scope, Name, File};
1362eb11fae6SDimitry Andric DEFINE_GETIMPL_STORE(DILabel, (Line), Ops);
1363eb11fae6SDimitry Andric }
1364eb11fae6SDimitry Andric
getImpl(LLVMContext & Context,ArrayRef<uint64_t> Elements,StorageType Storage,bool ShouldCreate)13655a5ac124SDimitry Andric DIExpression *DIExpression::getImpl(LLVMContext &Context,
13665a5ac124SDimitry Andric ArrayRef<uint64_t> Elements,
13675a5ac124SDimitry Andric StorageType Storage, bool ShouldCreate) {
13685a5ac124SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements));
13695a5ac124SDimitry Andric DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements));
13705a5ac124SDimitry Andric }
isEntryValue() const1371145449b1SDimitry Andric bool DIExpression::isEntryValue() const {
1372b1c73532SDimitry Andric if (auto singleLocElts = getSingleLocationExpressionElements()) {
1373b1c73532SDimitry Andric return singleLocElts->size() > 0 &&
1374b1c73532SDimitry Andric (*singleLocElts)[0] == dwarf::DW_OP_LLVM_entry_value;
1375b1c73532SDimitry Andric }
1376b1c73532SDimitry Andric return false;
1377145449b1SDimitry Andric }
startsWithDeref() const1378145449b1SDimitry Andric bool DIExpression::startsWithDeref() const {
1379b1c73532SDimitry Andric if (auto singleLocElts = getSingleLocationExpressionElements())
1380b1c73532SDimitry Andric return singleLocElts->size() > 0 &&
1381b1c73532SDimitry Andric (*singleLocElts)[0] == dwarf::DW_OP_deref;
1382b1c73532SDimitry Andric return false;
1383145449b1SDimitry Andric }
isDeref() const13847fa27ce4SDimitry Andric bool DIExpression::isDeref() const {
1385b1c73532SDimitry Andric if (auto singleLocElts = getSingleLocationExpressionElements())
1386b1c73532SDimitry Andric return singleLocElts->size() == 1 &&
1387b1c73532SDimitry Andric (*singleLocElts)[0] == dwarf::DW_OP_deref;
1388b1c73532SDimitry Andric return false;
13897fa27ce4SDimitry Andric }
13905a5ac124SDimitry Andric
getImpl(LLVMContext & Context,StorageType Storage,bool ShouldCreate)1391e3b55780SDimitry Andric DIAssignID *DIAssignID::getImpl(LLVMContext &Context, StorageType Storage,
1392e3b55780SDimitry Andric bool ShouldCreate) {
1393e3b55780SDimitry Andric // Uniqued DIAssignID are not supported as the instance address *is* the ID.
1394e3b55780SDimitry Andric assert(Storage != StorageType::Uniqued && "uniqued DIAssignID unsupported");
1395e3b55780SDimitry Andric return storeImpl(new (0u, Storage) DIAssignID(Context, Storage), Storage);
1396e3b55780SDimitry Andric }
1397e3b55780SDimitry Andric
getSize() const13985a5ac124SDimitry Andric unsigned DIExpression::ExprOperand::getSize() const {
13991d5ae102SDimitry Andric uint64_t Op = getOp();
14001d5ae102SDimitry Andric
14011d5ae102SDimitry Andric if (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31)
14021d5ae102SDimitry Andric return 2;
14031d5ae102SDimitry Andric
14041d5ae102SDimitry Andric switch (Op) {
1405e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_convert:
1406b915e9e0SDimitry Andric case dwarf::DW_OP_LLVM_fragment:
1407ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_sext:
1408ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_zext:
14091d5ae102SDimitry Andric case dwarf::DW_OP_bregx:
14105a5ac124SDimitry Andric return 3;
1411b915e9e0SDimitry Andric case dwarf::DW_OP_constu:
14121d5ae102SDimitry Andric case dwarf::DW_OP_consts:
1413e6d15924SDimitry Andric case dwarf::DW_OP_deref_size:
14147c7aba6eSDimitry Andric case dwarf::DW_OP_plus_uconst:
1415e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_tag_offset:
14161d5ae102SDimitry Andric case dwarf::DW_OP_LLVM_entry_value:
1417344a3780SDimitry Andric case dwarf::DW_OP_LLVM_arg:
14181d5ae102SDimitry Andric case dwarf::DW_OP_regx:
14195a5ac124SDimitry Andric return 2;
14205a5ac124SDimitry Andric default:
14215a5ac124SDimitry Andric return 1;
14225a5ac124SDimitry Andric }
14235a5ac124SDimitry Andric }
14245a5ac124SDimitry Andric
isValid() const14255a5ac124SDimitry Andric bool DIExpression::isValid() const {
14265a5ac124SDimitry Andric for (auto I = expr_op_begin(), E = expr_op_end(); I != E; ++I) {
14275a5ac124SDimitry Andric // Check that there's space for the operand.
14285a5ac124SDimitry Andric if (I->get() + I->getSize() > E->get())
14295a5ac124SDimitry Andric return false;
14305a5ac124SDimitry Andric
14311d5ae102SDimitry Andric uint64_t Op = I->getOp();
14321d5ae102SDimitry Andric if ((Op >= dwarf::DW_OP_reg0 && Op <= dwarf::DW_OP_reg31) ||
14331d5ae102SDimitry Andric (Op >= dwarf::DW_OP_breg0 && Op <= dwarf::DW_OP_breg31))
14341d5ae102SDimitry Andric return true;
14351d5ae102SDimitry Andric
14365a5ac124SDimitry Andric // Check that the operand is valid.
14371d5ae102SDimitry Andric switch (Op) {
14385a5ac124SDimitry Andric default:
14395a5ac124SDimitry Andric return false;
1440b915e9e0SDimitry Andric case dwarf::DW_OP_LLVM_fragment:
1441b915e9e0SDimitry Andric // A fragment operator must appear at the end.
14425a5ac124SDimitry Andric return I->get() + I->getSize() == E->get();
1443b915e9e0SDimitry Andric case dwarf::DW_OP_stack_value: {
1444b915e9e0SDimitry Andric // Must be the last one or followed by a DW_OP_LLVM_fragment.
1445b915e9e0SDimitry Andric if (I->get() + I->getSize() == E->get())
1446b915e9e0SDimitry Andric break;
1447b915e9e0SDimitry Andric auto J = I;
1448b915e9e0SDimitry Andric if ((++J)->getOp() != dwarf::DW_OP_LLVM_fragment)
1449b915e9e0SDimitry Andric return false;
1450b915e9e0SDimitry Andric break;
1451b915e9e0SDimitry Andric }
145271d5a254SDimitry Andric case dwarf::DW_OP_swap: {
145371d5a254SDimitry Andric // Must be more than one implicit element on the stack.
145471d5a254SDimitry Andric
145571d5a254SDimitry Andric // FIXME: A better way to implement this would be to add a local variable
145671d5a254SDimitry Andric // that keeps track of the stack depth and introduce something like a
145771d5a254SDimitry Andric // DW_LLVM_OP_implicit_location as a placeholder for the location this
145871d5a254SDimitry Andric // DIExpression is attached to, or else pass the number of implicit stack
145971d5a254SDimitry Andric // elements into isValid.
146071d5a254SDimitry Andric if (getNumElements() == 1)
146171d5a254SDimitry Andric return false;
146271d5a254SDimitry Andric break;
146371d5a254SDimitry Andric }
14641d5ae102SDimitry Andric case dwarf::DW_OP_LLVM_entry_value: {
1465e3b55780SDimitry Andric // An entry value operator must appear at the beginning or immediately
1466e3b55780SDimitry Andric // following `DW_OP_LLVM_arg 0`, and the number of operations it cover can
1467e3b55780SDimitry Andric // currently only be 1, because we support only entry values of a simple
1468e3b55780SDimitry Andric // register location. One reason for this is that we currently can't
1469e3b55780SDimitry Andric // calculate the size of the resulting DWARF block for other expressions.
1470e3b55780SDimitry Andric auto FirstOp = expr_op_begin();
1471e3b55780SDimitry Andric if (FirstOp->getOp() == dwarf::DW_OP_LLVM_arg && FirstOp->getArg(0) == 0)
1472e3b55780SDimitry Andric ++FirstOp;
1473e3b55780SDimitry Andric return I->get() == FirstOp->get() && I->getArg(0) == 1;
1474e6d15924SDimitry Andric }
1475b60736ecSDimitry Andric case dwarf::DW_OP_LLVM_implicit_pointer:
1476e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_convert:
1477344a3780SDimitry Andric case dwarf::DW_OP_LLVM_arg:
1478e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_tag_offset:
1479ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_sext:
1480ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_zext:
1481b915e9e0SDimitry Andric case dwarf::DW_OP_constu:
14827c7aba6eSDimitry Andric case dwarf::DW_OP_plus_uconst:
14835a5ac124SDimitry Andric case dwarf::DW_OP_plus:
1484dd58ef01SDimitry Andric case dwarf::DW_OP_minus:
1485044eb2f6SDimitry Andric case dwarf::DW_OP_mul:
1486eb11fae6SDimitry Andric case dwarf::DW_OP_div:
1487eb11fae6SDimitry Andric case dwarf::DW_OP_mod:
1488eb11fae6SDimitry Andric case dwarf::DW_OP_or:
1489eb11fae6SDimitry Andric case dwarf::DW_OP_and:
1490eb11fae6SDimitry Andric case dwarf::DW_OP_xor:
1491eb11fae6SDimitry Andric case dwarf::DW_OP_shl:
1492eb11fae6SDimitry Andric case dwarf::DW_OP_shr:
1493eb11fae6SDimitry Andric case dwarf::DW_OP_shra:
14945a5ac124SDimitry Andric case dwarf::DW_OP_deref:
1495e6d15924SDimitry Andric case dwarf::DW_OP_deref_size:
149671d5a254SDimitry Andric case dwarf::DW_OP_xderef:
1497eb11fae6SDimitry Andric case dwarf::DW_OP_lit0:
1498eb11fae6SDimitry Andric case dwarf::DW_OP_not:
1499eb11fae6SDimitry Andric case dwarf::DW_OP_dup:
15001d5ae102SDimitry Andric case dwarf::DW_OP_regx:
15011d5ae102SDimitry Andric case dwarf::DW_OP_bregx:
1502cfca06d7SDimitry Andric case dwarf::DW_OP_push_object_address:
1503b60736ecSDimitry Andric case dwarf::DW_OP_over:
1504b60736ecSDimitry Andric case dwarf::DW_OP_consts:
15057fa27ce4SDimitry Andric case dwarf::DW_OP_eq:
15067fa27ce4SDimitry Andric case dwarf::DW_OP_ne:
15077fa27ce4SDimitry Andric case dwarf::DW_OP_gt:
15087fa27ce4SDimitry Andric case dwarf::DW_OP_ge:
15097fa27ce4SDimitry Andric case dwarf::DW_OP_lt:
15107fa27ce4SDimitry Andric case dwarf::DW_OP_le:
15115a5ac124SDimitry Andric break;
15125a5ac124SDimitry Andric }
15135a5ac124SDimitry Andric }
15145a5ac124SDimitry Andric return true;
15155a5ac124SDimitry Andric }
15165a5ac124SDimitry Andric
isImplicit() const1517e6d15924SDimitry Andric bool DIExpression::isImplicit() const {
1518706b4fc4SDimitry Andric if (!isValid())
1519706b4fc4SDimitry Andric return false;
1520706b4fc4SDimitry Andric
1521706b4fc4SDimitry Andric if (getNumElements() == 0)
1522706b4fc4SDimitry Andric return false;
1523706b4fc4SDimitry Andric
1524706b4fc4SDimitry Andric for (const auto &It : expr_ops()) {
1525706b4fc4SDimitry Andric switch (It.getOp()) {
1526706b4fc4SDimitry Andric default:
1527706b4fc4SDimitry Andric break;
1528e6d15924SDimitry Andric case dwarf::DW_OP_stack_value:
1529e6d15924SDimitry Andric return true;
1530e6d15924SDimitry Andric }
1531e6d15924SDimitry Andric }
1532706b4fc4SDimitry Andric
1533e6d15924SDimitry Andric return false;
1534e6d15924SDimitry Andric }
1535e6d15924SDimitry Andric
isComplex() const1536e6d15924SDimitry Andric bool DIExpression::isComplex() const {
1537e6d15924SDimitry Andric if (!isValid())
1538e6d15924SDimitry Andric return false;
1539e6d15924SDimitry Andric
1540e6d15924SDimitry Andric if (getNumElements() == 0)
1541e6d15924SDimitry Andric return false;
1542e6d15924SDimitry Andric
1543e6d15924SDimitry Andric // If there are any elements other than fragment or tag_offset, then some
1544e6d15924SDimitry Andric // kind of complex computation occurs.
1545e6d15924SDimitry Andric for (const auto &It : expr_ops()) {
1546e6d15924SDimitry Andric switch (It.getOp()) {
1547e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_tag_offset:
1548e6d15924SDimitry Andric case dwarf::DW_OP_LLVM_fragment:
1549e3b55780SDimitry Andric case dwarf::DW_OP_LLVM_arg:
1550e6d15924SDimitry Andric continue;
1551c0981da4SDimitry Andric default:
1552c0981da4SDimitry Andric return true;
1553e6d15924SDimitry Andric }
1554e6d15924SDimitry Andric }
1555e6d15924SDimitry Andric
1556e6d15924SDimitry Andric return false;
1557e6d15924SDimitry Andric }
1558e6d15924SDimitry Andric
isSingleLocationExpression() const1559e3b55780SDimitry Andric bool DIExpression::isSingleLocationExpression() const {
1560e3b55780SDimitry Andric if (!isValid())
1561e3b55780SDimitry Andric return false;
1562e3b55780SDimitry Andric
1563e3b55780SDimitry Andric if (getNumElements() == 0)
1564e3b55780SDimitry Andric return true;
1565e3b55780SDimitry Andric
1566e3b55780SDimitry Andric auto ExprOpBegin = expr_ops().begin();
1567e3b55780SDimitry Andric auto ExprOpEnd = expr_ops().end();
1568b1c73532SDimitry Andric if (ExprOpBegin->getOp() == dwarf::DW_OP_LLVM_arg) {
1569b1c73532SDimitry Andric if (ExprOpBegin->getArg(0) != 0)
1570b1c73532SDimitry Andric return false;
1571e3b55780SDimitry Andric ++ExprOpBegin;
1572b1c73532SDimitry Andric }
1573e3b55780SDimitry Andric
1574e3b55780SDimitry Andric return !std::any_of(ExprOpBegin, ExprOpEnd, [](auto Op) {
1575e3b55780SDimitry Andric return Op.getOp() == dwarf::DW_OP_LLVM_arg;
1576e3b55780SDimitry Andric });
1577e3b55780SDimitry Andric }
1578e3b55780SDimitry Andric
1579b1c73532SDimitry Andric std::optional<ArrayRef<uint64_t>>
getSingleLocationExpressionElements() const1580b1c73532SDimitry Andric DIExpression::getSingleLocationExpressionElements() const {
1581b1c73532SDimitry Andric // Check for `isValid` covered by `isSingleLocationExpression`.
1582b1c73532SDimitry Andric if (!isSingleLocationExpression())
1583b1c73532SDimitry Andric return std::nullopt;
1584b1c73532SDimitry Andric
1585b1c73532SDimitry Andric // An empty expression is already non-variadic.
1586b1c73532SDimitry Andric if (!getNumElements())
1587b1c73532SDimitry Andric return ArrayRef<uint64_t>();
1588b1c73532SDimitry Andric
1589b1c73532SDimitry Andric // If Expr does not have a leading DW_OP_LLVM_arg then we don't need to do
1590b1c73532SDimitry Andric // anything.
1591b1c73532SDimitry Andric if (getElements()[0] == dwarf::DW_OP_LLVM_arg)
1592b1c73532SDimitry Andric return getElements().drop_front(2);
1593b1c73532SDimitry Andric return getElements();
1594b1c73532SDimitry Andric }
1595b1c73532SDimitry Andric
1596e3b55780SDimitry Andric const DIExpression *
convertToUndefExpression(const DIExpression * Expr)1597e3b55780SDimitry Andric DIExpression::convertToUndefExpression(const DIExpression *Expr) {
1598e3b55780SDimitry Andric SmallVector<uint64_t, 3> UndefOps;
1599e3b55780SDimitry Andric if (auto FragmentInfo = Expr->getFragmentInfo()) {
1600e3b55780SDimitry Andric UndefOps.append({dwarf::DW_OP_LLVM_fragment, FragmentInfo->OffsetInBits,
1601e3b55780SDimitry Andric FragmentInfo->SizeInBits});
1602e3b55780SDimitry Andric }
1603e3b55780SDimitry Andric return DIExpression::get(Expr->getContext(), UndefOps);
1604e3b55780SDimitry Andric }
1605e3b55780SDimitry Andric
1606e3b55780SDimitry Andric const DIExpression *
convertToVariadicExpression(const DIExpression * Expr)1607e3b55780SDimitry Andric DIExpression::convertToVariadicExpression(const DIExpression *Expr) {
1608e3b55780SDimitry Andric if (any_of(Expr->expr_ops(), [](auto ExprOp) {
1609e3b55780SDimitry Andric return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1610e3b55780SDimitry Andric }))
1611e3b55780SDimitry Andric return Expr;
1612e3b55780SDimitry Andric SmallVector<uint64_t> NewOps;
1613e3b55780SDimitry Andric NewOps.reserve(Expr->getNumElements() + 2);
1614e3b55780SDimitry Andric NewOps.append({dwarf::DW_OP_LLVM_arg, 0});
1615e3b55780SDimitry Andric NewOps.append(Expr->elements_begin(), Expr->elements_end());
1616e3b55780SDimitry Andric return DIExpression::get(Expr->getContext(), NewOps);
1617e3b55780SDimitry Andric }
1618e3b55780SDimitry Andric
1619e3b55780SDimitry Andric std::optional<const DIExpression *>
convertToNonVariadicExpression(const DIExpression * Expr)1620e3b55780SDimitry Andric DIExpression::convertToNonVariadicExpression(const DIExpression *Expr) {
1621b1c73532SDimitry Andric if (!Expr)
1622e3b55780SDimitry Andric return std::nullopt;
1623e3b55780SDimitry Andric
1624b1c73532SDimitry Andric if (auto Elts = Expr->getSingleLocationExpressionElements())
1625b1c73532SDimitry Andric return DIExpression::get(Expr->getContext(), *Elts);
1626e3b55780SDimitry Andric
1627b1c73532SDimitry Andric return std::nullopt;
1628e3b55780SDimitry Andric }
1629e3b55780SDimitry Andric
canonicalizeExpressionOps(SmallVectorImpl<uint64_t> & Ops,const DIExpression * Expr,bool IsIndirect)1630e3b55780SDimitry Andric void DIExpression::canonicalizeExpressionOps(SmallVectorImpl<uint64_t> &Ops,
1631e3b55780SDimitry Andric const DIExpression *Expr,
1632e3b55780SDimitry Andric bool IsIndirect) {
1633e3b55780SDimitry Andric // If Expr is not already variadic, insert the implied `DW_OP_LLVM_arg 0`
1634e3b55780SDimitry Andric // to the existing expression ops.
1635e3b55780SDimitry Andric if (none_of(Expr->expr_ops(), [](auto ExprOp) {
1636e3b55780SDimitry Andric return ExprOp.getOp() == dwarf::DW_OP_LLVM_arg;
1637e3b55780SDimitry Andric }))
1638e3b55780SDimitry Andric Ops.append({dwarf::DW_OP_LLVM_arg, 0});
1639e3b55780SDimitry Andric // If Expr is not indirect, we only need to insert the expression elements and
1640e3b55780SDimitry Andric // we're done.
1641e3b55780SDimitry Andric if (!IsIndirect) {
1642e3b55780SDimitry Andric Ops.append(Expr->elements_begin(), Expr->elements_end());
1643e3b55780SDimitry Andric return;
1644e3b55780SDimitry Andric }
1645e3b55780SDimitry Andric // If Expr is indirect, insert the implied DW_OP_deref at the end of the
1646e3b55780SDimitry Andric // expression but before DW_OP_{stack_value, LLVM_fragment} if they are
1647e3b55780SDimitry Andric // present.
1648e3b55780SDimitry Andric for (auto Op : Expr->expr_ops()) {
1649e3b55780SDimitry Andric if (Op.getOp() == dwarf::DW_OP_stack_value ||
1650e3b55780SDimitry Andric Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
1651e3b55780SDimitry Andric Ops.push_back(dwarf::DW_OP_deref);
1652e3b55780SDimitry Andric IsIndirect = false;
1653e3b55780SDimitry Andric }
1654e3b55780SDimitry Andric Op.appendToVector(Ops);
1655e3b55780SDimitry Andric }
1656e3b55780SDimitry Andric if (IsIndirect)
1657e3b55780SDimitry Andric Ops.push_back(dwarf::DW_OP_deref);
1658e3b55780SDimitry Andric }
1659e3b55780SDimitry Andric
isEqualExpression(const DIExpression * FirstExpr,bool FirstIndirect,const DIExpression * SecondExpr,bool SecondIndirect)1660e3b55780SDimitry Andric bool DIExpression::isEqualExpression(const DIExpression *FirstExpr,
1661e3b55780SDimitry Andric bool FirstIndirect,
1662e3b55780SDimitry Andric const DIExpression *SecondExpr,
1663e3b55780SDimitry Andric bool SecondIndirect) {
1664e3b55780SDimitry Andric SmallVector<uint64_t> FirstOps;
1665e3b55780SDimitry Andric DIExpression::canonicalizeExpressionOps(FirstOps, FirstExpr, FirstIndirect);
1666e3b55780SDimitry Andric SmallVector<uint64_t> SecondOps;
1667e3b55780SDimitry Andric DIExpression::canonicalizeExpressionOps(SecondOps, SecondExpr,
1668e3b55780SDimitry Andric SecondIndirect);
1669e3b55780SDimitry Andric return FirstOps == SecondOps;
1670e3b55780SDimitry Andric }
1671e3b55780SDimitry Andric
1672e3b55780SDimitry Andric std::optional<DIExpression::FragmentInfo>
getFragmentInfo(expr_op_iterator Start,expr_op_iterator End)1673b915e9e0SDimitry Andric DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) {
1674b915e9e0SDimitry Andric for (auto I = Start; I != End; ++I)
1675b915e9e0SDimitry Andric if (I->getOp() == dwarf::DW_OP_LLVM_fragment) {
1676b915e9e0SDimitry Andric DIExpression::FragmentInfo Info = {I->getArg(1), I->getArg(0)};
1677b915e9e0SDimitry Andric return Info;
1678b915e9e0SDimitry Andric }
1679e3b55780SDimitry Andric return std::nullopt;
1680b915e9e0SDimitry Andric }
1681b915e9e0SDimitry Andric
getActiveBits(DIVariable * Var)1682ac9a064cSDimitry Andric std::optional<uint64_t> DIExpression::getActiveBits(DIVariable *Var) {
1683ac9a064cSDimitry Andric std::optional<uint64_t> InitialActiveBits = Var->getSizeInBits();
1684ac9a064cSDimitry Andric std::optional<uint64_t> ActiveBits = InitialActiveBits;
1685ac9a064cSDimitry Andric for (auto Op : expr_ops()) {
1686ac9a064cSDimitry Andric switch (Op.getOp()) {
1687ac9a064cSDimitry Andric default:
1688ac9a064cSDimitry Andric // We assume the worst case for anything we don't currently handle and
1689ac9a064cSDimitry Andric // revert to the initial active bits.
1690ac9a064cSDimitry Andric ActiveBits = InitialActiveBits;
1691ac9a064cSDimitry Andric break;
1692ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_zext:
1693ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_sext: {
1694ac9a064cSDimitry Andric // We can't handle an extract whose sign doesn't match that of the
1695ac9a064cSDimitry Andric // variable.
1696ac9a064cSDimitry Andric std::optional<DIBasicType::Signedness> VarSign = Var->getSignedness();
1697ac9a064cSDimitry Andric bool VarSigned = (VarSign == DIBasicType::Signedness::Signed);
1698ac9a064cSDimitry Andric bool OpSigned = (Op.getOp() == dwarf::DW_OP_LLVM_extract_bits_sext);
1699ac9a064cSDimitry Andric if (!VarSign || VarSigned != OpSigned) {
1700ac9a064cSDimitry Andric ActiveBits = InitialActiveBits;
1701ac9a064cSDimitry Andric break;
1702ac9a064cSDimitry Andric }
1703ac9a064cSDimitry Andric [[fallthrough]];
1704ac9a064cSDimitry Andric }
1705ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_fragment:
1706ac9a064cSDimitry Andric // Extract or fragment narrows the active bits
1707ac9a064cSDimitry Andric if (ActiveBits)
1708ac9a064cSDimitry Andric ActiveBits = std::min(*ActiveBits, Op.getArg(1));
1709ac9a064cSDimitry Andric else
1710ac9a064cSDimitry Andric ActiveBits = Op.getArg(1);
1711ac9a064cSDimitry Andric break;
1712ac9a064cSDimitry Andric }
1713ac9a064cSDimitry Andric }
1714ac9a064cSDimitry Andric return ActiveBits;
1715ac9a064cSDimitry Andric }
1716ac9a064cSDimitry Andric
appendOffset(SmallVectorImpl<uint64_t> & Ops,int64_t Offset)1717a303c417SDimitry Andric void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,
1718a303c417SDimitry Andric int64_t Offset) {
1719a303c417SDimitry Andric if (Offset > 0) {
17207c7aba6eSDimitry Andric Ops.push_back(dwarf::DW_OP_plus_uconst);
1721a303c417SDimitry Andric Ops.push_back(Offset);
1722a303c417SDimitry Andric } else if (Offset < 0) {
17237c7aba6eSDimitry Andric Ops.push_back(dwarf::DW_OP_constu);
1724e3b55780SDimitry Andric // Avoid UB when encountering LLONG_MIN, because in 2's complement
1725e3b55780SDimitry Andric // abs(LLONG_MIN) is LLONG_MAX+1.
1726e3b55780SDimitry Andric uint64_t AbsMinusOne = -(Offset+1);
1727e3b55780SDimitry Andric Ops.push_back(AbsMinusOne + 1);
17287c7aba6eSDimitry Andric Ops.push_back(dwarf::DW_OP_minus);
1729a303c417SDimitry Andric }
1730a303c417SDimitry Andric }
1731a303c417SDimitry Andric
extractIfOffset(int64_t & Offset) const17326b3f41edSDimitry Andric bool DIExpression::extractIfOffset(int64_t &Offset) const {
1733b1c73532SDimitry Andric auto SingleLocEltsOpt = getSingleLocationExpressionElements();
1734b1c73532SDimitry Andric if (!SingleLocEltsOpt)
1735b1c73532SDimitry Andric return false;
1736b1c73532SDimitry Andric auto SingleLocElts = *SingleLocEltsOpt;
1737b1c73532SDimitry Andric
1738b1c73532SDimitry Andric if (SingleLocElts.size() == 0) {
17396b3f41edSDimitry Andric Offset = 0;
17406b3f41edSDimitry Andric return true;
17416b3f41edSDimitry Andric }
17427c7aba6eSDimitry Andric
1743b1c73532SDimitry Andric if (SingleLocElts.size() == 2 &&
1744b1c73532SDimitry Andric SingleLocElts[0] == dwarf::DW_OP_plus_uconst) {
1745b1c73532SDimitry Andric Offset = SingleLocElts[1];
17466b3f41edSDimitry Andric return true;
17476b3f41edSDimitry Andric }
17487c7aba6eSDimitry Andric
1749b1c73532SDimitry Andric if (SingleLocElts.size() == 3 && SingleLocElts[0] == dwarf::DW_OP_constu) {
1750b1c73532SDimitry Andric if (SingleLocElts[2] == dwarf::DW_OP_plus) {
1751b1c73532SDimitry Andric Offset = SingleLocElts[1];
17527c7aba6eSDimitry Andric return true;
17537c7aba6eSDimitry Andric }
1754b1c73532SDimitry Andric if (SingleLocElts[2] == dwarf::DW_OP_minus) {
1755b1c73532SDimitry Andric Offset = -SingleLocElts[1];
17566b3f41edSDimitry Andric return true;
17576b3f41edSDimitry Andric }
17587c7aba6eSDimitry Andric }
17597c7aba6eSDimitry Andric
17606b3f41edSDimitry Andric return false;
17616b3f41edSDimitry Andric }
17626b3f41edSDimitry Andric
extractLeadingOffset(int64_t & OffsetInBytes,SmallVectorImpl<uint64_t> & RemainingOps) const1763ac9a064cSDimitry Andric bool DIExpression::extractLeadingOffset(
1764ac9a064cSDimitry Andric int64_t &OffsetInBytes, SmallVectorImpl<uint64_t> &RemainingOps) const {
1765ac9a064cSDimitry Andric OffsetInBytes = 0;
1766ac9a064cSDimitry Andric RemainingOps.clear();
1767ac9a064cSDimitry Andric
1768ac9a064cSDimitry Andric auto SingleLocEltsOpt = getSingleLocationExpressionElements();
1769ac9a064cSDimitry Andric if (!SingleLocEltsOpt)
1770ac9a064cSDimitry Andric return false;
1771ac9a064cSDimitry Andric
1772ac9a064cSDimitry Andric auto ExprOpEnd = expr_op_iterator(SingleLocEltsOpt->end());
1773ac9a064cSDimitry Andric auto ExprOpIt = expr_op_iterator(SingleLocEltsOpt->begin());
1774ac9a064cSDimitry Andric while (ExprOpIt != ExprOpEnd) {
1775ac9a064cSDimitry Andric uint64_t Op = ExprOpIt->getOp();
1776ac9a064cSDimitry Andric if (Op == dwarf::DW_OP_deref || Op == dwarf::DW_OP_deref_size ||
1777ac9a064cSDimitry Andric Op == dwarf::DW_OP_deref_type || Op == dwarf::DW_OP_LLVM_fragment ||
1778ac9a064cSDimitry Andric Op == dwarf::DW_OP_LLVM_extract_bits_zext ||
1779ac9a064cSDimitry Andric Op == dwarf::DW_OP_LLVM_extract_bits_sext) {
1780ac9a064cSDimitry Andric break;
1781ac9a064cSDimitry Andric } else if (Op == dwarf::DW_OP_plus_uconst) {
1782ac9a064cSDimitry Andric OffsetInBytes += ExprOpIt->getArg(0);
1783ac9a064cSDimitry Andric } else if (Op == dwarf::DW_OP_constu) {
1784ac9a064cSDimitry Andric uint64_t Value = ExprOpIt->getArg(0);
1785ac9a064cSDimitry Andric ++ExprOpIt;
1786ac9a064cSDimitry Andric if (ExprOpIt->getOp() == dwarf::DW_OP_plus)
1787ac9a064cSDimitry Andric OffsetInBytes += Value;
1788ac9a064cSDimitry Andric else if (ExprOpIt->getOp() == dwarf::DW_OP_minus)
1789ac9a064cSDimitry Andric OffsetInBytes -= Value;
1790ac9a064cSDimitry Andric else
1791ac9a064cSDimitry Andric return false;
1792ac9a064cSDimitry Andric } else {
1793ac9a064cSDimitry Andric // Not a const plus/minus operation or deref.
1794ac9a064cSDimitry Andric return false;
1795ac9a064cSDimitry Andric }
1796ac9a064cSDimitry Andric ++ExprOpIt;
1797ac9a064cSDimitry Andric }
1798ac9a064cSDimitry Andric RemainingOps.append(ExprOpIt.getBase(), ExprOpEnd.getBase());
1799ac9a064cSDimitry Andric return true;
1800ac9a064cSDimitry Andric }
1801ac9a064cSDimitry Andric
hasAllLocationOps(unsigned N) const1802344a3780SDimitry Andric bool DIExpression::hasAllLocationOps(unsigned N) const {
1803344a3780SDimitry Andric SmallDenseSet<uint64_t, 4> SeenOps;
1804344a3780SDimitry Andric for (auto ExprOp : expr_ops())
1805344a3780SDimitry Andric if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)
1806344a3780SDimitry Andric SeenOps.insert(ExprOp.getArg(0));
1807344a3780SDimitry Andric for (uint64_t Idx = 0; Idx < N; ++Idx)
18087fa27ce4SDimitry Andric if (!SeenOps.contains(Idx))
1809344a3780SDimitry Andric return false;
1810344a3780SDimitry Andric return true;
1811344a3780SDimitry Andric }
1812344a3780SDimitry Andric
extractAddressClass(const DIExpression * Expr,unsigned & AddrClass)1813e6d15924SDimitry Andric const DIExpression *DIExpression::extractAddressClass(const DIExpression *Expr,
1814e6d15924SDimitry Andric unsigned &AddrClass) {
1815706b4fc4SDimitry Andric // FIXME: This seems fragile. Nothing that verifies that these elements
1816706b4fc4SDimitry Andric // actually map to ops and not operands.
1817b1c73532SDimitry Andric auto SingleLocEltsOpt = Expr->getSingleLocationExpressionElements();
1818b1c73532SDimitry Andric if (!SingleLocEltsOpt)
1819e6d15924SDimitry Andric return nullptr;
1820b1c73532SDimitry Andric auto SingleLocElts = *SingleLocEltsOpt;
1821b1c73532SDimitry Andric
1822b1c73532SDimitry Andric const unsigned PatternSize = 4;
1823b1c73532SDimitry Andric if (SingleLocElts.size() >= PatternSize &&
1824b1c73532SDimitry Andric SingleLocElts[PatternSize - 4] == dwarf::DW_OP_constu &&
1825b1c73532SDimitry Andric SingleLocElts[PatternSize - 2] == dwarf::DW_OP_swap &&
1826b1c73532SDimitry Andric SingleLocElts[PatternSize - 1] == dwarf::DW_OP_xderef) {
1827b1c73532SDimitry Andric AddrClass = SingleLocElts[PatternSize - 3];
1828b1c73532SDimitry Andric
1829b1c73532SDimitry Andric if (SingleLocElts.size() == PatternSize)
1830b1c73532SDimitry Andric return nullptr;
1831b1c73532SDimitry Andric return DIExpression::get(
1832b1c73532SDimitry Andric Expr->getContext(),
1833b1c73532SDimitry Andric ArrayRef(&*SingleLocElts.begin(), SingleLocElts.size() - PatternSize));
1834e6d15924SDimitry Andric }
1835e6d15924SDimitry Andric return Expr;
1836e6d15924SDimitry Andric }
1837e6d15924SDimitry Andric
prepend(const DIExpression * Expr,uint8_t Flags,int64_t Offset)1838e6d15924SDimitry Andric DIExpression *DIExpression::prepend(const DIExpression *Expr, uint8_t Flags,
1839e6d15924SDimitry Andric int64_t Offset) {
1840a303c417SDimitry Andric SmallVector<uint64_t, 8> Ops;
1841e6d15924SDimitry Andric if (Flags & DIExpression::DerefBefore)
1842a303c417SDimitry Andric Ops.push_back(dwarf::DW_OP_deref);
1843044eb2f6SDimitry Andric
1844044eb2f6SDimitry Andric appendOffset(Ops, Offset);
1845e6d15924SDimitry Andric if (Flags & DIExpression::DerefAfter)
1846044eb2f6SDimitry Andric Ops.push_back(dwarf::DW_OP_deref);
1847044eb2f6SDimitry Andric
1848e6d15924SDimitry Andric bool StackValue = Flags & DIExpression::StackValue;
1849e6d15924SDimitry Andric bool EntryValue = Flags & DIExpression::EntryValue;
1850e6d15924SDimitry Andric
1851e6d15924SDimitry Andric return prependOpcodes(Expr, Ops, StackValue, EntryValue);
1852eb11fae6SDimitry Andric }
1853eb11fae6SDimitry Andric
appendOpsToArg(const DIExpression * Expr,ArrayRef<uint64_t> Ops,unsigned ArgNo,bool StackValue)1854344a3780SDimitry Andric DIExpression *DIExpression::appendOpsToArg(const DIExpression *Expr,
1855344a3780SDimitry Andric ArrayRef<uint64_t> Ops,
1856344a3780SDimitry Andric unsigned ArgNo, bool StackValue) {
1857344a3780SDimitry Andric assert(Expr && "Can't add ops to this expression");
1858344a3780SDimitry Andric
1859344a3780SDimitry Andric // Handle non-variadic intrinsics by prepending the opcodes.
1860344a3780SDimitry Andric if (!any_of(Expr->expr_ops(),
1861344a3780SDimitry Andric [](auto Op) { return Op.getOp() == dwarf::DW_OP_LLVM_arg; })) {
1862344a3780SDimitry Andric assert(ArgNo == 0 &&
1863344a3780SDimitry Andric "Location Index must be 0 for a non-variadic expression.");
1864344a3780SDimitry Andric SmallVector<uint64_t, 8> NewOps(Ops.begin(), Ops.end());
1865344a3780SDimitry Andric return DIExpression::prependOpcodes(Expr, NewOps, StackValue);
1866344a3780SDimitry Andric }
1867344a3780SDimitry Andric
1868344a3780SDimitry Andric SmallVector<uint64_t, 8> NewOps;
1869344a3780SDimitry Andric for (auto Op : Expr->expr_ops()) {
1870e3b55780SDimitry Andric // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
1871e3b55780SDimitry Andric if (StackValue) {
1872e3b55780SDimitry Andric if (Op.getOp() == dwarf::DW_OP_stack_value)
1873e3b55780SDimitry Andric StackValue = false;
1874e3b55780SDimitry Andric else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
1875e3b55780SDimitry Andric NewOps.push_back(dwarf::DW_OP_stack_value);
1876e3b55780SDimitry Andric StackValue = false;
1877e3b55780SDimitry Andric }
1878e3b55780SDimitry Andric }
1879344a3780SDimitry Andric Op.appendToVector(NewOps);
1880344a3780SDimitry Andric if (Op.getOp() == dwarf::DW_OP_LLVM_arg && Op.getArg(0) == ArgNo)
1881344a3780SDimitry Andric NewOps.insert(NewOps.end(), Ops.begin(), Ops.end());
1882344a3780SDimitry Andric }
1883e3b55780SDimitry Andric if (StackValue)
1884e3b55780SDimitry Andric NewOps.push_back(dwarf::DW_OP_stack_value);
1885344a3780SDimitry Andric
1886344a3780SDimitry Andric return DIExpression::get(Expr->getContext(), NewOps);
1887344a3780SDimitry Andric }
1888344a3780SDimitry Andric
replaceArg(const DIExpression * Expr,uint64_t OldArg,uint64_t NewArg)1889344a3780SDimitry Andric DIExpression *DIExpression::replaceArg(const DIExpression *Expr,
1890344a3780SDimitry Andric uint64_t OldArg, uint64_t NewArg) {
1891344a3780SDimitry Andric assert(Expr && "Can't replace args in this expression");
1892344a3780SDimitry Andric
1893344a3780SDimitry Andric SmallVector<uint64_t, 8> NewOps;
1894344a3780SDimitry Andric
1895344a3780SDimitry Andric for (auto Op : Expr->expr_ops()) {
1896344a3780SDimitry Andric if (Op.getOp() != dwarf::DW_OP_LLVM_arg || Op.getArg(0) < OldArg) {
1897344a3780SDimitry Andric Op.appendToVector(NewOps);
1898344a3780SDimitry Andric continue;
1899344a3780SDimitry Andric }
1900344a3780SDimitry Andric NewOps.push_back(dwarf::DW_OP_LLVM_arg);
1901344a3780SDimitry Andric uint64_t Arg = Op.getArg(0) == OldArg ? NewArg : Op.getArg(0);
1902344a3780SDimitry Andric // OldArg has been deleted from the Op list, so decrement all indices
1903344a3780SDimitry Andric // greater than it.
1904344a3780SDimitry Andric if (Arg > OldArg)
1905344a3780SDimitry Andric --Arg;
1906344a3780SDimitry Andric NewOps.push_back(Arg);
1907344a3780SDimitry Andric }
1908344a3780SDimitry Andric return DIExpression::get(Expr->getContext(), NewOps);
1909344a3780SDimitry Andric }
1910344a3780SDimitry Andric
prependOpcodes(const DIExpression * Expr,SmallVectorImpl<uint64_t> & Ops,bool StackValue,bool EntryValue)1911eb11fae6SDimitry Andric DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
1912eb11fae6SDimitry Andric SmallVectorImpl<uint64_t> &Ops,
1913c0981da4SDimitry Andric bool StackValue, bool EntryValue) {
1914eb11fae6SDimitry Andric assert(Expr && "Can't prepend ops to this expression");
1915eb11fae6SDimitry Andric
1916e6d15924SDimitry Andric if (EntryValue) {
19171d5ae102SDimitry Andric Ops.push_back(dwarf::DW_OP_LLVM_entry_value);
1918344a3780SDimitry Andric // Use a block size of 1 for the target register operand. The
1919344a3780SDimitry Andric // DWARF backend currently cannot emit entry values with a block
1920344a3780SDimitry Andric // size > 1.
1921344a3780SDimitry Andric Ops.push_back(1);
1922e6d15924SDimitry Andric }
1923e6d15924SDimitry Andric
1924eb11fae6SDimitry Andric // If there are no ops to prepend, do not even add the DW_OP_stack_value.
1925eb11fae6SDimitry Andric if (Ops.empty())
1926eb11fae6SDimitry Andric StackValue = false;
1927a303c417SDimitry Andric for (auto Op : Expr->expr_ops()) {
1928a303c417SDimitry Andric // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
1929a303c417SDimitry Andric if (StackValue) {
1930a303c417SDimitry Andric if (Op.getOp() == dwarf::DW_OP_stack_value)
1931a303c417SDimitry Andric StackValue = false;
1932a303c417SDimitry Andric else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
1933a303c417SDimitry Andric Ops.push_back(dwarf::DW_OP_stack_value);
1934a303c417SDimitry Andric StackValue = false;
1935a303c417SDimitry Andric }
1936a303c417SDimitry Andric }
1937eb11fae6SDimitry Andric Op.appendToVector(Ops);
1938a303c417SDimitry Andric }
1939a303c417SDimitry Andric if (StackValue)
1940a303c417SDimitry Andric Ops.push_back(dwarf::DW_OP_stack_value);
1941a303c417SDimitry Andric return DIExpression::get(Expr->getContext(), Ops);
1942a303c417SDimitry Andric }
1943a303c417SDimitry Andric
append(const DIExpression * Expr,ArrayRef<uint64_t> Ops)1944eb11fae6SDimitry Andric DIExpression *DIExpression::append(const DIExpression *Expr,
1945eb11fae6SDimitry Andric ArrayRef<uint64_t> Ops) {
1946eb11fae6SDimitry Andric assert(Expr && !Ops.empty() && "Can't append ops to this expression");
1947eb11fae6SDimitry Andric
1948eb11fae6SDimitry Andric // Copy Expr's current op list.
1949eb11fae6SDimitry Andric SmallVector<uint64_t, 16> NewOps;
1950eb11fae6SDimitry Andric for (auto Op : Expr->expr_ops()) {
1951eb11fae6SDimitry Andric // Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.
1952eb11fae6SDimitry Andric if (Op.getOp() == dwarf::DW_OP_stack_value ||
1953eb11fae6SDimitry Andric Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
1954eb11fae6SDimitry Andric NewOps.append(Ops.begin(), Ops.end());
1955eb11fae6SDimitry Andric
1956eb11fae6SDimitry Andric // Ensure that the new opcodes are only appended once.
1957e3b55780SDimitry Andric Ops = std::nullopt;
1958eb11fae6SDimitry Andric }
1959eb11fae6SDimitry Andric Op.appendToVector(NewOps);
1960eb11fae6SDimitry Andric }
1961eb11fae6SDimitry Andric NewOps.append(Ops.begin(), Ops.end());
1962ac9a064cSDimitry Andric auto *result =
1963ac9a064cSDimitry Andric DIExpression::get(Expr->getContext(), NewOps)->foldConstantMath();
1964cfca06d7SDimitry Andric assert(result->isValid() && "concatenated expression is not valid");
1965cfca06d7SDimitry Andric return result;
1966eb11fae6SDimitry Andric }
1967eb11fae6SDimitry Andric
appendToStack(const DIExpression * Expr,ArrayRef<uint64_t> Ops)1968eb11fae6SDimitry Andric DIExpression *DIExpression::appendToStack(const DIExpression *Expr,
1969eb11fae6SDimitry Andric ArrayRef<uint64_t> Ops) {
1970eb11fae6SDimitry Andric assert(Expr && !Ops.empty() && "Can't append ops to this expression");
1971ac9a064cSDimitry Andric assert(std::none_of(expr_op_iterator(Ops.begin()),
1972ac9a064cSDimitry Andric expr_op_iterator(Ops.end()),
1973ac9a064cSDimitry Andric [](auto Op) {
1974ac9a064cSDimitry Andric return Op.getOp() == dwarf::DW_OP_stack_value ||
1975ac9a064cSDimitry Andric Op.getOp() == dwarf::DW_OP_LLVM_fragment;
1976eb11fae6SDimitry Andric }) &&
1977eb11fae6SDimitry Andric "Can't append this op");
1978eb11fae6SDimitry Andric
1979eb11fae6SDimitry Andric // Append a DW_OP_deref after Expr's current op list if it's non-empty and
1980eb11fae6SDimitry Andric // has no DW_OP_stack_value.
1981eb11fae6SDimitry Andric //
1982eb11fae6SDimitry Andric // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?.
1983e3b55780SDimitry Andric std::optional<FragmentInfo> FI = Expr->getFragmentInfo();
1984145449b1SDimitry Andric unsigned DropUntilStackValue = FI ? 3 : 0;
1985eb11fae6SDimitry Andric ArrayRef<uint64_t> ExprOpsBeforeFragment =
1986eb11fae6SDimitry Andric Expr->getElements().drop_back(DropUntilStackValue);
1987eb11fae6SDimitry Andric bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) &&
1988eb11fae6SDimitry Andric (ExprOpsBeforeFragment.back() != dwarf::DW_OP_stack_value);
1989eb11fae6SDimitry Andric bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.empty();
1990eb11fae6SDimitry Andric
1991eb11fae6SDimitry Andric // Append a DW_OP_deref after Expr's current op list if needed, then append
1992eb11fae6SDimitry Andric // the new ops, and finally ensure that a single DW_OP_stack_value is present.
1993eb11fae6SDimitry Andric SmallVector<uint64_t, 16> NewOps;
1994eb11fae6SDimitry Andric if (NeedsDeref)
1995eb11fae6SDimitry Andric NewOps.push_back(dwarf::DW_OP_deref);
1996eb11fae6SDimitry Andric NewOps.append(Ops.begin(), Ops.end());
1997eb11fae6SDimitry Andric if (NeedsStackValue)
1998eb11fae6SDimitry Andric NewOps.push_back(dwarf::DW_OP_stack_value);
1999eb11fae6SDimitry Andric return DIExpression::append(Expr, NewOps);
2000eb11fae6SDimitry Andric }
2001eb11fae6SDimitry Andric
createFragmentExpression(const DIExpression * Expr,unsigned OffsetInBits,unsigned SizeInBits)2002e3b55780SDimitry Andric std::optional<DIExpression *> DIExpression::createFragmentExpression(
2003044eb2f6SDimitry Andric const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) {
2004044eb2f6SDimitry Andric SmallVector<uint64_t, 8> Ops;
2005e3b55780SDimitry Andric // Track whether it's safe to split the value at the top of the DWARF stack,
2006e3b55780SDimitry Andric // assuming that it'll be used as an implicit location value.
2007e3b55780SDimitry Andric bool CanSplitValue = true;
2008ac9a064cSDimitry Andric // Track whether we need to add a fragment expression to the end of Expr.
2009ac9a064cSDimitry Andric bool EmitFragment = true;
2010044eb2f6SDimitry Andric // Copy over the expression, but leave off any trailing DW_OP_LLVM_fragment.
2011044eb2f6SDimitry Andric if (Expr) {
2012044eb2f6SDimitry Andric for (auto Op : Expr->expr_ops()) {
2013044eb2f6SDimitry Andric switch (Op.getOp()) {
2014c0981da4SDimitry Andric default:
2015c0981da4SDimitry Andric break;
2016706b4fc4SDimitry Andric case dwarf::DW_OP_shr:
2017706b4fc4SDimitry Andric case dwarf::DW_OP_shra:
2018706b4fc4SDimitry Andric case dwarf::DW_OP_shl:
2019044eb2f6SDimitry Andric case dwarf::DW_OP_plus:
2020706b4fc4SDimitry Andric case dwarf::DW_OP_plus_uconst:
2021044eb2f6SDimitry Andric case dwarf::DW_OP_minus:
2022706b4fc4SDimitry Andric // We can't safely split arithmetic or shift operations into multiple
2023706b4fc4SDimitry Andric // fragments because we can't express carry-over between fragments.
2024044eb2f6SDimitry Andric //
2025044eb2f6SDimitry Andric // FIXME: We *could* preserve the lowest fragment of a constant offset
2026044eb2f6SDimitry Andric // operation if the offset fits into SizeInBits.
2027e3b55780SDimitry Andric CanSplitValue = false;
2028e3b55780SDimitry Andric break;
2029e3b55780SDimitry Andric case dwarf::DW_OP_deref:
2030e3b55780SDimitry Andric case dwarf::DW_OP_deref_size:
2031e3b55780SDimitry Andric case dwarf::DW_OP_deref_type:
2032e3b55780SDimitry Andric case dwarf::DW_OP_xderef:
2033e3b55780SDimitry Andric case dwarf::DW_OP_xderef_size:
2034e3b55780SDimitry Andric case dwarf::DW_OP_xderef_type:
2035e3b55780SDimitry Andric // Preceeding arithmetic operations have been applied to compute an
2036e3b55780SDimitry Andric // address. It's okay to split the value loaded from that address.
2037e3b55780SDimitry Andric CanSplitValue = true;
2038e3b55780SDimitry Andric break;
2039e3b55780SDimitry Andric case dwarf::DW_OP_stack_value:
2040e3b55780SDimitry Andric // Bail if this expression computes a value that cannot be split.
2041e3b55780SDimitry Andric if (!CanSplitValue)
2042e3b55780SDimitry Andric return std::nullopt;
2043e3b55780SDimitry Andric break;
2044044eb2f6SDimitry Andric case dwarf::DW_OP_LLVM_fragment: {
2045ac9a064cSDimitry Andric // If we've decided we don't need a fragment then give up if we see that
2046ac9a064cSDimitry Andric // there's already a fragment expression.
2047ac9a064cSDimitry Andric // FIXME: We could probably do better here
2048ac9a064cSDimitry Andric if (!EmitFragment)
2049ac9a064cSDimitry Andric return std::nullopt;
2050044eb2f6SDimitry Andric // Make the new offset point into the existing fragment.
2051044eb2f6SDimitry Andric uint64_t FragmentOffsetInBits = Op.getArg(0);
2052eb11fae6SDimitry Andric uint64_t FragmentSizeInBits = Op.getArg(1);
2053eb11fae6SDimitry Andric (void)FragmentSizeInBits;
2054eb11fae6SDimitry Andric assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
2055044eb2f6SDimitry Andric "new fragment outside of original fragment");
2056044eb2f6SDimitry Andric OffsetInBits += FragmentOffsetInBits;
2057044eb2f6SDimitry Andric continue;
2058044eb2f6SDimitry Andric }
2059ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_zext:
2060ac9a064cSDimitry Andric case dwarf::DW_OP_LLVM_extract_bits_sext: {
2061ac9a064cSDimitry Andric // If we're extracting bits from inside of the fragment that we're
2062ac9a064cSDimitry Andric // creating then we don't have a fragment after all, and just need to
2063ac9a064cSDimitry Andric // adjust the offset that we're extracting from.
2064ac9a064cSDimitry Andric uint64_t ExtractOffsetInBits = Op.getArg(0);
2065ac9a064cSDimitry Andric uint64_t ExtractSizeInBits = Op.getArg(1);
2066ac9a064cSDimitry Andric if (ExtractOffsetInBits >= OffsetInBits &&
2067ac9a064cSDimitry Andric ExtractOffsetInBits + ExtractSizeInBits <=
2068ac9a064cSDimitry Andric OffsetInBits + SizeInBits) {
2069ac9a064cSDimitry Andric Ops.push_back(Op.getOp());
2070ac9a064cSDimitry Andric Ops.push_back(ExtractOffsetInBits - OffsetInBits);
2071ac9a064cSDimitry Andric Ops.push_back(ExtractSizeInBits);
2072ac9a064cSDimitry Andric EmitFragment = false;
2073ac9a064cSDimitry Andric continue;
2074ac9a064cSDimitry Andric }
2075ac9a064cSDimitry Andric // If the extracted bits aren't fully contained within the fragment then
2076ac9a064cSDimitry Andric // give up.
2077ac9a064cSDimitry Andric // FIXME: We could probably do better here
2078ac9a064cSDimitry Andric return std::nullopt;
2079ac9a064cSDimitry Andric }
2080044eb2f6SDimitry Andric }
2081eb11fae6SDimitry Andric Op.appendToVector(Ops);
2082044eb2f6SDimitry Andric }
2083044eb2f6SDimitry Andric }
2084e3b55780SDimitry Andric assert((!Expr->isImplicit() || CanSplitValue) && "Expr can't be split");
20851d5ae102SDimitry Andric assert(Expr && "Unknown DIExpression");
2086ac9a064cSDimitry Andric if (EmitFragment) {
2087044eb2f6SDimitry Andric Ops.push_back(dwarf::DW_OP_LLVM_fragment);
2088044eb2f6SDimitry Andric Ops.push_back(OffsetInBits);
2089044eb2f6SDimitry Andric Ops.push_back(SizeInBits);
2090ac9a064cSDimitry Andric }
2091044eb2f6SDimitry Andric return DIExpression::get(Expr->getContext(), Ops);
2092044eb2f6SDimitry Andric }
2093044eb2f6SDimitry Andric
2094ac9a064cSDimitry Andric /// See declaration for more info.
calculateFragmentIntersect(const DataLayout & DL,const Value * SliceStart,uint64_t SliceOffsetInBits,uint64_t SliceSizeInBits,const Value * DbgPtr,int64_t DbgPtrOffsetInBits,int64_t DbgExtractOffsetInBits,DIExpression::FragmentInfo VarFrag,std::optional<DIExpression::FragmentInfo> & Result,int64_t & OffsetFromLocationInBits)2095ac9a064cSDimitry Andric bool DIExpression::calculateFragmentIntersect(
2096ac9a064cSDimitry Andric const DataLayout &DL, const Value *SliceStart, uint64_t SliceOffsetInBits,
2097ac9a064cSDimitry Andric uint64_t SliceSizeInBits, const Value *DbgPtr, int64_t DbgPtrOffsetInBits,
2098ac9a064cSDimitry Andric int64_t DbgExtractOffsetInBits, DIExpression::FragmentInfo VarFrag,
2099ac9a064cSDimitry Andric std::optional<DIExpression::FragmentInfo> &Result,
2100ac9a064cSDimitry Andric int64_t &OffsetFromLocationInBits) {
2101ac9a064cSDimitry Andric
2102ac9a064cSDimitry Andric if (VarFrag.SizeInBits == 0)
2103ac9a064cSDimitry Andric return false; // Variable size is unknown.
2104ac9a064cSDimitry Andric
2105ac9a064cSDimitry Andric // Difference between mem slice start and the dbg location start.
2106ac9a064cSDimitry Andric // 0 4 8 12 16 ...
2107ac9a064cSDimitry Andric // | |
2108ac9a064cSDimitry Andric // dbg location start
2109ac9a064cSDimitry Andric // |
2110ac9a064cSDimitry Andric // mem slice start
2111ac9a064cSDimitry Andric // Here MemStartRelToDbgStartInBits is 8. Note this can be negative.
2112ac9a064cSDimitry Andric int64_t MemStartRelToDbgStartInBits;
2113ac9a064cSDimitry Andric {
2114ac9a064cSDimitry Andric auto MemOffsetFromDbgInBytes = SliceStart->getPointerOffsetFrom(DbgPtr, DL);
2115ac9a064cSDimitry Andric if (!MemOffsetFromDbgInBytes)
2116ac9a064cSDimitry Andric return false; // Can't calculate difference in addresses.
2117ac9a064cSDimitry Andric // Difference between the pointers.
2118ac9a064cSDimitry Andric MemStartRelToDbgStartInBits = *MemOffsetFromDbgInBytes * 8;
2119ac9a064cSDimitry Andric // Add the difference of the offsets.
2120ac9a064cSDimitry Andric MemStartRelToDbgStartInBits +=
2121ac9a064cSDimitry Andric SliceOffsetInBits - (DbgPtrOffsetInBits + DbgExtractOffsetInBits);
2122ac9a064cSDimitry Andric }
2123ac9a064cSDimitry Andric
2124ac9a064cSDimitry Andric // Out-param. Invert offset to get offset from debug location.
2125ac9a064cSDimitry Andric OffsetFromLocationInBits = -MemStartRelToDbgStartInBits;
2126ac9a064cSDimitry Andric
2127ac9a064cSDimitry Andric // Check if the variable fragment sits outside (before) this memory slice.
2128ac9a064cSDimitry Andric int64_t MemEndRelToDbgStart = MemStartRelToDbgStartInBits + SliceSizeInBits;
2129ac9a064cSDimitry Andric if (MemEndRelToDbgStart < 0) {
2130ac9a064cSDimitry Andric Result = {0, 0}; // Out-param.
2131ac9a064cSDimitry Andric return true;
2132ac9a064cSDimitry Andric }
2133ac9a064cSDimitry Andric
2134ac9a064cSDimitry Andric // Work towards creating SliceOfVariable which is the bits of the variable
2135ac9a064cSDimitry Andric // that the memory region covers.
2136ac9a064cSDimitry Andric // 0 4 8 12 16 ...
2137ac9a064cSDimitry Andric // | |
2138ac9a064cSDimitry Andric // dbg location start with VarFrag offset=32
2139ac9a064cSDimitry Andric // |
2140ac9a064cSDimitry Andric // mem slice start: SliceOfVariable offset=40
2141ac9a064cSDimitry Andric int64_t MemStartRelToVarInBits =
2142ac9a064cSDimitry Andric MemStartRelToDbgStartInBits + VarFrag.OffsetInBits;
2143ac9a064cSDimitry Andric int64_t MemEndRelToVarInBits = MemStartRelToVarInBits + SliceSizeInBits;
2144ac9a064cSDimitry Andric // If the memory region starts before the debug location the fragment
2145ac9a064cSDimitry Andric // offset would be negative, which we can't encode. Limit those to 0. This
2146ac9a064cSDimitry Andric // is fine because those bits necessarily don't overlap with the existing
2147ac9a064cSDimitry Andric // variable fragment.
2148ac9a064cSDimitry Andric int64_t MemFragStart = std::max<int64_t>(0, MemStartRelToVarInBits);
2149ac9a064cSDimitry Andric int64_t MemFragSize =
2150ac9a064cSDimitry Andric std::max<int64_t>(0, MemEndRelToVarInBits - MemFragStart);
2151ac9a064cSDimitry Andric DIExpression::FragmentInfo SliceOfVariable(MemFragSize, MemFragStart);
2152ac9a064cSDimitry Andric
2153ac9a064cSDimitry Andric // Intersect the memory region fragment with the variable location fragment.
2154ac9a064cSDimitry Andric DIExpression::FragmentInfo TrimmedSliceOfVariable =
2155ac9a064cSDimitry Andric DIExpression::FragmentInfo::intersect(SliceOfVariable, VarFrag);
2156ac9a064cSDimitry Andric if (TrimmedSliceOfVariable == VarFrag)
2157ac9a064cSDimitry Andric Result = std::nullopt; // Out-param.
2158ac9a064cSDimitry Andric else
2159ac9a064cSDimitry Andric Result = TrimmedSliceOfVariable; // Out-param.
2160ac9a064cSDimitry Andric return true;
2161ac9a064cSDimitry Andric }
2162ac9a064cSDimitry Andric
2163c0981da4SDimitry Andric std::pair<DIExpression *, const ConstantInt *>
constantFold(const ConstantInt * CI)2164c0981da4SDimitry Andric DIExpression::constantFold(const ConstantInt *CI) {
2165c0981da4SDimitry Andric // Copy the APInt so we can modify it.
2166c0981da4SDimitry Andric APInt NewInt = CI->getValue();
2167c0981da4SDimitry Andric SmallVector<uint64_t, 8> Ops;
2168c0981da4SDimitry Andric
2169c0981da4SDimitry Andric // Fold operators only at the beginning of the expression.
2170c0981da4SDimitry Andric bool First = true;
2171c0981da4SDimitry Andric bool Changed = false;
2172c0981da4SDimitry Andric for (auto Op : expr_ops()) {
2173c0981da4SDimitry Andric switch (Op.getOp()) {
2174c0981da4SDimitry Andric default:
2175c0981da4SDimitry Andric // We fold only the leading part of the expression; if we get to a part
2176c0981da4SDimitry Andric // that we're going to copy unchanged, and haven't done any folding,
2177c0981da4SDimitry Andric // then the entire expression is unchanged and we can return early.
2178c0981da4SDimitry Andric if (!Changed)
2179c0981da4SDimitry Andric return {this, CI};
2180c0981da4SDimitry Andric First = false;
2181c0981da4SDimitry Andric break;
2182c0981da4SDimitry Andric case dwarf::DW_OP_LLVM_convert:
2183c0981da4SDimitry Andric if (!First)
2184c0981da4SDimitry Andric break;
2185c0981da4SDimitry Andric Changed = true;
2186c0981da4SDimitry Andric if (Op.getArg(1) == dwarf::DW_ATE_signed)
2187c0981da4SDimitry Andric NewInt = NewInt.sextOrTrunc(Op.getArg(0));
2188c0981da4SDimitry Andric else {
2189c0981da4SDimitry Andric assert(Op.getArg(1) == dwarf::DW_ATE_unsigned && "Unexpected operand");
2190c0981da4SDimitry Andric NewInt = NewInt.zextOrTrunc(Op.getArg(0));
2191c0981da4SDimitry Andric }
2192c0981da4SDimitry Andric continue;
2193c0981da4SDimitry Andric }
2194c0981da4SDimitry Andric Op.appendToVector(Ops);
2195c0981da4SDimitry Andric }
2196c0981da4SDimitry Andric if (!Changed)
2197c0981da4SDimitry Andric return {this, CI};
2198c0981da4SDimitry Andric return {DIExpression::get(getContext(), Ops),
2199c0981da4SDimitry Andric ConstantInt::get(getContext(), NewInt)};
2200c0981da4SDimitry Andric }
2201c0981da4SDimitry Andric
getNumLocationOperands() const2202344a3780SDimitry Andric uint64_t DIExpression::getNumLocationOperands() const {
2203344a3780SDimitry Andric uint64_t Result = 0;
2204344a3780SDimitry Andric for (auto ExprOp : expr_ops())
2205344a3780SDimitry Andric if (ExprOp.getOp() == dwarf::DW_OP_LLVM_arg)
2206344a3780SDimitry Andric Result = std::max(Result, ExprOp.getArg(0) + 1);
2207344a3780SDimitry Andric assert(hasAllLocationOps(Result) &&
2208344a3780SDimitry Andric "Expression is missing one or more location operands.");
2209344a3780SDimitry Andric return Result;
22105a5ac124SDimitry Andric }
22115a5ac124SDimitry Andric
2212e3b55780SDimitry Andric std::optional<DIExpression::SignedOrUnsignedConstant>
isConstant() const2213344a3780SDimitry Andric DIExpression::isConstant() const {
2214344a3780SDimitry Andric
2215344a3780SDimitry Andric // Recognize signed and unsigned constants.
2216344a3780SDimitry Andric // An signed constants can be represented as DW_OP_consts C DW_OP_stack_value
2217344a3780SDimitry Andric // (DW_OP_LLVM_fragment of Len).
2218344a3780SDimitry Andric // An unsigned constant can be represented as
2219344a3780SDimitry Andric // DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment of Len).
2220344a3780SDimitry Andric
2221344a3780SDimitry Andric if ((getNumElements() != 2 && getNumElements() != 3 &&
2222344a3780SDimitry Andric getNumElements() != 6) ||
2223344a3780SDimitry Andric (getElement(0) != dwarf::DW_OP_consts &&
2224344a3780SDimitry Andric getElement(0) != dwarf::DW_OP_constu))
2225e3b55780SDimitry Andric return std::nullopt;
2226344a3780SDimitry Andric
2227344a3780SDimitry Andric if (getNumElements() == 2 && getElement(0) == dwarf::DW_OP_consts)
2228344a3780SDimitry Andric return SignedOrUnsignedConstant::SignedConstant;
2229344a3780SDimitry Andric
2230344a3780SDimitry Andric if ((getNumElements() == 3 && getElement(2) != dwarf::DW_OP_stack_value) ||
2231344a3780SDimitry Andric (getNumElements() == 6 && (getElement(2) != dwarf::DW_OP_stack_value ||
2232344a3780SDimitry Andric getElement(3) != dwarf::DW_OP_LLVM_fragment)))
2233e3b55780SDimitry Andric return std::nullopt;
2234344a3780SDimitry Andric return getElement(0) == dwarf::DW_OP_constu
2235344a3780SDimitry Andric ? SignedOrUnsignedConstant::UnsignedConstant
2236344a3780SDimitry Andric : SignedOrUnsignedConstant::SignedConstant;
2237b60736ecSDimitry Andric }
2238b60736ecSDimitry Andric
getExtOps(unsigned FromSize,unsigned ToSize,bool Signed)2239706b4fc4SDimitry Andric DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize,
2240706b4fc4SDimitry Andric bool Signed) {
2241706b4fc4SDimitry Andric dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned;
2242706b4fc4SDimitry Andric DIExpression::ExtOps Ops{{dwarf::DW_OP_LLVM_convert, FromSize, TK,
2243706b4fc4SDimitry Andric dwarf::DW_OP_LLVM_convert, ToSize, TK}};
2244706b4fc4SDimitry Andric return Ops;
2245706b4fc4SDimitry Andric }
2246706b4fc4SDimitry Andric
appendExt(const DIExpression * Expr,unsigned FromSize,unsigned ToSize,bool Signed)2247706b4fc4SDimitry Andric DIExpression *DIExpression::appendExt(const DIExpression *Expr,
2248706b4fc4SDimitry Andric unsigned FromSize, unsigned ToSize,
2249706b4fc4SDimitry Andric bool Signed) {
2250706b4fc4SDimitry Andric return appendToStack(Expr, getExtOps(FromSize, ToSize, Signed));
2251706b4fc4SDimitry Andric }
2252706b4fc4SDimitry Andric
2253b915e9e0SDimitry Andric DIGlobalVariableExpression *
getImpl(LLVMContext & Context,Metadata * Variable,Metadata * Expression,StorageType Storage,bool ShouldCreate)2254b915e9e0SDimitry Andric DIGlobalVariableExpression::getImpl(LLVMContext &Context, Metadata *Variable,
2255b915e9e0SDimitry Andric Metadata *Expression, StorageType Storage,
2256b915e9e0SDimitry Andric bool ShouldCreate) {
2257b915e9e0SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIGlobalVariableExpression, (Variable, Expression));
2258b915e9e0SDimitry Andric Metadata *Ops[] = {Variable, Expression};
2259b915e9e0SDimitry Andric DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGlobalVariableExpression, Ops);
22605a5ac124SDimitry Andric }
DIObjCProperty(LLVMContext & C,StorageType Storage,unsigned Line,unsigned Attributes,ArrayRef<Metadata * > Ops)2261145449b1SDimitry Andric DIObjCProperty::DIObjCProperty(LLVMContext &C, StorageType Storage,
2262145449b1SDimitry Andric unsigned Line, unsigned Attributes,
2263145449b1SDimitry Andric ArrayRef<Metadata *> Ops)
2264145449b1SDimitry Andric : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops),
2265145449b1SDimitry Andric Line(Line), Attributes(Attributes) {}
22665a5ac124SDimitry Andric
getImpl(LLVMContext & Context,MDString * Name,Metadata * File,unsigned Line,MDString * GetterName,MDString * SetterName,unsigned Attributes,Metadata * Type,StorageType Storage,bool ShouldCreate)22675a5ac124SDimitry Andric DIObjCProperty *DIObjCProperty::getImpl(
22685a5ac124SDimitry Andric LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
22695a5ac124SDimitry Andric MDString *GetterName, MDString *SetterName, unsigned Attributes,
22705a5ac124SDimitry Andric Metadata *Type, StorageType Storage, bool ShouldCreate) {
22715a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
22725a5ac124SDimitry Andric assert(isCanonical(GetterName) && "Expected canonical MDString");
22735a5ac124SDimitry Andric assert(isCanonical(SetterName) && "Expected canonical MDString");
227401095a5dSDimitry Andric DEFINE_GETIMPL_LOOKUP(DIObjCProperty, (Name, File, Line, GetterName,
227501095a5dSDimitry Andric SetterName, Attributes, Type));
22765a5ac124SDimitry Andric Metadata *Ops[] = {Name, File, GetterName, SetterName, Type};
22775a5ac124SDimitry Andric DEFINE_GETIMPL_STORE(DIObjCProperty, (Line, Attributes), Ops);
22785a5ac124SDimitry Andric }
22795a5ac124SDimitry Andric
getImpl(LLVMContext & Context,unsigned Tag,Metadata * Scope,Metadata * Entity,Metadata * File,unsigned Line,MDString * Name,Metadata * Elements,StorageType Storage,bool ShouldCreate)22805a5ac124SDimitry Andric DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag,
22815a5ac124SDimitry Andric Metadata *Scope, Metadata *Entity,
228293c91e39SDimitry Andric Metadata *File, unsigned Line,
2283c0981da4SDimitry Andric MDString *Name, Metadata *Elements,
2284c0981da4SDimitry Andric StorageType Storage,
22855a5ac124SDimitry Andric bool ShouldCreate) {
22865a5ac124SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
228793c91e39SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIImportedEntity,
2288c0981da4SDimitry Andric (Tag, Scope, Entity, File, Line, Name, Elements));
2289c0981da4SDimitry Andric Metadata *Ops[] = {Scope, Entity, Name, File, Elements};
22905a5ac124SDimitry Andric DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops);
22915a5ac124SDimitry Andric }
2292dd58ef01SDimitry Andric
getImpl(LLVMContext & Context,unsigned MIType,unsigned Line,MDString * Name,MDString * Value,StorageType Storage,bool ShouldCreate)2293c0981da4SDimitry Andric DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType, unsigned Line,
2294c0981da4SDimitry Andric MDString *Name, MDString *Value, StorageType Storage,
2295c0981da4SDimitry Andric bool ShouldCreate) {
2296dd58ef01SDimitry Andric assert(isCanonical(Name) && "Expected canonical MDString");
229701095a5dSDimitry Andric DEFINE_GETIMPL_LOOKUP(DIMacro, (MIType, Line, Name, Value));
2298dd58ef01SDimitry Andric Metadata *Ops[] = {Name, Value};
2299dd58ef01SDimitry Andric DEFINE_GETIMPL_STORE(DIMacro, (MIType, Line), Ops);
2300dd58ef01SDimitry Andric }
2301dd58ef01SDimitry Andric
getImpl(LLVMContext & Context,unsigned MIType,unsigned Line,Metadata * File,Metadata * Elements,StorageType Storage,bool ShouldCreate)2302dd58ef01SDimitry Andric DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
2303dd58ef01SDimitry Andric unsigned Line, Metadata *File,
2304dd58ef01SDimitry Andric Metadata *Elements, StorageType Storage,
2305dd58ef01SDimitry Andric bool ShouldCreate) {
2306c0981da4SDimitry Andric DEFINE_GETIMPL_LOOKUP(DIMacroFile, (MIType, Line, File, Elements));
2307dd58ef01SDimitry Andric Metadata *Ops[] = {File, Elements};
2308dd58ef01SDimitry Andric DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);
2309dd58ef01SDimitry Andric }
2310344a3780SDimitry Andric
get(LLVMContext & Context,ArrayRef<ValueAsMetadata * > Args)2311b1c73532SDimitry Andric DIArgList *DIArgList::get(LLVMContext &Context,
2312b1c73532SDimitry Andric ArrayRef<ValueAsMetadata *> Args) {
2313b1c73532SDimitry Andric auto ExistingIt = Context.pImpl->DIArgLists.find_as(DIArgListKeyInfo(Args));
2314b1c73532SDimitry Andric if (ExistingIt != Context.pImpl->DIArgLists.end())
2315b1c73532SDimitry Andric return *ExistingIt;
2316b1c73532SDimitry Andric DIArgList *NewArgList = new DIArgList(Context, Args);
2317b1c73532SDimitry Andric Context.pImpl->DIArgLists.insert(NewArgList);
2318b1c73532SDimitry Andric return NewArgList;
2319344a3780SDimitry Andric }
2320344a3780SDimitry Andric
handleChangedOperand(void * Ref,Metadata * New)2321344a3780SDimitry Andric void DIArgList::handleChangedOperand(void *Ref, Metadata *New) {
2322344a3780SDimitry Andric ValueAsMetadata **OldVMPtr = static_cast<ValueAsMetadata **>(Ref);
2323344a3780SDimitry Andric assert((!New || isa<ValueAsMetadata>(New)) &&
2324344a3780SDimitry Andric "DIArgList must be passed a ValueAsMetadata");
2325344a3780SDimitry Andric untrack();
2326b1c73532SDimitry Andric // We need to update the set storage once the Args are updated since they
2327c0981da4SDimitry Andric // form the key to the DIArgLists store.
2328b1c73532SDimitry Andric getContext().pImpl->DIArgLists.erase(this);
2329344a3780SDimitry Andric ValueAsMetadata *NewVM = cast_or_null<ValueAsMetadata>(New);
2330344a3780SDimitry Andric for (ValueAsMetadata *&VM : Args) {
2331344a3780SDimitry Andric if (&VM == OldVMPtr) {
2332344a3780SDimitry Andric if (NewVM)
2333344a3780SDimitry Andric VM = NewVM;
2334344a3780SDimitry Andric else
23357fa27ce4SDimitry Andric VM = ValueAsMetadata::get(PoisonValue::get(VM->getValue()->getType()));
2336344a3780SDimitry Andric }
2337344a3780SDimitry Andric }
2338b1c73532SDimitry Andric // We've changed the contents of this DIArgList, and the set storage may
2339b1c73532SDimitry Andric // already contain a DIArgList with our new set of args; if it does, then we
2340b1c73532SDimitry Andric // must RAUW this with the existing DIArgList, otherwise we simply insert this
2341b1c73532SDimitry Andric // back into the set storage.
2342b1c73532SDimitry Andric DIArgList *ExistingArgList = getUniqued(getContext().pImpl->DIArgLists, this);
2343b1c73532SDimitry Andric if (ExistingArgList) {
2344b1c73532SDimitry Andric replaceAllUsesWith(ExistingArgList);
2345b1c73532SDimitry Andric // Clear this here so we don't try to untrack in the destructor.
2346b1c73532SDimitry Andric Args.clear();
2347b1c73532SDimitry Andric delete this;
2348b1c73532SDimitry Andric return;
2349c0981da4SDimitry Andric }
2350b1c73532SDimitry Andric getContext().pImpl->DIArgLists.insert(this);
2351344a3780SDimitry Andric track();
2352344a3780SDimitry Andric }
track()2353344a3780SDimitry Andric void DIArgList::track() {
2354344a3780SDimitry Andric for (ValueAsMetadata *&VAM : Args)
2355344a3780SDimitry Andric if (VAM)
2356344a3780SDimitry Andric MetadataTracking::track(&VAM, *VAM, *this);
2357344a3780SDimitry Andric }
untrack()2358344a3780SDimitry Andric void DIArgList::untrack() {
2359344a3780SDimitry Andric for (ValueAsMetadata *&VAM : Args)
2360344a3780SDimitry Andric if (VAM)
2361344a3780SDimitry Andric MetadataTracking::untrack(&VAM, *VAM);
2362344a3780SDimitry Andric }
dropAllReferences(bool Untrack)2363b1c73532SDimitry Andric void DIArgList::dropAllReferences(bool Untrack) {
2364b1c73532SDimitry Andric if (Untrack)
2365344a3780SDimitry Andric untrack();
2366344a3780SDimitry Andric Args.clear();
2367b1c73532SDimitry Andric ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
2368344a3780SDimitry Andric }
2369