1*0b57cec5SDimitry Andric //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 10*0b57cec5SDimitry Andric #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "DebugLocStream.h" 13*0b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 14*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 15*0b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h" 16*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 17*0b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric namespace llvm { 21*0b57cec5SDimitry Andric class AsmPrinter; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric /// A single location or constant. 24*0b57cec5SDimitry Andric class DbgValueLoc { 25*0b57cec5SDimitry Andric /// Any complex address location expression for this DbgValueLoc. 26*0b57cec5SDimitry Andric const DIExpression *Expression; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric /// Type of entry that this represents. 29*0b57cec5SDimitry Andric enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; 30*0b57cec5SDimitry Andric enum EntryType EntryKind; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric /// Either a constant, 33*0b57cec5SDimitry Andric union { 34*0b57cec5SDimitry Andric int64_t Int; 35*0b57cec5SDimitry Andric const ConstantFP *CFP; 36*0b57cec5SDimitry Andric const ConstantInt *CIP; 37*0b57cec5SDimitry Andric } Constant; 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric /// Or a location in the machine frame. 40*0b57cec5SDimitry Andric MachineLocation Loc; 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric public: 43*0b57cec5SDimitry Andric DbgValueLoc(const DIExpression *Expr, int64_t i) 44*0b57cec5SDimitry Andric : Expression(Expr), EntryKind(E_Integer) { 45*0b57cec5SDimitry Andric Constant.Int = i; 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP) 48*0b57cec5SDimitry Andric : Expression(Expr), EntryKind(E_ConstantFP) { 49*0b57cec5SDimitry Andric Constant.CFP = CFP; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP) 52*0b57cec5SDimitry Andric : Expression(Expr), EntryKind(E_ConstantInt) { 53*0b57cec5SDimitry Andric Constant.CIP = CIP; 54*0b57cec5SDimitry Andric } 55*0b57cec5SDimitry Andric DbgValueLoc(const DIExpression *Expr, MachineLocation Loc) 56*0b57cec5SDimitry Andric : Expression(Expr), EntryKind(E_Location), Loc(Loc) { 57*0b57cec5SDimitry Andric assert(cast<DIExpression>(Expr)->isValid()); 58*0b57cec5SDimitry Andric } 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric bool isLocation() const { return EntryKind == E_Location; } 61*0b57cec5SDimitry Andric bool isInt() const { return EntryKind == E_Integer; } 62*0b57cec5SDimitry Andric bool isConstantFP() const { return EntryKind == E_ConstantFP; } 63*0b57cec5SDimitry Andric bool isConstantInt() const { return EntryKind == E_ConstantInt; } 64*0b57cec5SDimitry Andric int64_t getInt() const { return Constant.Int; } 65*0b57cec5SDimitry Andric const ConstantFP *getConstantFP() const { return Constant.CFP; } 66*0b57cec5SDimitry Andric const ConstantInt *getConstantInt() const { return Constant.CIP; } 67*0b57cec5SDimitry Andric MachineLocation getLoc() const { return Loc; } 68*0b57cec5SDimitry Andric bool isFragment() const { return getExpression()->isFragment(); } 69*0b57cec5SDimitry Andric bool isEntryVal() const { return getExpression()->isEntryValue(); } 70*0b57cec5SDimitry Andric const DIExpression *getExpression() const { return Expression; } 71*0b57cec5SDimitry Andric friend bool operator==(const DbgValueLoc &, const DbgValueLoc &); 72*0b57cec5SDimitry Andric friend bool operator<(const DbgValueLoc &, const DbgValueLoc &); 73*0b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 74*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void dump() const { 75*0b57cec5SDimitry Andric if (isLocation()) { 76*0b57cec5SDimitry Andric llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " "; 77*0b57cec5SDimitry Andric if (Loc.isIndirect()) 78*0b57cec5SDimitry Andric llvm::dbgs() << "+0"; 79*0b57cec5SDimitry Andric llvm::dbgs() << "} "; 80*0b57cec5SDimitry Andric } else if (isConstantInt()) 81*0b57cec5SDimitry Andric Constant.CIP->dump(); 82*0b57cec5SDimitry Andric else if (isConstantFP()) 83*0b57cec5SDimitry Andric Constant.CFP->dump(); 84*0b57cec5SDimitry Andric if (Expression) 85*0b57cec5SDimitry Andric Expression->dump(); 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric #endif 88*0b57cec5SDimitry Andric }; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric /// This struct describes location entries emitted in the .debug_loc 91*0b57cec5SDimitry Andric /// section. 92*0b57cec5SDimitry Andric class DebugLocEntry { 93*0b57cec5SDimitry Andric /// Begin and end symbols for the address range that this location is valid. 94*0b57cec5SDimitry Andric const MCSymbol *Begin; 95*0b57cec5SDimitry Andric const MCSymbol *End; 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric /// A nonempty list of locations/constants belonging to this entry, 98*0b57cec5SDimitry Andric /// sorted by offset. 99*0b57cec5SDimitry Andric SmallVector<DbgValueLoc, 1> Values; 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric public: 102*0b57cec5SDimitry Andric /// Create a location list entry for the range [\p Begin, \p End). 103*0b57cec5SDimitry Andric /// 104*0b57cec5SDimitry Andric /// \param Vals One or more values describing (parts of) the variable. 105*0b57cec5SDimitry Andric DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End, 106*0b57cec5SDimitry Andric ArrayRef<DbgValueLoc> Vals) 107*0b57cec5SDimitry Andric : Begin(Begin), End(End) { 108*0b57cec5SDimitry Andric addValues(Vals); 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric /// Attempt to merge this DebugLocEntry with Next and return 112*0b57cec5SDimitry Andric /// true if the merge was successful. Entries can be merged if they 113*0b57cec5SDimitry Andric /// share the same Loc/Constant and if Next immediately follows this 114*0b57cec5SDimitry Andric /// Entry. 115*0b57cec5SDimitry Andric bool MergeRanges(const DebugLocEntry &Next) { 116*0b57cec5SDimitry Andric // If this and Next are describing the same variable, merge them. 117*0b57cec5SDimitry Andric if ((End == Next.Begin && Values == Next.Values)) { 118*0b57cec5SDimitry Andric End = Next.End; 119*0b57cec5SDimitry Andric return true; 120*0b57cec5SDimitry Andric } 121*0b57cec5SDimitry Andric return false; 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric const MCSymbol *getBeginSym() const { return Begin; } 125*0b57cec5SDimitry Andric const MCSymbol *getEndSym() const { return End; } 126*0b57cec5SDimitry Andric ArrayRef<DbgValueLoc> getValues() const { return Values; } 127*0b57cec5SDimitry Andric void addValues(ArrayRef<DbgValueLoc> Vals) { 128*0b57cec5SDimitry Andric Values.append(Vals.begin(), Vals.end()); 129*0b57cec5SDimitry Andric sortUniqueValues(); 130*0b57cec5SDimitry Andric assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) { 131*0b57cec5SDimitry Andric return V.isFragment(); 132*0b57cec5SDimitry Andric })) && "must either have a single value or multiple pieces"); 133*0b57cec5SDimitry Andric } 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric // Sort the pieces by offset. 136*0b57cec5SDimitry Andric // Remove any duplicate entries by dropping all but the first. 137*0b57cec5SDimitry Andric void sortUniqueValues() { 138*0b57cec5SDimitry Andric llvm::sort(Values); 139*0b57cec5SDimitry Andric Values.erase(std::unique(Values.begin(), Values.end(), 140*0b57cec5SDimitry Andric [](const DbgValueLoc &A, const DbgValueLoc &B) { 141*0b57cec5SDimitry Andric return A.getExpression() == B.getExpression(); 142*0b57cec5SDimitry Andric }), 143*0b57cec5SDimitry Andric Values.end()); 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric /// Lower this entry into a DWARF expression. 147*0b57cec5SDimitry Andric void finalize(const AsmPrinter &AP, 148*0b57cec5SDimitry Andric DebugLocStream::ListBuilder &List, 149*0b57cec5SDimitry Andric const DIBasicType *BT, 150*0b57cec5SDimitry Andric DwarfCompileUnit &TheCU); 151*0b57cec5SDimitry Andric }; 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric /// Compare two DbgValueLocs for equality. 154*0b57cec5SDimitry Andric inline bool operator==(const DbgValueLoc &A, 155*0b57cec5SDimitry Andric const DbgValueLoc &B) { 156*0b57cec5SDimitry Andric if (A.EntryKind != B.EntryKind) 157*0b57cec5SDimitry Andric return false; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric if (A.Expression != B.Expression) 160*0b57cec5SDimitry Andric return false; 161*0b57cec5SDimitry Andric 162*0b57cec5SDimitry Andric switch (A.EntryKind) { 163*0b57cec5SDimitry Andric case DbgValueLoc::E_Location: 164*0b57cec5SDimitry Andric return A.Loc == B.Loc; 165*0b57cec5SDimitry Andric case DbgValueLoc::E_Integer: 166*0b57cec5SDimitry Andric return A.Constant.Int == B.Constant.Int; 167*0b57cec5SDimitry Andric case DbgValueLoc::E_ConstantFP: 168*0b57cec5SDimitry Andric return A.Constant.CFP == B.Constant.CFP; 169*0b57cec5SDimitry Andric case DbgValueLoc::E_ConstantInt: 170*0b57cec5SDimitry Andric return A.Constant.CIP == B.Constant.CIP; 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric llvm_unreachable("unhandled EntryKind"); 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric /// Compare two fragments based on their offset. 176*0b57cec5SDimitry Andric inline bool operator<(const DbgValueLoc &A, 177*0b57cec5SDimitry Andric const DbgValueLoc &B) { 178*0b57cec5SDimitry Andric return A.getExpression()->getFragmentInfo()->OffsetInBits < 179*0b57cec5SDimitry Andric B.getExpression()->getFragmentInfo()->OffsetInBits; 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric #endif 185