Home | History | Annotate | Line # | Download | only in AsmPrinter
      1 //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
     10 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
     11 
     12 #include "DebugLocStream.h"
     13 #include "llvm/Config/llvm-config.h"
     14 #include "llvm/IR/Constants.h"
     15 #include "llvm/IR/DebugInfo.h"
     16 #include "llvm/MC/MCSymbol.h"
     17 #include "llvm/MC/MachineLocation.h"
     18 #include "llvm/Support/Debug.h"
     19 
     20 namespace llvm {
     21 class AsmPrinter;
     22 
     23 /// This struct describes target specific location.
     24 struct TargetIndexLocation {
     25   int Index;
     26   int Offset;
     27 
     28   TargetIndexLocation() = default;
     29   TargetIndexLocation(unsigned Idx, int64_t Offset)
     30       : Index(Idx), Offset(Offset) {}
     31 
     32   bool operator==(const TargetIndexLocation &Other) const {
     33     return Index == Other.Index && Offset == Other.Offset;
     34   }
     35 };
     36 
     37 /// A single location or constant within a variable location description, with
     38 /// either a single entry (with an optional DIExpression) used for a DBG_VALUE,
     39 /// or a list of entries used for a DBG_VALUE_LIST.
     40 class DbgValueLocEntry {
     41 
     42   /// Type of entry that this represents.
     43   enum EntryType {
     44     E_Location,
     45     E_Integer,
     46     E_ConstantFP,
     47     E_ConstantInt,
     48     E_TargetIndexLocation
     49   };
     50   enum EntryType EntryKind;
     51 
     52   /// Either a constant,
     53   union {
     54     int64_t Int;
     55     const ConstantFP *CFP;
     56     const ConstantInt *CIP;
     57   } Constant;
     58 
     59   union {
     60     /// Or a location in the machine frame.
     61     MachineLocation Loc;
     62     /// Or a location from target specific location.
     63     TargetIndexLocation TIL;
     64   };
     65 
     66 public:
     67   DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; }
     68   DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) {
     69     Constant.CFP = CFP;
     70   }
     71   DbgValueLocEntry(const ConstantInt *CIP) : EntryKind(E_ConstantInt) {
     72     Constant.CIP = CIP;
     73   }
     74   DbgValueLocEntry(MachineLocation Loc) : EntryKind(E_Location), Loc(Loc) {}
     75   DbgValueLocEntry(TargetIndexLocation Loc)
     76       : EntryKind(E_TargetIndexLocation), TIL(Loc) {}
     77 
     78   bool isLocation() const { return EntryKind == E_Location; }
     79   bool isTargetIndexLocation() const {
     80     return EntryKind == E_TargetIndexLocation;
     81   }
     82   bool isInt() const { return EntryKind == E_Integer; }
     83   bool isConstantFP() const { return EntryKind == E_ConstantFP; }
     84   bool isConstantInt() const { return EntryKind == E_ConstantInt; }
     85   int64_t getInt() const { return Constant.Int; }
     86   const ConstantFP *getConstantFP() const { return Constant.CFP; }
     87   const ConstantInt *getConstantInt() const { return Constant.CIP; }
     88   MachineLocation getLoc() const { return Loc; }
     89   TargetIndexLocation getTargetIndexLocation() const { return TIL; }
     90   friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &);
     91 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     92   LLVM_DUMP_METHOD void dump() const {
     93     if (isLocation()) {
     94       llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
     95       if (Loc.isIndirect())
     96         llvm::dbgs() << "+0";
     97       llvm::dbgs() << "} ";
     98     } else if (isConstantInt())
     99       Constant.CIP->dump();
    100     else if (isConstantFP())
    101       Constant.CFP->dump();
    102   }
    103 #endif
    104 };
    105 
    106 /// The location of a single variable, composed of an expression and 0 or more
    107 /// DbgValueLocEntries.
    108 class DbgValueLoc {
    109   /// Any complex address location expression for this DbgValueLoc.
    110   const DIExpression *Expression;
    111 
    112   SmallVector<DbgValueLocEntry, 2> ValueLocEntries;
    113 
    114   bool IsVariadic;
    115 
    116 public:
    117   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)
    118       : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
    119         IsVariadic(true) {
    120 #ifndef NDEBUG
    121     // Currently, DBG_VALUE_VAR expressions must use stack_value.
    122     assert(Expr && Expr->isValid() &&
    123            is_contained(Locs, dwarf::DW_OP_stack_value));
    124 #endif
    125   }
    126 
    127   DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,
    128               bool IsVariadic)
    129       : Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),
    130         IsVariadic(IsVariadic) {
    131 #ifndef NDEBUG
    132     assert(cast<DIExpression>(Expr)->isValid() ||
    133            !any_of(Locs, [](auto LE) { return LE.isLocation(); }));
    134     if (!IsVariadic) {
    135       assert(ValueLocEntries.size() == 1);
    136     } else {
    137       // Currently, DBG_VALUE_VAR expressions must use stack_value.
    138       assert(Expr && Expr->isValid() &&
    139              is_contained(Expr->getElements(), dwarf::DW_OP_stack_value));
    140     }
    141 #endif
    142   }
    143 
    144   DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc)
    145       : Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) {
    146     assert(((Expr && Expr->isValid()) || !Loc.isLocation()) &&
    147            "DBG_VALUE with a machine location must have a valid expression.");
    148   }
    149 
    150   bool isFragment() const { return getExpression()->isFragment(); }
    151   bool isEntryVal() const { return getExpression()->isEntryValue(); }
    152   bool isVariadic() const { return IsVariadic; }
    153   const DIExpression *getExpression() const { return Expression; }
    154   const ArrayRef<DbgValueLocEntry> getLocEntries() const {
    155     return ValueLocEntries;
    156   }
    157   friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);
    158   friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);
    159 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    160   LLVM_DUMP_METHOD void dump() const {
    161     for (DbgValueLocEntry DV : ValueLocEntries)
    162       DV.dump();
    163     if (Expression)
    164       Expression->dump();
    165   }
    166 #endif
    167 };
    168 
    169 /// This struct describes location entries emitted in the .debug_loc
    170 /// section.
    171 class DebugLocEntry {
    172   /// Begin and end symbols for the address range that this location is valid.
    173   const MCSymbol *Begin;
    174   const MCSymbol *End;
    175 
    176   /// A nonempty list of locations/constants belonging to this entry,
    177   /// sorted by offset.
    178   SmallVector<DbgValueLoc, 1> Values;
    179 
    180 public:
    181   /// Create a location list entry for the range [\p Begin, \p End).
    182   ///
    183   /// \param Vals One or more values describing (parts of) the variable.
    184   DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,
    185                 ArrayRef<DbgValueLoc> Vals)
    186       : Begin(Begin), End(End) {
    187     addValues(Vals);
    188   }
    189 
    190   /// Attempt to merge this DebugLocEntry with Next and return
    191   /// true if the merge was successful. Entries can be merged if they
    192   /// share the same Loc/Constant and if Next immediately follows this
    193   /// Entry.
    194   bool MergeRanges(const DebugLocEntry &Next) {
    195     // If this and Next are describing the same variable, merge them.
    196     if ((End == Next.Begin && Values == Next.Values)) {
    197       End = Next.End;
    198       return true;
    199     }
    200     return false;
    201   }
    202 
    203   const MCSymbol *getBeginSym() const { return Begin; }
    204   const MCSymbol *getEndSym() const { return End; }
    205   ArrayRef<DbgValueLoc> getValues() const { return Values; }
    206   void addValues(ArrayRef<DbgValueLoc> Vals) {
    207     Values.append(Vals.begin(), Vals.end());
    208     sortUniqueValues();
    209     assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
    210               return V.isFragment();
    211             })) && "must either have a single value or multiple pieces");
    212   }
    213 
    214   // Sort the pieces by offset.
    215   // Remove any duplicate entries by dropping all but the first.
    216   void sortUniqueValues() {
    217     llvm::sort(Values);
    218     Values.erase(std::unique(Values.begin(), Values.end(),
    219                              [](const DbgValueLoc &A, const DbgValueLoc &B) {
    220                                return A.getExpression() == B.getExpression();
    221                              }),
    222                  Values.end());
    223   }
    224 
    225   /// Lower this entry into a DWARF expression.
    226   void finalize(const AsmPrinter &AP,
    227                 DebugLocStream::ListBuilder &List,
    228                 const DIBasicType *BT,
    229                 DwarfCompileUnit &TheCU);
    230 };
    231 
    232 /// Compare two DbgValueLocEntries for equality.
    233 inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {
    234   if (A.EntryKind != B.EntryKind)
    235     return false;
    236 
    237   switch (A.EntryKind) {
    238   case DbgValueLocEntry::E_Location:
    239     return A.Loc == B.Loc;
    240   case DbgValueLocEntry::E_TargetIndexLocation:
    241     return A.TIL == B.TIL;
    242   case DbgValueLocEntry::E_Integer:
    243     return A.Constant.Int == B.Constant.Int;
    244   case DbgValueLocEntry::E_ConstantFP:
    245     return A.Constant.CFP == B.Constant.CFP;
    246   case DbgValueLocEntry::E_ConstantInt:
    247     return A.Constant.CIP == B.Constant.CIP;
    248   }
    249   llvm_unreachable("unhandled EntryKind");
    250 }
    251 
    252 /// Compare two DbgValueLocs for equality.
    253 inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) {
    254   return A.ValueLocEntries == B.ValueLocEntries &&
    255          A.Expression == B.Expression && A.IsVariadic == B.IsVariadic;
    256 }
    257 
    258 /// Compare two fragments based on their offset.
    259 inline bool operator<(const DbgValueLoc &A,
    260                       const DbgValueLoc &B) {
    261   return A.getExpression()->getFragmentInfo()->OffsetInBits <
    262          B.getExpression()->getFragmentInfo()->OffsetInBits;
    263 }
    264 
    265 }
    266 
    267 #endif
    268