Skip to content

Commit 14899ab

Browse files
committed
stdlib/FixedPoint: define the same set of 'truncatingBitPattern'
initializers on all platforms rdar://18167806 Swift SVN r21570
1 parent cf747b7 commit 14899ab

File tree

4 files changed

+136
-17
lines changed

4 files changed

+136
-17
lines changed

stdlib/core/FixedPoint.swift.gyb

+16-8
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,13 @@ T : _UnsignedIntegerType, U : _SignedIntegerType
101101
return .from(IntMax(x.toUIntMax()))
102102
}
103103

104-
% for (name, bits, signed) in all_integer_types(word_bits):
104+
% for self_ty in all_integer_types_new(word_bits):
105+
% bits = self_ty.bits
106+
% signed = self_ty.is_signed
105107
% (sign, ext) = ('s', 'sext') if signed else ('u', 'zext')
106-
% BuiltinName = builtin_int_name(name)
107-
% Self = int_name(name, signed)
108-
% OtherSelf = other_int_name(name, signed)
108+
% Self = self_ty.stdlib_name
109+
% BuiltinName = self_ty.builtin_name
110+
% OtherSelf = self_ty.get_opposite_signedness().stdlib_name
109111

110112
public struct ${Self}
111113
: ${'SignedIntegerType' if sign == 's' else 'UnsignedIntegerType'} {
@@ -332,9 +334,11 @@ extension ${Self} : SignedNumberType {}
332334
// construction from other integer types
333335
@transparent
334336
extension ${Self} {
335-
% for (srcName, srcBits, srcSigned) in all_integer_types(word_bits):
336-
% Src = int_name(srcName, srcSigned)
337-
% srcBuiltinName = builtin_int_name(srcName)
337+
% for src_ty in all_integer_types_new(word_bits):
338+
% srcBits = src_ty.bits
339+
% srcSigned = src_ty.is_signed
340+
% Src = src_ty.stdlib_name
341+
% srcBuiltinName = src_ty.builtin_name
338342
% (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
339343
% if Self != Src:
340344
public init(_ v: ${Src}) {
@@ -375,7 +379,7 @@ extension ${Self} {
375379
}
376380
% end
377381

378-
% if srcBits > bits:
382+
% if should_define_truncating_bit_pattern_init(src_ty=src_ty, dst_ty=self_ty):
379383
/// Construct a `${Self}` having the same bitwise representation as
380384
/// the least significant bits of the provided bit pattern.
381385
///
@@ -389,7 +393,11 @@ extension ${Self} {
389393
let srcNotWord = truncatingBitPattern.value
390394
% end
391395
%
396+
% if self_ty.bits == src_ty.bits:
397+
let dstNotWord = srcNotWord
398+
% else:
392399
let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(srcNotWord)
400+
% end
393401
%
394402
% if BuiltinName == 'Word':
395403
value = Builtin.${CastToWord}(dstNotWord)

test/stdlib/FixedPointDiagnostics.swift

+52
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,58 @@ var u32 : UInt32 = u // expected-error {{'UInt' is not convertible to 'UInt32'}}
2222
var u16 : UInt16 = u // expected-error {{'UInt' is not convertible to 'UInt16'}}
2323
var u8 : UInt8 = u // expected-error {{'UInt' is not convertible to 'UInt8'}}
2424

25+
func expectSameType<T>(_: T.Type, _: T.Type) {}
26+
27+
func test_truncatingBitPatternAPIIsStableAcrossPlatforms() {
28+
// Audit and update this test when adding new integer types.
29+
expectSameType(Int64.self, IntMax.self)
30+
expectSameType(UInt64.self, UIntMax.self)
31+
32+
UInt8(truncatingBitPattern: UInt(0))
33+
UInt16(truncatingBitPattern: UInt(0))
34+
UInt32(truncatingBitPattern: UInt(0))
35+
UInt64(truncatingBitPattern: UInt(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
36+
UInt(truncatingBitPattern: UInt(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
37+
38+
Int8(truncatingBitPattern: UInt(0))
39+
Int16(truncatingBitPattern: UInt(0))
40+
Int32(truncatingBitPattern: UInt(0))
41+
Int64(truncatingBitPattern: UInt(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
42+
Int(truncatingBitPattern: UInt(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
43+
44+
UInt8(truncatingBitPattern: Int(0))
45+
UInt16(truncatingBitPattern: Int(0))
46+
UInt32(truncatingBitPattern: Int(0))
47+
UInt64(truncatingBitPattern: Int(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
48+
UInt(truncatingBitPattern: Int(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
49+
50+
Int8(truncatingBitPattern: Int(0))
51+
Int16(truncatingBitPattern: Int(0))
52+
Int32(truncatingBitPattern: Int(0))
53+
Int64(truncatingBitPattern: Int(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
54+
Int(truncatingBitPattern: Int(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
55+
56+
UInt(truncatingBitPattern: UInt8(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
57+
UInt(truncatingBitPattern: UInt16(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
58+
UInt(truncatingBitPattern: UInt32(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
59+
UInt(truncatingBitPattern: UInt64(0))
60+
61+
Int(truncatingBitPattern: UInt8(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
62+
Int(truncatingBitPattern: UInt16(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
63+
Int(truncatingBitPattern: UInt32(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
64+
Int(truncatingBitPattern: UInt64(0))
65+
66+
UInt(truncatingBitPattern: Int8(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
67+
UInt(truncatingBitPattern: Int16(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
68+
UInt(truncatingBitPattern: Int32(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
69+
UInt(truncatingBitPattern: Int64(0))
70+
71+
Int(truncatingBitPattern: Int8(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
72+
Int(truncatingBitPattern: Int16(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
73+
Int(truncatingBitPattern: Int32(0)) // expected-error {{extraneous argument label 'truncatingBitPattern:' in call}}
74+
Int(truncatingBitPattern: Int64(0))
75+
}
76+
2577
func testOps<T : IntegerArithmeticType>(x: T, y: T) -> T {
2678
let a = x + y
2779
let s = x - y

utils/SwiftIntTypes.py

+60-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212

1313
# Bit counts for all int types
1414
_all_integer_type_bitwidths = [8, 16, 32, 64, 'Int']
15+
_all_integer_type_bitwidths_new = [8, 16, 32, 64]
1516

1617
# Number of bits in the biggest int type
17-
int_max_bits = 64
18+
int_max_bits = max(_all_integer_type_bitwidths_new)
1819

1920
def all_integer_types(word_bits):
2021
for name in _all_integer_type_bitwidths:
@@ -41,3 +42,61 @@ def other_int_name(name, signed):
4142
def is_signed_int(name):
4243
return name[0] != 'U'
4344

45+
class SwiftIntegerType(object):
46+
def __init__(self, is_word, bits, is_signed):
47+
self.is_word = is_word
48+
self.bits = bits
49+
self.is_signed = is_signed
50+
51+
if is_word:
52+
self.possible_bitwidths = [ 32, 64 ]
53+
else:
54+
self.possible_bitwidths = [ bits ]
55+
56+
# Derived properties
57+
self.stdlib_name = \
58+
('' if is_signed else 'U') + \
59+
'Int' + \
60+
('' if is_word else str(bits))
61+
62+
self.builtin_name = ('Word' if is_word else 'Int' + str(bits))
63+
64+
def get_opposite_signedness(self):
65+
return SwiftIntegerType(self.is_word, self.bits, not self.is_signed)
66+
67+
def __eq__(self, other):
68+
return self.is_word == other.is_word and \
69+
self.bits == other.bits and \
70+
self.is_signed == other.is_signed
71+
72+
def __ne__(self, other):
73+
return not self.__eq__(other)
74+
75+
def all_integer_types_new(word_bits):
76+
for bitwidth in _all_integer_type_bitwidths_new:
77+
for is_signed in [ False, True ]:
78+
yield SwiftIntegerType(is_word=False, bits=bitwidth,
79+
is_signed=is_signed)
80+
81+
for is_signed in [ False, True ]:
82+
yield SwiftIntegerType(is_word=True, bits=word_bits,
83+
is_signed=is_signed)
84+
85+
# 'truncatingBitPattern' initializer is defined if the conversion is truncating
86+
# on any platform that Swift supports.
87+
def should_define_truncating_bit_pattern_init(src_ty, dst_ty):
88+
# Don't define a truncating conversion between a type and itself.
89+
if src_ty == dst_ty:
90+
return False
91+
92+
# Conversion to opposite signedness is never truncating.
93+
if src_ty == dst_ty.get_opposite_signedness():
94+
return False
95+
96+
for src_ty_bits in src_ty.possible_bitwidths:
97+
for dst_ty_bits in dst_ty.possible_bitwidths:
98+
if src_ty_bits > dst_ty_bits:
99+
return True
100+
101+
return False
102+

validation-test/stdlib/FixedPoint.swift.gyb

+8-8
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,23 @@ truncating_bit_pattern_test_template = gyb.parseTemplate("truncating_bit_pattern
5252
"""
5353
% from SwiftIntTypes import *
5454

55-
% for (dst_name, dst_bits, dst_signed) in all_integer_types(word_bits):
56-
% Dst = int_name(dst_name, dst_signed)
55+
% for dst_ty in all_integer_types_new(word_bits):
56+
% Dst = dst_ty.stdlib_name
5757

5858
FixedPoint.test("${Dst}(truncatingBitPattern:)") {
5959

60-
% for (src_name, src_bits, src_signed) in all_integer_types(word_bits):
61-
% Src = int_name(src_name, src_signed)
62-
% if src_bits > dst_bits:
60+
% for src_ty in all_integer_types_new(word_bits):
61+
% Src = src_ty.stdlib_name
62+
% if should_define_truncating_bit_pattern_init(src_ty=src_ty, dst_ty=dst_ty):
6363
%
6464
% for bit_pattern in test_bit_patterns:
6565

6666
if true {
67-
% input = prepare_bit_pattern(bit_pattern, src_bits, src_signed)
67+
% input = prepare_bit_pattern(bit_pattern, src_ty.bits, src_ty.is_signed)
6868
let input = get${Src}(${input})
69-
% input = prepare_bit_pattern(input, src_bits, False)
69+
% input = prepare_bit_pattern(input, src_ty.bits, False)
7070
let output = get${Dst}(${Dst}(truncatingBitPattern: input))
71-
let expected = get${Dst}(${prepare_bit_pattern(input, dst_bits, dst_signed)})
71+
let expected = get${Dst}(${prepare_bit_pattern(input, dst_ty.bits, dst_ty.is_signed)})
7272
expectEqual(output, expected)
7373
}
7474

0 commit comments

Comments
 (0)