diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/sigmatch.nim | 47 | ||||
-rw-r--r-- | compiler/types.nim | 40 |
2 files changed, 65 insertions, 22 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2c4f5d2ea..591a7c2a2 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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): @@ -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 @@ -405,7 +411,7 @@ 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 @@ -413,13 +419,14 @@ proc isConvertibleToRange(f, a: PType): bool = 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: @@ -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) @@ -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: diff --git a/compiler/types.nim b/compiler/types.nim index 0ade59fd0..4bbbaf13c 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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) @@ -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) @@ -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) |