forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFixedPoint.swift.gyb
666 lines (593 loc) · 19.3 KB
/
FixedPoint.swift.gyb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
//===--- FixedPoint.swift.gyb ---------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%{
from SwiftIntTypes import *
#
# Utility code for later in this template
#
def hexify(n):
"""Return a legible hex representation of n, using '_' separators """
z = '%X' % n
l = len(z)
r = []
while z:
r.insert(0, z[-4:])
z = z[:-4]
return '0x' + '_'.join(r)
# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
# Number of bits in integer literals.
builtinIntLiteralBits = 2048
def maskBits(n):
"""Return an n-bit mask in hex"""
return hexify((1 << n) - 1)
IntMax = 'Int%s' % int_max_bits
UIntMax = 'UInt%s' % int_max_bits
}%
/// The largest native signed integer type.
public typealias IntMax = ${IntMax}
/// The largest native unsigned integer type.
public typealias UIntMax = ${UIntMax}
/// This protocol is an implementation detail of `IntegerType`; do
/// not use it directly.
public protocol _IntegerType
: _BuiltinIntegerLiteralConvertible,
IntegerLiteralConvertible,
CustomStringConvertible,
Hashable,
IntegerArithmeticType,
BitwiseOperationsType,
_Incrementable
{
}
/// A set of common requirements for Swift's integer types.
public protocol IntegerType : _IntegerType, RandomAccessIndexType {
}
/// This protocol is an implementation detail of `SignedIntegerType`;
/// do not use it directly.
public protocol _SignedIntegerType : _IntegerType, SignedNumberType {
/// Represent this number using Swift's widest native signed integer
/// type.
@warn_unused_result
func toIntMax() -> IntMax
/// Convert from Swift's widest signed integer type, trapping on
/// overflow.
init(_: IntMax)
}
/// A set of common requirements for Swift's signed integer types.
public protocol SignedIntegerType : _SignedIntegerType, IntegerType {
/// Represent this number using Swift's widest native signed integer
/// type.
func toIntMax() -> IntMax
/// Convert from Swift's widest signed integer type, trapping on
/// overflow.
init(_: IntMax)
}
/// This protocol is an implementation detail of `UnsignedIntegerType`;
/// do not use it directly.
public protocol _DisallowMixedSignArithmetic : _IntegerType {
// Used to create a deliberate ambiguity in cases like UInt(1) +
// Int(1), which would otherwise compile due to the arithmetic
// operators defined for Strideable types (unsigned types are
// Strideable).
typealias _DisallowMixedSignArithmetic : SignedIntegerType = Int
}
/// A set of common requirements for Swift's unsigned integer types.
public protocol UnsignedIntegerType : _DisallowMixedSignArithmetic, IntegerType {
/// Represent this number using Swift's widest native unsigned
/// integer type.
@warn_unused_result
func toUIntMax() -> UIntMax
/// Convert from Swift's widest unsigned integer type, trapping on
/// overflow.
init(_: UIntMax)
}
/// Convert `x` to type `U`, trapping on overflow in -Onone and -O
/// builds.
///
/// Typically used to do conversion to any contextually-deduced
/// integer type:
///
/// func f(x: Int32) {}
/// func g(x: Int64) { f(numericCast(x)) }
@warn_unused_result
public func numericCast<
T : _SignedIntegerType, U : _SignedIntegerType
>(x: T) -> U {
return U(x.toIntMax())
}
/// Convert `x` to type `U`, trapping on overflow in -Onone and -O
/// builds.
///
/// Typically used to do conversion to any contextually-deduced
/// integer type:
///
/// func f(x: UInt32) {}
/// func g(x: UInt64) { f(numericCast(x)) }
@warn_unused_result
public func numericCast<
T : UnsignedIntegerType, U : UnsignedIntegerType
>(x: T) -> U {
return U(x.toUIntMax())
}
/// Convert `x` to type `U`, trapping on overflow in -Onone and -O
/// builds.
///
/// Typically used to do conversion to any contextually-deduced
/// integer type:
///
/// func f(x: UInt32) {}
/// func g(x: Int64) { f(numericCast(x)) }
@warn_unused_result
public func numericCast<
T : _SignedIntegerType, U : UnsignedIntegerType
>(x: T) -> U {
return U(UIntMax(x.toIntMax()))
}
/// Convert `x` to type `U`, trapping on overflow in -Onone and -O
/// builds.
///
/// Typically used to do conversion to any contextually-deduced
/// integer type:
///
/// func f(x: Int32) {}
/// func g(x: UInt64) { f(numericCast(x)) }
@warn_unused_result
public func numericCast<
T : UnsignedIntegerType, U : _SignedIntegerType
>(x: T) -> U {
return U(IntMax(x.toUIntMax()))
}
//===--- Loop over all integer types --------------------------------------===//
% for self_ty in all_integer_types(word_bits):
% bits = self_ty.bits
% signed = self_ty.is_signed
% (sign, ext) = ('s', 'sext') if signed else ('u', 'zext')
% Self = self_ty.stdlib_name
% BuiltinName = self_ty.builtin_name
% OtherSelf = self_ty.get_opposite_signedness().stdlib_name
/// A ${bits}-bit ${'un' if sign == 'u' else ''}signed integer value
/// type.
public struct ${Self}
: ${'SignedIntegerType' if sign == 's' else 'UnsignedIntegerType'},
Comparable, Equatable {
public // @testable
var _value: Builtin.${BuiltinName}
// FIXME: this declaration should be inferred.
// <rdar://problem/18379938> Type checker refuses to use the default for
// Int.Distance associated type
/// A type that can represent the number of steps between pairs of
/// values.
public typealias Distance = Int
/// Create an instance initialized to zero.
@_transparent public
init() {
let maxWidthZero: IntMax = 0
self._value = Builtin.truncOrBitCast_Int${int_max_bits}_${BuiltinName}(
maxWidthZero._value)
}
@_transparent public
init(_ _v: Builtin.${BuiltinName}) {
self._value = _v
}
@_transparent public
init(_bits: Builtin.${BuiltinName}) {
self._value = _bits
}
% if self_ty.is_word:
@_transparent
public // @testable
init(_ v: Builtin.Word) {
% if BuiltinName == 'Int32':
self._value = Builtin.truncOrBitCast_Word_Int32(v)
% elif BuiltinName == 'Int64':
self._value = Builtin.zextOrBitCast_Word_Int64(v)
% end
}
@_transparent
public // @testable
var _builtinWordValue: Builtin.Word {
% if BuiltinName == 'Int32':
return Builtin.zextOrBitCast_Int32_Word(_value)
% elif BuiltinName == 'Int64':
return Builtin.truncOrBitCast_Int64_Word(_value)
% end
}
% end
/// Create an instance initialized to `value`.
@_transparent public
init(_ value: ${Self}) { self = value }
% if bits > 8:
/// Creates an integer from its big-endian representation, changing the
/// byte order if necessary.
@_transparent public
init(bigEndian value: ${Self}) {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._value) )
#else
_UnsupportedArchitectureError()
#endif
}
/// Creates an integer from its little-endian representation, changing the
/// byte order if necessary.
@_transparent public
init(littleEndian value: ${Self}) {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
self = value
#else
_UnsupportedArchitectureError()
#endif
}
% end
@_transparent public
init(_builtinIntegerLiteral value: Builtin.Int${builtinIntLiteralBits}) {
self = ${Self}(Builtin.s_to_${sign}_checked_trunc_Int${builtinIntLiteralBits}_${BuiltinName}(value).0)
}
/// Create an instance initialized to `value`.
@_transparent public
init(integerLiteral value: ${Self}) {
self = value
}
% if bits > 8:
/// Returns the big-endian representation of the integer, changing the
/// byte order if necessary.
public var bigEndian: ${Self} {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
#else
_UnsupportedArchitectureError()
#endif
}
/// Returns the little-endian representation of the integer, changing the
/// byte order if necessary.
public var littleEndian: ${Self} {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
return self
#else
_UnsupportedArchitectureError()
#endif
}
% end
% if bits > 8:
/// Returns the current integer with the byte order swapped.
public var byteSwapped: ${Self} {
return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
}
% end
% max = maskBits((bits - 1) if signed else bits)
@_transparent public
static var max: ${Self} { return ${max} }
@_transparent public
static var min: ${Self} { return ${'-%s-1' % max if signed else '0'} }
@_transparent
public static var _sizeInBits: ${Self} { return ${bits} }
public static var _sizeInBytes: ${Self} { return ${bits}/8 }
}
extension ${Self} : Hashable {
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`.
///
/// - Note: The hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int {
% if bits <= word_bits and signed:
// Sign extend the value.
return Int(self)
% elif bits <= word_bits and not signed:
// Sign extend the value.
return Int(${OtherSelf}(bitPattern: self))
% elif bits == word_bits * 2:
// We have twice as many bits as we need to return.
return
Int(truncatingBitPattern: self) ^
Int(truncatingBitPattern: self >> 32)
% else:
_Unimplemented()
% end
}
}
extension ${Self} : CustomStringConvertible {
/// A textual representation of `self`.
public var description: String {
% if signed:
return _int64ToString(self.toIntMax())
% else:
return _uint64ToString(self.toUIntMax())
% end
}
}
// When ${Self} is used as an index, there are always bounds---more
// restrictive than the full range of ${Self}---against which we're
// not able to check. Overflows are not useful indicators of
// precondition violations in this context. Therefore, we use masked
// arithmetic in this conformance, and we need to be be sure that
// generic implementations of the arithmetic operators for
// RandomAccessIndexType's are all shadowed by more-specific
// implementations that *do* check for overflows.
@_transparent
extension ${Self} : RandomAccessIndexType {
// HACK: Disable indexing and slicing Ranges of IntegerType types
// outside of a generic context. See the implementation of Range
// for details of how this works.
public typealias _DisabledRangeIndex = ${Self}
/// Returns the next consecutive value after `self`.
///
/// - Requires: The next value is representable.
@_transparent public
func successor() -> ${Self} {
return self &+ 1
}
/// Returns the previous consecutive value before `self`.
///
/// - Requires: The previous value is representable.
@_transparent public
func predecessor() -> ${Self} {
return self &- 1
}
@_transparent public
func distanceTo(other: ${Self}) -> ${Self}.Distance {
return numericCast((numericCast(other) as IntMax) &- numericCast(self))
}
@_transparent public
func advancedBy(n: ${Self}.Distance) -> ${Self} {
return numericCast((numericCast(self) as IntMax) &+ numericCast(n))
}
}
// Operations that return an overflow bit in addition to a partial result,
// helpful for checking for overflow when you want to handle it.
extension ${Self} {
% for Method,op in [('add', 'add'), ('subtract', 'sub'), ('multiply', 'mul')]:
/// ${Method.capitalize()} `lhs` and `rhs`, returning a result and a
/// `Bool` that is true iff the operation caused an arithmetic
/// overflow.
@_transparent public
static func ${Method}WithOverflow(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, overflow: Bool) {
let tmp = Builtin.${sign}${op}_with_overflow_${BuiltinName}(lhs._value, rhs._value, false._value)
return (${Self}(tmp.0), Bool(tmp.1))
}
% end
% for Method,op in [('divide', 'div'), ('remainder', 'rem')]:
/// Divide `lhs` and `rhs`, returning
/// ${'a result' if op == 'div' else 'the remainder'} and a `Bool`
/// that is true iff the operation caused an arithmetic overflow.
@_transparent public
static func ${Method}WithOverflow(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, overflow: Bool) {
if rhs == 0 {
return (0, true)
}
% if signed:
if lhs == ${Self}.min && rhs == -1 {
return (0, true)
}
% end
// FIXME: currently doesn't detect overflow -- blocked by:
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
let tmp = Builtin.${sign}${op}_${BuiltinName}(lhs._value, rhs._value)
return (${Self}(tmp), false)
}
%end
% (U, un) = ('','') if signed else ('U','un')
/// Represent this number using Swift's widest native ${un}signed
/// integer type.
@_transparent public
func to${U}IntMax() -> ${U}IntMax {
return ${'self' if Self == U+'Int%s'%int_max_bits else U+'IntMax(self)'}
}
% if not signed:
/// Explicitly convert to `IntMax`${', trapping on overflow (except in -Ounchecked builds)' if bits == int_max_bits else ''}.
@_transparent public
func toIntMax() -> IntMax {
return IntMax(toUIntMax())
}
% end
}
% if signed:
@_transparent
extension ${Self} : SignedNumberType {}
% end
// construction from other integer types
@_transparent
extension ${Self} {
% for src_ty in all_integer_types(word_bits):
% srcBits = src_ty.bits
% srcSigned = src_ty.is_signed
% Src = src_ty.stdlib_name
% (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
% if Self != Src:
public init(_ v: ${Src}) {
%
let srcNotWord = v._value
%
% if srcBits == bits and srcSign == sign:
let dstNotWord = srcNotWord
%
% elif srcBits == bits:
let tmp = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord)
Builtin.condfail(tmp.1)
let dstNotWord = tmp.0
%
% elif srcBits > bits:
let tmp = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord)
Builtin.condfail(tmp.1)
let dstNotWord = tmp.0
%
% elif srcSigned and not signed:
let tmp = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord)
Builtin.condfail(tmp.1)
let dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp.0)
%
% else:
let dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord)
% end
%
self._value = dstNotWord
}
% end
% if should_define_truncating_bit_pattern_init(src_ty=src_ty, dst_ty=self_ty):
/// Construct a `${Self}` having the same bitwise representation as
/// the least significant bits of the provided bit pattern.
///
/// No range or overflow checking occurs.
@_transparent
public init(truncatingBitPattern: ${Src}) {
%
let srcNotWord = truncatingBitPattern._value
%
% if self_ty.bits == src_ty.bits:
let dstNotWord = srcNotWord
% else:
let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(srcNotWord)
% end
%
self._value = dstNotWord
}
% end
% end
/// Construct a `${Self}` having the same memory representation as
/// the `${OtherSelf}` `bitPattern`. No range or overflow checking
/// occurs, and the resulting `${Self}` may not have the same numeric
/// value as `bitPattern`--it is only guaranteed to use the same
/// pattern of bits.
@_transparent
public init(bitPattern: ${OtherSelf}) {
self._value = bitPattern._value
}
}
// Operations with potentially-static overflow checking
//
// FIXME: must use condfail in these operators, rather than
// overflowChecked, pending <rdar://problem/16271923> so that we don't
// foil static checking for numeric overflows.
% for op,method in ('+','add'), ('*','mul'), ('-','sub'):
@_transparent
public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
let (result, error) = Builtin.${sign}${method}_with_overflow_${BuiltinName}(
lhs._value, rhs._value, true._value)
// return overflowChecked((${Self}(result), Bool(error)))
Builtin.condfail(error)
return ${Self}(result)
}
% end
% for op,inst in [('/', 'div'), ('%', 'rem')]:
@_transparent
public func ${op}(lhs: ${Self}, rhs: ${Self}) -> ${Self} {
Builtin.condfail((rhs == 0)._value)
% if signed:
Builtin.condfail(((lhs == ${Self}.min) && (rhs == -1))._value)
% end
// FIXME: currently doesn't detect overflow -- blocked by:
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
let tmp = Builtin.${sign}${inst}_${BuiltinName}(lhs._value, rhs._value)
return ${Self}(tmp)
}
%end
// Bitwise negate
@_transparent
public prefix func ~(rhs: ${Self}) -> ${Self} {
let mask = ${Self}.subtractWithOverflow(0, 1).0
return ${Self}(Builtin.xor_${BuiltinName}(rhs._value, mask._value))
}
% for op, name in (
% ('==','eq'), ('!=','ne'),
% ('<',sign+'lt'), ('<=',sign+'le'),
% ('>',sign+'gt'), ('>=',sign+'ge')):
@_transparent
public func ${op} (lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_${name}_${BuiltinName}(lhs._value, rhs._value))
}
% end
% for op, name in (('<<','shl'), ('>>','ashr' if signed else 'lshr')):
@_transparent
public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
% if signed:
_precondition(U${Self}(rhs) < U${Self}._sizeInBits,
"shift amount is larger than type size in bits")
% else:
_precondition(rhs < ${Self}._sizeInBits,
"shift amount is larger than type size in bits")
% end
return ${Self}(Builtin.${name}_${BuiltinName}(lhs._value, rhs._value))
}
% end
% for op, name in (('&','and'), ('^','xor'), ('|','or')):
@_transparent
public func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}(Builtin.${name}_${BuiltinName}(lhs._value, rhs._value))
}
% end
// bitwise operations
@_transparent
extension ${Self} : BitwiseOperationsType {
/// The empty bitset of type ${Self}.
public static var allZeros: ${Self} { return 0 }
}
// Compound assignments
% for op in '+', '-', '*', '<<', '>>', '&', '|', '^':
@_transparent
public func ${op}=(inout lhs: ${Self}, rhs: ${Self}) {
lhs = lhs ${op} rhs
}
% end
// Prefix and postfix increment and decrement.
// FIXME: After <rdar://problem/20226526> is fixed, we should be able
// to remove these.
@_transparent
public prefix func ++ (inout x: ${Self}) -> ${Self} {
x = x + 1
return x
}
@_transparent
public postfix func ++ (inout x: ${Self}) -> ${Self} {
let ret = x
x = x + 1
return ret
}
@_transparent
public prefix func -- (inout x: ${Self}) -> ${Self} {
x = x - 1
return x
}
@_transparent
public postfix func -- (inout x: ${Self}) -> ${Self} {
let ret = x
x = x - 1
return ret
}
% if signed:
// TODO: Consider removing the underscore.
/// Returns the argument and specifies that the value is not negative.
/// It has only an effect if the argument is a load or call.
@_transparent
@warn_unused_result
public func _assumeNonNegative(x: ${Self}) -> ${Self} {
_sanityCheck(x >= 0)
return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value))
}
% end
% end
% fixedBitWidths = [2**x for x in range(3, 8) if 2**x <= 2 * word_bits]
% for bits in fixedBitWidths:
@_transparent
public func _leadingZeros(x: Builtin.Int${bits}) -> Builtin.Int${bits} {
return Builtin.int_ctlz_Int${bits}(x, true._value)
}
% end
//===--- End loop over all integer types ----------------------------------===//
@available(*, unavailable, renamed="Int")
public typealias Word = Int
@available(*, unavailable, renamed="UInt")
public typealias UWord = UInt
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: