@@ -433,6 +433,34 @@ extension Type {
433433// Builder initialization
434434//===----------------------------------------------------------------------===//
435435
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+
436464extension Builder {
437465 /// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
438466 init ( before insPnt: Instruction , location: Location , _ context: some MutatingContext ) {
@@ -441,8 +469,23 @@ extension Builder {
441469 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
442470 }
443471
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:_:)``.
445478 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 ) {
446489 context. verifyIsTransforming ( function: insPnt. parentFunction)
447490 self . init ( insertAt: . before( insPnt) , location: insPnt. location,
448491 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
@@ -460,10 +503,10 @@ extension Builder {
460503 }
461504 }
462505
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.
464508 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)
467510 }
468511
469512 /// Creates a builder which inserts at the end of `block`, using a custom `location`.
@@ -482,11 +525,12 @@ extension Builder {
482525 }
483526
484527 /// 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`.
486529 init ( atBeginOf block: BasicBlock , _ context: some MutatingContext ) {
487530 context. verifyIsTransforming ( function: block. parentFunction)
488531 let firstInst = block. instructions. first!
489- self . init ( insertAt: . before( firstInst) , location: firstInst. location,
532+ self . init ( insertAt: . before( firstInst) ,
533+ location: firstInst. locationOfNextNonMetaInstruction,
490534 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
491535 }
492536
0 commit comments