This commit is contained in:
araq
2025-12-05 17:14:32 +01:00
parent 8b99ee9930
commit 54d5535bf4
2 changed files with 104 additions and 107 deletions

View File

@@ -30,7 +30,10 @@ import ic / [cbackend, integrity, navigator, ic]
import ../dist/checksums/src/checksums/sha1
import pipelines, nifbackend
import pipelines
when not defined(nimKochBootstrap):
import nifbackend
when not defined(leanCompiler):
import docgen
@@ -137,14 +140,17 @@ proc commandNifC(graph: ModuleGraph) =
## Generate C code from precompiled NIF files.
## This is the new IC approach: compile modules to NIF first with `nim m`,
## then generate C code from the entry.nif file with whole-program DCE.
let conf = graph.config
extccomp.initVars(conf)
when not defined(nimKochBootstrap):
let conf = graph.config
extccomp.initVars(conf)
if not extccomp.ccHasSaneOverflow(conf):
conf.symbols.defineSymbol("nimEmulateOverflowChecks")
if not extccomp.ccHasSaneOverflow(conf):
conf.symbols.defineSymbol("nimEmulateOverflowChecks")
# Use the NIF backend to generate C code
nifbackend.generateCode(graph, conf.projectMainIdx)
# Use the NIF backend to generate C code
nifbackend.generateCode(graph, conf.projectMainIdx)
else:
rawMessage(graph.config, errGenerated, "NIF backend not available during bootstrap build")
proc commandCompileToC(graph: ModuleGraph) =
let conf = graph.config

View File

@@ -17,110 +17,101 @@
## 1. Compile modules to NIF: nim m mymodule.nim
## 2. Generate C from NIF: nim nifc myproject.nim
when defined(nimKochBootstrap):
# During bootstrap, NIF functionality is not available
import ".." / [ast, options, lineinfos, modulegraphs, pathutils, msgs]
import std/[intsets, tables, sets, os]
proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
when defined(nimPreviewSlimSystem):
import std/assertions
import ast, options, lineinfos, modulegraphs, cgendata, cgen,
pathutils, extccomp, msgs, modulepaths, idents, types, ast2nif
proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[PSym] =
## Traverse the module dependency graph using a stack.
## Returns all modules that need code generation, in dependency order.
var visited = initIntSet()
var stack: seq[FileIndex] = @[mainFileIdx]
var modules: seq[PSym] = @[]
var cachedModules: seq[FileIndex] = @[]
while stack.len > 0:
let fileIdx = stack.pop()
if visited.containsOrIncl(int(fileIdx)):
continue
# Load module from NIF
let module = moduleFromNifFile(g, fileIdx, cachedModules)
if module == nil:
continue
modules.add module
# Add dependencies to stack (they come from cachedModules)
for dep in cachedModules:
if not visited.contains(int(dep)):
stack.add dep
cachedModules.setLen(0)
result = modules
proc setupNifBackendModule(g: ModuleGraph; module: PSym): BModule =
## Set up a BModule for code generation from a NIF module.
if g.backend == nil:
g.backend = cgendata.newModuleList(g)
result = cgen.newModule(BModuleList(g.backend), module, g.config)
proc generateCodeForModule(g: ModuleGraph; module: PSym) =
## Generate C code for a single module.
let moduleId = module.position
var bmod = BModuleList(g.backend).modules[moduleId]
if bmod == nil:
bmod = setupNifBackendModule(g, module)
# Generate code for the module's top-level statements
if module.ast != nil:
cgen.genTopLevelStmt(bmod, module.ast)
# Finalize the module
finalCodegenActions(g, bmod, newNodeI(nkStmtList, module.info))
# Generate dispatcher methods
for disp in getDispatchers(g):
genProcAux(bmod, disp)
proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
## Main entry point for NIF-based C code generation.
## Traverses the module dependency graph and generates C code.
# Reset backend state
resetForBackend(g)
# Load all modules in dependency order using stack traversal
let modules = loadModuleDependencies(g, mainFileIdx)
if modules.len == 0:
rawMessage(g.config, errGenerated,
"NIF backend not available during bootstrap build")
"Cannot load NIF file for main module: " & toFullPath(g.config, mainFileIdx))
return
else:
import std/[intsets, tables, sets, os]
# Set up backend modules
for module in modules:
discard setupNifBackendModule(g, module)
when defined(nimPreviewSlimSystem):
import std/assertions
# Generate code for all modules except main (main goes last)
let mainModule = g.getModule(mainFileIdx)
for module in modules:
if module != mainModule:
generateCodeForModule(g, module)
import ast, options, lineinfos, modulegraphs, cgendata, cgen,
pathutils, extccomp, msgs, modulepaths, idents, types, ast2nif
# Generate main module last (so all init procs are registered)
if mainModule != nil:
generateCodeForModule(g, mainModule)
proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[PSym] =
## Traverse the module dependency graph using a stack.
## Returns all modules that need code generation, in dependency order.
var visited = initIntSet()
var stack: seq[FileIndex] = @[mainFileIdx]
var modules: seq[PSym] = @[]
var cachedModules: seq[FileIndex] = @[]
# Write C files
if g.backend != nil:
cgenWriteModules(g.backend, g.config)
while stack.len > 0:
let fileIdx = stack.pop()
if visited.containsOrIncl(int(fileIdx)):
continue
# Load module from NIF
let module = moduleFromNifFile(g, fileIdx, cachedModules)
if module == nil:
continue
modules.add module
# Add dependencies to stack (they come from cachedModules)
for dep in cachedModules:
if not visited.contains(int(dep)):
stack.add dep
cachedModules.setLen(0)
result = modules
proc setupNifBackendModule(g: ModuleGraph; module: PSym): BModule =
## Set up a BModule for code generation from a NIF module.
if g.backend == nil:
g.backend = cgendata.newModuleList(g)
result = cgen.newModule(BModuleList(g.backend), module, g.config)
proc generateCodeForModule(g: ModuleGraph; module: PSym) =
## Generate C code for a single module.
let moduleId = module.position
var bmod = BModuleList(g.backend).modules[moduleId]
if bmod == nil:
bmod = setupNifBackendModule(g, module)
# Generate code for the module's top-level statements
if module.ast != nil:
cgen.genTopLevelStmt(bmod, module.ast)
# Finalize the module
finalCodegenActions(g, bmod, newNodeI(nkStmtList, module.info))
# Generate dispatcher methods
for disp in getDispatchers(g):
genProcAux(bmod, disp)
proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
## Main entry point for NIF-based C code generation.
## Traverses the module dependency graph and generates C code.
# Reset backend state
resetForBackend(g)
# Load all modules in dependency order using stack traversal
let modules = loadModuleDependencies(g, mainFileIdx)
if modules.len == 0:
rawMessage(g.config, errGenerated,
"Cannot load NIF file for main module: " & toFullPath(g.config, mainFileIdx))
return
# Set up backend modules
for module in modules:
discard setupNifBackendModule(g, module)
# Generate code for all modules except main (main goes last)
let mainModule = g.getModule(mainFileIdx)
for module in modules:
if module != mainModule:
generateCodeForModule(g, module)
# Generate main module last (so all init procs are registered)
if mainModule != nil:
generateCodeForModule(g, mainModule)
# Write C files
if g.backend != nil:
cgenWriteModules(g.backend, g.config)
# Run C compiler
if g.config.cmd != cmdTcc:
extccomp.callCCompiler(g.config)
if not g.config.hcrOn:
extccomp.writeJsonBuildInstructions(g.config, g.cachedFiles)
# Run C compiler
if g.config.cmd != cmdTcc:
extccomp.callCCompiler(g.config)
if not g.config.hcrOn:
extccomp.writeJsonBuildInstructions(g.config, g.cachedFiles)