@@ -401,6 +401,88 @@ public protocol VarDeclInstruction {
401401 var varDecl : VarDecl ? { get }
402402}
403403
404+ /// A scoped instruction whose single result introduces a variable scope.
405+ ///
406+ /// The scope-ending uses represent the end of the variable scope. This allows trivial 'let' variables to be treated
407+ /// like a value with ownership. 'var' variables are primarily represented as addressable allocations via alloc_box or
408+ /// alloc_stack, but may have redundant VariableScopeInstructions.
409+ public enum VariableScopeInstruction {
410+ case beginBorrow( BeginBorrowInst )
411+ case moveValue( MoveValueInst )
412+
413+ public init ? ( _ inst: Instruction ? ) {
414+ switch inst {
415+ case let bbi as BeginBorrowInst :
416+ guard bbi. isFromVarDecl else {
417+ return nil
418+ }
419+ self = . beginBorrow( bbi)
420+ case let mvi as MoveValueInst :
421+ guard mvi. isFromVarDecl else {
422+ return nil
423+ }
424+ self = . moveValue( mvi)
425+ default :
426+ return nil
427+ }
428+ }
429+
430+ public var instruction : Instruction {
431+ switch self {
432+ case let . beginBorrow( bbi) :
433+ return bbi
434+ case let . moveValue( mvi) :
435+ return mvi
436+ }
437+ }
438+
439+ public var scopeBegin : Value {
440+ instruction as! SingleValueInstruction
441+ }
442+
443+ public var endOperands : LazyFilterSequence < UseList > {
444+ return scopeBegin. uses. endingLifetime
445+ }
446+
447+ // TODO: with SIL verification, we might be able to make varDecl non-Optional.
448+ public var varDecl : VarDecl ? {
449+ if let debugVarDecl = instruction. debugVarDecl {
450+ return debugVarDecl
451+ }
452+ // SILGen may produce double var_decl instructions for the same variable:
453+ // %box = alloc_box [var_decl] "x"
454+ // begin_borrow %box [var_decl]
455+ //
456+ // Assume that, if the begin_borrow or move_value does not have its own debug_value, then it must actually be
457+ // associated with its operand's var_decl.
458+ return instruction. operands [ 0 ] . value. definingInstruction? . findVarDecl ( )
459+ }
460+ }
461+
462+ extension Instruction {
463+ /// Find a variable declaration assoicated with this instruction.
464+ public func findVarDecl( ) -> VarDecl ? {
465+ if let varDeclInst = self as? VarDeclInstruction {
466+ return varDeclInst. varDecl
467+ }
468+ if let varScopeInst = VariableScopeInstruction ( self ) {
469+ return varScopeInst. varDecl
470+ }
471+ return debugVarDecl
472+ }
473+
474+ var debugVarDecl : VarDecl ? {
475+ for result in results {
476+ for use in result. uses {
477+ if let debugVal = use. instruction as? DebugValueInst {
478+ return debugVal. varDecl
479+ }
480+ }
481+ }
482+ return nil
483+ }
484+ }
485+
404486public protocol DebugVariableInstruction : VarDeclInstruction {
405487 typealias DebugVariable = OptionalBridgedSILDebugVariable
406488
0 commit comments