Home | History | Annotate | Download | only in AsmPrinter
      1 //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
     11 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
     12 #include "llvm/ADT/SmallString.h"
     13 #include "llvm/IR/Constants.h"
     14 #include "llvm/IR/DebugInfo.h"
     15 #include "llvm/MC/MCSymbol.h"
     16 #include "llvm/MC/MachineLocation.h"
     17 
     18 namespace llvm {
     19 class AsmPrinter;
     20 class MDNode;
     21 /// \brief This struct describes location entries emitted in the .debug_loc
     22 /// section.
     23 class DebugLocEntry {
     24   /// Begin and end symbols for the address range that this location is valid.
     25   const MCSymbol *Begin;
     26   const MCSymbol *End;
     27 
     28 public:
     29   /// \brief A single location or constant.
     30   struct Value {
     31     Value(const MDNode *Var, const MDNode *Expr, int64_t i)
     32         : Variable(Var), Expression(Expr), EntryKind(E_Integer) {
     33       Constant.Int = i;
     34     }
     35     Value(const MDNode *Var, const MDNode *Expr, const ConstantFP *CFP)
     36         : Variable(Var), Expression(Expr), EntryKind(E_ConstantFP) {
     37       Constant.CFP = CFP;
     38     }
     39     Value(const MDNode *Var, const MDNode *Expr, const ConstantInt *CIP)
     40         : Variable(Var), Expression(Expr), EntryKind(E_ConstantInt) {
     41       Constant.CIP = CIP;
     42     }
     43     Value(const MDNode *Var, const MDNode *Expr, MachineLocation Loc)
     44         : Variable(Var), Expression(Expr), EntryKind(E_Location), Loc(Loc) {
     45       assert(isa<MDLocalVariable>(Var));
     46       assert(cast<MDExpression>(Expr)->isValid());
     47     }
     48 
     49     /// The variable to which this location entry corresponds.
     50     const MDNode *Variable;
     51 
     52     /// Any complex address location expression for this Value.
     53     const MDNode *Expression;
     54 
     55     /// Type of entry that this represents.
     56     enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
     57     enum EntryType EntryKind;
     58 
     59     /// Either a constant,
     60     union {
     61       int64_t Int;
     62       const ConstantFP *CFP;
     63       const ConstantInt *CIP;
     64     } Constant;
     65 
     66     // Or a location in the machine frame.
     67     MachineLocation Loc;
     68 
     69     bool isLocation() const { return EntryKind == E_Location; }
     70     bool isInt() const { return EntryKind == E_Integer; }
     71     bool isConstantFP() const { return EntryKind == E_ConstantFP; }
     72     bool isConstantInt() const { return EntryKind == E_ConstantInt; }
     73     int64_t getInt() const { return Constant.Int; }
     74     const ConstantFP *getConstantFP() const { return Constant.CFP; }
     75     const ConstantInt *getConstantInt() const { return Constant.CIP; }
     76     MachineLocation getLoc() const { return Loc; }
     77     DIVariable getVariable() const { return cast<MDLocalVariable>(Variable); }
     78     bool isBitPiece() const { return getExpression()->isBitPiece(); }
     79     DIExpression getExpression() const {
     80       return cast_or_null<MDExpression>(Expression);
     81     }
     82     friend bool operator==(const Value &, const Value &);
     83     friend bool operator<(const Value &, const Value &);
     84   };
     85 
     86 private:
     87   /// A nonempty list of locations/constants belonging to this entry,
     88   /// sorted by offset.
     89   SmallVector<Value, 1> Values;
     90   SmallString<8> DWARFBytes;
     91   SmallVector<std::string, 1> Comments;
     92 
     93 public:
     94   DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val)
     95       : Begin(B), End(E) {
     96     Values.push_back(std::move(Val));
     97   }
     98 
     99   /// \brief If this and Next are describing different pieces of the same
    100   /// variable, merge them by appending Next's values to the current
    101   /// list of values.
    102   /// Return true if the merge was successful.
    103   bool MergeValues(const DebugLocEntry &Next) {
    104     if (Begin == Next.Begin) {
    105       DIExpression Expr = cast_or_null<MDExpression>(Values[0].Expression);
    106       DIVariable Var = cast_or_null<MDLocalVariable>(Values[0].Variable);
    107       DIExpression NextExpr =
    108           cast_or_null<MDExpression>(Next.Values[0].Expression);
    109       DIVariable NextVar = cast_or_null<MDLocalVariable>(Next.Values[0].Variable);
    110       if (Var == NextVar && Expr->isBitPiece() && NextExpr->isBitPiece()) {
    111         addValues(Next.Values);
    112         End = Next.End;
    113         return true;
    114       }
    115     }
    116     return false;
    117   }
    118 
    119   /// \brief Attempt to merge this DebugLocEntry with Next and return
    120   /// true if the merge was successful. Entries can be merged if they
    121   /// share the same Loc/Constant and if Next immediately follows this
    122   /// Entry.
    123   bool MergeRanges(const DebugLocEntry &Next) {
    124     // If this and Next are describing the same variable, merge them.
    125     if ((End == Next.Begin && Values == Next.Values)) {
    126       End = Next.End;
    127       return true;
    128     }
    129     return false;
    130   }
    131 
    132   const MCSymbol *getBeginSym() const { return Begin; }
    133   const MCSymbol *getEndSym() const { return End; }
    134   ArrayRef<Value> getValues() const { return Values; }
    135   void addValues(ArrayRef<DebugLocEntry::Value> Vals) {
    136     Values.append(Vals.begin(), Vals.end());
    137     sortUniqueValues();
    138     assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){
    139           return V.isBitPiece();
    140         }) && "value must be a piece");
    141   }
    142 
    143   // \brief Sort the pieces by offset.
    144   // Remove any duplicate entries by dropping all but the first.
    145   void sortUniqueValues() {
    146     std::sort(Values.begin(), Values.end());
    147     Values.erase(std::unique(Values.begin(), Values.end(),
    148                              [](const Value &A, const Value &B) {
    149                    return A.getVariable() == B.getVariable() &&
    150                           A.getExpression() == B.getExpression();
    151                  }),
    152                  Values.end());
    153   }
    154 
    155   /// \brief Lower this entry into a DWARF expression.
    156   void finalize(const AsmPrinter &AP,
    157                 const DITypeIdentifierMap &TypeIdentifierMap);
    158 
    159   /// \brief Return the lowered DWARF expression.
    160   StringRef getDWARFBytes() const { return DWARFBytes; }
    161   /// \brief Return the assembler comments for the lowered DWARF expression.
    162   const SmallVectorImpl<std::string> &getComments() const { return Comments; }
    163 };
    164 
    165 /// \brief Compare two Values for equality.
    166 inline bool operator==(const DebugLocEntry::Value &A,
    167                        const DebugLocEntry::Value &B) {
    168   if (A.EntryKind != B.EntryKind)
    169     return false;
    170 
    171   if (A.Expression != B.Expression)
    172     return false;
    173 
    174   if (A.Variable != B.Variable)
    175     return false;
    176 
    177   switch (A.EntryKind) {
    178   case DebugLocEntry::Value::E_Location:
    179     return A.Loc == B.Loc;
    180   case DebugLocEntry::Value::E_Integer:
    181     return A.Constant.Int == B.Constant.Int;
    182   case DebugLocEntry::Value::E_ConstantFP:
    183     return A.Constant.CFP == B.Constant.CFP;
    184   case DebugLocEntry::Value::E_ConstantInt:
    185     return A.Constant.CIP == B.Constant.CIP;
    186   }
    187   llvm_unreachable("unhandled EntryKind");
    188 }
    189 
    190 /// \brief Compare two pieces based on their offset.
    191 inline bool operator<(const DebugLocEntry::Value &A,
    192                       const DebugLocEntry::Value &B) {
    193   return A.getExpression()->getBitPieceOffset() <
    194          B.getExpression()->getBitPieceOffset();
    195 }
    196 
    197 }
    198 
    199 #endif
    200