@@ -401,6 +401,88 @@ public protocol VarDeclInstruction {
401
401
var varDecl : VarDecl ? { get }
402
402
}
403
403
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
+
404
486
public protocol DebugVariableInstruction : VarDeclInstruction {
405
487
typealias DebugVariable = OptionalBridgedSILDebugVariable
406
488
0 commit comments