Skip to content

Commit

Permalink
make -d:nimFpRoundtrips work consistently in vm vs rt, fix nim-lang#1…
Browse files Browse the repository at this point in the history
…8400, etc (nim-lang#18531)

* compiler/vmhooks: add getVar to allow vmops with var params
* addFloat vmops with var param
* cgen now renders float32 literals in c backend using roundtrip float to string
  • Loading branch information
timotheecour authored and PMunch committed Mar 28, 2022
1 parent 17d97b2 commit 7ba6713
Show file tree
Hide file tree
Showing 21 changed files with 287 additions and 200 deletions.
4 changes: 2 additions & 2 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ type
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot,
mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
mImplies, mIff, mExists, mForall, mOld,
Expand Down Expand Up @@ -720,7 +720,7 @@ const
mEqRef, mEqProc, mLePtr, mLtPtr, mEqCString, mXor,
mUnaryMinusI, mUnaryMinusI64, mAbsI, mNot, mUnaryPlusI, mBitnotI,
mUnaryPlusF64, mUnaryMinusF64,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr,
mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr,
mStrToStr, mEnumToStr,
mAnd, mOr,
mEqStr, mLeStr, mLtStr,
Expand Down
12 changes: 5 additions & 7 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,12 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
else:
result = makeCString(n.strVal)
of nkFloatLit, nkFloat64Lit:
result = rope(n.floatVal.toStrMaxPrecision)
if ty.kind == tyFloat32:
result = rope(n.floatVal.float32.toStrMaxPrecision)
else:
result = rope(n.floatVal.toStrMaxPrecision)
of nkFloat32Lit:
result = rope(n.floatVal.toStrMaxPrecision("f"))
result = rope(n.floatVal.float32.toStrMaxPrecision)
else:
internalError(p.config, n.info, "genLiteral(" & $n.kind & ')')
result = nil
Expand Down Expand Up @@ -2300,11 +2303,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)")
of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)")
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
of mFloatToStr:
if e[1].typ.skipTypes(abstractInst).kind == tyFloat32:
genDollar(p, e, d, "#nimFloat32ToStr($1)")
else:
genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e[1], d)
of mIsolate: genCall(p, e, d)
Expand Down
7 changes: 1 addition & 6 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,6 @@ const # magic checked op; magic unchecked op;
mBoolToStr: ["nimBoolToStr", "nimBoolToStr"],
mIntToStr: ["cstrToNimstr", "cstrToNimstr"],
mInt64ToStr: ["cstrToNimstr", "cstrToNimstr"],
mFloatToStr: ["cstrToNimstr", "cstrToNimstr"],
mCStrToStr: ["cstrToNimstr", "cstrToNimstr"],
mStrToStr: ["", ""]]

Expand Down Expand Up @@ -656,9 +655,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mBoolToStr: applyFormat("nimBoolToStr($1)", "nimBoolToStr($1)")
of mIntToStr: applyFormat("cstrToNimstr(($1) + \"\")", "cstrToNimstr(($1) + \"\")")
of mInt64ToStr: applyFormat("cstrToNimstr(($1) + \"\")", "cstrToNimstr(($1) + \"\")")
of mFloatToStr:
useMagic(p, "nimFloatToString")
applyFormat "cstrToNimstr(nimFloatToString($1))"
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
of mStrToStr, mUnown, mIsolate: applyFormat("$1", "$1")
else:
Expand All @@ -682,8 +678,7 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
gen(p, n[1], x)
gen(p, n[2], y)
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr,
mCStrToStr, mStrToStr, mEnumToStr:
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr, mStrToStr, mEnumToStr:
arithAux(p, n, r, op)
of mEqRef:
if mapType(n[1].typ) != etyBaseIndex:
Expand Down
1 change: 1 addition & 0 deletions compiler/nim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ hint:XDeclaredButNotUsed:off

define:booting
define:nimcore
define:nimFpRoundtrips

#import:"$projectpath/testability"

Expand Down
10 changes: 6 additions & 4 deletions compiler/rodutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ when not declared(signbit):
proc signbit*(x: SomeFloat): bool {.inline.} =
result = c_signbit(x) != 0

proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
import system/formatfloat

proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
const literalPostfix = when f is float32: "f" else: ""
case classify(f)
of fcNan:
if signbit(f):
Expand All @@ -55,9 +58,8 @@ proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
of fcNegInf:
result = "-INF"
else:
result = newString(81)
let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
setLen(result, n)
result.addFloatRoundtrip(f)
result.add literalPostfix

proc encodeStr*(s: string, result: var string) =
for i in 0..<s.len:
Expand Down
1 change: 0 additions & 1 deletion compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
of mBoolToStr:
if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
else: result = newStrNodeT("true", n, g)
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
of mCStrToStr, mCharToStr:
if a.kind == nkBracket:
var s = ""
Expand Down
3 changes: 1 addition & 2 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1127,8 +1127,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n[1], dest)
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
Expand Down
32 changes: 17 additions & 15 deletions compiler/vmhooks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,32 @@ proc setResult*(a: VmArgs; v: seq[string]) =
for x in v: n.add newStrNode(nkStrLit, x)
a.slots[a.ra].node = n

template getX(k, field) {.dirty.} =
template getReg(a, i): untyped =
doAssert i < a.rc-1
doAssert a.slots[i+a.rb+1].kind == k
result = a.slots[i+a.rb+1].field
a.slots[i+a.rb+1].unsafeAddr

template getX(k, field): untyped {.dirty.} =
let p = getReg(a, i)
doAssert p.kind == k, $p.kind
p.field

proc numArgs*(a: VmArgs): int =
result = a.rc-1

proc getInt*(a: VmArgs; i: Natural): BiggestInt = getX(rkInt, intVal)
proc getBool*(a: VmArgs; i: Natural): bool = getInt(a, i) != 0
proc getFloat*(a: VmArgs; i: Natural): BiggestFloat = getX(rkFloat, floatVal)
proc getString*(a: VmArgs; i: Natural): string =
doAssert i < a.rc-1
doAssert a.slots[i+a.rb+1].kind == rkNode
result = a.slots[i+a.rb+1].node.strVal

proc getNode*(a: VmArgs; i: Natural): PNode =
doAssert i < a.rc-1
doAssert a.slots[i+a.rb+1].kind == rkNode
result = a.slots[i+a.rb+1].node
proc getNode*(a: VmArgs; i: Natural): PNode = getX(rkNode, node)
proc getString*(a: VmArgs; i: Natural): string = getX(rkNode, node).strVal
proc getVar*(a: VmArgs; i: Natural): PNode =
let p = getReg(a, i)
# depending on whether we come from top-level or proc scope, we need to consider 2 cases
case p.kind
of rkRegisterAddr: result = p.regAddr.node
of rkNodeAddr: result = p.nodeAddr[]
else: doAssert false, $p.kind

proc getNodeAddr*(a: VmArgs; i: Natural): PNode =
doAssert i < a.rc-1
doAssert a.slots[i+a.rb+1].kind == rkNodeAddr
let nodeAddr = a.slots[i+a.rb+1].nodeAddr
let nodeAddr = getX(rkNodeAddr, nodeAddr)
doAssert nodeAddr != nil
result = nodeAddr[]
11 changes: 11 additions & 0 deletions compiler/vmops.nim
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ from std/md5 import getMD5
from std/times import cpuTime
from std/hashes import hash
from std/osproc import nil
from system/formatfloat import addFloatRoundtrip, addFloatSprintf

from sighashes import symBodyDigest

Expand Down Expand Up @@ -325,3 +326,13 @@ proc registerAdditionalOps*(c: PCtx) =
registerCallback c, "stdlib.typetraits.hasClosureImpl", proc (a: VmArgs) =
let fn = getNode(a, 0)
setResult(a, fn.kind == nkClosure or (fn.typ != nil and fn.typ.callConv == ccClosure))

registerCallback c, "stdlib.formatfloat.addFloatRoundtrip", proc(a: VmArgs) =
let p = a.getVar(0)
let x = a.getFloat(1)
addFloatRoundtrip(p.strVal, x)

registerCallback c, "stdlib.formatfloat.addFloatSprintf", proc(a: VmArgs) =
let p = a.getVar(0)
let x = a.getFloat(1)
addFloatSprintf(p.strVal, x)
3 changes: 0 additions & 3 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2472,9 +2472,6 @@ when defined(js) or defined(nimscript):
proc addInt*(result: var string; x: int64) =
result.add $x

proc addFloat*(result: var string; x: float) =
result.add $x

proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} =
## A shorthand for `echo(errormsg); quit(errorcode)`.
when defined(nimscript) or defined(js) or (hostOS == "standalone"):
Expand Down
13 changes: 5 additions & 8 deletions lib/system/dollars.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import std/private/digitsutils

import system/formatfloat
export addFloat

proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
Expand Down Expand Up @@ -40,13 +41,9 @@ proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
## The stringify operator for an integer argument. Returns `x`
## converted to a decimal string.

proc `$`*(x: float): string {.magic: "FloatToStr", noSideEffect.}
## The stringify operator for a float argument. Returns `x`
## converted to a decimal string.

proc `$`*(x: float32): string {.magic: "FloatToStr", noSideEffect.}
## The stringify operator for a float32 argument. Returns `x`
## converted to a decimal string.
func `$`*(x: float | float32): string =
## Outplace version of `addFloat`.
result.addFloat(x)

proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
## The stringify operator for a boolean argument. Returns `x`
Expand Down
Loading

0 comments on commit 7ba6713

Please sign in to comment.