Skip to content

Commit 345fcbe

Browse files
committed
Improve collections in the swift SIL/Optimizer
Improve block/instruction lists and similar collections * pretty print collections in the form “[a, b, c]” * also do this for lazy sequences * define a custom Mirror * in a collection, only print the name of blocks, functions and globals (instead of the full object) * replace `BasicBlock.reverseInstructions` with `BasicBlock.instructions.reversed()` - in an efficient way
1 parent 24b62d4 commit 345fcbe

File tree

8 files changed

+124
-59
lines changed

8 files changed

+124
-59
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/CalleeAnalysis.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public struct CalleeAnalysis {
2121
}
2222
}
2323

24-
public struct FunctionArray : RandomAccessCollection, CustomReflectable {
24+
public struct FunctionArray : RandomAccessCollection, FormattedLikeArray {
2525
fileprivate let bridged: BridgedCalleeList
2626

2727
public var startIndex: Int { 0 }
@@ -32,9 +32,4 @@ public struct FunctionArray : RandomAccessCollection, CustomReflectable {
3232
}
3333

3434
public var allCalleesKnown: Bool { bridged.incomplete == 0 }
35-
36-
public var customMirror: Mirror {
37-
let c: [Mirror.Child] = map { (label: nil, value: $0.name) }
38-
return Mirror(self, children: c)
39-
}
4035
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/SILPrinter.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ func runSILPrinter(function: Function, context: PassContext) {
2020
for (bbIdx, block) in function.blocks.enumerated() {
2121
print("bb\(bbIdx):")
2222

23-
print(" predecessors: " +
24-
block.predecessors.map { $0.label }.joined(separator: ", "))
25-
print(" successors: " +
26-
block.successors.map { $0.label }.joined(separator: ", "))
23+
print(" predecessors: \(block.predecessors)")
24+
print(" successors: \(block.successors)")
2725

2826
print(" arguments:")
2927
for arg in block.arguments {

SwiftCompilerSources/Sources/SIL/BasicBlock.swift

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,15 @@
1212

1313
import SILBridging
1414

15-
final public class BasicBlock : ListNode, CustomStringConvertible {
15+
final public class BasicBlock : ListNode, CustomStringConvertible, HasName {
1616
public var next: BasicBlock? { SILBasicBlock_next(bridged).block }
1717
public var previous: BasicBlock? { SILBasicBlock_previous(bridged).block }
1818

19+
// Needed for ReverseList<BasicBlock>.reversed(). Never use directly.
20+
public var _firstInList: BasicBlock { SILFunction_firstBlock(function.bridged).block! }
21+
// Needed for List<BasicBlock>.reversed(). Never use directly.
22+
public var _lastInList: BasicBlock { SILFunction_lastBlock(function.bridged).block! }
23+
1924
public var function: Function { SILBasicBlock_getFunction(bridged).function }
2025

2126
public var description: String {
@@ -25,11 +30,7 @@ final public class BasicBlock : ListNode, CustomStringConvertible {
2530
public var arguments: ArgumentArray { ArgumentArray(block: self) }
2631

2732
public var instructions: List<Instruction> {
28-
List(startAt: SILBasicBlock_firstInst(bridged).instruction)
29-
}
30-
31-
public var reverseInstructions: ReverseList<Instruction> {
32-
ReverseList(startAt: SILBasicBlock_lastInst(bridged).instruction)
33+
List(first: SILBasicBlock_firstInst(bridged).instruction)
3334
}
3435

3536
public var terminator: TermInst {
@@ -60,8 +61,8 @@ final public class BasicBlock : ListNode, CustomStringConvertible {
6061
}
6162
fatalError()
6263
}
63-
64-
public var label: String { "bb\(index)" }
64+
65+
public var name: String { "bb\(index)" }
6566

6667
var bridged: BridgedBasicBlock { BridgedBasicBlock(obj: SwiftObject(self)) }
6768
}
@@ -80,7 +81,7 @@ public struct ArgumentArray : RandomAccessCollection {
8081
}
8182
}
8283

83-
public struct SuccessorArray : RandomAccessCollection, CustomReflectable {
84+
public struct SuccessorArray : RandomAccessCollection, FormattedLikeArray {
8485
private let succArray: BridgedArrayRef
8586

8687
init(succArray: BridgedArrayRef) {
@@ -95,14 +96,9 @@ public struct SuccessorArray : RandomAccessCollection, CustomReflectable {
9596
let s = BridgedSuccessor(succ: succArray.data + index &* BridgedSuccessorSize);
9697
return SILSuccessor_getTargetBlock(s).block
9798
}
98-
99-
public var customMirror: Mirror {
100-
let c: [Mirror.Child] = map { (label: nil, value: $0.label) }
101-
return Mirror(self, children: c)
102-
}
10399
}
104100

105-
public struct PredecessorList : Sequence, IteratorProtocol, CustomReflectable {
101+
public struct PredecessorList : CollectionLikeSequence, IteratorProtocol {
106102
private var currentSucc: OptionalBridgedSuccessor
107103

108104
public init(startAt: OptionalBridgedSuccessor) { currentSucc = startAt }
@@ -115,11 +111,6 @@ public struct PredecessorList : Sequence, IteratorProtocol, CustomReflectable {
115111
}
116112
return nil
117113
}
118-
119-
public var customMirror: Mirror {
120-
let c: [Mirror.Child] = map { (label: nil, value: $0) }
121-
return Mirror(self, children: c)
122-
}
123114
}
124115

125116

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
import SILBridging
1414

15-
final public class Function : CustomStringConvertible {
15+
final public class Function : CustomStringConvertible, HasName {
16+
1617
public var name: String {
1718
return SILFunction_getName(bridged).string
1819
}
@@ -26,11 +27,7 @@ final public class Function : CustomStringConvertible {
2627
}
2728

2829
public var blocks : List<BasicBlock> {
29-
return List(startAt: SILFunction_firstBlock(bridged).block)
30-
}
31-
32-
public var reverseBlocks : ReverseList<BasicBlock> {
33-
return ReverseList(startAt: SILFunction_lastBlock(bridged).block)
30+
return List(first: SILFunction_firstBlock(bridged).block)
3431
}
3532

3633
public var arguments: LazyMapSequence<ArgumentArray, FunctionArgument> {

SwiftCompilerSources/Sources/SIL/GlobalVariable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import SILBridging
1414

15-
final public class GlobalVariable : CustomStringConvertible {
15+
final public class GlobalVariable : CustomStringConvertible, HasName {
1616
public var name: String {
1717
return SILGlobalVariable_getName(bridged).string
1818
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public class Instruction : ListNode, CustomStringConvertible, Hashable {
2525
SILInstruction_previous(bridged).instruction
2626
}
2727

28+
// Needed for ReverseList<Instruction>.reversed(). Never use directly.
29+
public var _firstInList: Instruction { SILBasicBlock_firstInst(block.bridged).instruction! }
30+
// Needed for List<Instruction>.reversed(). Never use directly.
31+
public var _lastInList: Instruction { SILBasicBlock_lastInst(block.bridged).instruction! }
32+
2833
final public var block: BasicBlock {
2934
SILInstruction_getParent(bridged).block
3035
}

SwiftCompilerSources/Sources/SIL/Operand.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public struct OperandArray : RandomAccessCollection, CustomReflectable {
9191
}
9292
}
9393

94-
public struct UseList : Sequence, CustomReflectable {
94+
public struct UseList : CollectionLikeSequence {
9595
public struct Iterator : IteratorProtocol {
9696
var currentOpPtr: UnsafeRawPointer?
9797

@@ -121,9 +121,4 @@ public struct UseList : Sequence, CustomReflectable {
121121
public func makeIterator() -> Iterator {
122122
return Iterator(currentOpPtr: firstOpPtr)
123123
}
124-
125-
public var customMirror: Mirror {
126-
let c: [Mirror.Child] = map { (label: "use", value: $0) }
127-
return Mirror(self, children: c)
128-
}
129124
}

SwiftCompilerSources/Sources/SIL/Utils.swift

Lines changed: 100 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,19 @@ public protocol ListNode : AnyObject {
2020
associatedtype Element
2121
var next: Element? { get }
2222
var previous: Element? { get }
23+
24+
/// The first node in the list. Used to implement `reversed()`.
25+
var _firstInList: Element { get }
26+
27+
/// The last node in the list. Used to implement `reversed()`.
28+
var _lastInList: Element { get }
2329
}
2430

2531
public struct List<NodeType: ListNode> :
26-
Sequence, IteratorProtocol, CustomReflectable
27-
where NodeType.Element == NodeType {
32+
CollectionLikeSequence, IteratorProtocol where NodeType.Element == NodeType {
2833
private var currentNode: NodeType?
2934

30-
public init(startAt: NodeType?) { currentNode = startAt }
35+
public init(first: NodeType?) { currentNode = first }
3136

3237
public mutating func next() -> NodeType? {
3338
if let node = currentNode {
@@ -39,18 +44,19 @@ public struct List<NodeType: ListNode> :
3944

4045
public var first: NodeType? { currentNode }
4146

42-
public var customMirror: Mirror {
43-
let c: [Mirror.Child] = map { (label: nil, value: $0) }
44-
return Mirror(self, children: c)
47+
public func reversed() -> ReverseList<NodeType> {
48+
if let node = first {
49+
return ReverseList(first: node._lastInList)
50+
}
51+
return ReverseList(first: nil)
4552
}
4653
}
4754

4855
public struct ReverseList<NodeType: ListNode> :
49-
Sequence, IteratorProtocol, CustomReflectable
50-
where NodeType.Element == NodeType {
56+
CollectionLikeSequence, IteratorProtocol where NodeType.Element == NodeType {
5157
private var currentNode: NodeType?
5258

53-
public init(startAt: NodeType?) { currentNode = startAt }
59+
public init(first: NodeType?) { currentNode = first }
5460

5561
public mutating func next() -> NodeType? {
5662
if let node = currentNode {
@@ -62,23 +68,101 @@ public struct ReverseList<NodeType: ListNode> :
6268

6369
public var first: NodeType? { currentNode }
6470

65-
public var customMirror: Mirror {
66-
let c: [Mirror.Child] = map { (label: nil, value: $0) }
67-
return Mirror(self, children: c)
71+
public func reversed() -> ReverseList<NodeType> {
72+
if let node = first {
73+
return ReverseList(first: node._firstInList)
74+
}
75+
return ReverseList(first: nil)
6876
}
6977
}
7078

7179

7280
//===----------------------------------------------------------------------===//
73-
// General Utilities
81+
// Sequence Utilities
7482
//===----------------------------------------------------------------------===//
7583

76-
extension Sequence {
77-
public var isEmpty: Bool {
78-
!contains(where: { _ in true })
84+
/// Types conforming to `HasName` will be displayed by their name (instead of the
85+
/// full object) in collection descriptions.
86+
///
87+
/// This is useful to make collections, e.g. of BasicBlocks or Functions, readable.
88+
public protocol HasName {
89+
var name: String { get }
90+
}
91+
92+
private struct CustomMirrorChild : CustomStringConvertible, CustomReflectable {
93+
public var description: String
94+
public var customMirror: Mirror { Mirror(self, children: []) }
95+
96+
public init(description: String) { self.description = description }
97+
}
98+
99+
/// Makes a Sequence's `description` and `customMirror` formatted like Array, e.g. [a, b, c].
100+
public protocol FormattedLikeArray : Sequence, CustomStringConvertible, CustomReflectable {
101+
}
102+
103+
extension FormattedLikeArray {
104+
/// Display a Sequence in an array like format, e.g. [a, b, c]
105+
public var description: String {
106+
"[" + map {
107+
if let named = $0 as? HasName {
108+
return named.name
109+
}
110+
return String(describing: $0)
111+
}.joined(separator: ", ") + "]"
112+
}
113+
114+
/// The mirror which adds the children of a Sequence, similar to `Array`.
115+
public var customMirror: Mirror {
116+
// If the one-line description is not too large, print that instead of the
117+
// children in separate lines.
118+
if description.count <= 80 {
119+
return Mirror(self, children: [])
120+
}
121+
let c: [Mirror.Child] = map {
122+
let val: Any
123+
if let named = $0 as? HasName {
124+
val = CustomMirrorChild(description: named.name)
125+
} else {
126+
val = $0
127+
}
128+
return (label: nil, value: val)
129+
}
130+
return Mirror(self, children: c, displayStyle: .collection)
79131
}
80132
}
81133

134+
/// A Sequence which is not consuming and therefore behaves like a Collection.
135+
///
136+
/// Many sequences in SIL and the optimizer should be collections but cannot
137+
/// because their Index cannot conform to Comparable. Those sequences conform
138+
/// to CollectionLikeSequence.
139+
///
140+
/// For convenience it also inherits from FormattedLikeArray.
141+
public protocol CollectionLikeSequence : FormattedLikeArray {
142+
}
143+
144+
public extension CollectionLikeSequence {
145+
var isEmpty: Bool { !contains(where: { _ in true }) }
146+
}
147+
148+
// Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.
149+
150+
extension LazySequence : CollectionLikeSequence,
151+
FormattedLikeArray, CustomStringConvertible, CustomReflectable
152+
where Base: CollectionLikeSequence {}
153+
154+
extension FlattenSequence : CollectionLikeSequence,
155+
FormattedLikeArray, CustomStringConvertible, CustomReflectable
156+
where Base: CollectionLikeSequence {}
157+
158+
extension LazyMapSequence : CollectionLikeSequence,
159+
FormattedLikeArray, CustomStringConvertible, CustomReflectable
160+
where Base: CollectionLikeSequence {}
161+
162+
extension LazyFilterSequence : CollectionLikeSequence,
163+
FormattedLikeArray, CustomStringConvertible, CustomReflectable
164+
where Base: CollectionLikeSequence {}
165+
82166
//===----------------------------------------------------------------------===//
83167
// Bridging Utilities
84168
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)