Shared processing logic used by all backends.
Imports
-
../ast/ast, ../ast/idents, ../ast/lineinfos, cgmeth, cgir, cgirgen, ../front/msgs, ../front/options, ../mir/datatables, ../mir/injecthooks, ../mir/mirbodies, ../mir/mirbridge, ../mir/mirchangesets, ../mir/mirconstr, ../mir/mirenv, ../mir/mirgen, ../mir/mirpasses, ../mir/mirtrees, ../mir/mirtypes, ../mir/sourcemaps, ../mir/utils, ../modules/modulegraphs, ../modules/magicsys, ../sem/injectdestructors, ../sem/modulelowering, ../sem/transf, ../sem/varpartitions, ../utils/containers, ../utils/idioms
Types
BackendConfig = object tconfig*: TranslationConfig ## passed on to ``mirgen``. See ``mirgen.generateCode`` for more ## details noImported*: bool ## if ``true``, indicates that a procedure with a body should not be ## treated as imported, even if it's marked as such
- Configuration state altering the operation of the process iterator. Source Edit
BackendEvent = object module*: FileIndex ## the module in whose context the processing happens. For actions ## related to .inline procedures, this is not necessarily the module ## the symbol is attached to case kind*: BackendEventKind of bekDiscovered: entity*: MirNode ## a reference to the discovered entity of bekModule: nil of bekConstant: cnst*: ConstId ## the ID of the constant of bekPartial, bekProcedure, bekImported: id*: ProcedureId ## the ID of the procedure sym*: PSym ## the symbol of the procedure the event is about ## XXX: only here for convenience, remove it once feasible body*: MirBody
- Progress event returned by the process iterator. Source Edit
BackendEventKind = enum bekDiscovered, ## a new entity was discovered during MIR processing. This ## ## event is meant to be used for pre-processing of symbols ## and ## registration with the code generators -- the ## environment must not be modified during processing of ## this event bekModule, ## the initial set of alive entities for a module was ## discovered bekConstant, ## a complete constant was processed and transformed bekPartial, ## a fragment of a procedure that's generated incrementally ## became ## available bekProcedure, ## a complete procedure was processed and transformed bekImported ## an alive runtime-imported procedure finished processing
- Source Edit
DiscoveryData = object progress: EnvCheckpoint ## tracks how much of the environment was already processed (e.g., ## translated, scanned, etc.) libs*: seq[LibId] ## all dynamic libraries that the alive graph depends on overrides: Table[ProcedureId, FileIndex] ## maps a procedure to the module it needs to be queued with. ## If not overriden, a procedure is queued with the module it's ## discovered from.
- Bundles all data needed during the disovery of alive, backend-relevant entities. Source Edit
Procs
func discoverFrom(env: var MirEnv; decl: PNode) {....raises: [], tags: [].}
- Updates env with all not-yet-seen entities from the list of declarative statements (decl). Source Edit
proc generateIR(graph: ModuleGraph; idgen: IdGenerator; env: var MirEnv; owner: PSym; body: sink MirBody): Body {. ...raises: [Exception, KeyError, ValueError, ERecoverableError], tags: [RootEffect, ReadDirEffect].}
- Translates the MIR code provided by code into CgNode IR and, if enabled, echoes the result. Source Edit
proc generateMain(graph: ModuleGraph; modules: ModuleList; result: PNode) {. ...raises: [KeyError, Exception], tags: [ReadDirEffect, RootEffect].}
- Generates the program initialization code and emits it to result. The initialization logic is the code that invokes each module's init procedures. Source Edit
proc generateMainProcedure(graph: ModuleGraph; idgen: IdGenerator; modules: ModuleList): PSym {. ...raises: [KeyError, Exception], tags: [ReadDirEffect, RootEffect].}
- Generates the procedure for initializing, running, and de-initializing the full program (modules). The procedure returns the value of the internal programResult global. Source Edit
proc generateTeardown(graph: ModuleGraph; modules: ModuleList; result: PNode) {. ...raises: [KeyError, Exception], tags: [ReadDirEffect, RootEffect].}
- Generates the code for de-initializing the program, and emits it to result. Source Edit
proc generateThreadTeardown(graph: ModuleGraph; modules: ModuleList; result: PNode) {....raises: [KeyError, Exception], tags: [ReadDirEffect, RootEffect].}
- Generates the code for de-initializing all threadvars for the program, and emits it to result. Destruction order is the same as for non- threadlocal state. Source Edit
func isEmpty(tree: MirTree): bool {....raises: [], tags: [].}
- Returns whether tree contains either no nodes or only nodes that have no meaning by themselves. Source Edit
func moduleId(o: PIdObj): int32 {.inline, ...raises: [], tags: [].}
- Returns the ID of the module o is attached to. Do note that in the case of generic instantiations, this is not the necessarily the same module as the one indicated via the owner. Source Edit
proc preprocess(queue: var WorkQueue; graph: ModuleGraph; idgen: IdGenerator; env: MirEnv; id: ProcedureId; module: FileIndex) {. ...raises: [KeyError, Exception, ERecoverableError, ValueError], tags: [ReadDirEffect, RootEffect].}
- Runs the transf pass on the body of prc and queues the steps needed for fully processing the procedure. module is the module the step was queued from: it's used as the module the next processing is queued from. Source Edit
func setModuleOverride(discovery: var DiscoveryData; id: ProcedureId; module: FileIndex) {....raises: [], tags: [].}
- Overrides which module the procedure identified by id will be reported as having been first seen with. This only works with procedures that haven't been queued for code generation yet. It's also fundamentally a workaround, try to use it as little as possible. Source Edit
proc translate(id: ProcedureId; body: PNode; graph: ModuleGraph; config: BackendConfig; idgen: IdGenerator; env: var MirEnv): MirBody {. ...raises: [Exception, ERecoverableError, KeyError, ValueError, IOError], tags: [RootEffect, ReadDirEffect, WriteIOEffect].}
- Translates body to MIR code, applies all applicable MIR passes, and returns the result. id is the ID of the procedure the fragment belongs to. Source Edit
Iterators
iterator deps(tree: MirTree): lent MirNode {....raises: [], tags: [].}
- Returns all external entities (procedures, globals, etc.) that tree references directly, in an unspecified order. Source Edit
iterator discover(env: var MirEnv; progress: EnvCheckpoint): tuple[s: PSym, n: MirNode] {....raises: [Exception, ERecoverableError, KeyError], tags: [RootEffect, ReadDirEffect].}
-
Returns all entities - in an unspecified order - added to env since the progress checkpoint was created. Procedures referenced from constants also added to the environment and returned.
This iterator is meant for a manual implementation of the backend processing -- don't use it in conjunction with the process iterator.
Source Edit iterator process(graph: ModuleGraph; modules: var ModuleList; env: var MirEnv; discovery: var DiscoveryData; conf: BackendConfig): BackendEvent {. ...raises: [Exception, KeyError, ERecoverableError, ValueError, IOError], tags: [RootEffect, ReadDirEffect, WriteIOEffect].}
-
Implements discovery of alive entities (procedures, globals, constants, etc.) and applying the various transformations and MIR passes to the alive procedures. Progress is reported by returning an event (refer to BackendEventKind for more informations about the events).
The iterator is complex and contains multiple yield statements, so it's advised to implement BackendEvent processing with a dedicated procedure.
At the callsite, no new entities must be registered with discovery during processing of a bekDiscovered event.
Source Edit