From 603953376d997db76e2ed90f56c37bf449da236b Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 30 Aug 2026 16:16:08 +0200 Subject: [PATCH] IC: add `-d:icSymCount`, and use it to settle the full-compiler comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Counts every `newSym` mint, by kind, and reports on exit. A gensym's number is its item id, so ONE extra symbol anywhere shifts every later name in the generated C — which makes a mint count far more sensitive than diffing output, and localises a difference by symbol kind instead of by whichever file happened to show it. It was written to answer a question I had reported wrongly. Comparing the cursor-driven and `PNode`-driven builds over the whole compiler showed 3 of 215 `.c` files differing, and I attributed 2 of them to the compiler being nondeterministic. That control was invalid: I had compared two runs across an edit to `ccgexprs.nim`, so what I read as nondeterminism was line numbers moving inside assertion strings. The compiler is DETERMINISTIC — same binary, same source, twice, 0 of 215 differ. What the count establishes: the two builds mint exactly the same symbols, 515_551 of them, with no per-kind difference at all. So nothing in the cursor path creates or skips a symbol, and the earlier gensym-numbered differences — which had zero non-gensym lines — were ordering, not extra work. On the current tree the comparison is clean: cursor-driven and `PNode`-driven produce BYTE-IDENTICAL `.c` for all 215 files of `compiler/nim.nim`. I have not isolated why the same comparison showed 3 differences one commit earlier; the commit between was behaviour-neutral by inspection, so I am recording the observation rather than a claim about its cause. Verified: both build configurations compile; the diagnostic is behind a define and costs nothing otherwise. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01XEF7FJvUkGKvG9LSGuEaNR --- compiler/ast.nim | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/ast.nim b/compiler/ast.nim index 8b5d62237c..1a2e91e955 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -781,10 +781,28 @@ when false: echo k echo v +when defined(icSymCount): + import std / [syncio, exitprocs, tables as symCountTables] + var symMints*: symCountTables.CountTable[string] + var symMintTotal*: int + var symCountHooked = false + proc newSym*(symKind: TSymKind, name: PIdent, idgen: IdGenerator; owner: PSym, info: TLineInfo; options: TOptions = {}): PSym = # generates a symbol and initializes the hash field too assert not name.isNil + when defined(icSymCount): + # Counting symbol MINTS, not their names in the output: a gensym's number is + # its item id, so one extra symbol anywhere shifts every later name. A count + # is therefore far more sensitive than diffing generated C, and it localises + # the extra mint by kind instead of by whatever file happened to show it. + inc symMintTotal + symMints.inc $symKind + if not symCountHooked: + symCountHooked = true + addExitProc proc () = + stderr.writeLine "SYMMINT total=" & $symMintTotal + for k, v in symMints: stderr.writeLine "SYMMINT " & k & "=" & $v let id = nextSymId idgen result = PSym(name: name, kindImpl: symKind, flagsImpl: {}, infoImpl: info, itemId: id, optionsImpl: options, ownerFieldImpl: owner, offsetImpl: defaultOffset,