Skip to content

Commit 56a559a

Browse files
authored
Merge branch 'devel' into sig-handler
2 parents 13f54d2 + 87dc182 commit 56a559a

File tree

10 files changed

+156
-45
lines changed

10 files changed

+156
-45
lines changed

compiler/ast.nim

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ type
819819
# nodes are compared by structure!
820820
counter*: int
821821
data*: TNodePairSeq
822+
ignoreTypes*: bool
822823

823824
TObjectSeq* = seq[RootRef]
824825
TObjectSet* = object
@@ -1641,8 +1642,8 @@ proc initObjectSet*(): TObjectSet =
16411642
result = TObjectSet(counter: 0)
16421643
newSeq(result.data, StartSize)
16431644

1644-
proc initNodeTable*(): TNodeTable =
1645-
result = TNodeTable(counter: 0)
1645+
proc initNodeTable*(ignoreTypes=false): TNodeTable =
1646+
result = TNodeTable(counter: 0, ignoreTypes: ignoreTypes)
16461647
newSeq(result.data, StartSize)
16471648

16481649
proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =

compiler/ccgexprs.nim

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,11 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
981981
var a: TLoc = initLocExpr(p, e[0])
982982
if e[0].kind in {nkHiddenStdConv, nkHiddenSubConv, nkConv} and not ignoreConv(e[0]):
983983
# addr (conv x) introduces a temp because `conv x` is not a rvalue
984-
putIntoDest(p, d, e, addrLoc(p.config, expressionsNeedsTmp(p, a)), a.storage)
984+
# transform addr ( conv ( x ) ) -> conv ( addr ( x ) )
985+
var exprLoc: TLoc = initLocExpr(p, e[0][1])
986+
var tmp = getTemp(p, e.typ, needsInit=false)
987+
putIntoDest(p, tmp, e, cCast(getTypeDesc(p.module, e.typ), addrLoc(p.config, exprLoc)))
988+
putIntoDest(p, d, e, rdLoc(tmp))
985989
else:
986990
putIntoDest(p, d, e, addrLoc(p.config, a), a.storage)
987991

compiler/transf.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ proc transformBlock(c: PTransf, n: PNode): PNode =
259259
var labl: PSym
260260
if c.inlining > 0:
261261
labl = newLabel(c, n[0])
262-
c.transCon.mapping[n[0].sym.itemId] = newSymNode(labl)
262+
if n[0].kind != nkEmpty:
263+
c.transCon.mapping[n[0].sym.itemId] = newSymNode(labl)
263264
else:
264265
labl =
265266
if n[0].kind != nkEmpty:

compiler/treetab.nim

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,32 +42,37 @@ proc hashTree*(n: PNode): Hash =
4242
#echo "hashTree ", result
4343
#echo n
4444

45-
proc treesEquivalent(a, b: PNode): bool =
45+
proc treesEquivalent(a, b: PNode; ignoreTypes: bool): bool =
4646
if a == b:
4747
result = true
4848
elif (a != nil) and (b != nil) and (a.kind == b.kind):
4949
case a.kind
50-
of nkEmpty, nkNilLit, nkType: result = true
50+
of nkEmpty: result = true
5151
of nkSym: result = a.sym.id == b.sym.id
5252
of nkIdent: result = a.ident.id == b.ident.id
5353
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
54-
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
54+
of nkFloatLit..nkFloat64Lit:
55+
result = cast[uint64](a.floatVal) == cast[uint64](b.floatVal)
56+
#result = a.floatVal == b.floatVal
5557
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
58+
of nkType, nkNilLit:
59+
result = a.typ == b.typ
5660
else:
5761
if a.len == b.len:
5862
for i in 0..<a.len:
59-
if not treesEquivalent(a[i], b[i]): return
63+
if not treesEquivalent(a[i], b[i], ignoreTypes): return
6064
result = true
6165
else:
6266
result = false
63-
if result: result = sameTypeOrNil(a.typ, b.typ)
67+
if result and not ignoreTypes:
68+
result = sameTypeOrNil(a.typ, b.typ)
6469
else:
6570
result = false
6671

6772
proc nodeTableRawGet(t: TNodeTable, k: Hash, key: PNode): int =
6873
var h: Hash = k and high(t.data)
6974
while t.data[h].key != nil:
70-
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key):
75+
if (t.data[h].h == k) and treesEquivalent(t.data[h].key, key, t.ignoreTypes):
7176
return h
7277
h = nextTry(h, high(t.data))
7378
result = -1

compiler/vmdef.nim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ type
249249
# to not slow down interpretation
250250
globals*: PNode #
251251
constants*: PNode # constant data
252+
contstantTab*: TNodeTable
252253
types*: seq[PType] # some instructions reference types (e.g. 'except')
253254
currentExceptionA*, currentExceptionB*: PNode
254255
exceptionInstr*: int # index of instruction that raised the exception
@@ -298,7 +299,8 @@ proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator
298299
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
299300
callDepth: g.config.maxCallDepthVM,
300301
comesFromHeuristic: unknownLineInfo, callbacks: @[], callbackIndex: initTable[string, int](), errorFlag: "",
301-
cache: cache, config: g.config, graph: g, idgen: idgen)
302+
cache: cache, config: g.config, graph: g, idgen: idgen,
303+
contstantTab: initNodeTable(true))
302304

303305
proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) =
304306
c.module = module

compiler/vmgen.nim

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ when defined(nimPreviewSlimSystem):
3333

3434
import
3535
ast, types, msgs, renderer, vmdef, trees,
36-
magicsys, options, lowerings, lineinfos, transf, astmsgs
36+
magicsys, options, lowerings, lineinfos, transf, astmsgs,
37+
treetab
3738

3839
from modulegraphs import getBody
3940

@@ -478,10 +479,16 @@ proc sameConstant*(a, b: PNode): bool =
478479
result = true
479480

480481
proc genLiteral(c: PCtx; n: PNode): int =
481-
# types do not matter here:
482-
for i in 0..<c.constants.len:
483-
if sameConstant(c.constants[i], n): return i
484-
result = rawGenLiteral(c, n)
482+
result = nodeTableTestOrSet(c.contstantTab, n, c.constants.len)
483+
if result == c.constants.len:
484+
let lit = rawGenLiteral(c, n)
485+
assert lit == result
486+
487+
when false:
488+
# types do not matter here:
489+
for i in 0..<c.constants.len:
490+
if sameConstant(c.constants[i], n): return i
491+
result = rawGenLiteral(c, n)
485492

486493
proc unused(c: PCtx; n: PNode; x: TDest) {.inline.} =
487494
if x >= 0:
@@ -1182,8 +1189,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
11821189
of mEqF64: genBinaryABC(c, n, dest, opcEqFloat)
11831190
of mLeF64: genBinaryABC(c, n, dest, opcLeFloat)
11841191
of mLtF64: genBinaryABC(c, n, dest, opcLtFloat)
1185-
of mLePtr, mLeU: genBinaryABC(c, n, dest, opcLeu)
1186-
of mLtPtr, mLtU: genBinaryABC(c, n, dest, opcLtu)
1192+
of mLeU: genBinaryABC(c, n, dest, opcLeu)
1193+
of mLtU: genBinaryABC(c, n, dest, opcLtu)
1194+
of mLePtr, mLtPtr:
1195+
globalError(c.config, n.info, "pointer comparisons are not available at compile-time")
11871196
of mEqProc, mEqRef:
11881197
genBinaryABC(c, n, dest, opcEqRef)
11891198
of mXor: genBinaryABC(c, n, dest, opcXor)
@@ -1547,8 +1556,7 @@ template cannotEval(c: PCtx; n: PNode) =
15471556
if c.config.cmd == cmdCheck and c.config.m.errorOutputs != {}:
15481557
# nim check command with no error outputs doesn't need to cascade here,
15491558
# includes `tryConstExpr` case which should not continue generating code
1550-
localError(c.config, n.info, "cannot evaluate at compile time: " &
1551-
n.renderTree)
1559+
localError(c.config, n.info, "cannot evaluate at compile time: " & n.renderTree)
15521560
c.cannotEval = true
15531561
return
15541562
globalError(c.config, n.info, "cannot evaluate at compile time: " &
@@ -1886,7 +1894,7 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
18861894
c.freeTemp(objR)
18871895

18881896
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
1889-
if n[0].typ == nil:
1897+
if n[0].typ == nil:
18901898
globalError(c.config, n.info, "cannot access array with nil type")
18911899
return
18921900

lib/pure/strutils.nim

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import std/parseutils
7474
from std/math import pow, floor, log10
7575
from std/algorithm import fill, reverse
7676
import std/enumutils
77+
from std/bitops import fastLog2
7778

7879
from std/unicode import toLower, toUpper
7980
export toLower, toUpper
@@ -2639,37 +2640,35 @@ func formatSize*(bytes: int64,
26392640
## * `strformat module<strformat.html>`_ for string interpolation and formatting
26402641
runnableExamples:
26412642
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB"
2642-
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
2643+
doAssert formatSize((2.234*1024*1024).int) == "2.233MiB"
26432644
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
26442645
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
26452646
doAssert formatSize(4096) == "4KiB"
2646-
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
2647+
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,129MB"
26472648

2648-
const iecPrefixes = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"]
2649-
const collPrefixes = ["", "k", "M", "G", "T", "P", "E", "Z", "Y"]
2650-
var
2651-
xb: int64 = bytes
2652-
fbytes: float
2653-
lastXb: int64 = bytes
2654-
matchedIndex = 0
2655-
prefixes: array[9, string]
2649+
# It doesn't needs Zi and larger units until we use int72 or larger ints.
2650+
const iecPrefixes = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"]
2651+
const collPrefixes = ["", "k", "M", "G", "T", "P", "E"]
2652+
2653+
let lg2 = if bytes == 0:
2654+
0
2655+
else:
2656+
when hasWorkingInt64:
2657+
fastLog2(bytes)
2658+
else:
2659+
fastLog2(int32 bytes)
2660+
let matchedIndex = lg2 div 10
2661+
# Lower bits that are smaller than 0.001 when `bytes` is converted to a real number and added prefix, are discard.
2662+
# Then it is converted to float with round down.
2663+
let discardBits = (lg2 div 10 - 1) * 10
2664+
2665+
var prefixes: array[7, string]
26562666
if prefix == bpColloquial:
26572667
prefixes = collPrefixes
26582668
else:
26592669
prefixes = iecPrefixes
26602670

2661-
# Iterate through prefixes seeing if value will be greater than
2662-
# 0 in each case
2663-
for index in 1..<prefixes.len:
2664-
lastXb = xb
2665-
xb = bytes div (1'i64 shl (index*10))
2666-
matchedIndex = index
2667-
if xb == 0:
2668-
xb = lastXb
2669-
matchedIndex = index - 1
2670-
break
2671-
# xb has the integer number for the latest value; index should be correct
2672-
fbytes = bytes.float / (1'i64 shl (matchedIndex*10)).float
2671+
let fbytes = if lg2 < 10: bytes.float elif lg2 < 20: bytes.float / 1024.0 else: (bytes shr discardBits).float / 1024.0
26732672
result = formatFloat(fbytes, format = ffDecimal, precision = 3,
26742673
decimalSep = decimalSep)
26752674
result.trimZeros(decimalSep)

tests/ccgbugs/taddrconvs.nim

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,23 @@ block:
2525
var m = uint64(12)
2626
foo(culonglong(m))
2727
main()
28+
29+
block: # bug #25109
30+
type T = culonglong
31+
proc r(c: var T) = c = 1
32+
proc h(a: var culonglong) = r(T(a))
33+
var a: culonglong
34+
h(a)
35+
doAssert a == 1
36+
37+
block: # bug #25111
38+
type T = culonglong
39+
proc r(c: var T) = c = 1
40+
41+
proc foo =
42+
var a: uint64
43+
r(T(a))
44+
doAssert a == 1
45+
46+
foo()
47+

tests/iter/titer_issues.nim

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,3 +412,15 @@ block: # bug #24033
412412
collections.add (id, str, $num)
413413

414414
doAssert collections[1] == (1, "foo", "3.14")
415+
416+
417+
block: # bug #25121
418+
iterator k(): int =
419+
when nimvm:
420+
yield 0
421+
else:
422+
yield 0
423+
424+
for _ in k():
425+
(proc() = (; let _ = block: 0))()
426+

tests/stdlib/tstrutils.nim

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,12 +789,71 @@ bar
789789
block: # formatSize
790790
disableVm:
791791
when hasWorkingInt64:
792+
doAssert formatSize(1024'i64 * 1024 * 1024 * 2 - 1) == "1.999GiB"
793+
doAssert formatSize(1024'i64 * 1024 * 1024 * 2) == "2GiB"
792794
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
793-
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
795+
doAssert formatSize(int64.high) == "7.999EiB"
796+
doAssert formatSize(int64.high div 2 + 1) == "4EiB"
797+
doAssert formatSize(int64.high div 2) == "3.999EiB"
798+
doAssert formatSize(int64.high div 4 + 1) == "2EiB"
799+
doAssert formatSize(int64.high div 4) == "1.999EiB"
800+
doAssert formatSize(int64.high div 8 + 1) == "1EiB"
801+
doAssert formatSize(int64.high div 8) == "1023.999PiB"
802+
doAssert formatSize(int64.high div 16 + 1) == "512PiB"
803+
doAssert formatSize(int64.high div 16) == "511.999PiB"
804+
doAssert formatSize(0) == "0B"
805+
doAssert formatSize(0, includeSpace = true) == "0 B"
806+
doAssert formatSize(1) == "1B"
807+
doAssert formatSize(2) == "2B"
808+
doAssert formatSize(1022) == "1022B"
809+
doAssert formatSize(1023) == "1023B"
810+
doAssert formatSize(1024) == "1KiB"
811+
doAssert formatSize(1025) == "1.001KiB"
812+
doAssert formatSize(1026) == "1.002KiB"
813+
doAssert formatSize(1024 * 2 - 2) == "1.998KiB"
814+
doAssert formatSize(1024 * 2 - 1) == "1.999KiB"
815+
doAssert formatSize(1024 * 2) == "2KiB"
816+
doAssert formatSize(1024 * 2 + 1) == "2.001KiB"
817+
doAssert formatSize(1024 * 2 + 2) == "2.002KiB"
818+
doAssert formatSize(4096 - 1) == "3.999KiB"
794819
doAssert formatSize(4096) == "4KiB"
820+
doAssert formatSize(4096 + 1) == "4.001KiB"
821+
doAssert formatSize(1024 * 512 - 1) == "511.999KiB"
822+
doAssert formatSize(1024 * 512) == "512KiB"
823+
doAssert formatSize(1024 * 512 + 1) == "512.001KiB"
824+
doAssert formatSize(1024 * 1024 - 2) == "1023.998KiB"
825+
doAssert formatSize(1024 * 1024 - 1) == "1023.999KiB"
826+
doAssert formatSize(1024 * 1024) == "1MiB"
827+
doAssert formatSize(1024 * 1024 + 1) == "1MiB"
828+
doAssert formatSize(1024 * 1024 + 1023) == "1MiB"
829+
doAssert formatSize(1024 * 1024 + 1024) == "1.001MiB"
830+
doAssert formatSize(1024 * 1024 + 1024 * 2) == "1.002MiB"
831+
doAssert formatSize(1024 * 1024 * 2 - 1) == "1.999MiB"
832+
doAssert formatSize(1024 * 1024 * 2) == "2MiB"
833+
doAssert formatSize(1024 * 1024 * 2 + 1) == "2MiB"
834+
doAssert formatSize(1024 * 1024 * 2 + 1024) == "2.001MiB"
835+
doAssert formatSize(1024 * 1024 * 2 + 1024 * 2) == "2.002MiB"
836+
doAssert formatSize(1024 * 1024 * 4 - 1) == "3.999MiB"
837+
doAssert formatSize(1024 * 1024 * 4) == "4MiB"
838+
doAssert formatSize(1024 * (1024 * 4 + 1)) == "4.001MiB"
839+
doAssert formatSize(1024 * 1024 * 512 - 1025) == "511.998MiB"
840+
doAssert formatSize(1024 * 1024 * 512 - 1) == "511.999MiB"
841+
doAssert formatSize(1024 * 1024 * 512) == "512MiB"
842+
doAssert formatSize(1024 * 1024 * 512 + 1) == "512MiB"
843+
doAssert formatSize(1024 * 1024 * 512 + 1024) == "512.001MiB"
844+
doAssert formatSize(1024 * 1024 * 512 + 1024 * 2) == "512.002MiB"
845+
doAssert formatSize(1024 * 1024 * 1024 - 1) == "1023.999MiB"
846+
doAssert formatSize(1024 * 1024 * 1024) == "1GiB"
847+
doAssert formatSize(1024 * 1024 * 1024 + 1) == "1GiB"
848+
doAssert formatSize(1024 * 1024 * 1025) == "1.001GiB"
849+
doAssert formatSize(1024 * 1024 * 1026) == "1.002GiB"
850+
# != 2.234MiB as (2.234 * 1024 * 1024).int.float / (1024 * 1024) = 2.23399...
851+
# and formatSize round down the value
852+
doAssert formatSize((2.234*1024*1024).int) == "2.233MiB"
795853
doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
796854
doAssert formatSize(4096, includeSpace = true) == "4 KiB"
797-
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
855+
# (5378934).float / (1024 * 1024) = 5.12975...
856+
doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,129MB"
798857

799858
block: # formatEng
800859
disableVm:

0 commit comments

Comments
 (0)