1 //===-- LVLocation.h --------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the LVOperation and LVLocation classes, which are used
10 // to describe variable locations.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H
15 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H
16 
17 #include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
18 
19 namespace llvm {
20 namespace logicalview {
21 
22 using LVLineRange = std::pair<LVLine *, LVLine *>;
23 
24 // The DW_AT_data_member_location attribute is a simple member offset.
25 const LVSmall LVLocationMemberOffset = 0;
26 
27 class LVOperation final {
28   // To describe an operation:
29   // OpCode
30   // Operands[0]: First operand.
31   // Operands[1]: Second operand.
32   //   OP_bregx, OP_bit_piece, OP_[GNU_]const_type,
33   //   OP_[GNU_]deref_type, OP_[GNU_]entry_value, OP_implicit_value,
34   //   OP_[GNU_]implicit_pointer, OP_[GNU_]regval_type, OP_xderef_type.
35   LVSmall Opcode = 0;
36   SmallVector<uint64_t> Operands;
37 
38 public:
39   LVOperation() = delete;
LVOperation(LVSmall Opcode,ArrayRef<LVUnsigned> Operands)40   LVOperation(LVSmall Opcode, ArrayRef<LVUnsigned> Operands)
41       : Opcode(Opcode), Operands(Operands) {}
42   LVOperation(const LVOperation &) = delete;
43   LVOperation &operator=(const LVOperation &) = delete;
44   ~LVOperation() = default;
45 
getOpcode()46   LVSmall getOpcode() const { return Opcode; }
47   std::string getOperandsDWARFInfo();
48   std::string getOperandsCodeViewInfo();
49 
50   void print(raw_ostream &OS, bool Full = true) const;
51 
52 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()53   void dump() { print(dbgs()); }
54 #endif
55 };
56 
57 class LVLocation : public LVObject {
58   enum class Property {
59     IsAddressRange,
60     IsBaseClassOffset,
61     IsBaseClassStep,
62     IsClassOffset,
63     IsFixedAddress,
64     IsLocationSimple,
65     IsGapEntry,
66     IsOperation,
67     IsOperationList,
68     IsRegister,
69     IsStackOffset,
70     IsDiscardedRange,
71     IsInvalidRange,
72     IsInvalidLower,
73     IsInvalidUpper,
74     IsCallSite,
75     LastEntry
76   };
77   // Typed bitvector with properties for this location.
78   LVProperties<Property> Properties;
79 
80   // True if the location it is associated with a debug range.
hasAssociatedRange()81   bool hasAssociatedRange() const {
82     return !getIsClassOffset() && !getIsDiscardedRange();
83   }
84 
85 protected:
86   // Line numbers associated with locations ranges.
87   LVLine *LowerLine = nullptr;
88   LVLine *UpperLine = nullptr;
89 
90   // Active range:
91   // LowPC: an offset from an applicable base address, not a PC value.
92   // HighPC: an offset from an applicable base address, or a length.
93   LVAddress LowPC = 0;
94   LVAddress HighPC = 0;
95 
96   void setKind();
97 
98 public:
LVLocation()99   LVLocation() : LVObject() { setIsLocation(); }
100   LVLocation(const LVLocation &) = delete;
101   LVLocation &operator=(const LVLocation &) = delete;
102   virtual ~LVLocation() = default;
103 
104   PROPERTY(Property, IsAddressRange);
105   PROPERTY(Property, IsBaseClassOffset);
106   PROPERTY(Property, IsBaseClassStep);
107   PROPERTY_1(Property, IsClassOffset, IsLocationSimple);
108   PROPERTY_1(Property, IsFixedAddress, IsLocationSimple);
109   PROPERTY(Property, IsLocationSimple);
110   PROPERTY(Property, IsGapEntry);
111   PROPERTY(Property, IsOperationList);
112   PROPERTY(Property, IsOperation);
113   PROPERTY(Property, IsRegister);
114   PROPERTY_1(Property, IsStackOffset, IsLocationSimple);
115   PROPERTY(Property, IsDiscardedRange);
116   PROPERTY(Property, IsInvalidRange);
117   PROPERTY(Property, IsInvalidLower);
118   PROPERTY(Property, IsInvalidUpper);
119   PROPERTY(Property, IsCallSite);
120 
121   const char *kind() const override;
122   // Mark the locations that have only DW_OP_fbreg as stack offset based.
updateKind()123   virtual void updateKind() {}
124 
125   // Line numbers for locations.
getLowerLine()126   const LVLine *getLowerLine() const { return LowerLine; }
setLowerLine(LVLine * Line)127   void setLowerLine(LVLine *Line) { LowerLine = Line; }
getUpperLine()128   const LVLine *getUpperLine() const { return UpperLine; }
setUpperLine(LVLine * Line)129   void setUpperLine(LVLine *Line) { UpperLine = Line; }
130 
131   // Addresses for locations.
getLowerAddress()132   LVAddress getLowerAddress() const override { return LowPC; }
setLowerAddress(LVAddress Address)133   void setLowerAddress(LVAddress Address) override { LowPC = Address; }
getUpperAddress()134   LVAddress getUpperAddress() const override { return HighPC; }
setUpperAddress(LVAddress Address)135   void setUpperAddress(LVAddress Address) override { HighPC = Address; }
136 
137   std::string getIntervalInfo() const;
138 
139   bool validateRanges();
140 
141   // In order to calculate a symbol coverage (percentage), take the ranges
142   // and obtain the number of units (bytes) covered by those ranges. We can't
143   // use the line numbers, because they can be zero or invalid.
144   // We return:
145   //   false: No locations or multiple locations.
146   //   true: a single location.
147   static bool calculateCoverage(LVLocations *Locations, unsigned &Factor,
148                                 float &Percentage);
149 
addObject(LVAddress LowPC,LVAddress HighPC,LVUnsigned SectionOffset,uint64_t LocDescOffset)150   virtual void addObject(LVAddress LowPC, LVAddress HighPC,
151                          LVUnsigned SectionOffset, uint64_t LocDescOffset) {}
addObject(LVSmall Opcode,ArrayRef<LVUnsigned> Operands)152   virtual void addObject(LVSmall Opcode, ArrayRef<LVUnsigned> Operands) {}
153 
154   static void print(LVLocations *Locations, raw_ostream &OS, bool Full = true);
155   void printInterval(raw_ostream &OS, bool Full = true) const;
156   void printRaw(raw_ostream &OS, bool Full = true) const;
157   virtual void printRawExtra(raw_ostream &OS, bool Full = true) const {}
158 
159   void print(raw_ostream &OS, bool Full = true) const override;
160   void printExtra(raw_ostream &OS, bool Full = true) const override;
161 
162 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()163   void dump() const override { print(dbgs()); }
164 #endif
165 };
166 
167 class LVLocationSymbol final : public LVLocation {
168   // Location descriptors for the active range.
169   std::unique_ptr<LVOperations> Entries;
170 
171   void updateKind() override;
172 
173 public:
LVLocationSymbol()174   LVLocationSymbol() : LVLocation() {}
175   LVLocationSymbol(const LVLocationSymbol &) = delete;
176   LVLocationSymbol &operator=(const LVLocationSymbol &) = delete;
177   ~LVLocationSymbol() = default;
178 
179   void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset,
180                  uint64_t LocDescOffset) override;
181   void addObject(LVSmall Opcode, ArrayRef<LVUnsigned> Operands) override;
182 
183   void printRawExtra(raw_ostream &OS, bool Full = true) const override;
184   void printExtra(raw_ostream &OS, bool Full = true) const override;
185 };
186 
187 } // end namespace logicalview
188 } // end namespace llvm
189 
190 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVLOCATION_H
191