LLVM API Documentation
00001 //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 00011 #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 00012 #include "llvm/IR/Constants.h" 00013 #include "llvm/IR/DebugInfo.h" 00014 #include "llvm/MC/MachineLocation.h" 00015 #include "llvm/MC/MCSymbol.h" 00016 00017 namespace llvm { 00018 class MDNode; 00019 /// \brief This struct describes location entries emitted in the .debug_loc 00020 /// section. 00021 class DebugLocEntry { 00022 // Begin and end symbols for the address range that this location is valid. 00023 const MCSymbol *Begin; 00024 const MCSymbol *End; 00025 00026 public: 00027 /// A single location or constant. 00028 struct Value { 00029 Value(const MDNode *Var, int64_t i) 00030 : Variable(Var), EntryKind(E_Integer) { 00031 Constant.Int = i; 00032 } 00033 Value(const MDNode *Var, const ConstantFP *CFP) 00034 : Variable(Var), EntryKind(E_ConstantFP) { 00035 Constant.CFP = CFP; 00036 } 00037 Value(const MDNode *Var, const ConstantInt *CIP) 00038 : Variable(Var), EntryKind(E_ConstantInt) { 00039 Constant.CIP = CIP; 00040 } 00041 Value(const MDNode *Var, MachineLocation Loc) 00042 : Variable(Var), EntryKind(E_Location), Loc(Loc) { 00043 } 00044 00045 // The variable to which this location entry corresponds. 00046 const MDNode *Variable; 00047 00048 // Type of entry that this represents. 00049 enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; 00050 enum EntryType EntryKind; 00051 00052 // Either a constant, 00053 union { 00054 int64_t Int; 00055 const ConstantFP *CFP; 00056 const ConstantInt *CIP; 00057 } Constant; 00058 00059 // Or a location in the machine frame. 00060 MachineLocation Loc; 00061 00062 bool isLocation() const { return EntryKind == E_Location; } 00063 bool isInt() const { return EntryKind == E_Integer; } 00064 bool isConstantFP() const { return EntryKind == E_ConstantFP; } 00065 bool isConstantInt() const { return EntryKind == E_ConstantInt; } 00066 int64_t getInt() const { return Constant.Int; } 00067 const ConstantFP *getConstantFP() const { return Constant.CFP; } 00068 const ConstantInt *getConstantInt() const { return Constant.CIP; } 00069 MachineLocation getLoc() const { return Loc; } 00070 const MDNode *getVariableNode() const { return Variable; } 00071 DIVariable getVariable() const { return DIVariable(Variable); } 00072 bool isVariablePiece() const { return getVariable().isVariablePiece(); } 00073 friend bool operator==(const Value &, const Value &); 00074 friend bool operator<(const Value &, const Value &); 00075 }; 00076 00077 private: 00078 /// A nonempty list of locations/constants belonging to this entry, 00079 /// sorted by offset. 00080 SmallVector<Value, 1> Values; 00081 00082 public: 00083 DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val) 00084 : Begin(B), End(E) { 00085 Values.push_back(std::move(Val)); 00086 } 00087 00088 /// \brief If this and Next are describing different pieces of the same 00089 // variable, merge them by appending Next's values to the current 00090 // list of values. 00091 // Return true if the merge was successful. 00092 bool MergeValues(const DebugLocEntry &Next) { 00093 if (Begin == Next.Begin && Values.size() > 0 && Next.Values.size() > 0) { 00094 DIVariable Var(Values[0].Variable); 00095 DIVariable NextVar(Next.Values[0].Variable); 00096 if (Var.getName() == NextVar.getName() && 00097 Var.isVariablePiece() && NextVar.isVariablePiece()) { 00098 addValues(Next.Values); 00099 End = Next.End; 00100 return true; 00101 } 00102 } 00103 return false; 00104 } 00105 00106 /// \brief Attempt to merge this DebugLocEntry with Next and return 00107 /// true if the merge was successful. Entries can be merged if they 00108 /// share the same Loc/Constant and if Next immediately follows this 00109 /// Entry. 00110 bool MergeRanges(const DebugLocEntry &Next) { 00111 // If this and Next are describing the same variable, merge them. 00112 if ((End == Next.Begin && Values == Next.Values)) { 00113 End = Next.End; 00114 return true; 00115 } 00116 return false; 00117 } 00118 00119 const MCSymbol *getBeginSym() const { return Begin; } 00120 const MCSymbol *getEndSym() const { return End; } 00121 ArrayRef<Value> getValues() const { return Values; } 00122 void addValues(ArrayRef<DebugLocEntry::Value> Vals) { 00123 Values.append(Vals.begin(), Vals.end()); 00124 sortUniqueValues(); 00125 assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){ 00126 return V.isVariablePiece(); 00127 }) && "value must be a piece"); 00128 } 00129 00130 // Sort the pieces by offset. 00131 // Remove any duplicate entries by dropping all but the first. 00132 void sortUniqueValues() { 00133 std::sort(Values.begin(), Values.end()); 00134 Values.erase(std::unique(Values.begin(), Values.end(), 00135 [](const Value &A, const Value &B) { 00136 return A.getVariable() == B.getVariable(); 00137 }), Values.end()); 00138 } 00139 }; 00140 00141 /// Compare two Values for equality. 00142 inline bool operator==(const DebugLocEntry::Value &A, 00143 const DebugLocEntry::Value &B) { 00144 if (A.EntryKind != B.EntryKind) 00145 return false; 00146 00147 if (A.getVariable() != B.getVariable()) 00148 return false; 00149 00150 switch (A.EntryKind) { 00151 case DebugLocEntry::Value::E_Location: 00152 return A.Loc == B.Loc; 00153 case DebugLocEntry::Value::E_Integer: 00154 return A.Constant.Int == B.Constant.Int; 00155 case DebugLocEntry::Value::E_ConstantFP: 00156 return A.Constant.CFP == B.Constant.CFP; 00157 case DebugLocEntry::Value::E_ConstantInt: 00158 return A.Constant.CIP == B.Constant.CIP; 00159 } 00160 llvm_unreachable("unhandled EntryKind"); 00161 } 00162 00163 /// Compare two pieces based on their offset. 00164 inline bool operator<(const DebugLocEntry::Value &A, 00165 const DebugLocEntry::Value &B) { 00166 return A.getVariable().getPieceOffset() < B.getVariable().getPieceOffset(); 00167 } 00168 00169 } 00170 00171 #endif