This module implements the C code generator.This include file contains the logic to produce constant string and seq literals. The code here is responsible that const x = ["a", "b"] works without hidden runtime creation code. The price is that seqs and strings are not purely a library implementation.Generates traversal procs for the C backend.Code specialization instead of the old, incredibly slow 'genericReset' implementation.Thread var support for architectures that lack native support for thread local storage.
Imports
-
ast, astalgo, trees, platform, magicsys, extccomp, options, nversion, nimsets, msgs, bitsets, idents, types, ccgutils, ropes, wordrecg, treetab, cgmeth, rodutils, renderer, cgendata, aliases, lowerings, lineinfos, pathutils, transf, injectdestructors, astmsgs, modulepaths, pushpoppragmas, mangleutils, cbuilderbase, modulegraphs, icprof, expanddefaults, ast2nif, typekeys, cnif, pipelineutils, spawn, semparallel, sighashes, aliasanalysis, parampatterns
Procs
proc cgenWriteModules(backend: RootRef; config: ConfigRef) {....raises: [KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect, WriteDirEffect], forbids: [].}
- Source Edit
proc fillObjectFields(m: BModule; typ: PType) {....raises: [Exception, ValueError, OSError, KeyError, IOError, ERecoverableError], tags: [RootEffect, ReadDirEffect, WriteIOEffect, ReadIOEffect, ReadEnvEffect], forbids: [].}
- Source Edit
proc finalCodegenActions(graph: ModuleGraph; m: BModule; n: PNode) {....raises: [ KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Also called from IC. Source Edit
proc genIcModuleDestroyGlobals(graph: ModuleGraph; m: BModule): string {....raises: [ KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
-
Per-module backend (cg stage), non-main module: wrap this module's accumulated top-level global destructors in a nullary exported proc and return its C name ("" when there are none).
graph.globalDestructors is filled while a module's own cg process injects destructors into its top level, but the teardown code is emitted by the MAIN module's cg — a different process, whose graph only ever sees its own entries. So each module emits its own teardown here and records the name in its .c.nif meta head; the main module's cg reads the heads (like it already does for init/datInit) and calls them.
Source Edit proc genProcLvl3(m: BModule; prc: PSym) {....raises: [KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Source Edit
proc genTopLevelStmt(m: BModule; n: PNode) {....raises: [KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Also called from ic/cbackend.nim. Source Edit
proc getCFile(m: BModule): AbsoluteFile {. ...raises: [KeyError, OSError, Exception, ValueError, IOError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteDirEffect], forbids: [].}
- Source Edit
proc getSomeNameForModule(m: BModule): Rope {. ...raises: [KeyError, OSError, Exception, ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
- Returns a mangled module name. Source Edit
proc multiFormat(frmt: var string; chars: static openArray[char]; args: openArray[seq[string]])
- Source Edit
proc newModule(g: BModuleList; module: PSym; conf: ConfigRef; idgen: IdGenerator): BModule {. ...raises: [KeyError, OSError, Exception, ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
- Source Edit
proc ownsRuntimeRoutine(s: PSym; modPos: int): bool {. ...raises: [KeyError, OSError, Exception, ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
-
A concrete, non-generic, runtime routine with a real body, OWNED by the module at modPos. Shared by the cg stage's owned-routine seeding (so a routine called only from other modules is still emitted by somebody) and the lower stage's owned-routine enumeration, so both stages see exactly the same set. The exclusions:
- nested/closure procs (owner is a proc, not a module): emitted via their enclosing routine's lambda-lifting, never standalone;
- generic instances (sfFromGeneric): emitted by demand, deduped by merge;
- importc/compileTime/error/forward sentinels and meta signatures: not real codegen targets.
- method DISPATCHERS (sfDispatcher): their bodies are (re)synthesized into the main TU by emitMethodDispatchers/generateIfMethodDispatchers, never per module. A dispatcher is a copySym clone of the method that shares the method's body sub-tree (incl. its closure iterator); transforming it here would lambda-lift that SHARED iterator a SECOND time under a different owner identity, baking a conflicting up field → "up references do not agree" (the divergence is impossible in non-IC, where the dispatcher body is empty at lift time). So a dispatcher is never an owned runtime routine.
A {.closure.} iterator IS a standalone runtime routine (unlike an inline iterator, which is expanded at each call site) and must be emitted by its owner — else a cross-module for over it links to nothing.
Generic INSTANCES (sfFromGeneric) are NEVER an owned runtime routine — not in cg and not in the lower stage. They are demanded by the backend's emit-everywhere path and deduped by merge (content C name); the frontend materialises them through the (offer) mechanism. The lower stage must not transform an instance: a not-fully-concrete instance (a closure factory over a static param, or a $/= op instance whose body resolves only at its further-specialised use sites) still carries unresolved overload choices and crashes transformBody (empty-namePos lambda, nil-typed const-fold).
Source Edit proc registerReusedModuleToMain(g: BModuleList; m: BModule; initRequired, datInitRequired: bool) {....raises: [ KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect], forbids: [].}
- registerModuleToMain for a module whose cached translation unit is reused: the init/datInit presence comes from the artifact's meta head instead of the (never generated) sections. Mirrors the non-hcr path of registerModuleToMain — reuse is disabled when hcr is on. Source Edit
proc requestProcDef(m: BModule; prc: PSym) {....raises: [KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Public demand entry: request prc's definition; it is routed to the module that owns it and generated once, exactly as if some generated code had referenced it. Source Edit
proc setupCgen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {. ...raises: [KeyError, OSError, Exception, ValueError, IOError], tags: [ ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteDirEffect], forbids: [].}
- Source Edit
proc signatureHasMetaType(t: PType; depth: int = 0): bool {. ...raises: [KeyError, OSError, Exception, ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}
- Whether a routine signature mentions a compile-time/meta element type (typed/untyped — e.g. echo's varargs[typed] — typedesc, static, generic param). Such routines are expanded at their call sites and never emitted standalone, so the per-module owned-routine seeding must skip them (getTypeDescAux(tyTyped) otherwise). tfHasMeta alone misses the varargs element case, hence the explicit scan. Source Edit
Templates
template cgDeclFrmt(s: PSym): string
- Source Edit