Skip to content

Commit b3016c9

Browse files
authored
Merge pull request #41485 from lorentey/clock-fixes
[stdlib] Fix some Clock issues
2 parents e62a5b0 + b7cae85 commit b3016c9

File tree

6 files changed

+118
-88
lines changed

6 files changed

+118
-88
lines changed

stdlib/public/Concurrency/Clock.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ void swift_get_time(
8989
#endif
9090
break;
9191
}
92+
default:
93+
abort();
9294
}
9395
}
9496

@@ -136,5 +138,7 @@ switch (clock_id) {
136138
#endif
137139
break;
138140
}
141+
default:
142+
abort();
139143
}
140144
}

stdlib/public/Concurrency/Clock.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,25 +74,21 @@ extension Clock {
7474
}
7575
}
7676

77-
@available(SwiftStdlib 5.7, *)
78-
@usableFromInline
7977
enum _ClockID: Int32 {
8078
case continuous = 1
8179
case suspending = 2
8280
}
8381

8482
@available(SwiftStdlib 5.7, *)
8583
@_silgen_name("swift_get_time")
86-
@usableFromInline
8784
internal func _getTime(
8885
seconds: UnsafeMutablePointer<Int64>,
8986
nanoseconds: UnsafeMutablePointer<Int64>,
90-
clock: _ClockID)
87+
clock: CInt)
9188

9289
@available(SwiftStdlib 5.7, *)
9390
@_silgen_name("swift_get_clock_res")
94-
@usableFromInline
9591
internal func _getClockRes(
9692
seconds: UnsafeMutablePointer<Int64>,
9793
nanoseconds: UnsafeMutablePointer<Int64>,
98-
clock: _ClockID)
94+
clock: CInt)

stdlib/public/Concurrency/ContinuousClock.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ extension ContinuousClock: Clock {
5959
_getClockRes(
6060
seconds: &seconds,
6161
nanoseconds: &nanoseconds,
62-
clock: .continuous)
62+
clock: _ClockID.continuous.rawValue)
6363
return .seconds(seconds) + .nanoseconds(nanoseconds)
6464
}
6565

@@ -70,7 +70,7 @@ extension ContinuousClock: Clock {
7070
_getTime(
7171
seconds: &seconds,
7272
nanoseconds: &nanoseconds,
73-
clock: .continuous)
73+
clock: _ClockID.continuous.rawValue)
7474
return ContinuousClock.Instant(_value:
7575
.seconds(seconds) + .nanoseconds(nanoseconds))
7676
}

stdlib/public/Concurrency/SuspendingClock.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ extension SuspendingClock: Clock {
6060
_getTime(
6161
seconds: &seconds,
6262
nanoseconds: &nanoseconds,
63-
clock: .suspending)
63+
clock: _ClockID.suspending.rawValue)
6464
return SuspendingClock.Instant(_value:
6565
.seconds(seconds) + .nanoseconds(nanoseconds))
6666
}
@@ -73,7 +73,7 @@ extension SuspendingClock: Clock {
7373
_getClockRes(
7474
seconds: &seconds,
7575
nanoseconds: &nanoseconds,
76-
clock: .suspending)
76+
clock: _ClockID.suspending.rawValue)
7777
return .seconds(seconds) + .nanoseconds(nanoseconds)
7878
}
7979

stdlib/public/core/Duration.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,14 @@ public struct Duration: Sendable {
4242
@usableFromInline
4343
internal var _high: Int64
4444

45+
@inlinable
46+
internal init(_low: UInt64, high: Int64) {
47+
self._low = _low
48+
self._high = high
49+
}
50+
4551
internal init(_attoseconds: _Int128) {
46-
self._low = _attoseconds.low
47-
self._high = _attoseconds.high
52+
self.init(_low: _attoseconds.low, high: _attoseconds.high)
4853
}
4954

5055
/// Construct a `Duration` by adding attoseconds to a seconds value.

stdlib/public/core/Int128.swift.gyb

Lines changed: 101 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
% for signed in [False, True]:
14-
% U = 'U' if signed else ''
14+
% U = '' if signed else 'U'
15+
% Self = '_Int128' if signed else '_UInt128'
16+
% Other = '_UInt128' if signed else '_Int128'
1517
/// A 128-bit ${'signed' if signed else 'unsigned'} integer type.
1618
internal struct _${U}Int128 {
1719
internal typealias High = ${U}Int64
@@ -40,6 +42,13 @@ internal struct _${U}Int128 {
4042
internal init() {
4143
self.init(high: 0, low: 0)
4244
}
45+
46+
internal init(bitPattern v: ${Other}) {
47+
self.init(high: High(bitPattern: v.high), low: v.low)
48+
}
49+
50+
internal static var zero: Self { Self(high: 0, low: 0) }
51+
internal static var one: Self { Self(high: 0, low: 1) }
4352
}
4453

4554
extension _${U}Int128: CustomStringConvertible {
@@ -82,9 +91,9 @@ extension _${U}Int128 {
8291

8392
extension _${U}Int128: AdditiveArithmetic {
8493
internal static func - (_ lhs: Self, _ rhs: Self) -> Self {
85-
var lhs = lhs
86-
lhs -= rhs
87-
return lhs
94+
let (result, overflow) = lhs.subtractingReportingOverflow(rhs)
95+
_precondition(!overflow, "Overflow in -")
96+
return result
8897
}
8998

9099
internal static func -= (_ lhs: inout Self, _ rhs: Self) {
@@ -94,9 +103,9 @@ extension _${U}Int128: AdditiveArithmetic {
94103
}
95104

96105
internal static func + (_ lhs: Self, _ rhs: Self) -> Self {
97-
var lhs = lhs
98-
lhs += rhs
99-
return lhs
106+
let (result, overflow) = lhs.addingReportingOverflow(rhs)
107+
_precondition(!overflow, "Overflow in +")
108+
return result
100109
}
101110

102111
internal static func += (_ lhs: inout Self, _ rhs: Self) {
@@ -110,7 +119,15 @@ extension _${U}Int128: Numeric {
110119
internal typealias Magnitude = _UInt128
111120

112121
internal var magnitude: Magnitude {
113-
Magnitude(_wideMagnitude22(self.components))
122+
% if signed:
123+
var result = _UInt128(bitPattern: self)
124+
guard high._isNegative else { return result }
125+
result.high = ~result.high
126+
result.low = ~result.low
127+
return result.addingReportingOverflow(.one).partialValue
128+
% else:
129+
return self
130+
% end
114131
}
115132

116133
internal init(_ magnitude: Magnitude) {
@@ -148,9 +165,9 @@ extension _${U}Int128: Numeric {
148165
}
149166

150167
internal static func * (_ lhs: Self, _ rhs: Self) -> Self {
151-
var lhs = lhs
152-
lhs *= rhs
153-
return lhs
168+
let (result, overflow) = lhs.multipliedReportingOverflow(by: rhs)
169+
_precondition(!overflow, "Overflow in *")
170+
return result
154171
}
155172

156173
internal static func *= (_ lhs: inout Self, _ rhs: Self) {
@@ -160,57 +177,49 @@ extension _${U}Int128: Numeric {
160177
}
161178
}
162179

163-
164-
% if signed:
165-
extension _Int128 {
166-
internal typealias Words = _UInt128.Words
167-
}
168-
% else:
169-
extension _UInt128 {
180+
extension _${U}Int128 {
170181
internal struct Words {
171-
internal var high: High.Words
172-
internal var low: Low.Words
173-
174-
internal init(_ value: _UInt128) {
175-
self.init(high: value.high.words, low: value.low.words)
176-
}
182+
internal var _value: _${U}Int128
177183

178-
internal init(_ value: _Int128) {
179-
self.init(_UInt128(truncatingIfNeeded: value))
180-
}
181-
182-
internal init(high: High.Words, low: Low.Words) {
183-
self.high = high
184-
self.low = low
184+
internal init(_ value: _${U}Int128) {
185+
self._value = value
185186
}
186187
}
187188
}
188189

189-
extension _UInt128.Words: RandomAccessCollection {
190+
extension _${U}Int128.Words: RandomAccessCollection {
191+
internal typealias Element = UInt
190192
internal typealias Index = Int
191-
192-
internal var startIndex: Index {
193-
0
194-
}
195-
196-
internal var endIndex: Index {
197-
count
198-
}
199-
200-
internal var count: Int {
201-
low.count + high.count
202-
}
203-
204-
internal subscript(_ i: Index) -> UInt {
205-
if i < low.count {
206-
return low[i + low.startIndex]
193+
internal typealias Indices = Range<Int>
194+
internal typealias SubSequence = Slice<Self>
195+
196+
internal var count: Int { 128 / UInt.bitWidth }
197+
internal var startIndex: Int { 0 }
198+
internal var endIndex: Int { count }
199+
internal var indices: Indices { startIndex ..< endIndex }
200+
internal func index(after i: Int) -> Int { i + 1 }
201+
internal func index(before i: Int) -> Int { i - 1 }
202+
203+
internal subscript(position: Int) -> UInt {
204+
get {
205+
_precondition(position >= 0 && position < endIndex,
206+
"Word index out of range")
207+
let shift = position &* UInt.bitWidth
208+
_internalInvariant(shift < _${U}Int128.bitWidth)
209+
210+
let r = _wideMaskedShiftRight(
211+
_value.components, UInt64(truncatingIfNeeded: shift))
212+
return r.low._lowWord
207213
}
208-
return high[i - low.count + high.startIndex]
209214
}
210215
}
211-
% end
212216

213217
extension _${U}Int128: FixedWidthInteger {
218+
@_transparent
219+
internal var _lowWord: UInt {
220+
low._lowWord
221+
}
222+
214223
internal var words: Words {
215224
Words(self)
216225
}
@@ -227,9 +236,7 @@ extension _${U}Int128: FixedWidthInteger {
227236
self.init(high: High.min, low: Low.min)
228237
}
229238

230-
internal static var bitWidth: Int {
231-
High.bitWidth + Low.bitWidth
232-
}
239+
internal static var bitWidth: Int { 128 }
233240

234241
internal func addingReportingOverflow(
235242
_ rhs: Self
@@ -249,15 +256,23 @@ extension _${U}Int128: FixedWidthInteger {
249256
internal func multipliedReportingOverflow(
250257
by rhs: Self
251258
) -> (partialValue: Self, overflow: Bool) {
252-
let (carry, product) = multipliedFullWidth(by: rhs)
253-
let result = Self(truncatingIfNeeded: product)
254-
255-
let isNegative = Self.isSigned && (self._isNegative != rhs._isNegative)
256-
let didCarry = isNegative ? carry != ~Self.zero : carry != Self.zero
257-
let hadPositiveOverflow = Self.isSigned &&
258-
!isNegative && product.leadingZeroBitCount == 0
259-
260-
return (result, didCarry || hadPositiveOverflow)
259+
% if signed:
260+
let isNegative = (self._isNegative != rhs._isNegative)
261+
let (p, overflow) = self.magnitude.multipliedReportingOverflow(
262+
by: rhs.magnitude)
263+
let r = _Int128(bitPattern: isNegative ? ~(p &- .one) : p)
264+
return (r, overflow || (isNegative != r._isNegative))
265+
% else:
266+
let h1 = self.high.multipliedReportingOverflow(by: rhs.low)
267+
let h2 = self.low.multipliedReportingOverflow(by: rhs.high)
268+
let h3 = h1.partialValue.addingReportingOverflow(h2.partialValue)
269+
let (h, l) = self.low.multipliedFullWidth(by: rhs.low)
270+
let high = h3.partialValue.addingReportingOverflow(h)
271+
let overflow = (
272+
(self.high != 0 && rhs.high != 0)
273+
|| h1.overflow || h2.overflow || h3.overflow || high.overflow)
274+
return (Self(high: high.partialValue, low: l), overflow)
275+
% end
261276
}
262277

263278
internal func quotientAndRemainder(
@@ -333,7 +348,7 @@ extension _${U}Int128: FixedWidthInteger {
333348
low: mid1.high + mid2.low)
334349

335350
if isNegative {
336-
let (lowComplement, overflow) = (~low).addingReportingOverflow(1)
351+
let (lowComplement, overflow) = (~low).addingReportingOverflow(.one)
337352
return (~high + (overflow ? 1 : 0), lowComplement)
338353
} else {
339354
return (high, low)
@@ -343,15 +358,10 @@ extension _${U}Int128: FixedWidthInteger {
343358
internal func dividingFullWidth(
344359
_ dividend: (high: Self, low: Self.Magnitude)
345360
) -> (quotient: Self, remainder: Self) {
361+
% if signed:
346362
let m = _wideMagnitude22(dividend)
347-
let (q, r) = _wideDivide42(
348-
(m.high.components, m.low.components),
349-
by: self.magnitude.components)
350-
let quotient = Self.Magnitude(q)
351-
let remainder = Self.Magnitude(r)
352-
guard Self.isSigned else {
353-
return (Self(quotient), Self(remainder))
354-
}
363+
let (quotient, remainder) = self.magnitude.dividingFullWidth(m)
364+
355365
let isNegative = (self.high._isNegative != dividend.high.high._isNegative)
356366
let quotient_ = (isNegative
357367
? (quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient))
@@ -360,13 +370,20 @@ extension _${U}Int128: FixedWidthInteger {
360370
? 0 - Self(remainder)
361371
: Self(remainder))
362372
return (quotient_, remainder_)
373+
% else:
374+
let (q, r) = _wideDivide42(
375+
(dividend.high.components, dividend.low.components),
376+
by: self.components)
377+
return (Self(q), Self(r))
378+
% end
363379
}
364380

365-
/* disabled since it causes a compile failure in LLDB
381+
#if false // This triggers an unexpected type checking issue with `~0` in an
382+
// lldb test
366383
internal static prefix func ~(x: Self) -> Self {
367384
Self(high: ~x.high, low: ~x.low)
368385
}
369-
*/
386+
#endif
370387

371388
internal static func &= (_ lhs: inout Self, _ rhs: Self) {
372389
lhs.low &= rhs.low
@@ -413,11 +430,19 @@ extension _${U}Int128: FixedWidthInteger {
413430
lhs &>>= rhs
414431
}
415432

416-
internal static func &<<= (_ lhs: inout Self, _ rhs: Self) {
433+
internal static func &<< (lhs: Self, rhs: Self) -> Self {
434+
Self(_wideMaskedShiftLeft(lhs.components, rhs.low))
435+
}
436+
437+
internal static func &>> (lhs: Self, rhs: Self) -> Self {
438+
Self(_wideMaskedShiftRight(lhs.components, rhs.low))
439+
}
440+
441+
internal static func &<<= (lhs: inout Self, rhs: Self) {
417442
_wideMaskedShiftLeft(&lhs.components, rhs.low)
418443
}
419444

420-
internal static func &>>= (_ lhs: inout Self, _ rhs: Self) {
445+
internal static func &>>= (lhs: inout Self, rhs: Self) {
421446
_wideMaskedShiftRight(&lhs.components, rhs.low)
422447
}
423448

@@ -590,7 +615,7 @@ private func _wideMaskedShiftLeft<F: FixedWidthInteger>(
590615
var high = lhs.high &<< F(rhs)
591616
let rollover = F.Magnitude(F.bitWidth) &- rhs
592617
high |= F(truncatingIfNeeded: lhs.low &>> rollover)
593-
var low = lhs.low &<< rhs
618+
let low = lhs.low &<< rhs
594619
return (high, low)
595620
}
596621

0 commit comments

Comments
 (0)