cgen

Source   Edit  

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.

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 genTypeInfo(config: ConfigRef; m: BModule; t: PType; info: TLineInfo): Rope {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
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