From 53586d1f32dfe4f2e859178a3e43a6614520763f Mon Sep 17 00:00:00 2001 From: konsumlamm <44230978+konsumlamm@users.noreply.github.com> Date: Sun, 6 Aug 2023 14:24:35 +0200 Subject: [PATCH] Fix some jsgen bugs (#22330) Fix `succ`, `pred` Fix `genRangeChck` for unsigned ints Fix typo in `dec` --- compiler/jsgen.nim | 53 +++++++++++++++++++++++++++++++------ compiler/semmagic.nim | 4 --- tests/int/tunsignedconv.nim | 36 ++++++++++++++++++------- 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index a5f4d29b27..f4d7d64563 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -676,8 +676,38 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = applyFormat("modInt64($1, $2)", "$1 % $2") else: applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)") - of mSucc: applyFormat("addInt($1, $2)", "($1 + $2)") - of mPred: applyFormat("subInt($1, $2)", "($1 - $2)") + of mSucc: + let typ = n[1].typ.skipTypes(abstractVarRange) + case typ.kind + of tyUInt..tyUInt32: + binaryUintExpr(p, n, r, "+") + of tyUInt64: + if optJsBigInt64 in p.config.globalOptions: + applyFormat("BigInt.asUintN(64, $1 + BigInt($2))") + else: binaryUintExpr(p, n, r, "+") + elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions: + if optOverflowCheck notin p.options: + applyFormat("BigInt.asIntN(64, $1 + BigInt($2))") + else: binaryExpr(p, n, r, "addInt64", "addInt64($1, BigInt($2))") + else: + if optOverflowCheck notin p.options: applyFormat("$1 + $2") + else: binaryExpr(p, n, r, "addInt", "addInt($1, $2)") + of mPred: + let typ = n[1].typ.skipTypes(abstractVarRange) + case typ.kind + of tyUInt..tyUInt32: + binaryUintExpr(p, n, r, "-") + of tyUInt64: + if optJsBigInt64 in p.config.globalOptions: + applyFormat("BigInt.asUintN(64, $1 - BigInt($2))") + else: binaryUintExpr(p, n, r, "-") + elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions: + if optOverflowCheck notin p.options: + applyFormat("BigInt.asIntN(64, $1 - BigInt($2))") + else: binaryExpr(p, n, r, "subInt64", "subInt64($1, BigInt($2))") + else: + if optOverflowCheck notin p.options: applyFormat("$1 - $2") + else: binaryExpr(p, n, r, "subInt", "subInt($1, $2)") of mAddF64: applyFormat("($1 + $2)", "($1 + $2)") of mSubF64: applyFormat("($1 - $2)", "($1 - $2)") of mMulF64: applyFormat("($1 * $2)", "($1 * $2)") @@ -2346,7 +2376,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of tyUInt64: if optJsBigInt64 in p.config.globalOptions: binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 - BigInt($2))", true) - else: binaryUintExpr(p, n, r, "+", true) + else: binaryUintExpr(p, n, r, "-", true) elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions: if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 - BigInt($2))", true) @@ -2564,12 +2594,19 @@ proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) = gen(p, n[0], r) let src = skipTypes(n[0].typ, abstractVarRange) let dest = skipTypes(n.typ, abstractVarRange) - if src.kind in {tyInt64, tyUInt64} and dest.kind notin {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions: - r.res = "Number($1)" % [r.res] - if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and - checkUnsignedConversions notin p.config.legacyFeatures): - discard "XXX maybe emit masking instructions here" + if optRangeCheck notin p.options: + return + elif dest.kind in {tyUInt..tyUInt64} and checkUnsignedConversions notin p.config.legacyFeatures: + if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions: + r.res = "BigInt.asUintN($1, $2)" % [$(dest.size * 8), r.res] + else: + r.res = "BigInt.asUintN($1, BigInt($2))" % [$(dest.size * 8), r.res] + if not (dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions): + r.res = "Number($1)" % [r.res] else: + if src.kind in {tyInt64, tyUInt64} and dest.kind notin {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions: + # we do a range check anyway, so it's ok if the number gets rounded + r.res = "Number($1)" % [r.res] gen(p, n[1], a) gen(p, n[2], b) useMagic(p, "chckRange") diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 97a3207744..4fba4eaf92 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -656,10 +656,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, if not checkIsolate(n[1]): localError(c.config, n.info, "expression cannot be isolated: " & $n[1]) result = n - of mPred: - if n[1].typ.skipTypes(abstractInst).kind in {tyUInt..tyUInt64}: - n[0].sym.magic = mSubU - result = n of mPrivateAccess: result = semPrivateAccess(c, n) of mArrToSeq: diff --git a/tests/int/tunsignedconv.nim b/tests/int/tunsignedconv.nim index c32f85b4dc..6c73521d38 100644 --- a/tests/int/tunsignedconv.nim +++ b/tests/int/tunsignedconv.nim @@ -1,15 +1,19 @@ +discard """ + targets: "c cpp js" +""" + # Tests unsigned literals and implicit conversion between uints and ints -var h8:uint8 = 128 -var h16:uint16 = 32768 -var h32:uint32 = 2147483648'u32 -var h64:uint64 = 9223372036854775808'u64 -var foobar:uint64 = 9223372036854775813'u64 # Issue 728 +var h8: uint8 = 128 +var h16: uint16 = 32768 +var h32: uint32 = 2147483648'u32 +var h64: uint64 = 9223372036854775808'u64 +var foobar: uint64 = 9223372036854775813'u64 # Issue 728 -var v8:uint8 = 10 -var v16:uint16 = 10 -var v32:uint32 = 10 -var v64:uint64 = 10 +var v8: uint8 = 10 +var v16: uint16 = 10 +var v32: uint32 = 10 +var v64: uint64 = 10 # u8 + literal produces u8: var a8: uint8 = v8 + 10 @@ -95,3 +99,17 @@ template main() = static: main() main() + +block: + let a = uint64.high + let b = uint32.high + + doAssert a.uint64 == a + doAssert a.uint32 == uint32.high + doAssert a.uint16 == uint16.high + doAssert a.uint8 == uint8.high + + doAssert b.uint64 == b + doAssert b.uint32 == b + doAssert b.uint16 == uint16.high + doAssert b.uint8 == uint8.high