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; |
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 | |
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) |
53 | void dump() { print(OS&: 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. |
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: |
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. |
123 | virtual void updateKind() {} |
124 | |
125 | // Line numbers for locations. |
126 | const LVLine *getLowerLine() const { return LowerLine; } |
127 | void setLowerLine(LVLine *Line) { LowerLine = Line; } |
128 | const LVLine *getUpperLine() const { return UpperLine; } |
129 | void setUpperLine(LVLine *Line) { UpperLine = Line; } |
130 | |
131 | // Addresses for locations. |
132 | LVAddress getLowerAddress() const override { return LowPC; } |
133 | void setLowerAddress(LVAddress Address) override { LowPC = Address; } |
134 | LVAddress getUpperAddress() const override { return HighPC; } |
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 | |
150 | virtual void addObject(LVAddress LowPC, LVAddress HighPC, |
151 | LVUnsigned SectionOffset, uint64_t LocDescOffset) {} |
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 (raw_ostream &OS, bool Full = true) const {} |
158 | |
159 | void print(raw_ostream &OS, bool Full = true) const override; |
160 | void (raw_ostream &OS, bool Full = true) const override; |
161 | |
162 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
163 | void dump() const override { print(OS&: 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: |
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 (raw_ostream &OS, bool Full = true) const override; |
184 | void (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 | |