//===-- LVLocation.h --------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the LVOperation and LVLocation classes, which are used // to describe variable locations. // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H #include "llvm/DebugInfo/LogicalView/Core/LVObject.h" namespace llvm { namespace logicalview { using LVLineRange = std::pair; // The DW_AT_data_member_location attribute is a simple member offset. const LVSmall LVLocationMemberOffset = 0; class LVOperation final { // To describe an operation: // OpCode // Operands[0]: First operand. // Operands[1]: Second operand. // OP_bregx, OP_bit_piece, OP_[GNU_]const_type, // OP_[GNU_]deref_type, OP_[GNU_]entry_value, OP_implicit_value, // OP_[GNU_]implicit_pointer, OP_[GNU_]regval_type, OP_xderef_type. LVSmall Opcode = 0; SmallVector Operands; public: LVOperation() = delete; LVOperation(LVSmall Opcode, ArrayRef Operands) : Opcode(Opcode), Operands(Operands) {} LVOperation(const LVOperation &) = delete; LVOperation &operator=(const LVOperation &) = delete; ~LVOperation() = default; LVSmall getOpcode() const { return Opcode; } std::string getOperandsDWARFInfo(); std::string getOperandsCodeViewInfo(); void print(raw_ostream &OS, bool Full = true) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() { print(dbgs()); } #endif }; class LVLocation : public LVObject { enum class Property { IsAddressRange, IsBaseClassOffset, IsBaseClassStep, IsClassOffset, IsFixedAddress, IsLocationSimple, IsGapEntry, IsOperation, IsOperationList, IsRegister, IsStackOffset, IsDiscardedRange, IsInvalidRange, IsInvalidLower, IsInvalidUpper, IsCallSite, LastEntry }; // Typed bitvector with properties for this location. LVProperties Properties; // True if the location it is associated with a debug range. bool hasAssociatedRange() const { return !getIsClassOffset() && !getIsDiscardedRange(); } protected: // Line numbers associated with locations ranges. LVLine *LowerLine = nullptr; LVLine *UpperLine = nullptr; // Active range: // LowPC: an offset from an applicable base address, not a PC value. // HighPC: an offset from an applicable base address, or a length. LVAddress LowPC = 0; LVAddress HighPC = 0; void setKind(); public: LVLocation() : LVObject() { setIsLocation(); } LVLocation(const LVLocation &) = delete; LVLocation &operator=(const LVLocation &) = delete; virtual ~LVLocation() = default; PROPERTY(Property, IsAddressRange); PROPERTY(Property, IsBaseClassOffset); PROPERTY(Property, IsBaseClassStep); PROPERTY_1(Property, IsClassOffset, IsLocationSimple); PROPERTY_1(Property, IsFixedAddress, IsLocationSimple); PROPERTY(Property, IsLocationSimple); PROPERTY(Property, IsGapEntry); PROPERTY(Property, IsOperationList); PROPERTY(Property, IsOperation); PROPERTY(Property, IsRegister); PROPERTY_1(Property, IsStackOffset, IsLocationSimple); PROPERTY(Property, IsDiscardedRange); PROPERTY(Property, IsInvalidRange); PROPERTY(Property, IsInvalidLower); PROPERTY(Property, IsInvalidUpper); PROPERTY(Property, IsCallSite); const char *kind() const override; // Mark the locations that have only DW_OP_fbreg as stack offset based. virtual void updateKind() {} // Line numbers for locations. const LVLine *getLowerLine() const { return LowerLine; } void setLowerLine(LVLine *Line) { LowerLine = Line; } const LVLine *getUpperLine() const { return UpperLine; } void setUpperLine(LVLine *Line) { UpperLine = Line; } // Addresses for locations. LVAddress getLowerAddress() const override { return LowPC; } void setLowerAddress(LVAddress Address) override { LowPC = Address; } LVAddress getUpperAddress() const override { return HighPC; } void setUpperAddress(LVAddress Address) override { HighPC = Address; } std::string getIntervalInfo() const; bool validateRanges(); // In order to calculate a symbol coverage (percentage), take the ranges // and obtain the number of units (bytes) covered by those ranges. We can't // use the line numbers, because they can be zero or invalid. // We return: // false: No locations or multiple locations. // true: a single location. static bool calculateCoverage(LVLocations *Locations, unsigned &Factor, float &Percentage); virtual void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset) {} virtual void addObject(LVSmall Opcode, ArrayRef Operands) {} static void print(LVLocations *Locations, raw_ostream &OS, bool Full = true); void printInterval(raw_ostream &OS, bool Full = true) const; void printRaw(raw_ostream &OS, bool Full = true) const; virtual void printRawExtra(raw_ostream &OS, bool Full = true) const {} void print(raw_ostream &OS, bool Full = true) const override; void printExtra(raw_ostream &OS, bool Full = true) const override; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const override { print(dbgs()); } #endif }; class LVLocationSymbol final : public LVLocation { // Location descriptors for the active range. std::unique_ptr Entries; void updateKind() override; public: LVLocationSymbol() : LVLocation() {} LVLocationSymbol(const LVLocationSymbol &) = delete; LVLocationSymbol &operator=(const LVLocationSymbol &) = delete; ~LVLocationSymbol() = default; void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset, uint64_t LocDescOffset) override; void addObject(LVSmall Opcode, ArrayRef Operands) override; void printRawExtra(raw_ostream &OS, bool Full = true) const override; void printExtra(raw_ostream &OS, bool Full = true) const override; }; } // end namespace logicalview } // end namespace llvm #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H