mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
dd4f3073ca
For very large functions this optimization can run into noticeable quadratic behavior. Therefore, ignore functions with more than 100000 SIL instructions. This limit is large enough to not affect most of real-world SIL functions.
189 lines
6.0 KiB
Swift
189 lines
6.0 KiB
Swift
//===--- SequenceUtilities.swift ------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import Basic
|
|
|
|
/// Types conforming to `HasShortDescription` will be displayed by their name (instead
|
|
/// of the full object) in collection descriptions.
|
|
///
|
|
/// This is useful to make collections, e.g. of BasicBlocks or Functions, readable.
|
|
public protocol HasShortDescription {
|
|
var shortDescription: String { get }
|
|
}
|
|
|
|
private struct CustomMirrorChild : CustomStringConvertible, NoReflectionChildren {
|
|
public var description: String
|
|
|
|
public init(description: String) { self.description = description }
|
|
}
|
|
|
|
/// Makes a Sequence's `description` and `customMirror` formatted like Array, e.g. [a, b, c].
|
|
public protocol FormattedLikeArray : Sequence, CustomStringConvertible, CustomReflectable {
|
|
}
|
|
|
|
extension FormattedLikeArray {
|
|
/// Display a Sequence in an array like format, e.g. [a, b, c]
|
|
public var description: String {
|
|
"[" + map {
|
|
if let named = $0 as? HasShortDescription {
|
|
return named.shortDescription
|
|
}
|
|
return String(describing: $0)
|
|
}.joined(separator: ", ") + "]"
|
|
}
|
|
|
|
/// The mirror which adds the children of a Sequence, similar to `Array`.
|
|
public var customMirror: Mirror {
|
|
// If the one-line description is not too large, print that instead of the
|
|
// children in separate lines.
|
|
if description.count <= 80 {
|
|
return Mirror(self, children: [])
|
|
}
|
|
let c: [Mirror.Child] = map {
|
|
let val: Any
|
|
if let named = $0 as? HasShortDescription {
|
|
val = CustomMirrorChild(description: named.shortDescription)
|
|
} else {
|
|
val = $0
|
|
}
|
|
return (label: nil, value: val)
|
|
}
|
|
return Mirror(self, children: c, displayStyle: .collection)
|
|
}
|
|
}
|
|
|
|
/// A Sequence which is not consuming and therefore behaves like a Collection.
|
|
///
|
|
/// Many sequences in SIL and the optimizer should be collections but cannot
|
|
/// because their Index cannot conform to Comparable. Those sequences conform
|
|
/// to CollectionLikeSequence.
|
|
///
|
|
/// For convenience it also inherits from FormattedLikeArray.
|
|
public protocol CollectionLikeSequence : FormattedLikeArray {
|
|
}
|
|
|
|
public extension Sequence {
|
|
var isEmpty: Bool { !contains(where: { _ in true }) }
|
|
|
|
var singleElement: Element? {
|
|
var singleElement: Element? = nil
|
|
for e in self {
|
|
if singleElement != nil {
|
|
return nil
|
|
}
|
|
singleElement = e
|
|
}
|
|
return singleElement
|
|
}
|
|
|
|
var first: Element? { first(where: { _ in true }) }
|
|
|
|
func countExceeds(_ n: Int) -> Bool {
|
|
for (idx, _) in self.enumerated() {
|
|
if idx > n {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.
|
|
|
|
extension LazySequence : /*@retroactive*/ SIL.CollectionLikeSequence,
|
|
/*@retroactive*/ SIL.FormattedLikeArray,
|
|
/*@retroactive*/ Swift.CustomStringConvertible,
|
|
/*@retroactive*/ Swift.CustomReflectable
|
|
where Base: CollectionLikeSequence {}
|
|
|
|
extension FlattenSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
|
|
/*@retroactive*/ SIL.FormattedLikeArray,
|
|
/*@retroactive*/ Swift.CustomStringConvertible,
|
|
/*@retroactive*/ Swift.CustomReflectable
|
|
where Base: CollectionLikeSequence {}
|
|
|
|
extension LazyMapSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
|
|
/*@retroactive*/ SIL.FormattedLikeArray,
|
|
/*@retroactive*/ Swift.CustomStringConvertible,
|
|
/*@retroactive*/ Swift.CustomReflectable
|
|
where Base: CollectionLikeSequence {}
|
|
|
|
extension LazyFilterSequence : /*@retroactive*/ SIL.CollectionLikeSequence,
|
|
/*@retroactive*/ SIL.FormattedLikeArray,
|
|
/*@retroactive*/ Swift.CustomStringConvertible,
|
|
/*@retroactive*/ Swift.CustomReflectable
|
|
where Base: CollectionLikeSequence {}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Single-Element Inline Array
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public struct SingleInlineArray<Element>: RandomAccessCollection, FormattedLikeArray {
|
|
public var singleElement: Element?
|
|
private var multipleElements: [Element] = []
|
|
|
|
public init() {}
|
|
|
|
public init(element: Element) {
|
|
singleElement = element
|
|
}
|
|
|
|
public var startIndex: Int { 0 }
|
|
public var endIndex: Int {
|
|
singleElement == nil ? 0 : multipleElements.count + 1
|
|
}
|
|
|
|
public subscript(_ index: Int) -> Element {
|
|
_read {
|
|
if index == 0 {
|
|
yield singleElement!
|
|
} else {
|
|
yield multipleElements[index - 1]
|
|
}
|
|
}
|
|
_modify {
|
|
if index == 0 {
|
|
yield &singleElement!
|
|
} else {
|
|
yield &multipleElements[index - 1]
|
|
}
|
|
}
|
|
}
|
|
|
|
public mutating func append(_ element: __owned Element) {
|
|
push(element)
|
|
}
|
|
|
|
public mutating func append<S: Sequence>(contentsOf newElements: __owned S) where S.Element == Element {
|
|
for element in newElements {
|
|
push(element)
|
|
}
|
|
}
|
|
|
|
public mutating func push(_ element: __owned Element) {
|
|
guard singleElement != nil else {
|
|
singleElement = element
|
|
return
|
|
}
|
|
multipleElements.append(element)
|
|
}
|
|
|
|
public mutating func popLast() -> Element? {
|
|
if multipleElements.isEmpty {
|
|
let last = singleElement
|
|
singleElement = nil
|
|
return last
|
|
}
|
|
return multipleElements.popLast()
|
|
}
|
|
}
|