mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-11 17:45:25 +00:00
progress
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user