Skip to content

Commit 1efcb41

Browse files
authored
Merge pull request #70217 from kubamracek/embedded-set
[embedded] Add Set to the embedded stdlib
2 parents 6d00750 + bde23e2 commit 1efcb41

18 files changed

+249
-15
lines changed

stdlib/public/core/BridgeStorage.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
//===----------------------------------------------------------------------===//
2121
import SwiftShims
2222

23+
#if !$Embedded
24+
2325
@frozen
2426
@usableFromInline
2527
internal struct _BridgeStorage<NativeClass: AnyObject> {
@@ -159,3 +161,77 @@ internal struct _BridgeStorage<NativeClass: AnyObject> {
159161
}
160162
}
161163
}
164+
165+
#else
166+
167+
@frozen
168+
@usableFromInline
169+
internal struct _BridgeStorage<NativeClass: AnyObject> {
170+
@usableFromInline
171+
internal typealias Native = NativeClass
172+
173+
// rawValue is passed inout to _isUnique. Although its value
174+
// is unchanged, it must appear mutable to the optimizer.
175+
@usableFromInline
176+
internal var rawValue: NativeClass
177+
178+
@inlinable
179+
@inline(__always)
180+
internal init(native: Native) {
181+
_internalInvariant(_usesNativeSwiftReferenceCounting(NativeClass.self))
182+
rawValue = native
183+
}
184+
185+
@inlinable
186+
@inline(__always)
187+
internal mutating func isUniquelyReferencedNative() -> Bool {
188+
return _isUnique(&rawValue)
189+
}
190+
191+
@_alwaysEmitIntoClient
192+
@inline(__always)
193+
internal mutating func beginCOWMutationNative() -> Bool {
194+
return Bool(Builtin.beginCOWMutation(&rawValue))
195+
}
196+
197+
@inlinable
198+
static var flagMask: UInt {
199+
@inline(__always) get {
200+
return (1 as UInt) << _objectPointerLowSpareBitShift
201+
}
202+
}
203+
204+
@inlinable
205+
internal var nativeInstance: Native {
206+
@inline(__always) get {
207+
return rawValue
208+
}
209+
}
210+
211+
@inlinable
212+
internal var unflaggedNativeInstance: Native {
213+
@inline(__always) get {
214+
return rawValue
215+
}
216+
}
217+
218+
@inlinable
219+
@inline(__always)
220+
internal mutating func isUniquelyReferencedUnflaggedNative() -> Bool {
221+
return _isUnique_native(&rawValue)
222+
}
223+
224+
@_alwaysEmitIntoClient
225+
@inline(__always)
226+
internal mutating func beginCOWMutationUnflaggedNative() -> Bool {
227+
return Bool(Builtin.beginCOWMutation_native(&rawValue))
228+
}
229+
230+
@_alwaysEmitIntoClient
231+
@inline(__always)
232+
internal mutating func endCOWMutation() {
233+
Builtin.endCOWMutation(&rawValue)
234+
}
235+
}
236+
237+
#endif

stdlib/public/core/Builtin.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,11 @@ func _isUnique_native<T>(_ object: inout T) -> Bool {
725725
// This could be a bridge object, single payload enum, or plain old
726726
// reference. Any case it's non pointer bits must be zero, so
727727
// force cast it to BridgeObject and check the spare bits.
728+
#if !$Embedded
728729
_internalInvariant(
729730
(_bitPattern(Builtin.reinterpretCast(object)) & _objectPointerSpareBits)
730731
== 0)
732+
#endif
731733
_internalInvariant(_usesNativeSwiftReferenceCounting(
732734
type(of: Builtin.reinterpretCast(object) as AnyObject)))
733735
return Bool(Builtin.isUnique_native(&object))

stdlib/public/core/CMakeLists.txt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ split_embedded_sources(
4343
EMBEDDED Assert.swift
4444
EMBEDDED AssertCommon.swift
4545
EMBEDDED BidirectionalCollection.swift
46-
NORMAL Bitset.swift
46+
EMBEDDED Bitset.swift
4747
EMBEDDED Bool.swift
4848
NORMAL BridgeObjectiveC.swift
49-
NORMAL BridgeStorage.swift
49+
EMBEDDED BridgeStorage.swift
5050
NORMAL BridgingBuffer.swift
5151
EMBEDDED Builtin.swift
5252
EMBEDDED BuiltinMath.swift
@@ -89,7 +89,7 @@ split_embedded_sources(
8989
# END WORKAROUND
9090
EMBEDDED Hasher.swift
9191
NORMAL Hashing.swift
92-
NORMAL HashTable.swift
92+
EMBEDDED HashTable.swift
9393
EMBEDDED Identifiable.swift
9494
EMBEDDED Indices.swift
9595
NORMAL InputStream.swift
@@ -111,7 +111,7 @@ split_embedded_sources(
111111
EMBEDDED Misc.swift
112112
EMBEDDED MutableCollection.swift
113113
NORMAL NativeDictionary.swift
114-
NORMAL NativeSet.swift
114+
EMBEDDED NativeSet.swift
115115
NORMAL NewtypeWrapper.swift
116116
NORMAL NFC.swift
117117
NORMAL NFD.swift
@@ -139,15 +139,15 @@ split_embedded_sources(
139139
EMBEDDED SipHash.swift
140140
EMBEDDED Sequence.swift
141141
EMBEDDED SequenceAlgorithms.swift
142-
NORMAL Set.swift
142+
EMBEDDED Set.swift
143143
EMBEDDED SetAlgebra.swift
144144
NORMAL SetAnyHashableExtensions.swift
145145
NORMAL SetBridging.swift
146-
NORMAL SetBuilder.swift
147-
NORMAL SetCasting.swift
148-
NORMAL SetStorage.swift
149-
NORMAL SetVariant.swift
150-
NORMAL ShadowProtocols.swift
146+
EMBEDDED SetBuilder.swift
147+
EMBEDDED SetCasting.swift
148+
EMBEDDED SetStorage.swift
149+
EMBEDDED SetVariant.swift
150+
EMBEDDED ShadowProtocols.swift
151151
NORMAL Shims.swift
152152
EMBEDDED Slice.swift
153153
NORMAL SmallString.swift

stdlib/public/core/ContiguousArrayBuffer.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ internal final class __EmptyArrayStorage
6464
}
6565

6666
#if $Embedded
67+
// In embedded Swift, the stdlib is a .swiftmodule only without any .o/.a files,
68+
// to allow consuming it by clients with different LLVM codegen setting (-mcpu
69+
// flags, etc.), which means we cannot declare the singleton in a C/C++ file.
70+
//
71+
// TODO: We should figure out how to make this a constant so that it's placed in
72+
// non-writable memory (can't be a let, Builtin.addressof below requires a var).
6773
public var _swiftEmptyArrayStorage: (Int, Int, Int, Int) =
6874
(/*isa*/0, /*refcount*/-1, /*count*/0, /*flags*/1)
6975
#endif

stdlib/public/core/DictionaryStorage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ extension _DictionaryStorage {
473473
truncatingIfNeeded: ObjectIdentifier(storage).hashValue)
474474
}
475475

476-
storage._seed = seed ?? _HashTable.hashSeed(for: storage, scale: scale)
476+
storage._seed = seed ?? _HashTable.hashSeed(for: Builtin.castToNativeObject(storage), scale: scale)
477477
storage._rawKeys = UnsafeMutableRawPointer(keysAddr)
478478
storage._rawValues = UnsafeMutableRawPointer(valuesAddr)
479479

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,9 @@ public func swift_deletedMethodError() -> Never {
275275
public func swift_willThrow() throws {
276276
}
277277

278+
@_extern(c, "arc4random_buf")
279+
func arc4random_buf(buf: UnsafeMutableRawPointer, nbytes: Int)
280+
281+
public func swift_stdlib_random(_ buf: UnsafeMutableRawPointer, _ nbytes: Int) {
282+
arc4random_buf(buf: buf, nbytes: nbytes)
283+
}

stdlib/public/core/HashTable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ extension _HashTable {
102102
}
103103

104104
internal static func hashSeed(
105-
for object: AnyObject,
105+
for object: Builtin.NativeObject,
106106
scale: Int8
107107
) -> Int {
108108
// We generate a new hash seed whenever a new hash table is allocated and

stdlib/public/core/Hasher.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ extension Hasher {
251251
}
252252
}
253253

254+
#if $Embedded
255+
@usableFromInline
256+
var _swift_stdlib_Hashing_parameters: _SwiftHashingParameters = {
257+
var seed0: UInt64 = 0, seed1: UInt64 = 0
258+
swift_stdlib_random(&seed0, MemoryLayout<UInt64>.size)
259+
swift_stdlib_random(&seed1, MemoryLayout<UInt64>.size)
260+
return .init(seed0: seed0, seed1: seed1, deterministic: false)
261+
}()
262+
#endif
263+
254264
/// The universal hash function used by `Set` and `Dictionary`.
255265
///
256266
/// `Hasher` can be used to map an arbitrary sequence of bytes to an integer

stdlib/public/core/NativeSet.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ extension _NativeSet: _SetBuffer {
351351
// This function has a highly visible name to make it stand out in stack traces.
352352
@usableFromInline
353353
@inline(never)
354+
@_unavailableInEmbedded
354355
internal func ELEMENT_TYPE_OF_SET_VIOLATES_HASHABLE_REQUIREMENTS(
355356
_ elementType: Any.Type
356357
) -> Never {
@@ -379,7 +380,11 @@ extension _NativeSet { // Insertions
379380
// because we'll need to compare elements in case of hash collisions.
380381
let (bucket, found) = find(element, hashValue: hashValue)
381382
guard !found else {
383+
#if !$Embedded
382384
ELEMENT_TYPE_OF_SET_VIOLATES_HASHABLE_REQUIREMENTS(Element.self)
385+
#else
386+
fatalError("duplicate elements in a Set")
387+
#endif
383388
}
384389
hashTable.insert(bucket)
385390
uncheckedInitialize(at: bucket, to: element)
@@ -418,7 +423,11 @@ extension _NativeSet { // Insertions
418423
if rehashed {
419424
let (b, f) = find(element)
420425
if f {
426+
#if !$Embedded
421427
ELEMENT_TYPE_OF_SET_VIOLATES_HASHABLE_REQUIREMENTS(Element.self)
428+
#else
429+
fatalError("duplicate elements in a Set")
430+
#endif
422431
}
423432
bucket = b
424433
}
@@ -437,7 +446,11 @@ extension _NativeSet { // Insertions
437446
if rehashed {
438447
let (b, f) = find(element)
439448
if f != found {
449+
#if !$Embedded
440450
ELEMENT_TYPE_OF_SET_VIOLATES_HASHABLE_REQUIREMENTS(Element.self)
451+
#else
452+
fatalError("duplicate elements in a Set")
453+
#endif
441454
}
442455
bucket = b
443456
}

stdlib/public/core/Set.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,14 @@ extension Set: Hashable {
448448
}
449449
}
450450

451+
@_unavailableInEmbedded
451452
extension Set: _HasCustomAnyHashableRepresentation {
452453
public __consuming func _toCustomAnyHashable() -> AnyHashable? {
453454
return AnyHashable(_box: _SetAnyHashableBox(self))
454455
}
455456
}
456457

458+
@_unavailableInEmbedded
457459
internal struct _SetAnyHashableBox<Element: Hashable>: _AnyHashableBox {
458460
internal let _value: Set<Element>
459461
internal let _canonical: Set<AnyHashable>
@@ -1034,6 +1036,7 @@ extension Set: SetAlgebra {
10341036
}
10351037
}
10361038

1039+
@_unavailableInEmbedded
10371040
extension Set: CustomStringConvertible, CustomDebugStringConvertible {
10381041
/// A string that represents the contents of the set.
10391042
public var description: String {

stdlib/public/core/SetCasting.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extension Set {
4141
/// - Precondition: `BaseValue` is a base class or base `@objc`
4242
/// protocol (such as `AnyObject`) of `DerivedValue`.
4343
@inlinable
44+
@_unavailableInEmbedded
4445
public func _setUpCast<DerivedValue, BaseValue>(
4546
_ source: Set<DerivedValue>
4647
) -> Set<BaseValue> {
@@ -57,6 +58,7 @@ public func _setUpCast<DerivedValue, BaseValue>(
5758

5859
/// Called by the casting machinery.
5960
@_silgen_name("_swift_setDownCastIndirect")
61+
@_unavailableInEmbedded
6062
internal func _setDownCastIndirect<SourceValue, TargetValue>(
6163
_ source: UnsafePointer<Set<SourceValue>>,
6264
_ target: UnsafeMutablePointer<Set<TargetValue>>) {
@@ -71,6 +73,7 @@ internal func _setDownCastIndirect<SourceValue, TargetValue>(
7173
/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
7274
/// are reference types.
7375
@inlinable
76+
@_unavailableInEmbedded
7477
public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
7578
-> Set<DerivedValue> {
7679

@@ -99,6 +102,7 @@ public func _setDownCast<BaseValue, DerivedValue>(_ source: Set<BaseValue>)
99102

100103
/// Called by the casting machinery.
101104
@_silgen_name("_swift_setDownCastConditionalIndirect")
105+
@_unavailableInEmbedded
102106
internal func _setDownCastConditionalIndirect<SourceValue, TargetValue>(
103107
_ source: UnsafePointer<Set<SourceValue>>,
104108
_ target: UnsafeMutablePointer<Set<TargetValue>>
@@ -118,6 +122,7 @@ internal func _setDownCastConditionalIndirect<SourceValue, TargetValue>(
118122
/// - Precondition: `DerivedValue` is a subtype of `BaseValue` and both
119123
/// are reference types.
120124
@inlinable
125+
@_unavailableInEmbedded
121126
public func _setDownCastConditional<BaseValue, DerivedValue>(
122127
_ source: Set<BaseValue>
123128
) -> Set<DerivedValue>? {

stdlib/public/core/SetStorage.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,28 @@ internal class __EmptySetSingleton: __RawSetStorage {
127127
#endif
128128
}
129129

130+
#if $Embedded
131+
// In embedded Swift, the stdlib is a .swiftmodule only without any .o/.a files,
132+
// to allow consuming it by clients with different LLVM codegen setting (-mcpu
133+
// flags, etc.), which means we cannot declare the singleton in a C/C++ file.
134+
//
135+
// TODO: We should figure out how to make this a constant so that it's placed in
136+
// non-writable memory (can't be a let, Builtin.addressof below requires a var).
137+
public var _swiftEmptySetSingleton: (Int, Int, Int, Int, UInt8, UInt8, UInt16, UInt32, Int, Int, Int) =
138+
(
139+
/*isa*/0, /*refcount*/-1, // HeapObject header
140+
/*count*/0,
141+
/*capacity*/0,
142+
/*scale*/0,
143+
/*reservedScale*/0,
144+
/*extra*/0,
145+
/*age*/0,
146+
/*seed*/0,
147+
/*rawElements*/1,
148+
/*metadata*/-1
149+
)
150+
#endif
151+
130152
extension __RawSetStorage {
131153
/// The empty singleton that is used for every single Set that is created
132154
/// without any elements. The contents of the storage must never be mutated.
@@ -364,7 +386,7 @@ extension _SetStorage {
364386
truncatingIfNeeded: ObjectIdentifier(storage).hashValue)
365387
}
366388

367-
storage._seed = seed ?? _HashTable.hashSeed(for: storage, scale: scale)
389+
storage._seed = seed ?? _HashTable.hashSeed(for: Builtin.castToNativeObject(storage), scale: scale)
368390
storage._rawElements = UnsafeMutableRawPointer(elementsAddr)
369391

370392
// Initialize hash table metadata.

stdlib/public/core/SetVariant.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ extension Set {
3636
@inlinable
3737
@inline(__always)
3838
init(dummy: ()) {
39-
#if _pointerBitWidth(_64)
39+
#if _pointerBitWidth(_64) && !$Embedded
4040
self.object = _BridgeStorage(taggedPayload: 0)
41-
#elseif _pointerBitWidth(_32)
41+
#elseif _pointerBitWidth(_32) || $Embedded
4242
self.init(native: _NativeSet())
4343
#else
4444
#error("Unknown platform")

stdlib/public/core/TemporaryAllocation.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,18 @@ internal func _isStackAllocationSafe(byteCount: Int, alignment: Int) -> Bool {
8888
return true
8989
}
9090

91+
#if !$Embedded
9192
// Finally, take a slow path through the standard library to see if the
9293
// current environment can accept a larger stack allocation.
9394
guard #available(macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4, *) //SwiftStdlib 5.6
9495
else {
9596
return false
9697
}
9798
return swift_stdlib_isStackAllocationSafe(byteCount, alignment)
99+
#else
100+
return false
101+
#endif
102+
98103
#else
99104
fatalError("unsupported compiler")
100105
#endif

0 commit comments

Comments
 (0)