@@ -433,6 +433,34 @@ extension Type {
433
433
// Builder initialization
434
434
//===----------------------------------------------------------------------===//
435
435
436
+ private extension Instruction {
437
+ /// Returns self, unless self is a meta instruction, in which case the next
438
+ /// non-meta instruction is returned. Returns nil if there are no non-meta
439
+ /// instructions in the basic block.
440
+ var nextNonMetaInstruction : Instruction ? {
441
+ for inst in InstructionList ( first: self ) where !( inst is MetaInstruction ) {
442
+ return inst
443
+ }
444
+ return nil
445
+ }
446
+
447
+ /// Returns the next interesting location. As it is impossible to set a
448
+ /// breakpoint on a meta instruction, those are skipped.
449
+ /// However, we don't want to take a location with different inlining
450
+ /// information than this instruction, so in that case, we will return the
451
+ /// location of the meta instruction. If the meta instruction is the only
452
+ /// instruction in the basic block, we also take its location.
453
+ var locationOfNextNonMetaInstruction : Location {
454
+ let location = self . location
455
+ guard !location. isInlined,
456
+ let nextLocation = nextNonMetaInstruction? . location,
457
+ !nextLocation. isInlined else {
458
+ return location
459
+ }
460
+ return nextLocation
461
+ }
462
+ }
463
+
436
464
extension Builder {
437
465
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
438
466
init ( before insPnt: Instruction , location: Location , _ context: some MutatingContext ) {
@@ -441,8 +469,23 @@ extension Builder {
441
469
context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
442
470
}
443
471
444
- /// Creates a builder which inserts _before_ `insPnt`, using the location of `insPnt`.
472
+ /// Creates a builder which inserts before `insPnt`, using `insPnt`'s next
473
+ /// non-meta instruction's location.
474
+ /// This function should be used when moving code to an unknown insert point,
475
+ /// when we want to inherit the location of the closest non-meta instruction.
476
+ /// For replacing an existing meta instruction with another, use
477
+ /// ``Builder.init(replacing:_:)``.
445
478
init ( before insPnt: Instruction , _ context: some MutatingContext ) {
479
+ context. verifyIsTransforming ( function: insPnt. parentFunction)
480
+ self . init ( insertAt: . before( insPnt) ,
481
+ location: insPnt. locationOfNextNonMetaInstruction,
482
+ context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
483
+ }
484
+
485
+ /// Creates a builder which inserts _before_ `insPnt`, using the exact location of `insPnt`,
486
+ /// for the purpose of replacing that meta instruction with an equivalent instruction.
487
+ /// This function does not delete `insPnt`.
488
+ init ( replacing insPnt: MetaInstruction , _ context: some MutatingContext ) {
446
489
context. verifyIsTransforming ( function: insPnt. parentFunction)
447
490
self . init ( insertAt: . before( insPnt) , location: insPnt. location,
448
491
context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
@@ -460,10 +503,10 @@ extension Builder {
460
503
}
461
504
}
462
505
463
- /// Creates a builder which inserts _after_ `insPnt`, using the location of `insPnt`.
506
+ /// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
507
+ /// non-meta instruction's location.
464
508
init ( after insPnt: Instruction , _ context: some MutatingContext ) {
465
- context. verifyIsTransforming ( function: insPnt. parentFunction)
466
- self . init ( after: insPnt, location: insPnt. location, context)
509
+ self . init ( after: insPnt, location: insPnt. locationOfNextNonMetaInstruction, context)
467
510
}
468
511
469
512
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
@@ -482,11 +525,12 @@ extension Builder {
482
525
}
483
526
484
527
/// Creates a builder which inserts at the begin of `block`, using the location of the first
485
- /// instruction of `block`.
528
+ /// non-meta instruction of `block`.
486
529
init ( atBeginOf block: BasicBlock , _ context: some MutatingContext ) {
487
530
context. verifyIsTransforming ( function: block. parentFunction)
488
531
let firstInst = block. instructions. first!
489
- self . init ( insertAt: . before( firstInst) , location: firstInst. location,
532
+ self . init ( insertAt: . before( firstInst) ,
533
+ location: firstInst. locationOfNextNonMetaInstruction,
490
534
context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
491
535
}
492
536
0 commit comments