xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
10b57cec5SDimitry Andric //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
100b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "DebugLocStream.h"
130b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
140b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
150b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
170b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h"
180b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric class AsmPrinter;
220b57cec5SDimitry Andric 
23*480093f4SDimitry Andric /// This struct describes target specific location.
24*480093f4SDimitry Andric struct TargetIndexLocation {
25*480093f4SDimitry Andric   int Index;
26*480093f4SDimitry Andric   int Offset;
27*480093f4SDimitry Andric 
28*480093f4SDimitry Andric   TargetIndexLocation() = default;
29*480093f4SDimitry Andric   TargetIndexLocation(unsigned Idx, int64_t Offset)
30*480093f4SDimitry Andric       : Index(Idx), Offset(Offset) {}
31*480093f4SDimitry Andric 
32*480093f4SDimitry Andric   bool operator==(const TargetIndexLocation &Other) const {
33*480093f4SDimitry Andric     return Index == Other.Index && Offset == Other.Offset;
34*480093f4SDimitry Andric   }
35*480093f4SDimitry Andric };
36*480093f4SDimitry Andric 
370b57cec5SDimitry Andric /// A single location or constant.
380b57cec5SDimitry Andric class DbgValueLoc {
390b57cec5SDimitry Andric   /// Any complex address location expression for this DbgValueLoc.
400b57cec5SDimitry Andric   const DIExpression *Expression;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   /// Type of entry that this represents.
43*480093f4SDimitry Andric   enum EntryType {
44*480093f4SDimitry Andric     E_Location,
45*480093f4SDimitry Andric     E_Integer,
46*480093f4SDimitry Andric     E_ConstantFP,
47*480093f4SDimitry Andric     E_ConstantInt,
48*480093f4SDimitry Andric     E_TargetIndexLocation
49*480093f4SDimitry Andric   };
500b57cec5SDimitry Andric   enum EntryType EntryKind;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   /// Either a constant,
530b57cec5SDimitry Andric   union {
540b57cec5SDimitry Andric     int64_t Int;
550b57cec5SDimitry Andric     const ConstantFP *CFP;
560b57cec5SDimitry Andric     const ConstantInt *CIP;
570b57cec5SDimitry Andric   } Constant;
580b57cec5SDimitry Andric 
59*480093f4SDimitry Andric   union {
600b57cec5SDimitry Andric     /// Or a location in the machine frame.
610b57cec5SDimitry Andric     MachineLocation Loc;
62*480093f4SDimitry Andric     /// Or a location from target specific location.
63*480093f4SDimitry Andric     TargetIndexLocation TIL;
64*480093f4SDimitry Andric   };
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric public:
670b57cec5SDimitry Andric   DbgValueLoc(const DIExpression *Expr, int64_t i)
680b57cec5SDimitry Andric       : Expression(Expr), EntryKind(E_Integer) {
690b57cec5SDimitry Andric     Constant.Int = i;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric   DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP)
720b57cec5SDimitry Andric       : Expression(Expr), EntryKind(E_ConstantFP) {
730b57cec5SDimitry Andric     Constant.CFP = CFP;
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric   DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP)
760b57cec5SDimitry Andric       : Expression(Expr), EntryKind(E_ConstantInt) {
770b57cec5SDimitry Andric     Constant.CIP = CIP;
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric   DbgValueLoc(const DIExpression *Expr, MachineLocation Loc)
800b57cec5SDimitry Andric       : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
810b57cec5SDimitry Andric     assert(cast<DIExpression>(Expr)->isValid());
820b57cec5SDimitry Andric   }
83*480093f4SDimitry Andric   DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc)
84*480093f4SDimitry Andric       : Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {}
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   bool isLocation() const { return EntryKind == E_Location; }
87*480093f4SDimitry Andric   bool isTargetIndexLocation() const {
88*480093f4SDimitry Andric     return EntryKind == E_TargetIndexLocation;
89*480093f4SDimitry Andric   }
900b57cec5SDimitry Andric   bool isInt() const { return EntryKind == E_Integer; }
910b57cec5SDimitry Andric   bool isConstantFP() const { return EntryKind == E_ConstantFP; }
920b57cec5SDimitry Andric   bool isConstantInt() const { return EntryKind == E_ConstantInt; }
930b57cec5SDimitry Andric   int64_t getInt() const { return Constant.Int; }
940b57cec5SDimitry Andric   const ConstantFP *getConstantFP() const { return Constant.CFP; }
950b57cec5SDimitry Andric   const ConstantInt *getConstantInt() const { return Constant.CIP; }
960b57cec5SDimitry Andric   MachineLocation getLoc() const { return Loc; }
97*480093f4SDimitry Andric   TargetIndexLocation getTargetIndexLocation() const { return TIL; }
980b57cec5SDimitry Andric   bool isFragment() const { return getExpression()->isFragment(); }
990b57cec5SDimitry Andric   bool isEntryVal() const { return getExpression()->isEntryValue(); }
1000b57cec5SDimitry Andric   const DIExpression *getExpression() const { return Expression; }
1010b57cec5SDimitry Andric   friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);
1020b57cec5SDimitry Andric   friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);
1030b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1040b57cec5SDimitry Andric   LLVM_DUMP_METHOD void dump() const {
1050b57cec5SDimitry Andric     if (isLocation()) {
1060b57cec5SDimitry Andric       llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
1070b57cec5SDimitry Andric       if (Loc.isIndirect())
1080b57cec5SDimitry Andric         llvm::dbgs() << "+0";
1090b57cec5SDimitry Andric       llvm::dbgs() << "} ";
1100b57cec5SDimitry Andric     } else if (isConstantInt())
1110b57cec5SDimitry Andric       Constant.CIP->dump();
1120b57cec5SDimitry Andric     else if (isConstantFP())
1130b57cec5SDimitry Andric       Constant.CFP->dump();
1140b57cec5SDimitry Andric     if (Expression)
1150b57cec5SDimitry Andric       Expression->dump();
1160b57cec5SDimitry Andric   }
1170b57cec5SDimitry Andric #endif
1180b57cec5SDimitry Andric };
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric /// This struct describes location entries emitted in the .debug_loc
1210b57cec5SDimitry Andric /// section.
1220b57cec5SDimitry Andric class DebugLocEntry {
1230b57cec5SDimitry Andric   /// Begin and end symbols for the address range that this location is valid.
1240b57cec5SDimitry Andric   const MCSymbol *Begin;
1250b57cec5SDimitry Andric   const MCSymbol *End;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   /// A nonempty list of locations/constants belonging to this entry,
1280b57cec5SDimitry Andric   /// sorted by offset.
1290b57cec5SDimitry Andric   SmallVector<DbgValueLoc, 1> Values;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric public:
1320b57cec5SDimitry Andric   /// Create a location list entry for the range [\p Begin, \p End).
1330b57cec5SDimitry Andric   ///
1340b57cec5SDimitry Andric   /// \param Vals One or more values describing (parts of) the variable.
1350b57cec5SDimitry Andric   DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,
1360b57cec5SDimitry Andric                 ArrayRef<DbgValueLoc> Vals)
1370b57cec5SDimitry Andric       : Begin(Begin), End(End) {
1380b57cec5SDimitry Andric     addValues(Vals);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   /// Attempt to merge this DebugLocEntry with Next and return
1420b57cec5SDimitry Andric   /// true if the merge was successful. Entries can be merged if they
1430b57cec5SDimitry Andric   /// share the same Loc/Constant and if Next immediately follows this
1440b57cec5SDimitry Andric   /// Entry.
1450b57cec5SDimitry Andric   bool MergeRanges(const DebugLocEntry &Next) {
1460b57cec5SDimitry Andric     // If this and Next are describing the same variable, merge them.
1470b57cec5SDimitry Andric     if ((End == Next.Begin && Values == Next.Values)) {
1480b57cec5SDimitry Andric       End = Next.End;
1490b57cec5SDimitry Andric       return true;
1500b57cec5SDimitry Andric     }
1510b57cec5SDimitry Andric     return false;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   const MCSymbol *getBeginSym() const { return Begin; }
1550b57cec5SDimitry Andric   const MCSymbol *getEndSym() const { return End; }
1560b57cec5SDimitry Andric   ArrayRef<DbgValueLoc> getValues() const { return Values; }
1570b57cec5SDimitry Andric   void addValues(ArrayRef<DbgValueLoc> Vals) {
1580b57cec5SDimitry Andric     Values.append(Vals.begin(), Vals.end());
1590b57cec5SDimitry Andric     sortUniqueValues();
1600b57cec5SDimitry Andric     assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
1610b57cec5SDimitry Andric               return V.isFragment();
1620b57cec5SDimitry Andric             })) && "must either have a single value or multiple pieces");
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   // Sort the pieces by offset.
1660b57cec5SDimitry Andric   // Remove any duplicate entries by dropping all but the first.
1670b57cec5SDimitry Andric   void sortUniqueValues() {
1680b57cec5SDimitry Andric     llvm::sort(Values);
1690b57cec5SDimitry Andric     Values.erase(std::unique(Values.begin(), Values.end(),
1700b57cec5SDimitry Andric                              [](const DbgValueLoc &A, const DbgValueLoc &B) {
1710b57cec5SDimitry Andric                                return A.getExpression() == B.getExpression();
1720b57cec5SDimitry Andric                              }),
1730b57cec5SDimitry Andric                  Values.end());
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   /// Lower this entry into a DWARF expression.
1770b57cec5SDimitry Andric   void finalize(const AsmPrinter &AP,
1780b57cec5SDimitry Andric                 DebugLocStream::ListBuilder &List,
1790b57cec5SDimitry Andric                 const DIBasicType *BT,
1800b57cec5SDimitry Andric                 DwarfCompileUnit &TheCU);
1810b57cec5SDimitry Andric };
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric /// Compare two DbgValueLocs for equality.
1840b57cec5SDimitry Andric inline bool operator==(const DbgValueLoc &A,
1850b57cec5SDimitry Andric                        const DbgValueLoc &B) {
1860b57cec5SDimitry Andric   if (A.EntryKind != B.EntryKind)
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   if (A.Expression != B.Expression)
1900b57cec5SDimitry Andric     return false;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   switch (A.EntryKind) {
1930b57cec5SDimitry Andric   case DbgValueLoc::E_Location:
1940b57cec5SDimitry Andric     return A.Loc == B.Loc;
195*480093f4SDimitry Andric   case DbgValueLoc::E_TargetIndexLocation:
196*480093f4SDimitry Andric     return A.TIL == B.TIL;
1970b57cec5SDimitry Andric   case DbgValueLoc::E_Integer:
1980b57cec5SDimitry Andric     return A.Constant.Int == B.Constant.Int;
1990b57cec5SDimitry Andric   case DbgValueLoc::E_ConstantFP:
2000b57cec5SDimitry Andric     return A.Constant.CFP == B.Constant.CFP;
2010b57cec5SDimitry Andric   case DbgValueLoc::E_ConstantInt:
2020b57cec5SDimitry Andric     return A.Constant.CIP == B.Constant.CIP;
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric   llvm_unreachable("unhandled EntryKind");
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric /// Compare two fragments based on their offset.
2080b57cec5SDimitry Andric inline bool operator<(const DbgValueLoc &A,
2090b57cec5SDimitry Andric                       const DbgValueLoc &B) {
2100b57cec5SDimitry Andric   return A.getExpression()->getFragmentInfo()->OffsetInBits <
2110b57cec5SDimitry Andric          B.getExpression()->getFragmentInfo()->OffsetInBits;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric #endif
217