Skip to content

Commit 1bf8e41

Browse files
Dave AbrahamsMax Moiseev
authored andcommitted
[stdlib] Rationalize bitshifting in protocols
Only FixedWidthInteger, not BinaryInteger, should have masking shifts. BinaryInteger should have a non-masking shift requirement. Removed some dead code. Ported the endianness-related changes from master. (cherry picked from commit 33e9ec4)
1 parent 27ea284 commit 1bf8e41

File tree

2 files changed

+107
-179
lines changed

2 files changed

+107
-179
lines changed

stdlib/public/core/Integers.swift.gyb

Lines changed: 94 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,14 +1488,25 @@ ${assignmentOperatorComment(x.operator, False)}
14881488
/// - Complexity: O(1).
14891489
static prefix func ~ (_ x: Self) -> Self
14901490

1491-
% for x in binaryBitwise + maskingShifts:
1491+
% for x in binaryBitwise:
14921492
${operatorComment(x.operator, False)}
14931493
static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self
14941494

14951495
${assignmentOperatorComment(x.operator, False)}
14961496
static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self)
14971497
% end
14981498

1499+
% for x in maskingShifts:
1500+
${operatorComment(x.nonMaskingOperator, False)}
1501+
static func ${x.nonMaskingOperator}<RHS: BinaryInteger>(
1502+
_ lhs: Self, _ rhs: RHS
1503+
) -> Self
1504+
1505+
${assignmentOperatorComment(x.nonMaskingOperator, False)}
1506+
static func ${x.nonMaskingOperator}=<RHS: BinaryInteger>(
1507+
_ lhs: inout Self, _ rhs: RHS)
1508+
% end
1509+
14991510
/// Returns the quotient and remainder of this value divided by the given
15001511
/// value.
15011512
///
@@ -1548,8 +1559,9 @@ extension BinaryInteger {
15481559
return (self / rhs, self % rhs)
15491560
}
15501561

1551-
% for x in binaryBitwise + maskingShifts:
1562+
% for x in binaryBitwise:
15521563

1564+
// Homogeneous
15531565
${operatorComment(x.operator, False)}
15541566
@_transparent
15551567
public static func ${x.operator} (lhs: Self, rhs: Self) -> Self {
@@ -1560,24 +1572,18 @@ ${operatorComment(x.operator, False)}
15601572

15611573
% end
15621574

1563-
% for x in maskingShifts:
1564-
1565-
${operatorComment(x.operator, False)}
1566-
public static func ${x.operator} <
1567-
Other : BinaryInteger
1568-
>(lhs: Self, rhs: Other) -> Self {
1569-
return lhs ${x.operator} Self(extendingOrTruncating: rhs)
1570-
}
1571-
1572-
${assignmentOperatorComment(x.operator, False)}
1573-
@_transparent
1574-
public static func ${x.operator}= <
1575-
Other : BinaryInteger
1576-
>(lhs: inout Self, rhs: Other) {
1577-
lhs = lhs ${x.operator} rhs
1575+
% for x in maskingShifts:
1576+
// Heterogeneous non-masking shift in terms of shift-assignment
1577+
${operatorComment(x.nonMaskingOperator, False)}
1578+
public static func ${x.nonMaskingOperator}<RHS: BinaryInteger>(
1579+
_ lhs: Self, _ rhs: RHS
1580+
) -> Self {
1581+
var r = lhs
1582+
r ${x.nonMaskingOperator}= rhs
1583+
return r
15781584
}
1585+
% end
15791586

1580-
% end
15811587
}
15821588

15831589
// Strideable conformance
@@ -1834,50 +1840,6 @@ extension BinaryInteger {
18341840
}
18351841
}
18361842

1837-
//===----------------------------------------------------------------------===//
1838-
//===--- BinaryInteger smart shifts ---------------------------------------===//
1839-
//===----------------------------------------------------------------------===//
1840-
// FIXME(integers): uncomment once <rdar://problem/29643515> gets fixed
1841-
#if false
1842-
extension BinaryInteger {
1843-
% for x in maskingShifts:
1844-
@_transparent
1845-
public static func ${x.nonMaskingOperator} <
1846-
Other : BinaryInteger
1847-
>(lhs: Self, rhs: Other) -> Self {
1848-
var lhs = lhs
1849-
lhs ${x.nonMaskingOperator}= rhs
1850-
return lhs
1851-
}
1852-
1853-
// It is hard to imagine overshift to the left in an arbitrarily sized
1854-
// integer, but shifting too far to the right and negative shift cases are
1855-
// supported.
1856-
% reversedOperator = x.operator.translate(maketrans('<>', '><'))
1857-
% isRightShift = '>' in x.operator
1858-
@_transparent
1859-
public static func ${x.nonMaskingOperator}= <
1860-
Other : BinaryInteger
1861-
>(lhs: inout Self, rhs: Other) {
1862-
if rhs < (0 as Other) {
1863-
lhs ${reversedOperator}= (0 - rhs)
1864-
return
1865-
}
1866-
% if isRightShift:
1867-
let overshift = Self.isSigned
1868-
? (lhs < (0 as Self) ? ~(0 as Self) : 0 )
1869-
: 0
1870-
if rhs >= lhs.bitWidth {
1871-
lhs = overshift
1872-
return
1873-
}
1874-
% end
1875-
lhs ${x.operator}= Self(extendingOrTruncating: rhs)
1876-
}
1877-
% end
1878-
}
1879-
#endif
1880-
18811843
//===----------------------------------------------------------------------===//
18821844
//===--- FixedWidthInteger ------------------------------------------------===//
18831845
//===----------------------------------------------------------------------===//
@@ -2102,6 +2064,15 @@ ${overflowOperationComment(x.operator)}
21022064

21032065
/// A representation of this integer with the byte order swapped.
21042066
var byteSwapped: Self { get }
2067+
2068+
% for x in maskingShifts:
2069+
${operatorComment(x.operator, False)}
2070+
static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self
2071+
2072+
${assignmentOperatorComment(x.operator, False)}
2073+
static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self)
2074+
% end
2075+
21052076
}
21062077

21072078
extension FixedWidthInteger {
@@ -2128,6 +2099,67 @@ extension FixedWidthInteger {
21282099
@_inlineable
21292100
public var bitWidth: Int { return Self.bitWidth }
21302101

2102+
public init(littleEndian value: Self) {
2103+
#if _endian(little)
2104+
self = value
2105+
#else
2106+
self = value.byteSwapped
2107+
#endif
2108+
}
2109+
2110+
public init(bigEndian value: Self) {
2111+
#if _endian(big)
2112+
self = value
2113+
#else
2114+
self = value.byteSwapped
2115+
#endif
2116+
}
2117+
2118+
public var littleEndian: Self {
2119+
#if _endian(little)
2120+
return self
2121+
#else
2122+
return byteSwapped
2123+
#endif
2124+
}
2125+
2126+
public var bigEndian: Self {
2127+
#if _endian(big)
2128+
return self
2129+
#else
2130+
return byteSwapped
2131+
#endif
2132+
}
2133+
2134+
% for x in maskingShifts:
2135+
2136+
// Homogeneous masking shift
2137+
${operatorComment(x.operator, False)}
2138+
@_transparent
2139+
public static func ${x.operator} (lhs: Self, rhs: Self) -> Self {
2140+
var lhs = lhs
2141+
lhs ${x.operator}= rhs
2142+
return lhs
2143+
}
2144+
2145+
// Heterogeneous masking shift
2146+
${operatorComment(x.operator, False)}
2147+
public static func ${x.operator} <
2148+
Other : BinaryInteger
2149+
>(lhs: Self, rhs: Other) -> Self {
2150+
return lhs ${x.operator} Self(extendingOrTruncating: rhs)
2151+
}
2152+
2153+
// Heterogeneous masking shift assignment
2154+
${assignmentOperatorComment(x.operator, False)}
2155+
@_transparent
2156+
public static func ${x.operator}= <
2157+
Other : BinaryInteger
2158+
>(lhs: inout Self, rhs: Other) {
2159+
lhs = lhs ${x.operator} rhs
2160+
}
2161+
2162+
% end
21312163
}
21322164

21332165
//===----------------------------------------------------------------------===//
@@ -2147,7 +2179,6 @@ extension FixedWidthInteger {
21472179
//===----------------------------------------------------------------------===//
21482180

21492181
${operatorComment(x.nonMaskingOperator, True)}
2150-
@available(swift, introduced: 4)
21512182
@_transparent
21522183
public static func ${x.nonMaskingOperator} <
21532184
Other : BinaryInteger
@@ -2157,21 +2188,6 @@ ${operatorComment(x.nonMaskingOperator, True)}
21572188
return lhs
21582189
}
21592190

2160-
// FIXME(integers): uncommenting this overload results in a compiler not being
2161-
// able to typecheck expression like `(int64 >> 8) & 0xFF`.
2162-
#if false
2163-
@_transparent
2164-
public static func ${x.nonMaskingOperator} (_ lhs: Self, _ rhs: Int) -> Self {
2165-
return ${x.helper}(lhs, rhs)
2166-
}
2167-
2168-
@_transparent
2169-
public static func ${x.nonMaskingOperator}= (_ lhs: inout Self, _ rhs: Int) {
2170-
lhs = ${x.helper}(lhs, rhs)
2171-
}
2172-
#endif
2173-
2174-
@available(swift, introduced: 4)
21752191
@_transparent
21762192
public static func ${x.nonMaskingOperator}= <
21772193
Other : BinaryInteger
@@ -2866,86 +2882,6 @@ ${assignmentOperatorComment(x.operator, True)}
28662882
% end
28672883
}
28682884

2869-
/// Creates an integer using the specified big-endian representation,
2870-
/// changing the byte order if necessary.
2871-
///
2872-
/// On a big-endian platform, for any integer `x`,
2873-
/// `x == ${Self}(bigEndian: x)`.
2874-
///
2875-
/// - Parameter value: A value to use as the big-endian representation of the
2876-
/// new integer.
2877-
@_transparent
2878-
public init(bigEndian value: ${Self}) {
2879-
% if bits <= 8:
2880-
self = value
2881-
% else:
2882-
#if _endian(big)
2883-
self = value
2884-
#else
2885-
self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._value) )
2886-
#endif
2887-
% end
2888-
}
2889-
2890-
/// Creates an integer using the specified little-endian representation,
2891-
/// changing the byte order if necessary.
2892-
///
2893-
/// On a little-endian platform, for any integer `x`,
2894-
/// `x == ${Self}(littleEndian: x)`.
2895-
///
2896-
/// - Parameter value: A value to use as the little-endian representation of
2897-
/// the new integer.
2898-
@_transparent
2899-
public init(littleEndian value: ${Self}) {
2900-
% if bits <= 8:
2901-
self = value
2902-
% else:
2903-
#if _endian(little)
2904-
self = value
2905-
#else
2906-
self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._value) )
2907-
#endif
2908-
% end
2909-
}
2910-
2911-
/// The big-endian representation of this integer.
2912-
///
2913-
/// If necessary, the byte order of this value is reversed from the typical
2914-
/// byte order of this integer type. On a big-endian platform, for any
2915-
/// integer `x`, `x == x.bigEndian`.
2916-
///
2917-
/// - SeeAlso: `littleEndian`
2918-
public var bigEndian: ${Self} {
2919-
% if bits <= 8:
2920-
return self
2921-
% else:
2922-
#if _endian(big)
2923-
return self
2924-
#else
2925-
return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
2926-
#endif
2927-
% end
2928-
}
2929-
2930-
/// The little-endian representation of this integer.
2931-
///
2932-
/// If necessary, the byte order of this value is reversed from the typical
2933-
/// byte order of this integer type. On a little-endian platform, for any
2934-
/// integer `x`, `x == x.littleEndian`.
2935-
///
2936-
/// - SeeAlso: `bigEndian`
2937-
public var littleEndian: ${Self} {
2938-
% if bits <= 8:
2939-
return self
2940-
% else:
2941-
#if _endian(little)
2942-
return self
2943-
#else
2944-
return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
2945-
#endif
2946-
% end
2947-
}
2948-
29492885
/// A representation of this integer with the byte order swapped.
29502886
public var byteSwapped: ${Self} {
29512887
% if bits <= 8:

0 commit comments

Comments
 (0)