xref: /openbsd-src/gnu/llvm/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
1009467b48Spatrick #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
1109467b48Spatrick 
1209467b48Spatrick #include "DebugLocStream.h"
1309467b48Spatrick #include "llvm/Config/llvm-config.h"
1409467b48Spatrick #include "llvm/IR/Constants.h"
1509467b48Spatrick #include "llvm/IR/DebugInfo.h"
1609467b48Spatrick #include "llvm/MC/MCSymbol.h"
1709467b48Spatrick #include "llvm/MC/MachineLocation.h"
1809467b48Spatrick #include "llvm/Support/Debug.h"
1909467b48Spatrick 
2009467b48Spatrick namespace llvm {
2109467b48Spatrick class AsmPrinter;
2209467b48Spatrick 
2309467b48Spatrick /// This struct describes target specific location.
2409467b48Spatrick struct TargetIndexLocation {
2509467b48Spatrick   int Index;
2609467b48Spatrick   int Offset;
2709467b48Spatrick 
2809467b48Spatrick   TargetIndexLocation() = default;
TargetIndexLocationTargetIndexLocation2909467b48Spatrick   TargetIndexLocation(unsigned Idx, int64_t Offset)
3009467b48Spatrick       : Index(Idx), Offset(Offset) {}
3109467b48Spatrick 
3209467b48Spatrick   bool operator==(const TargetIndexLocation &Other) const {
3309467b48Spatrick     return Index == Other.Index && Offset == Other.Offset;
3409467b48Spatrick   }
3509467b48Spatrick };
3609467b48Spatrick 
3773471bf0Spatrick /// A single location or constant within a variable location description, with
3873471bf0Spatrick /// either a single entry (with an optional DIExpression) used for a DBG_VALUE,
3973471bf0Spatrick /// or a list of entries used for a DBG_VALUE_LIST.
4073471bf0Spatrick class DbgValueLocEntry {
4109467b48Spatrick 
4209467b48Spatrick   /// Type of entry that this represents.
4309467b48Spatrick   enum EntryType {
4409467b48Spatrick     E_Location,
4509467b48Spatrick     E_Integer,
4609467b48Spatrick     E_ConstantFP,
4709467b48Spatrick     E_ConstantInt,
4809467b48Spatrick     E_TargetIndexLocation
4909467b48Spatrick   };
5009467b48Spatrick   enum EntryType EntryKind;
5109467b48Spatrick 
5209467b48Spatrick   /// Either a constant,
5309467b48Spatrick   union {
5409467b48Spatrick     int64_t Int;
5509467b48Spatrick     const ConstantFP *CFP;
5609467b48Spatrick     const ConstantInt *CIP;
5709467b48Spatrick   } Constant;
5809467b48Spatrick 
5909467b48Spatrick   union {
6009467b48Spatrick     /// Or a location in the machine frame.
6109467b48Spatrick     MachineLocation Loc;
6209467b48Spatrick     /// Or a location from target specific location.
6309467b48Spatrick     TargetIndexLocation TIL;
6409467b48Spatrick   };
6509467b48Spatrick 
6609467b48Spatrick public:
DbgValueLocEntry(int64_t i)6773471bf0Spatrick   DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; }
DbgValueLocEntry(const ConstantFP * CFP)6873471bf0Spatrick   DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) {
6909467b48Spatrick     Constant.CFP = CFP;
7009467b48Spatrick   }
DbgValueLocEntry(const ConstantInt * CIP)7173471bf0Spatrick   DbgValueLocEntry(const ConstantInt *CIP) : EntryKind(E_ConstantInt) {
7209467b48Spatrick     Constant.CIP = CIP;
7309467b48Spatrick   }
DbgValueLocEntry(MachineLocation Loc)7473471bf0Spatrick   DbgValueLocEntry(MachineLocation Loc) : EntryKind(E_Location), Loc(Loc) {}
DbgValueLocEntry(TargetIndexLocation Loc)7573471bf0Spatrick   DbgValueLocEntry(TargetIndexLocation Loc)
7673471bf0Spatrick       : EntryKind(E_TargetIndexLocation), TIL(Loc) {}
7709467b48Spatrick 
isLocation()7809467b48Spatrick   bool isLocation() const { return EntryKind == E_Location; }
isIndirectLocation()79*d415bd75Srobert   bool isIndirectLocation() const {
80*d415bd75Srobert     return EntryKind == E_Location && Loc.isIndirect();
81*d415bd75Srobert   }
isTargetIndexLocation()8209467b48Spatrick   bool isTargetIndexLocation() const {
8309467b48Spatrick     return EntryKind == E_TargetIndexLocation;
8409467b48Spatrick   }
isInt()8509467b48Spatrick   bool isInt() const { return EntryKind == E_Integer; }
isConstantFP()8609467b48Spatrick   bool isConstantFP() const { return EntryKind == E_ConstantFP; }
isConstantInt()8709467b48Spatrick   bool isConstantInt() const { return EntryKind == E_ConstantInt; }
getInt()8809467b48Spatrick   int64_t getInt() const { return Constant.Int; }
getConstantFP()8909467b48Spatrick   const ConstantFP *getConstantFP() const { return Constant.CFP; }
getConstantInt()9009467b48Spatrick   const ConstantInt *getConstantInt() const { return Constant.CIP; }
getLoc()9109467b48Spatrick   MachineLocation getLoc() const { return Loc; }
getTargetIndexLocation()9209467b48Spatrick   TargetIndexLocation getTargetIndexLocation() const { return TIL; }
9373471bf0Spatrick   friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &);
9409467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()9509467b48Spatrick   LLVM_DUMP_METHOD void dump() const {
9609467b48Spatrick     if (isLocation()) {
9709467b48Spatrick       llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
9809467b48Spatrick       if (Loc.isIndirect())
9909467b48Spatrick         llvm::dbgs() << "+0";
10009467b48Spatrick       llvm::dbgs() << "} ";
10109467b48Spatrick     } else if (isConstantInt())
10209467b48Spatrick       Constant.CIP->dump();
10309467b48Spatrick     else if (isConstantFP())
10409467b48Spatrick       Constant.CFP->dump();
10573471bf0Spatrick   }
10673471bf0Spatrick #endif
10773471bf0Spatrick };
10873471bf0Spatrick 
10973471bf0Spatrick /// The location of a single variable, composed of an expression and 0 or more
11073471bf0Spatrick /// DbgValueLocEntries.
11173471bf0Spatrick class DbgValueLoc {
11273471bf0Spatrick   /// Any complex address location expression for this DbgValueLoc.
11373471bf0Spatrick   const DIExpression *Expression;
11473471bf0Spatrick 
11573471bf0Spatrick   SmallVector<DbgValueLocEntry, 2> ValueLocEntries;
11673471bf0Spatrick 
11773471bf0Spatrick   bool IsVariadic;
11873471bf0Spatrick 
11973471bf0Spatrick public:
DbgValueLoc(const DIExpression * Expr,ArrayRef<DbgValueLocEntry> Locs)12073471bf0Spatrick   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)
12173471bf0Spatrick       : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
122*d415bd75Srobert         IsVariadic(true) {}
12373471bf0Spatrick 
DbgValueLoc(const DIExpression * Expr,ArrayRef<DbgValueLocEntry> Locs,bool IsVariadic)12473471bf0Spatrick   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,
12573471bf0Spatrick               bool IsVariadic)
12673471bf0Spatrick       : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
12773471bf0Spatrick         IsVariadic(IsVariadic) {
12873471bf0Spatrick #ifndef NDEBUG
12973471bf0Spatrick     assert(cast<DIExpression>(Expr)->isValid() ||
13073471bf0Spatrick            !any_of(Locs, [](auto LE) { return LE.isLocation(); }));
13173471bf0Spatrick     if (!IsVariadic) {
13273471bf0Spatrick       assert(ValueLocEntries.size() == 1);
13373471bf0Spatrick     }
13473471bf0Spatrick #endif
13573471bf0Spatrick   }
13673471bf0Spatrick 
DbgValueLoc(const DIExpression * Expr,DbgValueLocEntry Loc)13773471bf0Spatrick   DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc)
13873471bf0Spatrick       : Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) {
13973471bf0Spatrick     assert(((Expr && Expr->isValid()) || !Loc.isLocation()) &&
14073471bf0Spatrick            "DBG_VALUE with a machine location must have a valid expression.");
14173471bf0Spatrick   }
14273471bf0Spatrick 
isFragment()14373471bf0Spatrick   bool isFragment() const { return getExpression()->isFragment(); }
isEntryVal()14473471bf0Spatrick   bool isEntryVal() const { return getExpression()->isEntryValue(); }
isVariadic()14573471bf0Spatrick   bool isVariadic() const { return IsVariadic; }
isEquivalent(const DbgValueLoc & Other)146*d415bd75Srobert   bool isEquivalent(const DbgValueLoc &Other) const {
147*d415bd75Srobert     // Cannot be equivalent with different numbers of entries.
148*d415bd75Srobert     if (ValueLocEntries.size() != Other.ValueLocEntries.size())
149*d415bd75Srobert       return false;
150*d415bd75Srobert     bool ThisIsIndirect =
151*d415bd75Srobert         !IsVariadic && ValueLocEntries[0].isIndirectLocation();
152*d415bd75Srobert     bool OtherIsIndirect =
153*d415bd75Srobert         !Other.IsVariadic && Other.ValueLocEntries[0].isIndirectLocation();
154*d415bd75Srobert     // Check equivalence of DIExpressions + Directness together.
155*d415bd75Srobert     if (!DIExpression::isEqualExpression(Expression, ThisIsIndirect,
156*d415bd75Srobert                                          Other.Expression, OtherIsIndirect))
157*d415bd75Srobert       return false;
158*d415bd75Srobert     // Indirectness should have been accounted for in the above check, so just
159*d415bd75Srobert     // compare register values directly here.
160*d415bd75Srobert     if (ThisIsIndirect || OtherIsIndirect) {
161*d415bd75Srobert       DbgValueLocEntry ThisOp = ValueLocEntries[0];
162*d415bd75Srobert       DbgValueLocEntry OtherOp = Other.ValueLocEntries[0];
163*d415bd75Srobert       return ThisOp.isLocation() && OtherOp.isLocation() &&
164*d415bd75Srobert              ThisOp.getLoc().getReg() == OtherOp.getLoc().getReg();
16573471bf0Spatrick     }
166*d415bd75Srobert     // If neither are indirect, then just compare the loc entries directly.
167*d415bd75Srobert     return ValueLocEntries == Other.ValueLocEntries;
168*d415bd75Srobert   }
getExpression()169*d415bd75Srobert   const DIExpression *getExpression() const { return Expression; }
getLocEntries()170*d415bd75Srobert   ArrayRef<DbgValueLocEntry> getLocEntries() const { return ValueLocEntries; }
17173471bf0Spatrick   friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);
17273471bf0Spatrick   friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);
17373471bf0Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()17473471bf0Spatrick   LLVM_DUMP_METHOD void dump() const {
175*d415bd75Srobert     for (const DbgValueLocEntry &DV : ValueLocEntries)
17673471bf0Spatrick       DV.dump();
17709467b48Spatrick     if (Expression)
17809467b48Spatrick       Expression->dump();
17909467b48Spatrick   }
18009467b48Spatrick #endif
18109467b48Spatrick };
18209467b48Spatrick 
18309467b48Spatrick /// This struct describes location entries emitted in the .debug_loc
18409467b48Spatrick /// section.
18509467b48Spatrick class DebugLocEntry {
18609467b48Spatrick   /// Begin and end symbols for the address range that this location is valid.
18709467b48Spatrick   const MCSymbol *Begin;
18809467b48Spatrick   const MCSymbol *End;
18909467b48Spatrick 
19009467b48Spatrick   /// A nonempty list of locations/constants belonging to this entry,
19109467b48Spatrick   /// sorted by offset.
19209467b48Spatrick   SmallVector<DbgValueLoc, 1> Values;
19309467b48Spatrick 
19409467b48Spatrick public:
19509467b48Spatrick   /// Create a location list entry for the range [\p Begin, \p End).
19609467b48Spatrick   ///
19709467b48Spatrick   /// \param Vals One or more values describing (parts of) the variable.
DebugLocEntry(const MCSymbol * Begin,const MCSymbol * End,ArrayRef<DbgValueLoc> Vals)19809467b48Spatrick   DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,
19909467b48Spatrick                 ArrayRef<DbgValueLoc> Vals)
20009467b48Spatrick       : Begin(Begin), End(End) {
20109467b48Spatrick     addValues(Vals);
20209467b48Spatrick   }
20309467b48Spatrick 
20409467b48Spatrick   /// Attempt to merge this DebugLocEntry with Next and return
20509467b48Spatrick   /// true if the merge was successful. Entries can be merged if they
20609467b48Spatrick   /// share the same Loc/Constant and if Next immediately follows this
20709467b48Spatrick   /// Entry.
MergeRanges(const DebugLocEntry & Next)20809467b48Spatrick   bool MergeRanges(const DebugLocEntry &Next) {
20909467b48Spatrick     // If this and Next are describing the same variable, merge them.
210*d415bd75Srobert     if (End != Next.Begin)
211*d415bd75Srobert       return false;
212*d415bd75Srobert     if (Values.size() != Next.Values.size())
213*d415bd75Srobert       return false;
214*d415bd75Srobert     for (unsigned EntryIdx = 0; EntryIdx < Values.size(); ++EntryIdx)
215*d415bd75Srobert       if (!Values[EntryIdx].isEquivalent(Next.Values[EntryIdx]))
216*d415bd75Srobert         return false;
21709467b48Spatrick     End = Next.End;
21809467b48Spatrick     return true;
21909467b48Spatrick   }
22009467b48Spatrick 
getBeginSym()22109467b48Spatrick   const MCSymbol *getBeginSym() const { return Begin; }
getEndSym()22209467b48Spatrick   const MCSymbol *getEndSym() const { return End; }
getValues()22309467b48Spatrick   ArrayRef<DbgValueLoc> getValues() const { return Values; }
addValues(ArrayRef<DbgValueLoc> Vals)22409467b48Spatrick   void addValues(ArrayRef<DbgValueLoc> Vals) {
22509467b48Spatrick     Values.append(Vals.begin(), Vals.end());
22609467b48Spatrick     sortUniqueValues();
22709467b48Spatrick     assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
22809467b48Spatrick               return V.isFragment();
22909467b48Spatrick             })) && "must either have a single value or multiple pieces");
23009467b48Spatrick   }
23109467b48Spatrick 
23209467b48Spatrick   // Sort the pieces by offset.
23309467b48Spatrick   // Remove any duplicate entries by dropping all but the first.
sortUniqueValues()23409467b48Spatrick   void sortUniqueValues() {
235*d415bd75Srobert     // Values is either 1 item that does not have a fragment, or many items
236*d415bd75Srobert     // that all do. No need to sort if the former and also prevents operator<
237*d415bd75Srobert     // being called on a non fragment item when _GLIBCXX_DEBUG is defined.
238*d415bd75Srobert     if (Values.size() == 1)
239*d415bd75Srobert       return;
24009467b48Spatrick     llvm::sort(Values);
24109467b48Spatrick     Values.erase(std::unique(Values.begin(), Values.end(),
24209467b48Spatrick                              [](const DbgValueLoc &A, const DbgValueLoc &B) {
24309467b48Spatrick                                return A.getExpression() == B.getExpression();
24409467b48Spatrick                              }),
24509467b48Spatrick                  Values.end());
24609467b48Spatrick   }
24709467b48Spatrick 
24809467b48Spatrick   /// Lower this entry into a DWARF expression.
24909467b48Spatrick   void finalize(const AsmPrinter &AP,
25009467b48Spatrick                 DebugLocStream::ListBuilder &List,
25109467b48Spatrick                 const DIBasicType *BT,
25209467b48Spatrick                 DwarfCompileUnit &TheCU);
25309467b48Spatrick };
25409467b48Spatrick 
25573471bf0Spatrick /// Compare two DbgValueLocEntries for equality.
25673471bf0Spatrick inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {
25709467b48Spatrick   if (A.EntryKind != B.EntryKind)
25809467b48Spatrick     return false;
25909467b48Spatrick 
26009467b48Spatrick   switch (A.EntryKind) {
26173471bf0Spatrick   case DbgValueLocEntry::E_Location:
26209467b48Spatrick     return A.Loc == B.Loc;
26373471bf0Spatrick   case DbgValueLocEntry::E_TargetIndexLocation:
26409467b48Spatrick     return A.TIL == B.TIL;
26573471bf0Spatrick   case DbgValueLocEntry::E_Integer:
26609467b48Spatrick     return A.Constant.Int == B.Constant.Int;
26773471bf0Spatrick   case DbgValueLocEntry::E_ConstantFP:
26809467b48Spatrick     return A.Constant.CFP == B.Constant.CFP;
26973471bf0Spatrick   case DbgValueLocEntry::E_ConstantInt:
27009467b48Spatrick     return A.Constant.CIP == B.Constant.CIP;
27109467b48Spatrick   }
27209467b48Spatrick   llvm_unreachable("unhandled EntryKind");
27309467b48Spatrick }
27409467b48Spatrick 
27573471bf0Spatrick /// Compare two DbgValueLocs for equality.
27673471bf0Spatrick inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) {
27773471bf0Spatrick   return A.ValueLocEntries == B.ValueLocEntries &&
27873471bf0Spatrick          A.Expression == B.Expression && A.IsVariadic == B.IsVariadic;
27973471bf0Spatrick }
28073471bf0Spatrick 
28109467b48Spatrick /// Compare two fragments based on their offset.
28209467b48Spatrick inline bool operator<(const DbgValueLoc &A,
28309467b48Spatrick                       const DbgValueLoc &B) {
28409467b48Spatrick   return A.getExpression()->getFragmentInfo()->OffsetInBits <
28509467b48Spatrick          B.getExpression()->getFragmentInfo()->OffsetInBits;
28609467b48Spatrick }
28709467b48Spatrick 
28809467b48Spatrick }
28909467b48Spatrick 
29009467b48Spatrick #endif
291