%# -*- mode: swift -*- %# Ignore the following admonition; it applies to the resulting .swift file only //// Automatically Generated From FixedPoint.gyb. Do Not Edit Directly! //===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// %{ # # 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) # Bit counts for all int types allNames = [8, 16, 32, 64, 'Int'] # Number of bits in the biggest int type maxBits = 64 # Number of bits in the Builtin.Word type wordBits = int(CMAKE_SIZEOF_VOID_P) * 8 # Number of bits in integer literals. builtinIntLiteralBits = 2048 # FIXME: checked and unchecked conversions of Word types CastFromWord = 'zextOrBitCast_Word_Int64' if wordBits==64 else 'truncOrBitCast_Word_Int32' CastToWord = 'truncOrBitCast_Int64_Word' if wordBits==64 else 'zextOrBitCast_Int32_Word' def maskBits(n): """Return an n-bit mask in hex""" return hexify((1 << n) - 1) def allInts(): for name in allNames: for signed in False, True: yield str(name), int(wordBits if name=='Int' else name), signed def baseIntName(name): return 'Int' if name == 'Int' else 'Int' + str(name) def builtinIntName(name): return 'Word' if name == 'Int' else 'Int' + str(name) def intName(name, signed): return ('' if signed else 'U') + baseIntName(name) def otherIntName(name, signed): return ('U' if signed else '') + baseIntName(name) }% typealias IntMax = Int${maxBits} typealias UIntMax = UInt${maxBits} protocol _Integer : _BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible, Printable, ArrayBound, Hashable, IntegerArithmetic, BitwiseOperations, _Incrementable { } protocol Integer : _Integer, RandomAccessIndex { } protocol _SignedInteger : _Integer, SignedNumber { func toIntMax() -> IntMax class func from(IntMax) -> Self } protocol SignedInteger : _SignedInteger, Integer { } protocol _UnsignedInteger : _Integer { func toUIntMax() -> UIntMax class func from(UIntMax) -> Self } protocol UnsignedInteger : _UnsignedInteger, Integer { } func numericCast(x: T) -> U { return .from(x.toIntMax()) } func numericCast(x: T) -> U { return .from(x.toUIntMax()) } func numericCast(x: T) -> U { return .from(UIntMax(x.toIntMax())) } func numericCast(x: T) -> U { return .from(IntMax(x.toUIntMax())) } % for (name, bits, signed) in allInts(): % (sign, ext) = ('s', 'sext') if signed else ('u', 'zext') % BuiltinName = builtinIntName(name) % Self = intName(name, signed) % OtherSelf = otherIntName(name, signed) % ConstructIntType = 'Int' if Self != 'Int' else '' struct ${Self} : ${'SignedInteger' if sign == 's' else 'UnsignedInteger'} { var value: Builtin.${BuiltinName} @transparent init() { var maxWidthZero: IntMax = 0 value = Builtin.truncOrBitCast_Int${maxBits}_${BuiltinName}(maxWidthZero.value) } @transparent init(_ v: Builtin.${BuiltinName}) { value = v } @transparent init(_ value: ${Self}) { self = value } @transparent static func _convertFromBuiltinIntegerLiteral(value: Builtin.Int${builtinIntLiteralBits}) -> ${Self} { return ${Self}(Builtin.s_to_${sign}_checked_trunc_Int${builtinIntLiteralBits}_${BuiltinName}(value).0) } @transparent static func convertFromIntegerLiteral(value: ${Self}) -> ${Self} { return value } @transparent func _getBuiltinArrayBoundValue() -> Builtin.Word { % if bits < wordBits: return Builtin.${ext}OrBitCast_${BuiltinName}_Word(self.value) % elif bits > wordBits: return Builtin.truncOrBitCast_${BuiltinName}_Word(self.value) % elif BuiltinName == 'Word': return self.value % else: return Builtin.${CastToWord}(self.value) % end } typealias ArrayBoundType = ${Self} func getArrayBoundValue() -> ${Self} { return self } % max = maskBits((bits - 1) if signed else bits) @transparent static var max: ${Self} { return ${max} } @transparent static var min: ${Self} { return ${'-%s-1' % max if signed else '0'} } } extension ${Self} : Hashable { var hashValue: Int { % if bits < wordBits: return Int(Builtin.sextOrBitCast_${BuiltinName}_Word(self.value)) % elif bits > wordBits: var result: Int = 0 for var i = 0; i < (sizeofValue(self) * 8); i += sizeof(Int.self) * 8 { result ^= Int(self >> ${Self}(i)) & ~0 } return result % elif BuiltinName == 'Word': return Int(self.value) % else: return Int(Builtin.${CastToWord}(self.value)) % end } } extension ${Self} : Printable { var description: String { % if signed: return _int64ToString(self.toIntMax()) % else: return _uint64ToString(self.toUIntMax()) % end } } @transparent extension ${Self} : RandomAccessIndex { @transparent func succ() -> ${Self} { return self + 1 } @transparent func pred() -> ${Self} { return self - 1 } @transparent func distanceTo(other: ${Self}) -> ${Self}.DistanceType { return numericCast((numericCast(other) as IntMax) - numericCast(self)) } @transparent func advancedBy(amount: ${Self}.DistanceType) -> ${Self} { return numericCast((numericCast(self) as IntMax) + numericCast(amount)) } % for Method,op in [('Add', 'add'), ('Subtract', 'sub'), ('Multiply', 'mul')]: @transparent static func unchecked${Method}(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, Bool) { var 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'), ('Modulus', 'rem')]: @transparent static func unchecked${Method}(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, 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: // Need [su]{div,rem}_with_overflow IR var tmp = Builtin.${sign}${op}_${BuiltinName}(lhs.value, rhs.value) return (${Self}(tmp), false) } %end % U = '' if signed else 'U' @transparent func to${U}IntMax() -> ${U}IntMax { return ${'self' if Self == U+'Int%s'%maxBits else U+'IntMax(self)'} } % if not signed: func toIntMax() -> IntMax { return IntMax(toUIntMax()) } % end @transparent static func from(x: ${U}IntMax) -> ${Self} { return ${'x' if Self == U+'Int%s'%maxBits else Self+'(x)'} } } % if signed: @transparent extension ${Self} : SignedNumber {} % end %# FIXME: checked conversions of Word types // construction from other integer types @transparent extension ${Self} { % for (srcName, srcBits, srcSigned) in allInts(): % Src = intName(srcName, srcSigned) % srcBuiltinName = builtinIntName(srcName) % (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext') % if Self != Src: init(_ v: ${Src}) { % % if srcBuiltinName == 'Word': var srcNotWord = Builtin.${CastFromWord}(v.value) % else: var srcNotWord = v.value % end % % if srcBits == bits and srcSign == sign: var dstNotWord = srcNotWord % % elif srcBits == bits: var tmp = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = tmp.0 % % elif srcBits > bits: var tmp = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = tmp.0 % % elif srcSigned and not signed: var tmp = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord) Builtin.condfail(tmp.1) var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp.0) % % else: var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord) % end % % if BuiltinName == 'Word': value = Builtin.${CastToWord}(dstNotWord) % else: value = dstNotWord % end } % end % end func as${'Unsigned' if signed else 'Signed'}() -> ${OtherSelf} { return ${OtherSelf}(value) } } // Operations with potentially-static overflow checking // // FIXME: must use condfail in these operators, rather than // overflowChecked, pending so that we don't // foil static checking for numeric overflows. % for op,method in ('+','add'), ('*','mul'), ('-','sub'): @transparent 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 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: // Need [su]{div,rem}_with_overflow IR var tmp = Builtin.${sign}${inst}_${BuiltinName}(lhs.value, rhs.value) return ${Self}(tmp) } %end // Bitwise negate @transparent @prefix func ~(rhs: ${Self}) -> ${Self} { let mask = ${Self}.uncheckedSubtract(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 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 func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { % if signed: assert(U${Self}(rhs) < U${Self}(sizeofValue(rhs) * 8)) % else: assert(rhs < ${Self}(sizeofValue(rhs) * 8)) % end return ${Self}(Builtin.${name}_${BuiltinName}(lhs.value, rhs.value)) } % end % for op, name in (('&','and'), ('^','xor'), ('|','or')): @transparent func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { return ${Self}(Builtin.${name}_${BuiltinName}(lhs.value, rhs.value)) } % end // bitwise operations @transparent extension ${Self} : BitwiseOperations { static var allZeros: ${Self} { return 0 } } // Compound assignments % for op in '+', '-', '*', '<<', '>>', '&', '|', '^': @transparent @assignment func ${op}=(inout lhs: ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs } % end % end # for bits in allInts typealias Word = Int typealias UWord = UInt // ${'Local Variables'}: // eval: (read-only-mode 1) // End: