41
41
#include < limits>
42
42
#include < memory>
43
43
#include < utility>
44
+ #include < variant>
44
45
#include < vector>
45
46
46
47
namespace llvm {
@@ -100,36 +101,59 @@ class DbgEntity {
100
101
}
101
102
};
102
103
103
- // / Helper class to model a DbgVariable whose location is derived from an
104
- // / EntryValue.
105
- // / TODO: split the current implementation of `DbgVariable` into a class per
106
- // / variant of location that it can represent, and make `DbgVariableEntryValue`
107
- // / a subclass.
108
- class DbgVariableEntryValue {
109
- struct EntryValueInfo {
110
- MCRegister Reg;
111
- const DIExpression &Expr;
112
-
113
- // / Operator enabling sorting based on fragment offset.
114
- bool operator <(const EntryValueInfo &Other) const {
115
- return getFragmentOffsetInBits () < Other.getFragmentOffsetInBits ();
116
- }
104
+ // / Proxy for one MMI entry.
105
+ struct FrameIndexExpr {
106
+ int FI;
107
+ const DIExpression *Expr;
108
+ };
117
109
118
- private:
119
- uint64_t getFragmentOffsetInBits () const {
120
- std::optional<DIExpression::FragmentInfo> Fragment =
121
- Expr.getFragmentInfo ();
122
- return Fragment ? Fragment->OffsetInBits : 0 ;
123
- }
124
- };
110
+ // / Represents an entry-value location, or a fragment of one.
111
+ struct EntryValueInfo {
112
+ MCRegister Reg;
113
+ const DIExpression &Expr;
125
114
126
- std::set<EntryValueInfo> EntryValues;
115
+ // / Operator enabling sorting based on fragment offset.
116
+ bool operator <(const EntryValueInfo &Other) const {
117
+ return getFragmentOffsetInBits () < Other.getFragmentOffsetInBits ();
118
+ }
127
119
128
- public:
129
- DbgVariableEntryValue (MCRegister Reg, const DIExpression &Expr) {
120
+ private:
121
+ uint64_t getFragmentOffsetInBits () const {
122
+ std::optional<DIExpression::FragmentInfo> Fragment = Expr.getFragmentInfo ();
123
+ return Fragment ? Fragment->OffsetInBits : 0 ;
124
+ }
125
+ };
126
+
127
+ // Namespace for private alternatives of a DbgVariable.
128
+ namespace {
129
+ // / Single value location description.
130
+ struct SingleLoc {
131
+ std::unique_ptr<DbgValueLoc> ValueLoc;
132
+ const DIExpression *Expr;
133
+ SingleLoc (DbgValueLoc ValueLoc)
134
+ : ValueLoc(std::make_unique<DbgValueLoc>(ValueLoc)),
135
+ Expr (ValueLoc.getExpression()) {
136
+ if (!Expr->getNumElements ())
137
+ Expr = nullptr ;
138
+ }
139
+ };
140
+ // / Multi-value location description.
141
+ struct MultiLoc {
142
+ // / Index of the entry list in DebugLocs.
143
+ unsigned DebugLocListIndex = ~0u ;
144
+ // / DW_OP_LLVM_tag_offset value from DebugLocs.
145
+ std::optional<uint8_t > DebugLocListTagOffset;
146
+ };
147
+ // / Single location defined by (potentially multiple) MMI entries.
148
+ struct MMILoc {
149
+ mutable SmallVector<FrameIndexExpr, 1 > FrameIndexExprs;
150
+ };
151
+ // / Single location defined by (potentially multiple) EntryValueInfo.
152
+ struct EntryValueLoc {
153
+ std::set<EntryValueInfo> EntryValues;
154
+ EntryValueLoc (MCRegister Reg, const DIExpression &Expr) {
130
155
addExpr (Reg, Expr);
131
156
};
132
-
133
157
// Add the pair Reg, Expr to the list of entry values describing the variable.
134
158
// If multiple expressions are added, it is the callers responsibility to
135
159
// ensure they are all non-overlapping fragments.
@@ -140,46 +164,48 @@ class DbgVariableEntryValue {
140
164
141
165
EntryValues.insert ({Reg, **NonVariadicExpr});
142
166
}
143
-
144
- // / Returns the set of EntryValueInfo.
145
- const std::set<EntryValueInfo> &getEntryValuesInfo () const {
146
- return EntryValues;
147
- }
148
167
};
168
+ } // namespace
149
169
150
170
// ===----------------------------------------------------------------------===//
151
171
// / This class is used to track local variable information.
152
172
// /
173
+ // / Variables that have been optimized out hold the \c monostate alternative.
174
+ // / This is not distinguished from the case of a constructed \c DbgVariable
175
+ // / which has not be initialized yet.
176
+ // /
153
177
// / Variables can be created from allocas, in which case they're generated from
154
- // / the MMI table. Such variables can have multiple expressions and frame
155
- // / indices.
178
+ // / the MMI table. Such variables hold the \c MMILoc alternative which can have
179
+ // / multiple expressions and frame indices.
156
180
// /
157
181
// / Variables can be created from the entry value of registers, in which case
158
- // / they're generated from the MMI table. Such variables can have either a
159
- // / single expression or multiple *fragment* expressions.
182
+ // / they're generated from the MMI table. Such variables hold the \c
183
+ // / EntryValueLoc alternative which can either have a single expression or
184
+ // / multiple *fragment* expressions.
160
185
// /
161
- // / Variables can be created from \c DBG_VALUE instructions. Those whose
162
- // / location changes over time use \a DebugLocListIndex, while those with a
163
- // / single location use \a ValueLoc and (optionally) a single entry of \a Expr.
164
- // /
165
- // / Variables that have been optimized out use none of these fields.
166
- class DbgVariable : public DbgEntity {
167
- // / Index of the entry list in DebugLocs.
168
- unsigned DebugLocListIndex = ~0u ;
169
- // / DW_OP_LLVM_tag_offset value from DebugLocs.
170
- std::optional<uint8_t > DebugLocListTagOffset;
171
-
172
- // / Single value location description.
173
- std::unique_ptr<DbgValueLoc> ValueLoc = nullptr ;
174
-
175
- struct FrameIndexExpr {
176
- int FI;
177
- const DIExpression *Expr;
178
- };
179
- mutable SmallVector<FrameIndexExpr, 1 >
180
- FrameIndexExprs; // / Frame index + expression.
181
-
182
- std::optional<DbgVariableEntryValue> EntryValue;
186
+ // / Variables can be created from \c DBG_VALUE instructions. Those whose
187
+ // / location changes over time hold a \c MultiLoc alternative which uses \c
188
+ // / DebugLocListIndex and (optionally) \c DebugLocListTagOffset, while those
189
+ // / with a single location hold a \c SingleLoc alternative which use \c ValueLoc
190
+ // / and (optionally) a single \c Expr.
191
+ class DbgVariable : public DbgEntity ,
192
+ private std::variant<std::monostate, SingleLoc, MultiLoc,
193
+ MMILoc, EntryValueLoc> {
194
+
195
+ // / Member shorthand for std::holds_alternative
196
+ template <typename T> bool holds () const {
197
+ return std::holds_alternative<T>(*this );
198
+ }
199
+ // / Asserting, noexcept member alternative to std::get
200
+ template <typename T> auto &get () noexcept {
201
+ assert (holds<T>());
202
+ return *std::get_if<T>(this );
203
+ }
204
+ // / Asserting, noexcept member alternative to std::get
205
+ template <typename T> const auto &get () const noexcept {
206
+ assert (holds<T>());
207
+ return *std::get_if<T>(this );
208
+ }
183
209
184
210
public:
185
211
// / Construct a DbgVariable.
@@ -189,41 +215,27 @@ class DbgVariable : public DbgEntity {
189
215
DbgVariable (const DILocalVariable *V, const DILocation *IA)
190
216
: DbgEntity(V, IA, DbgVariableKind) {}
191
217
192
- bool isInitialized () const {
193
- return !FrameIndexExprs.empty () || ValueLoc || EntryValue;
194
- }
195
-
196
218
// / Initialize from the MMI table.
197
- void initializeMMI (const DIExpression *E, int FI) {
198
- assert (!isInitialized () && " Already initialized?" );
199
-
200
- assert ((!E || E->isValid ()) && " Expected valid expression" );
201
- assert (FI != std::numeric_limits<int >::max () && " Expected valid index" );
202
-
203
- FrameIndexExprs.push_back ({FI, E});
204
- }
219
+ void initializeMMI (const DIExpression *E, int FI);
205
220
206
221
// Initialize variable's location.
207
- void initializeDbgValue (DbgValueLoc Value) {
208
- assert (!isInitialized () && " Already initialized?" );
209
- assert (!Value.getExpression ()->isFragment () && " Fragments not supported." );
222
+ void initializeDbgValue (DbgValueLoc Value);
210
223
211
- ValueLoc = std::make_unique<DbgValueLoc>(Value);
212
- if (auto *E = ValueLoc->getExpression ())
213
- if (E->getNumElements ())
214
- FrameIndexExprs.push_back ({0 , E});
215
- }
224
+ void initializeEntryValue (MCRegister Reg, const DIExpression &Expr);
216
225
217
- void initializeEntryValue (MCRegister Reg, const DIExpression &Expr) {
218
- assert (!isInitialized () && " Already initialized?" );
219
- EntryValue = DbgVariableEntryValue (Reg, Expr);
226
+ const std::set<EntryValueInfo> *getEntryValues () const {
227
+ if (const auto *EV = std::get_if<EntryValueLoc>(this ))
228
+ return &EV->EntryValues ;
229
+ return nullptr ;
220
230
}
221
-
222
- const std::optional<DbgVariableEntryValue> &getEntryValue () const {
223
- return EntryValue;
231
+ std::set<EntryValueInfo> *getEntryValues () {
232
+ if (auto *EV = std::get_if<EntryValueLoc>(this ))
233
+ return &EV->EntryValues ;
234
+ return nullptr ;
235
+ }
236
+ void addEntryValueExpr (MCRegister Reg, const DIExpression &Expr) {
237
+ get<EntryValueLoc>().addExpr (Reg, Expr);
224
238
}
225
-
226
- std::optional<DbgVariableEntryValue> &getEntryValue () { return EntryValue; }
227
239
228
240
// / Initialize from a DBG_VALUE instruction.
229
241
void initializeDbgValue (const MachineInstr *DbgValue);
@@ -234,21 +246,38 @@ class DbgVariable : public DbgEntity {
234
246
}
235
247
236
248
const DIExpression *getSingleExpression () const {
237
- assert (ValueLoc.get () && FrameIndexExprs.size () <= 1 );
238
- return FrameIndexExprs.size () ? FrameIndexExprs[0 ].Expr : nullptr ;
249
+ return get<SingleLoc>().Expr ;
239
250
}
240
251
241
- void setDebugLocListIndex (unsigned O) { DebugLocListIndex = O; }
242
- unsigned getDebugLocListIndex () const { return DebugLocListIndex; }
243
- void setDebugLocListTagOffset (uint8_t O) { DebugLocListTagOffset = O; }
252
+ void setDebugLocListIndex (uint8_t O) {
253
+ if (auto *M = std::get_if<MultiLoc>(this ))
254
+ M->DebugLocListIndex = O;
255
+ else
256
+ emplace<MultiLoc>().DebugLocListIndex = O;
257
+ }
258
+ unsigned getDebugLocListIndex () const {
259
+ if (auto *M = std::get_if<MultiLoc>(this ))
260
+ return M->DebugLocListIndex ;
261
+ return ~0U ;
262
+ }
263
+ void setDebugLocListTagOffset (uint8_t O) {
264
+ if (auto *M = std::get_if<MultiLoc>(this ))
265
+ M->DebugLocListTagOffset = O;
266
+ else
267
+ emplace<MultiLoc>().DebugLocListTagOffset = O;
268
+ }
244
269
std::optional<uint8_t > getDebugLocListTagOffset () const {
245
- return DebugLocListTagOffset;
270
+ return get<MultiLoc>(). DebugLocListTagOffset ;
246
271
}
247
272
StringRef getName () const { return getVariable ()->getName (); }
248
- const DbgValueLoc *getValueLoc () const { return ValueLoc.get (); }
273
+ const DbgValueLoc *getValueLoc () const {
274
+ if (auto *M = std::get_if<SingleLoc>(this ))
275
+ return M->ValueLoc .get ();
276
+ return nullptr ;
277
+ }
249
278
// / Get the FI entries, sorted by fragment offset.
250
279
ArrayRef<FrameIndexExpr> getFrameIndexExprs () const ;
251
- bool hasFrameIndexExprs () const { return !FrameIndexExprs. empty (); }
280
+ bool hasFrameIndexExprs () const { return holds<MMILoc> (); }
252
281
void addMMIEntry (const DbgVariable &V);
253
282
254
283
// Translate tag to proper Dwarf tag.
@@ -277,14 +306,7 @@ class DbgVariable : public DbgEntity {
277
306
return false ;
278
307
}
279
308
280
- bool hasComplexAddress () const {
281
- assert (ValueLoc.get () && " Expected DBG_VALUE, not MMI variable" );
282
- assert ((FrameIndexExprs.empty () ||
283
- (FrameIndexExprs.size () == 1 &&
284
- FrameIndexExprs[0 ].Expr ->getNumElements ())) &&
285
- " Invalid Expr for DBG_VALUE" );
286
- return !FrameIndexExprs.empty ();
287
- }
309
+ bool hasComplexAddress () const { return get<SingleLoc>().Expr ; }
288
310
289
311
const DIType *getType () const ;
290
312
0 commit comments