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