@@ -218,6 +218,96 @@ inline SILBasicBlock::iterator eraseFromParentWithDebugInsts(
218218bool hasNonTrivialNonDebugTransitiveUsers (
219219 PointerUnion<SILInstruction *, SILArgument *> V);
220220
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+
221311} // end namespace swift
222312
223313#endif // SWIFT_SIL_DEBUGUTILS_H
0 commit comments