Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
35271 views
//===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H9#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H1011#include "DebugLocStream.h"12#include "llvm/Config/llvm-config.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#include "llvm/Support/Debug.h"1819namespace llvm {20class AsmPrinter;2122/// This struct describes target specific location.23struct TargetIndexLocation {24int Index;25int Offset;2627TargetIndexLocation() = default;28TargetIndexLocation(unsigned Idx, int64_t Offset)29: Index(Idx), Offset(Offset) {}3031bool operator==(const TargetIndexLocation &Other) const {32return Index == Other.Index && Offset == Other.Offset;33}34};3536/// A single location or constant within a variable location description, with37/// either a single entry (with an optional DIExpression) used for a DBG_VALUE,38/// or a list of entries used for a DBG_VALUE_LIST.39class DbgValueLocEntry {4041/// Type of entry that this represents.42enum EntryType {43E_Location,44E_Integer,45E_ConstantFP,46E_ConstantInt,47E_TargetIndexLocation48};49enum EntryType EntryKind;5051/// Either a constant,52union {53int64_t Int;54const ConstantFP *CFP;55const ConstantInt *CIP;56} Constant;5758union {59/// Or a location in the machine frame.60MachineLocation Loc;61/// Or a location from target specific location.62TargetIndexLocation TIL;63};6465public:66DbgValueLocEntry(int64_t i) : EntryKind(E_Integer) { Constant.Int = i; }67DbgValueLocEntry(const ConstantFP *CFP) : EntryKind(E_ConstantFP) {68Constant.CFP = CFP;69}70DbgValueLocEntry(const ConstantInt *CIP) : EntryKind(E_ConstantInt) {71Constant.CIP = CIP;72}73DbgValueLocEntry(MachineLocation Loc) : EntryKind(E_Location), Loc(Loc) {}74DbgValueLocEntry(TargetIndexLocation Loc)75: EntryKind(E_TargetIndexLocation), TIL(Loc) {}7677bool isLocation() const { return EntryKind == E_Location; }78bool isIndirectLocation() const {79return EntryKind == E_Location && Loc.isIndirect();80}81bool isTargetIndexLocation() const {82return EntryKind == E_TargetIndexLocation;83}84bool isInt() const { return EntryKind == E_Integer; }85bool isConstantFP() const { return EntryKind == E_ConstantFP; }86bool isConstantInt() const { return EntryKind == E_ConstantInt; }87int64_t getInt() const { return Constant.Int; }88const ConstantFP *getConstantFP() const { return Constant.CFP; }89const ConstantInt *getConstantInt() const { return Constant.CIP; }90MachineLocation getLoc() const { return Loc; }91TargetIndexLocation getTargetIndexLocation() const { return TIL; }92friend bool operator==(const DbgValueLocEntry &, const DbgValueLocEntry &);93#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)94LLVM_DUMP_METHOD void dump() const {95if (isLocation()) {96llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";97if (Loc.isIndirect())98llvm::dbgs() << "+0";99llvm::dbgs() << "} ";100} else if (isConstantInt())101Constant.CIP->dump();102else if (isConstantFP())103Constant.CFP->dump();104}105#endif106};107108/// The location of a single variable, composed of an expression and 0 or more109/// DbgValueLocEntries.110class DbgValueLoc {111/// Any complex address location expression for this DbgValueLoc.112const DIExpression *Expression;113114SmallVector<DbgValueLocEntry, 2> ValueLocEntries;115116bool IsVariadic;117118public:119DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs)120: Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),121IsVariadic(true) {}122123DbgValueLoc(const DIExpression *Expr, ArrayRef<DbgValueLocEntry> Locs,124bool IsVariadic)125: Expression(Expr), ValueLocEntries(Locs.begin(), Locs.end()),126IsVariadic(IsVariadic) {127#ifndef NDEBUG128assert(Expr->isValid() ||129!any_of(Locs, [](auto LE) { return LE.isLocation(); }));130if (!IsVariadic) {131assert(ValueLocEntries.size() == 1);132}133#endif134}135136DbgValueLoc(const DIExpression *Expr, DbgValueLocEntry Loc)137: Expression(Expr), ValueLocEntries(1, Loc), IsVariadic(false) {138assert(((Expr && Expr->isValid()) || !Loc.isLocation()) &&139"DBG_VALUE with a machine location must have a valid expression.");140}141142bool isFragment() const { return getExpression()->isFragment(); }143bool isEntryVal() const { return getExpression()->isEntryValue(); }144bool isVariadic() const { return IsVariadic; }145bool isEquivalent(const DbgValueLoc &Other) const {146// Cannot be equivalent with different numbers of entries.147if (ValueLocEntries.size() != Other.ValueLocEntries.size())148return false;149bool ThisIsIndirect =150!IsVariadic && ValueLocEntries[0].isIndirectLocation();151bool OtherIsIndirect =152!Other.IsVariadic && Other.ValueLocEntries[0].isIndirectLocation();153// Check equivalence of DIExpressions + Directness together.154if (!DIExpression::isEqualExpression(Expression, ThisIsIndirect,155Other.Expression, OtherIsIndirect))156return false;157// Indirectness should have been accounted for in the above check, so just158// compare register values directly here.159if (ThisIsIndirect || OtherIsIndirect) {160DbgValueLocEntry ThisOp = ValueLocEntries[0];161DbgValueLocEntry OtherOp = Other.ValueLocEntries[0];162return ThisOp.isLocation() && OtherOp.isLocation() &&163ThisOp.getLoc().getReg() == OtherOp.getLoc().getReg();164}165// If neither are indirect, then just compare the loc entries directly.166return ValueLocEntries == Other.ValueLocEntries;167}168const DIExpression *getExpression() const { return Expression; }169ArrayRef<DbgValueLocEntry> getLocEntries() const { return ValueLocEntries; }170friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);171friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);172#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)173LLVM_DUMP_METHOD void dump() const {174for (const DbgValueLocEntry &DV : ValueLocEntries)175DV.dump();176if (Expression)177Expression->dump();178}179#endif180};181182/// This struct describes location entries emitted in the .debug_loc183/// section.184class DebugLocEntry {185/// Begin and end symbols for the address range that this location is valid.186const MCSymbol *Begin;187const MCSymbol *End;188189/// A nonempty list of locations/constants belonging to this entry,190/// sorted by offset.191SmallVector<DbgValueLoc, 1> Values;192193public:194/// Create a location list entry for the range [\p Begin, \p End).195///196/// \param Vals One or more values describing (parts of) the variable.197DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,198ArrayRef<DbgValueLoc> Vals)199: Begin(Begin), End(End) {200addValues(Vals);201}202203/// Attempt to merge this DebugLocEntry with Next and return204/// true if the merge was successful. Entries can be merged if they205/// share the same Loc/Constant and if Next immediately follows this206/// Entry.207bool MergeRanges(const DebugLocEntry &Next) {208// If this and Next are describing the same variable, merge them.209if (End != Next.Begin)210return false;211if (Values.size() != Next.Values.size())212return false;213for (unsigned EntryIdx = 0; EntryIdx < Values.size(); ++EntryIdx)214if (!Values[EntryIdx].isEquivalent(Next.Values[EntryIdx]))215return false;216End = Next.End;217return true;218}219220const MCSymbol *getBeginSym() const { return Begin; }221const MCSymbol *getEndSym() const { return End; }222ArrayRef<DbgValueLoc> getValues() const { return Values; }223void addValues(ArrayRef<DbgValueLoc> Vals) {224Values.append(Vals.begin(), Vals.end());225sortUniqueValues();226assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {227return V.isFragment();228})) && "must either have a single value or multiple pieces");229}230231// Sort the pieces by offset.232// Remove any duplicate entries by dropping all but the first.233void sortUniqueValues() {234// Values is either 1 item that does not have a fragment, or many items235// that all do. No need to sort if the former and also prevents operator<236// being called on a non fragment item when _GLIBCXX_DEBUG is defined.237if (Values.size() == 1)238return;239llvm::sort(Values);240Values.erase(llvm::unique(Values,241[](const DbgValueLoc &A, const DbgValueLoc &B) {242return A.getExpression() == B.getExpression();243}),244Values.end());245}246247/// Lower this entry into a DWARF expression.248void finalize(const AsmPrinter &AP,249DebugLocStream::ListBuilder &List,250const DIBasicType *BT,251DwarfCompileUnit &TheCU);252};253254/// Compare two DbgValueLocEntries for equality.255inline bool operator==(const DbgValueLocEntry &A, const DbgValueLocEntry &B) {256if (A.EntryKind != B.EntryKind)257return false;258259switch (A.EntryKind) {260case DbgValueLocEntry::E_Location:261return A.Loc == B.Loc;262case DbgValueLocEntry::E_TargetIndexLocation:263return A.TIL == B.TIL;264case DbgValueLocEntry::E_Integer:265return A.Constant.Int == B.Constant.Int;266case DbgValueLocEntry::E_ConstantFP:267return A.Constant.CFP == B.Constant.CFP;268case DbgValueLocEntry::E_ConstantInt:269return A.Constant.CIP == B.Constant.CIP;270}271llvm_unreachable("unhandled EntryKind");272}273274/// Compare two DbgValueLocs for equality.275inline bool operator==(const DbgValueLoc &A, const DbgValueLoc &B) {276return A.ValueLocEntries == B.ValueLocEntries &&277A.Expression == B.Expression && A.IsVariadic == B.IsVariadic;278}279280/// Compare two fragments based on their offset.281inline bool operator<(const DbgValueLoc &A,282const DbgValueLoc &B) {283return A.getExpression()->getFragmentInfo()->OffsetInBits <284B.getExpression()->getFragmentInfo()->OffsetInBits;285}286287}288289#endif290291292