From 54d5535bf4cdac81f4587d1161f43bf8f2bfa557 Mon Sep 17 00:00:00 2001 From: araq Date: Fri, 5 Dec 2025 17:14:32 +0100 Subject: [PATCH] progress --- compiler/main.nim | 20 +++-- compiler/nifbackend.nim | 191 +++++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 107 deletions(-) diff --git a/compiler/main.nim b/compiler/main.nim index 8a7a4c83e5..7321cb64fd 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -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 diff --git a/compiler/nifbackend.nim b/compiler/nifbackend.nim index 7edcb19244..6cf07c423d 100644 --- a/compiler/nifbackend.nim +++ b/compiler/nifbackend.nim @@ -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)