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