Files
swift-mirror/SwiftCompilerSources/Sources/SIL/Utilities/SequenceUtilities.swift
T
Erik Eckstein dd4f3073ca DestroyHoisting: add a complexity limit for very large functions
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.
2026-03-16 16:12:28 +01:00

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()
}
}