mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 19:33:42 +00:00
IC: stop baking a compile command the process cannot know
Every generated `.c` carries a "Command for C compiler" comment built
from `conf.compileOptions`. Under the per-module backend that is a lie,
and a non-deterministic one.
A global `{.passC.}` — system's `-pthread`, say — reaches
`conf.compileOptions` only in a process that compiled the module
declaring it, and a `cg` process sees one module's import closure. So
the command each `.c` records is a partial snapshot, and WHICH part
depends on how modules were grouped into processes. Measured on a
67-module program: 2 of 67 `.c` carried `-pthread` at batch size 1, 4 at
size 4, 5 at size 8 — against 16 of 16 for a whole-program `nim c`.
The object files were never affected: the `link` stage applies every
module's recorded directives (`replayer.applyBackendActions`) before
compiling anything. Only the comment was wrong. But it is also the reason
two `.c` files differed between batch sizes for no reason of their own,
which makes it noise in the one oracle that matters here — the final `.c`
set.
So under `--icBackendStage` the line says where the command actually
comes from instead of guessing at it. Whole-program `nim c` is untouched:
byte-identical `.c`, and it still prints the real command, which there it
genuinely knows.
ic 40/40, `koch boot -d:release` equal executables.
This commit is contained in:
@@ -2592,12 +2592,27 @@ proc headerTop(): Rope =
|
||||
proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope =
|
||||
result = headerTop()
|
||||
if optCompileOnly notin conf.globalOptions:
|
||||
result.add ("/* Compiled for: $1, $2, $3 */$N" &
|
||||
"/* Command for C compiler:$n $4 */$N") %
|
||||
result.add ("/* Compiled for: $1, $2, $3 */$N") %
|
||||
[rope(platform.OS[conf.target.targetOS].name),
|
||||
rope(platform.CPU[conf.target.targetCPU].name),
|
||||
rope(extccomp.CC[conf.cCompiler].name),
|
||||
rope(getCompileCFileCmd(conf, cfile))]
|
||||
rope(extccomp.CC[conf.cCompiler].name)]
|
||||
# The per-module IC backend cannot write this line truthfully. A global
|
||||
# `{.passC.}` (system's `-pthread`, say) reaches `conf.compileOptions` only
|
||||
# in a process that compiled the module declaring it, and a `cg` process
|
||||
# sees one module's import closure — so the command it would print is a
|
||||
# partial snapshot, and WHICH part depends on how modules were grouped into
|
||||
# processes. Measured on a 67-module program: 2 of 67 `.c` carried
|
||||
# `-pthread` at batch size 1, 4 at size 4, 5 at size 8, against 16 of 16 for
|
||||
# a whole-program `nim c`. The real command is assembled by the `link`
|
||||
# stage, which applies every module's recorded directives first
|
||||
# (`replayer.applyBackendActions`) — so the object files were always
|
||||
# correct; only this comment was wrong, and non-deterministically so.
|
||||
if conf.cmd == cmdNifC and conf.icBackendStage.len > 0:
|
||||
result.add "/* Command for C compiler: assembled by the link stage\L" &
|
||||
" from every module's recorded C directives. */\L"
|
||||
else:
|
||||
result.add ("/* Command for C compiler:$n $1 */$N") %
|
||||
[rope(getCompileCFileCmd(conf, cfile))]
|
||||
|
||||
proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
|
||||
var res = newBuilder(getCopyright(conf, cfile))
|
||||
|
||||
Reference in New Issue
Block a user