@@ -429,6 +429,34 @@ extension Type {
429429// Builder initialization
430430//===----------------------------------------------------------------------===//
431431
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+
432460extension Builder {
433461 /// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
434462 init ( before insPnt: Instruction , location: Location , _ context: some MutatingContext ) {
@@ -437,8 +465,23 @@ extension Builder {
437465 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
438466 }
439467
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 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:_:)``.
441474 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 ) {
442485 context. verifyIsTransforming ( function: insPnt. parentFunction)
443486 self . init ( insertAt: . before( insPnt) , location: insPnt. location,
444487 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
@@ -456,10 +499,10 @@ extension Builder {
456499 }
457500 }
458501
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.
460504 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)
463506 }
464507
465508 /// Creates a builder which inserts at the end of `block`, using a custom `location`.
@@ -478,11 +521,12 @@ extension Builder {
478521 }
479522
480523 /// 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`.
482525 init ( atBeginOf block: BasicBlock , _ context: some MutatingContext ) {
483526 context. verifyIsTransforming ( function: block. parentFunction)
484527 let firstInst = block. instructions. first!
485- self . init ( insertAt: . before( firstInst) , location: firstInst. location,
528+ self . init ( insertAt: . before( firstInst) ,
529+ location: firstInst. locationOfNextNonMetaInstruction,
486530 context. notifyInstructionChanged, context. _bridged. asNotificationHandler ( ) )
487531 }
488532
0 commit comments