Line data Source code
1 : //===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
11 : #define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
12 :
13 : #include "DebugLocStream.h"
14 : #include "llvm/Config/llvm-config.h"
15 : #include "llvm/IR/Constants.h"
16 : #include "llvm/IR/DebugInfo.h"
17 : #include "llvm/MC/MCSymbol.h"
18 : #include "llvm/MC/MachineLocation.h"
19 : #include "llvm/Support/Debug.h"
20 :
21 : namespace llvm {
22 : class AsmPrinter;
23 :
24 : /// This struct describes location entries emitted in the .debug_loc
25 : /// section.
26 301326 : class DebugLocEntry {
27 : /// Begin and end symbols for the address range that this location is valid.
28 : const MCSymbol *Begin;
29 : const MCSymbol *End;
30 :
31 : public:
32 : /// A single location or constant.
33 : struct Value {
34 : Value(const DIExpression *Expr, int64_t i)
35 1380 : : Expression(Expr), EntryKind(E_Integer) {
36 690 : Constant.Int = i;
37 : }
38 : Value(const DIExpression *Expr, const ConstantFP *CFP)
39 9 : : Expression(Expr), EntryKind(E_ConstantFP) {
40 9 : Constant.CFP = CFP;
41 : }
42 : Value(const DIExpression *Expr, const ConstantInt *CIP)
43 0 : : Expression(Expr), EntryKind(E_ConstantInt) {
44 0 : Constant.CIP = CIP;
45 : }
46 : Value(const DIExpression *Expr, MachineLocation Loc)
47 200818 : : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
48 : assert(cast<DIExpression>(Expr)->isValid());
49 : }
50 :
51 : /// Any complex address location expression for this Value.
52 : const DIExpression *Expression;
53 :
54 : /// Type of entry that this represents.
55 : enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
56 : enum EntryType EntryKind;
57 :
58 : /// Either a constant,
59 : union {
60 : int64_t Int;
61 : const ConstantFP *CFP;
62 : const ConstantInt *CIP;
63 : } Constant;
64 :
65 : // Or a location in the machine frame.
66 : MachineLocation Loc;
67 :
68 0 : bool isLocation() const { return EntryKind == E_Location; }
69 0 : bool isInt() const { return EntryKind == E_Integer; }
70 0 : bool isConstantFP() const { return EntryKind == E_ConstantFP; }
71 : bool isConstantInt() const { return EntryKind == E_ConstantInt; }
72 0 : int64_t getInt() const { return Constant.Int; }
73 0 : const ConstantFP *getConstantFP() const { return Constant.CFP; }
74 : const ConstantInt *getConstantInt() const { return Constant.CIP; }
75 0 : MachineLocation getLoc() const { return Loc; }
76 85416 : bool isFragment() const { return getExpression()->isFragment(); }
77 0 : const DIExpression *getExpression() const { return Expression; }
78 : friend bool operator==(const Value &, const Value &);
79 : friend bool operator<(const Value &, const Value &);
80 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
81 : LLVM_DUMP_METHOD void dump() const {
82 : if (isLocation()) {
83 : llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
84 : if (Loc.isIndirect())
85 : llvm::dbgs() << "+0";
86 : llvm::dbgs() << "} ";
87 : }
88 : else if (isConstantInt())
89 : Constant.CIP->dump();
90 : else if (isConstantFP())
91 : Constant.CFP->dump();
92 : if (Expression)
93 : Expression->dump();
94 : }
95 : #endif
96 : };
97 :
98 : private:
99 : /// A nonempty list of locations/constants belonging to this entry,
100 : /// sorted by offset.
101 : SmallVector<Value, 1> Values;
102 :
103 : public:
104 : DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val)
105 201517 : : Begin(B), End(E) {
106 201517 : Values.push_back(std::move(Val));
107 : }
108 :
109 : /// If this and Next are describing different pieces of the same
110 : /// variable, merge them by appending Next's values to the current
111 : /// list of values.
112 : /// Return true if the merge was successful.
113 : bool MergeValues(const DebugLocEntry &Next);
114 :
115 : /// Attempt to merge this DebugLocEntry with Next and return
116 : /// true if the merge was successful. Entries can be merged if they
117 : /// share the same Loc/Constant and if Next immediately follows this
118 : /// Entry.
119 : bool MergeRanges(const DebugLocEntry &Next) {
120 : // If this and Next are describing the same variable, merge them.
121 154221 : if ((End == Next.Begin && Values == Next.Values)) {
122 115982 : End = Next.End;
123 : return true;
124 : }
125 : return false;
126 : }
127 :
128 : const MCSymbol *getBeginSym() const { return Begin; }
129 : const MCSymbol *getEndSym() const { return End; }
130 : ArrayRef<Value> getValues() const { return Values; }
131 774 : void addValues(ArrayRef<DebugLocEntry::Value> Vals) {
132 1548 : Values.append(Vals.begin(), Vals.end());
133 774 : sortUniqueValues();
134 : assert(all_of(Values, [](DebugLocEntry::Value V) {
135 : return V.isFragment();
136 : }) && "value must be a piece");
137 774 : }
138 :
139 : // Sort the pieces by offset.
140 : // Remove any duplicate entries by dropping all but the first.
141 774 : void sortUniqueValues() {
142 : llvm::sort(Values);
143 : Values.erase(
144 : std::unique(
145 : Values.begin(), Values.end(), [](const Value &A, const Value &B) {
146 1035 : return A.getExpression() == B.getExpression();
147 : }),
148 : Values.end());
149 774 : }
150 :
151 : /// Lower this entry into a DWARF expression.
152 : void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List,
153 : const DIBasicType *BT);
154 : };
155 :
156 : /// Compare two Values for equality.
157 136148 : inline bool operator==(const DebugLocEntry::Value &A,
158 : const DebugLocEntry::Value &B) {
159 136148 : if (A.EntryKind != B.EntryKind)
160 : return false;
161 :
162 135940 : if (A.Expression != B.Expression)
163 : return false;
164 :
165 129877 : switch (A.EntryKind) {
166 129839 : case DebugLocEntry::Value::E_Location:
167 129839 : return A.Loc == B.Loc;
168 38 : case DebugLocEntry::Value::E_Integer:
169 38 : return A.Constant.Int == B.Constant.Int;
170 0 : case DebugLocEntry::Value::E_ConstantFP:
171 0 : return A.Constant.CFP == B.Constant.CFP;
172 0 : case DebugLocEntry::Value::E_ConstantInt:
173 0 : return A.Constant.CIP == B.Constant.CIP;
174 : }
175 0 : llvm_unreachable("unhandled EntryKind");
176 : }
177 :
178 : /// Compare two fragments based on their offset.
179 2115 : inline bool operator<(const DebugLocEntry::Value &A,
180 : const DebugLocEntry::Value &B) {
181 2115 : return A.getExpression()->getFragmentInfo()->OffsetInBits <
182 2115 : B.getExpression()->getFragmentInfo()->OffsetInBits;
183 : }
184 :
185 : }
186 :
187 : #endif
|