@@ -218,6 +218,96 @@ inline SILBasicBlock::iterator eraseFromParentWithDebugInsts(
218
218
bool hasNonTrivialNonDebugTransitiveUsers (
219
219
PointerUnion<SILInstruction *, SILArgument *> V);
220
220
221
+ // / A light weight abstraction on top of an instruction that carries within it
222
+ // / information about a debug variable. This allows one to write high level code
223
+ // / over the set of such instructions with greater correctness by using
224
+ // / exhaustive switches, methods, and keeping it light weight by using *, ->
225
+ // / operators to access functionality from the underlying instruction when
226
+ // / needed.
227
+ struct DebugVarCarryingInst {
228
+ enum class Kind {
229
+ Invalid = 0 ,
230
+ DebugValue,
231
+ DebugValueAddr,
232
+ AllocStack,
233
+ AllocBox,
234
+ };
235
+
236
+ Kind kind;
237
+ SILInstruction *inst;
238
+
239
+ DebugVarCarryingInst () : kind(Kind::Invalid), inst(nullptr ) {}
240
+ DebugVarCarryingInst (DebugValueInst *dvi)
241
+ : kind(Kind::DebugValue), inst(dvi) {}
242
+ DebugVarCarryingInst (DebugValueAddrInst *dvai)
243
+ : kind(Kind::DebugValueAddr), inst(dvai) {}
244
+ DebugVarCarryingInst (AllocStackInst *asi)
245
+ : kind(Kind::AllocStack), inst(asi) {}
246
+ DebugVarCarryingInst (AllocBoxInst *abi) : kind(Kind::AllocBox), inst(abi) {}
247
+ DebugVarCarryingInst (SILInstruction *newInst)
248
+ : kind(Kind::Invalid), inst(nullptr ) {
249
+ switch (newInst->getKind ()) {
250
+ default :
251
+ return ;
252
+ case SILInstructionKind::DebugValueInst:
253
+ kind = Kind::DebugValue;
254
+ break ;
255
+ case SILInstructionKind::DebugValueAddrInst:
256
+ kind = Kind::DebugValueAddr;
257
+ break ;
258
+ case SILInstructionKind::AllocStackInst:
259
+ kind = Kind::AllocStack;
260
+ break ;
261
+ case SILInstructionKind::AllocBoxInst:
262
+ kind = Kind::AllocBox;
263
+ break ;
264
+ }
265
+ inst = newInst;
266
+ }
267
+
268
+ // / Enable the composition struct to be used as an instruction easily. We use
269
+ // / a '*' so that in the source it is easily visible to the eye that something
270
+ // / is happening here.
271
+ SILInstruction *operator *() const { return inst; }
272
+
273
+ // / Enable one to access the methods of the wrapped instruction using
274
+ // / '->'. This keeps the wrapper light weight.
275
+ SILInstruction *operator ->() const { return inst; }
276
+
277
+ // / Add support for this struct in `if` statement.
278
+ explicit operator bool () const { return bool (kind); }
279
+
280
+ VarDecl *getDecl () const {
281
+ switch (kind) {
282
+ case Kind::Invalid:
283
+ llvm_unreachable (" Invalid?!" );
284
+ case Kind::DebugValue:
285
+ return cast<DebugValueInst>(inst)->getDecl ();
286
+ case Kind::DebugValueAddr:
287
+ return cast<DebugValueAddrInst>(inst)->getDecl ();
288
+ case Kind::AllocStack:
289
+ return cast<AllocStackInst>(inst)->getDecl ();
290
+ case Kind::AllocBox:
291
+ return cast<AllocBoxInst>(inst)->getDecl ();
292
+ }
293
+ }
294
+
295
+ Optional<SILDebugVariable> getVarInfo () const {
296
+ switch (kind) {
297
+ case Kind::Invalid:
298
+ llvm_unreachable (" Invalid?!" );
299
+ case Kind::DebugValue:
300
+ return cast<DebugValueInst>(inst)->getVarInfo ();
301
+ case Kind::DebugValueAddr:
302
+ return cast<DebugValueAddrInst>(inst)->getVarInfo ();
303
+ case Kind::AllocStack:
304
+ return cast<AllocStackInst>(inst)->getVarInfo ();
305
+ case Kind::AllocBox:
306
+ return cast<AllocBoxInst>(inst)->getVarInfo ();
307
+ }
308
+ }
309
+ };
310
+
221
311
} // end namespace swift
222
312
223
313
#endif // SWIFT_SIL_DEBUGUTILS_H
0 commit comments