Swift SIL: rework Instruction and BasicBlock lists to support deleting instructions during iteration

Replace the generic `List` with the (non-generic) `InstructionList` and `BasicBlockList`.
The `InstructionList` is now a bit different than the `BasicBlockList` because it supports that instructions are deleted while iterating over the list.
Also add a test pass which tests instruction modification while iteration.
This commit is contained in:
Erik Eckstein
2022-12-09 14:08:12 +01:00
parent a8ba48e71d
commit d4d1620f28
10 changed files with 423 additions and 84 deletions

View File

@@ -13,15 +13,10 @@
import Basic
import SILBridging
final public class BasicBlock : ListNode, CustomStringConvertible, HasShortDescription {
final public class BasicBlock : CustomStringConvertible, HasShortDescription {
public var next: BasicBlock? { SILBasicBlock_next(bridged).block }
public var previous: BasicBlock? { SILBasicBlock_previous(bridged).block }
// Needed for ReverseList<BasicBlock>.reversed(). Never use directly.
public var _firstInList: BasicBlock { SILFunction_firstBlock(function.bridged).block! }
// Needed for List<BasicBlock>.reversed(). Never use directly.
public var _lastInList: BasicBlock { SILFunction_lastBlock(function.bridged).block! }
public var function: Function { SILBasicBlock_getFunction(bridged).function }
public var description: String {
@@ -32,8 +27,8 @@ final public class BasicBlock : ListNode, CustomStringConvertible, HasShortDescr
public var arguments: ArgumentArray { ArgumentArray(block: self) }
public var instructions: List<Instruction> {
List(first: SILBasicBlock_firstInst(bridged).instruction)
public var instructions: InstructionList {
InstructionList(first: SILBasicBlock_firstInst(bridged).instruction)
}
public var terminator: TermInst {
@@ -75,6 +70,66 @@ final public class BasicBlock : ListNode, CustomStringConvertible, HasShortDescr
public func == (lhs: BasicBlock, rhs: BasicBlock) -> Bool { lhs === rhs }
public func != (lhs: BasicBlock, rhs: BasicBlock) -> Bool { lhs !== rhs }
/// The list of instructions in a BasicBlock.
///
/// It's allowed to delete the current, next or any other instructions while
/// iterating over the instruction list.
public struct InstructionList : CollectionLikeSequence, IteratorProtocol {
private var currentInstruction: Instruction?
public init(first: Instruction?) { currentInstruction = first }
public mutating func next() -> Instruction? {
if var inst = currentInstruction {
while inst.isDeleted {
guard let nextInst = inst.next else {
return nil
}
inst = nextInst
}
currentInstruction = inst.next
return inst
}
return nil
}
public var first: Instruction? { currentInstruction }
public func reversed() -> ReverseInstructionList {
if let inst = currentInstruction {
let lastInst = SILBasicBlock_lastInst(inst.block.bridged).instruction
return ReverseInstructionList(first: lastInst)
}
return ReverseInstructionList(first: nil)
}
}
/// The list of instructions in a BasicBlock in reverse order.
///
/// It's allowed to delete the current, next or any other instructions while
/// iterating over the instruction list.
public struct ReverseInstructionList : CollectionLikeSequence, IteratorProtocol {
private var currentInstruction: Instruction?
public init(first: Instruction?) { currentInstruction = first }
public mutating func next() -> Instruction? {
if var inst = currentInstruction {
while inst.isDeleted {
guard let nextInst = inst.previous else {
return nil
}
inst = nextInst
}
currentInstruction = inst.previous
return inst
}
return nil
}
public var first: Instruction? { currentInstruction }
}
public struct ArgumentArray : RandomAccessCollection {
fileprivate let block: BasicBlock