Skip to content

Commit

Permalink
tyInt tyUint fit target int bit width (nim-lang#20829)
Browse files Browse the repository at this point in the history
  • Loading branch information
bung87 authored Dec 1, 2022
1 parent a70d3ab commit 658b28d
Show file tree
Hide file tree
Showing 17 changed files with 314 additions and 275 deletions.
47 changes: 28 additions & 19 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,16 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
else:
result = t # Note: empty is valid here

proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
proc handleRange(c: PContext, f, a: PType, min, max: TTypeKind): TTypeRelation =
if a.kind == f.kind:
result = isEqual
else:
let ab = skipTypes(a, {tyRange})
let k = ab.kind
let nf = c.config.normalizeKind(f.kind)
let na = c.config.normalizeKind(k)
if k == f.kind: result = isSubrange
elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
elif k == tyInt and f.kind in {tyRange, tyInt..tyInt64,
tyUInt..tyUInt64} and
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
getInt(ab.n) <= lastOrd(nil, f):
Expand All @@ -389,9 +391,13 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
# integer literal in the proper range; we want ``i16 + 4`` to stay an
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16
result = isFromIntLit
elif f.kind == tyInt and k in {tyInt8..tyInt32}:
elif a.kind == tyInt and nf == c.config.targetSizeSignedToKind:
result = isIntConv
elif f.kind == tyUInt and k in {tyUInt8..tyUInt32}:
elif a.kind == tyUInt and nf == c.config.targetSizeUnsignedToKind:
result = isIntConv
elif f.kind == tyInt and na in {tyInt8 .. c.config.targetSizeSignedToKind}:
result = isIntConv
elif f.kind == tyUInt and na in {tyUInt8 .. c.config.targetSizeUnsignedToKind}:
result = isIntConv
elif k >= min and k <= max:
result = isConvertible
Expand All @@ -405,21 +411,22 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
result = isConvertible
else: result = isNone

proc isConvertibleToRange(f, a: PType): bool =
proc isConvertibleToRange(c: PContext, f, a: PType): bool =
if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and
a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}:
case f.kind
of tyInt8: result = isIntLit(a) or a.kind in {tyInt8}
of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16}
of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32}
# This is wrong, but seems like there's a lot of code that relies on it :(
of tyInt, tyUInt, tyUInt64: result = true
of tyInt, tyUInt: result = true
# of tyInt: result = isIntLit(a) or a.kind in {tyInt8 .. c.config.targetSizeSignedToKind}
of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64}
of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8}
of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16}
of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32}
#of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt}
#of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64}
# of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8 .. c.config.targetSizeUnsignedToKind}
of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt64}
else: result = false
elif f.kind in {tyFloat..tyFloat128}:
# `isIntLit` is correct and should be used above as well, see PR:
Expand Down Expand Up @@ -1148,18 +1155,18 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let f = skipTypes(f, {tyRange})
if f.kind == a.kind and (f.kind != tyEnum or sameEnumTypes(f, a)):
result = isIntConv
elif isConvertibleToRange(f, a):
elif isConvertibleToRange(c.c, f, a):
result = isConvertible # a convertible to f
of tyInt: result = handleRange(f, a, tyInt8, tyInt32)
of tyInt8: result = handleRange(f, a, tyInt8, tyInt8)
of tyInt16: result = handleRange(f, a, tyInt8, tyInt16)
of tyInt32: result = handleRange(f, a, tyInt8, tyInt32)
of tyInt64: result = handleRange(f, a, tyInt, tyInt64)
of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32)
of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8)
of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16)
of tyUInt32: result = handleRange(f, a, tyUInt8, tyUInt32)
of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64)
of tyInt: result = handleRange(c.c, f, a, tyInt8, c.c.config.targetSizeSignedToKind)
of tyInt8: result = handleRange(c.c, f, a, tyInt8, tyInt8)
of tyInt16: result = handleRange(c.c, f, a, tyInt8, tyInt16)
of tyInt32: result = handleRange(c.c, f, a, tyInt8, tyInt32)
of tyInt64: result = handleRange(c.c, f, a, tyInt, tyInt64)
of tyUInt: result = handleRange(c.c, f, a, tyUInt8, c.c.config.targetSizeUnsignedToKind)
of tyUInt8: result = handleRange(c.c, f, a, tyUInt8, tyUInt8)
of tyUInt16: result = handleRange(c.c, f, a, tyUInt8, tyUInt16)
of tyUInt32: result = handleRange(c.c, f, a, tyUInt8, tyUInt32)
of tyUInt64: result = handleRange(c.c, f, a, tyUInt, tyUInt64)
of tyFloat: result = handleFloatRange(f, a)
of tyFloat32: result = handleFloatRange(f, a)
of tyFloat64: result = handleFloatRange(f, a)
Expand Down Expand Up @@ -2114,6 +2121,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
of isIntConv:
# I'm too lazy to introduce another ``*matches`` field, so we conflate
# ``isIntConv`` and ``isIntLit`` here:
if f.skipTypes({tyRange}).kind notin {tyInt, tyUInt}:
inc(m.intConvMatches)
inc(m.intConvMatches)
result = implicitConv(nkHiddenStdConv, f, arg, m, c)
of isSubtype:
Expand Down
40 changes: 37 additions & 3 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,13 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
assert(t.n.kind == nkRange)
result = getOrdValue(t.n[0])
of tyInt:
if conf != nil and conf.target.intSize == 4:
result = toInt128(-2147483648)
if conf != nil:
case conf.target.intSize
of 8: result = toInt128(0x8000000000000000'i64)
of 4: result = toInt128(-2147483648)
of 2: result = toInt128(-32768)
of 1: result = toInt128(-128)
else: discard
else:
result = toInt128(0x8000000000000000'i64)
of tyInt8: result = toInt128(-128)
Expand Down Expand Up @@ -797,6 +802,29 @@ proc firstFloat*(t: PType): BiggestFloat =
internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')')
NaN

proc targetSizeSignedToKind*(conf: ConfigRef): TTypeKind =
case conf.target.intSize
of 8: result = tyInt64
of 4: result = tyInt32
of 2: result = tyInt16
else: discard

proc targetSizeUnsignedToKind*(conf: ConfigRef): TTypeKind =
case conf.target.intSize
of 8: result = tyUInt64
of 4: result = tyUInt32
of 2: result = tyUInt16
else: discard

proc normalizeKind*(conf: ConfigRef, k: TTypeKind): TTypeKind =
case k
of tyInt:
result = conf.targetSizeSignedToKind()
of tyUInt:
result = conf.targetSizeUnsignedToKind()
else:
result = k

proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
case t.kind
of tyBool: result = toInt128(1'u)
Expand All @@ -808,7 +836,13 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
assert(t.n.kind == nkRange)
result = getOrdValue(t.n[1])
of tyInt:
if conf != nil and conf.target.intSize == 4: result = toInt128(0x7FFFFFFF)
if conf != nil:
case conf.target.intSize
of 8: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
of 4: result = toInt128(0x7FFFFFFF)
of 2: result = toInt128(0x00007FFF)
of 1: result = toInt128(0x0000007F)
else: discard
else: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
of tyInt8: result = toInt128(0x0000007F)
of tyInt16: result = toInt128(0x00007FFF)
Expand Down
6 changes: 3 additions & 3 deletions lib/std/formatfloat.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat)
##
## returns the amount of bytes written to `buf` not counting the
## terminating '\0' character.
result = toChars(buf, value, forceTrailingDotZero=true)
result = toChars(buf, value, forceTrailingDotZero=true).int
buf[result] = '\0'

proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int =
result = float32ToChars(buf, value, forceTrailingDotZero=true)
result = float32ToChars(buf, value, forceTrailingDotZero=true).int
buf[result] = '\0'

proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
Expand All @@ -49,7 +49,7 @@ proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat):
##
## returns the amount of bytes written to `buf` not counting the
## terminating '\0' character.
var n: int = c_sprintf(cast[cstring](addr buf), "%.16g", value)
var n = c_sprintf(cast[cstring](addr buf), "%.16g", value).int
var hasDot = false
for i in 0..n-1:
if buf[i] == ',':
Expand Down
6 changes: 3 additions & 3 deletions lib/std/private/digitsutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.}
#copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))

proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
return trailingZeros100[digits]
return trailingZeros100[digits.int8]

when defined(js):
proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".}
Expand Down Expand Up @@ -63,14 +63,14 @@ func addIntImpl(result: var string, x: uint64) {.inline.} =
while num >= nbatch:
let originNum = num
num = num div nbatch
let index = (originNum - num * nbatch) shl 1
let index = int16((originNum - num * nbatch) shl 1)
tmp[next] = digits100[index + 1]
tmp[next - 1] = digits100[index]
dec(next, 2)

# process last 1-2 digits
if num < 10:
tmp[next] = chr(ord('0') + num)
tmp[next] = chr(ord('0') + num.uint8)
else:
let index = num * 2
tmp[next] = digits100[index + 1]
Expand Down
38 changes: 19 additions & 19 deletions lib/std/private/dragonbox.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1146,7 +1146,7 @@ proc printDecimalDigitsBackwards*(buf: var openArray[char]; pos: int; output64:
buf[pos] = chr(ord('0') + q)
return tz

proc decimalLength*(v: uint64): int32 {.inline.} =
proc decimalLength*(v: uint64): int {.inline.} =
dragonbox_Assert(v >= 1)
dragonbox_Assert(v <= 99999999999999999'u64)
if cast[uint32](v shr 32) != 0:
Expand All @@ -1166,48 +1166,48 @@ proc decimalLength*(v: uint64): int32 {.inline.} =
return 11
return 10
let v32: uint32 = cast[uint32](v)
if v32 >= 1000000000'u:
if v32 >= 1000000000'u32:
return 10
if v32 >= 100000000'u:
if v32 >= 100000000'u32:
return 9
if v32 >= 10000000'u:
if v32 >= 10000000'u32:
return 8
if v32 >= 1000000'u:
if v32 >= 1000000'u32:
return 7
if v32 >= 100000'u:
if v32 >= 100000'u32:
return 6
if v32 >= 10000'u:
if v32 >= 10000'u32:
return 5
if v32 >= 1000'u:
if v32 >= 1000'u32:
return 4
if v32 >= 100'u:
if v32 >= 100'u32:
return 3
if v32 >= 10'u:
if v32 >= 10'u32:
return 2
return 1

proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decimalExponent: int32;
proc formatDigits*[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint64; decimalExponent: int;
forceTrailingDotZero = false): int {.inline.} =
const
minFixedDecimalPoint: int32 = -6
minFixedDecimalPoint = -6
const
maxFixedDecimalPoint: int32 = 17
var pos = pos
maxFixedDecimalPoint = 17
var pos:int = pos.int
assert(minFixedDecimalPoint <= -1, "internal error")
assert(maxFixedDecimalPoint >= 17, "internal error")
dragonbox_Assert(digits >= 1)
dragonbox_Assert(digits <= 99999999999999999'u64)
dragonbox_Assert(decimalExponent >= -999)
dragonbox_Assert(decimalExponent <= 999)
var numDigits: int32 = decimalLength(digits)
let decimalPoint: int32 = numDigits + decimalExponent
var numDigits = decimalLength(digits)
let decimalPoint = numDigits + decimalExponent
let useFixed: bool = minFixedDecimalPoint <= decimalPoint and
decimalPoint <= maxFixedDecimalPoint
## Prepare the buffer.
for i in 0..<32: buffer[pos+i] = '0'
assert(minFixedDecimalPoint >= -30, "internal error")
assert(maxFixedDecimalPoint <= 32, "internal error")
var decimalDigitsPosition: int32
var decimalDigitsPosition: int
if useFixed:
if decimalPoint <= 0:
## 0.[000]digits
Expand Down Expand Up @@ -1258,7 +1258,7 @@ proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decima
## d.igitsE+123
buffer[pos+1] = '.'
pos = digitsEnd
let scientificExponent: int32 = decimalPoint - 1
let scientificExponent: int = decimalPoint - 1
## SF_ASSERT(scientific_exponent != 0);
buffer[pos] = 'e'
buffer[pos+1] = if scientificExponent < 0: '-' else: '+'
Expand Down Expand Up @@ -1291,7 +1291,7 @@ proc toChars*(buffer: var openArray[char]; v: float; forceTrailingDotZero = fals
if exponent != 0 or significand != 0:
## != 0
let dec = toDecimal64(significand, exponent)
return formatDigits(buffer, pos, dec.significand, dec.exponent,
return formatDigits(buffer, pos, dec.significand, dec.exponent.int,
forceTrailingDotZero)
else:
buffer[pos] = '0'
Expand Down
16 changes: 8 additions & 8 deletions lib/std/private/schubfach.nim
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ proc toDecimal32(ieeeSignificand: uint32; ieeeExponent: uint32): FloatingDecimal
## ToChars
## ==================================================================================================

proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uint32): int32 {.inline.} =
proc printDecimalDigitsBackwards[T: Ordinal](buf: var openArray[char]; pos: T; output: uint32): int32 {.inline.} =
var output = output
var pos = pos
var tz: int32 = 0
Expand Down Expand Up @@ -300,7 +300,7 @@ proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uin
buf[pos] = chr(uint32('0') + q)
return tz

proc decimalLength(v: uint32): int32 {.inline.} =
proc decimalLength(v: uint32): int {.inline.} =
sf_Assert(v >= 1)
sf_Assert(v <= 999999999'u)
if v >= 100000000'u:
Expand All @@ -321,7 +321,7 @@ proc decimalLength(v: uint32): int32 {.inline.} =
return 2
return 1

proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimalExponent: int32;
proc formatDigits[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint32; decimalExponent: int;
forceTrailingDotZero: bool = false): int {.inline.} =
const
minFixedDecimalPoint: int32 = -4
Expand All @@ -333,16 +333,16 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal
sf_Assert(digits <= 999999999'u)
sf_Assert(decimalExponent >= -99)
sf_Assert(decimalExponent <= 99)
var numDigits: int32 = decimalLength(digits)
let decimalPoint: int32 = numDigits + decimalExponent
var numDigits = decimalLength(digits)
let decimalPoint = numDigits + decimalExponent
let useFixed: bool = minFixedDecimalPoint <= decimalPoint and
decimalPoint <= maxFixedDecimalPoint
## Prepare the buffer.
## Avoid calling memset/memcpy with variable arguments below...
for i in 0..<32: buffer[pos+i] = '0'
assert(minFixedDecimalPoint >= -30, "internal error")
assert(maxFixedDecimalPoint <= 32, "internal error")
var decimalDigitsPosition: int32
var decimalDigitsPosition: int
if useFixed:
if decimalPoint <= 0:
## 0.[000]digits
Expand Down Expand Up @@ -386,7 +386,7 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal
## d.igitsE+123
buffer[pos+1] = '.'
pos = digitsEnd
let scientificExponent: int32 = decimalPoint - 1
let scientificExponent = decimalPoint - 1
## SF_ASSERT(scientific_exponent != 0);
buffer[pos] = 'e'
buffer[pos+1] = if scientificExponent < 0: '-' else: '+'
Expand All @@ -412,7 +412,7 @@ proc float32ToChars*(buffer: var openArray[char]; v: float32; forceTrailingDotZe
if exponent != 0 or significand != 0:
## != 0
let dec: auto = toDecimal32(significand, exponent)
return formatDigits(buffer, pos, dec.digits, dec.exponent, forceTrailingDotZero)
return formatDigits(buffer, pos, dec.digits, dec.exponent.int, forceTrailingDotZero)
else:
buffer[pos] = '0'
buffer[pos+1] = '.'
Expand Down
6 changes: 3 additions & 3 deletions lib/std/syncio.nim
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ proc readAllFile(file: File, len: int64): string =
result = newString(len)
let bytes = readBuffer(file, addr(result[0]), len)
if endOfFile(file):
if bytes < len:
if bytes.int64 < len:
result.setLen(bytes)
else:
# We read all the bytes but did not reach the EOF
Expand Down Expand Up @@ -717,7 +717,7 @@ proc open*(f: var File, filename: string,

result = true
f = cast[File](p)
if bufSize > 0 and bufSize <= high(cint).int:
if bufSize > 0 and bufSize.uint <= high(uint):
discard c_setvbuf(f, nil, IOFBF, cast[csize_t](bufSize))
elif bufSize == 0:
discard c_setvbuf(f, nil, IONBF, 0)
Expand Down Expand Up @@ -821,7 +821,7 @@ when defined(windows) and appType == "console" and
proc getConsoleCP(): cuint {.stdcall, dynlib: "kernel32",
importc: "GetConsoleCP".}

const Utf8codepage = 65001
const Utf8codepage = 65001'u32

let
consoleOutputCP = getConsoleOutputCP()
Expand Down
Loading

0 comments on commit 658b28d

Please sign in to comment.