compiler/mir/mirtrees

    Dark Mode
Search:
  Source   Edit

This module contains the main definitions that make up the mid-end IR (MIR).

See MIR for the grammar plus a high-level overview of the MIR.

Types

AstId = distinct uint32
Identifies an AST fragment stored in the MIR environment.   Source   Edit
ConstId = distinct uint32
Identifies a constant across all MIR code. This includes both user-defined constants as well as anonymous constants   Source   Edit
DataId = distinct uint32
Identifies a complete constant expression   Source   Edit
EffectKind = enum
  ekNone,                   ## no effect
  ekMutate,                 ## the value in the location is mutated
  ekReassign,               ## a new value is assigned to the location
  ekKill, ## the value is removed from the location (without observing
           ## it), leaving the location empty
  ekInvalidate ## all knowledge and assumptions about the location and its
               ## value become outdated. The state of it is now completely
               ## unknown
  Source   Edit
GlobalId = distinct uint32
Identifies a global across all MIR code   Source   Edit
LabelId = distinct uint32
ID of a label, used to identify the control-flow destinations and constructs.   Source   Edit
LocalId = distinct uint32
Identifies a local inside a code fragment   Source   Edit
MirNode = object
  typ*: TypeId               ## valid for all expression, including all calls
  info*: SourceId ## non-critical meta-data associated with the node (e.g., origin
                  ## information)
  case kind*: MirNodeKind
  of mnkProc, mnkProcVal:
      prc*: ProcedureId

  of mnkGlobal:
      global*: GlobalId

  of mnkConst:
      cnst*: ConstId

  of mnkParam, mnkLocal, mnkTemp, mnkAlias:
      local*: LocalId

  of mnkField:
      field*: int32          ## field position
    
  of mnkIntLit, mnkUIntLit, mnkFloatLit:
      number*: NumberId

  of mnkStrLit:
      strVal*: StringId

  of mnkAstLit:
      ast*: AstId

  of mnkLabel, mnkLeave:
      label*: LabelId

  of mnkImmediate:
      imm*: uint32           ## meaning depends on the context
    
  of mnkMagic:
      magic*: TMagic

  of mnkNone, mnkNilLit, mnkType, mnkResume:
      nil

  of {low(MirNodeKind)..high(MirNodeKind)} - {mnkNone..mnkLeave}:
      len*: uint32

  
  Source   Edit
MirNodeKind = enum
  mnkNone, mnkProc,         ## procedure reference; only allowed in callee slots
  mnkProcVal,               ## procedural value
  mnkConst,                 ## named constant
  mnkGlobal,                ## global location
  mnkParam,                 ## parameter
  mnkLocal,                 ## local location
  mnkTemp, ## like ``mnkLocal``, but the local was introduced by the
            ## compiler during the MIR phase
  mnkAlias, ## local run-time handle. This is essentially a ``var T`` or
             ## ``lent T`` local
  mnkField,                 ## declarative node only allowed in special contexts
  mnkLabel,                 ## name of a label
  mnkNilLit,                ## nil literal
  mnkIntLit,                ## reference to signed integer literal
  mnkUIntLit,               ## reference to unsigend integer literal
  mnkFloatLit,              ## reference to float literal
  mnkStrLit,                ## reference to a literal string
  mnkAstLit,                ## reference to AST fragment
  mnkType,                  ## a type literal
  mnkImmediate, ## special node only allowed in certain contexts. Used to
                 ## store extra, context-dependent information in the tree
  mnkMagic, ## only allowed in a callee position. Refers to a magic
             ## procedure
  mnkResume,                ## special action in a target list that means "resume
                             ## exception handling in caller"
  mnkLeave,                 ## a leave action within a target list
  mnkTargetList, ## describes the actions to perform prior to jumping, as well
                  ## as the final jump
  mnkDef, ## marks the start of existence of a local, global, procedure,
           ## or temporary. Supports an optional intial value (except for
           ## procedure definitions)
  mnkDefCursor,             ## marks the start of existence of a non-owning location
  mnkBind, ## introduces an alias that may be used for read/write
            ## access, but not for direct assignments. The source
            ## expression must not be empty
  mnkBindMut, ## introduces an alias that may be used for read/write access
               ## and assignments. The source expression must not be empty
  mnkAsgn, ## normal assignment; the destination might store a value
            ## already. Whether the source is copied or moved depends
            ## on the expression
  mnkInit, ## similar to ``mnkAsgn``, but makes the guarantee that the
            ## destination contains no value (i.e., is not initialized).
            ## "Not initialized" doesn't make any guarantees about the
            ## destination's in-memory contents
  mnkSwitch, ## sets the value of a discriminator field, changing the active
              ## branch, if necessary. The destination operand must be a
              ## ``mnkPathVariant`` expression
  mnkPathNamed,             ## access of a named field in a record
  mnkPathPos,               ## access of a field in record via its position
  mnkPathArray, ## access of an array-like (both dynamic and static) value
                 ## with an integer index
  mnkPathVariant, ## access a tagged union
                   ## XXX: this is likely only a temporary solution. Each
                   ##      record-case part of an object should be its own
                   ##      dedicated object type, which can then be addressed
                   ##      as a normal field
  mnkPathConv, ## a handle conversion. That is, a conversion that produces a
                ## 
                ## *handle*, and not a new *value*. At present, this operator
                ## 
                ## also applies to first-class handles, like ``ref``.
  mnkAddr,                  ## create a pointer from the provided lvalue
  mnkDeref,                 ## dereference a ``ptr`` or ``ref`` value
  mnkView,                  ## create a first-class safe alias from an lvalue
  mnkMutView,               ## create a safe mutable view from an lvalue
  mnkDerefView,             ## dereference a first-class safe alias
  mnkStdConv,               ## a standard conversion. Produce a new value.
  mnkConv,                  ## ``conv(x)``; a conversion. Produces a new value.
  mnkCast,                  ## cast the representation of a value into a different type
  mnkToSlice, ## has to variants:
               ## * the 1 argument variant creates an openArray from the
               ##   full sequence specified as the operand
               ## * the 3 argument variant creates an openArray from the
               ##   sub-sequence specified by the sequence and lower and
               ##   upper bound
  mnkToMutSlice,            ## version of ``mnkToSlice`` for creating a mutable slice
  mnkCall, ## invoke a procedure and pass along the provided arguments.
            ## Used for both static and dynamic calls
  mnkCheckedCall,           ## invoke a magic procedure and pass along the provided arguments
  mnkNeg,                   ## signed integer and float negation (for ints, overflow is UB)
  mnkAdd,                   ## signed integer and float addition (for ints, overflow is UB)
  mnkSub,                   ## signed integer and float subtraction (for ints, overflow is UB)
  mnkMul, ## signed integer and float multiplication (for ints, overflow is
           ##  UB)
  mnkDiv, ## signed integer and float division (for ints, division by zero is
           ## UB)
  mnkModI, ## compute the remainder of an integer division (division by zero
            ## is UB)
  mnkRaise, ## if the operand is an ``mnkNone`` node, reraises the
             ## currently active exception. Otherwise, consumes the operand
             ## and sets it as the active exception
  mnkSetConstr,             ## constructor for set values
  mnkRange, ## range constructor. May only appear in set constructions
             ## and as a branch label
  mnkArrayConstr,           ## constructor for array values
  mnkSeqConstr,             ## constructor for seq values
  mnkTupleConstr,           ## constructor for tuple values
  mnkClosureConstr,         ## constructor for closure values
  mnkObjConstr,             ## constructor for object values
  mnkRefConstr,             ## allocates a new managed heap cell and initializes it
  mnkBinding, ## only valid as an object or ref construction child node.
               ## Associates an argument with a field
  mnkCopy,                  ## denotes the assignment as copying the source value
  mnkMove, ## denotes the assignment as moving the value. This does
            ## not imply a phyiscal change to the source location
  mnkSink, ## collapses into one of the following:
            ## - a copy (`mnkCopy`)
            ## - a non-destructive move (`mnkMove`)
            ## - a destructive move
            ## 
            ## Collapsing ``mnkSink`` is the responsibility of the move
            ## analyzer.
  mnkArg, ## when used in a call: denotes an argument that may either be
           ## passed by value or by name. Evaluation order is unspecified
           ## when used in a construction: denotes a value that is copied
           ## (shallow) into the aggregate value
  mnkName,                  ## denotes an argument that is passed by name
  mnkConsume, ## similar to ``mnkArg``, but moves (non-destructively) the
               ## value into the aggregate or parameter
  mnkVoid, ## either a:
            ## * syntactic statement node for representing void calls
            ## * statement acting as a use of the given lvalue
  mnkScope, ## starts a scope, which are used to delimit lifetime of locals
             ## they enclose. Can be nested, but must always be paired with
             ## exactly one ``mnkEndScope`` statement
  mnkEndScope, ## closes the current scope. Must always be paired with a
                ## ``mnkScope`` statement
  mnkGoto,                  ## unconditional jump
  mnkIf, ## depending on the run-time value of `x`, transfers control-
          ## flow to either the start or the end of the spanned code
  mnkCase, ## dispatches to one of its branches based on the run-time
            ## value of the operand
  mnkBranch,                ## a branch in a ``mnkCase`` dispatcher
  mnkLoop,                  ## unconditional jump to the associated-with loop start
  mnkJoin,                  ## join point for gotos and branches
  mnkLoopJoin,              ## join point for loops. Represents the start of a loop
  mnkExcept,                ## starts an exception handler
  mnkFinally, ## starts a finally section. Must be paired with exactly one
               ## ``mnkContinue`` that follows
  mnkContinue,              ## marks the end of a finally section
  mnkEndStruct,             ## marks the end of an if or except
  mnkDestroy, ## destroys the value stored in the given location, leaving the
               ## location in an undefined state
  mnkAsm,                   ## embeds backend-dependent code directly into the output
  mnkEmit                    ## embeds backend-dependent code directly into the output
Users of MirNodeKind should not depend on the absolute or relative order between the enum values   Source   Edit
MirNodeSeq = seq[MirNode]
A buffer of MIR nodes without any further meaning   Source   Edit
MirTree = seq[MirNode]
  Source   Edit
NodeIndex = uint32
  Source   Edit
NodePosition = distinct int32
refers to a MirNode of which the position relative to other nodes has meaning. Uses a signed integer as the base   Source   Edit
NumberId = distinct uint32
Uniquely identifies some numerical value (float, signed int, unsigned int). Two values with the same bit pattern have the same ID   Source   Edit
OpValue = distinct uint32
refers to an node appearing in an expression/operand position   Source   Edit
ProcedureId = distinct uint32
Identifies a procedure   Source   Edit
SourceId = distinct range[0'u32 .. high(uint32) - 1]
The ID of a source-mapping that's stored separately from the MIR nodes.   Source   Edit
StringId = distinct uint32
Uniquely identifies a string value. Two strings sharing the same content map to the same ID   Source   Edit
TypeId = distinct uint32
Identifies a type   Source   Edit

Consts

AllNodeKinds = {mnkNone..mnkEmit}
Convenience set containing all existing node kinds   Source   Edit
ArgumentNodes = {mnkArg, mnkName, mnkConsume}
Nodes only allowed in argument contexts.   Source   Edit
AtomNodes = {mnkNone..mnkLeave}
Nodes that don't support sub nodes.   Source   Edit
Atoms = {mnkNone, mnkProcVal..mnkAlias, mnkNilLit..mnkType}
Nodes that may be appear in atom-expecting slots.   Source   Edit
BinaryOps = {mnkAdd, mnkSub, mnkMul, mnkDiv, mnkModI}
All binary operators   Source   Edit
CallKinds = {mnkCall, mnkCheckedCall}
  Source   Edit
ConstrTreeNodes = {mnkProcVal, mnkField, mnkNilLit..mnkAstLit,
                   mnkSetConstr..mnkBinding, mnkArg}
Nodes that can appear in the MIR subset used for constant expressions.   Source   Edit
DefNodes = {mnkDef, mnkDefCursor, mnkBind, mnkBindMut}
Node kinds that represent definition statements (i.e. something that introduces a named entity)   Source   Edit
ExprKinds = {mnkProcVal..mnkAlias, mnkNilLit..mnkType, mnkPathNamed..mnkModI,
             mnkSetConstr, mnkArrayConstr..mnkRefConstr, mnkCopy..mnkSink}
  Source   Edit
LabelNodes = {mnkLabel, mnkLeave}
  Source   Edit
LiteralDataNodes = {mnkNilLit, mnkIntLit, mnkUIntLit, mnkFloatLit, mnkStrLit,
                    mnkAstLit}
  Source   Edit
LvalueExprKinds = {mnkPathPos, mnkPathNamed, mnkPathArray, mnkPathVariant,
                   mnkPathConv, mnkDeref, mnkDerefView, mnkTemp, mnkAlias,
                   mnkLocal, mnkParam, mnkConst, mnkGlobal}
  Source   Edit
ModifierNodes = {mnkCopy, mnkMove, mnkSink}
Assignment modifiers. Nodes that can only appear directly in the source slot of assignments.   Source   Edit
RvalueExprKinds = {mnkProcVal, mnkNilLit..mnkType, mnkAddr, mnkView..mnkMutView,
                   mnkStdConv..mnkToMutSlice, mnkNeg..mnkModI}
  Source   Edit
SingleOperandNodes = {mnkPathNamed, mnkPathPos, mnkPathVariant, mnkPathConv,
                      mnkAddr, mnkDeref, mnkView, mnkDerefView, mnkStdConv,
                      mnkConv, mnkCast, mnkRaise, mnkArg, mnkName, mnkConsume,
                      mnkVoid, mnkCopy, mnkMove, mnkSink, mnkDestroy,
                      mnkMutView, mnkToMutSlice}
Nodes that start sub-trees but that always have a single sub node.   Source   Edit
StmtNodes = {mnkDef..mnkSwitch, mnkRaise, mnkVoid..mnkCase, mnkLoop..mnkEmit}
Nodes that are treated like statements, in terms of syntax.   Source   Edit
SubTreeNodes = {mnkTargetList..mnkEmit}
Nodes that start a sub-tree. They always store a length.   Source   Edit
UnaryOps = {mnkNeg}
All unary operators   Source   Edit

Procs

func `<=`(a, b: NodePosition): bool {.borrow, inline, ...raises: [], tags: [].}
  Source   Edit
func `<`(a, b: NodePosition): bool {.borrow, inline, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: AstId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: ConstId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: DataId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: GlobalId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: LabelId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: LocalId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: NodePosition): bool {.borrow, inline, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: NumberId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: ProcedureId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: SourceId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: StringId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `==`(a, b: TypeId): bool {.borrow, ...raises: [], tags: [].}
  Source   Edit
func `[]`(tree: MirTree; n: NodePosition; index: Natural): lent MirNode {.
    ...raises: [], tags: [].}
  Source   Edit
func `[]`(tree: MirTree; n: OpValue; index: Natural): lent MirNode {....raises: [],
    tags: [].}
  Source   Edit
func `in`(p: NodePosition; tree: MirTree): bool {.inline, ...raises: [], tags: [].}
  Source   Edit
func argument(tree: MirTree; n: NodePosition; i: Natural): OpValue {....raises: [],
    tags: [].}
Returns the i-th argument in the call-like tree at n, skipping tag nodes. It is expected that the call has at least i + 1 arguments.   Source   Edit
func callee(tree: MirTree; n: NodePosition): NodePosition {.inline, ...raises: [],
    tags: [].}
Returns the callee node for the call subtree n.   Source   Edit
func child(tree: MirTree; n: NodePosition; index: Natural): NodePosition {.
    ...raises: [], tags: [].}
Returns the position of the child node at index index. index must refer to a valid sub-node -- no validation is performed   Source   Edit
func computeSpan(tree: MirTree; n: NodePosition): Slice[NodePosition] {.
    ...raises: [], tags: [].}
If n refers to a leaf node, returns a span with the n as the single item. Otherwise, computes and returns the span of nodes part of the sub-tree at n. The 'end' node is included.   Source   Edit
func effect(tree: MirTree; n: NodePosition): EffectKind {.inline, ...raises: [],
    tags: [].}
Returns the effect for the mnkName node at n.   Source   Edit
func extract(id: ConstId): DataId {....raises: [], tags: [].}
Extracts the DataId from id.   Source   Edit
func field(tree: MirTree; n: NodePosition): int32 {.inline, ...raises: [], tags: [].}
Returns the field position specified for the field access at n.   Source   Edit
func findDef(tree: MirTree; n: NodePosition): NodePosition {....raises: [],
    tags: [].}
Finds and returns the first definition for the name of the temporary at node n. No control-flow analysis is performed.   Source   Edit
func findParent(tree: MirTree; start: NodePosition; kind: MirNodeKind): NodePosition {.
    ...raises: [], tags: [].}
Searches for the first enclosing sub-tree node of kind kind (which is required to exist). The node at start is itself also considered during the search   Source   Edit
func isAnon(id: ConstId): bool {....raises: [], tags: [].}
Returns whether id represents an anonymous constant.   Source   Edit
func last(tree: MirTree; n: NodePosition): NodePosition {....raises: [], tags: [].}
Returns the last child node in the subtree at n.   Source   Edit
func len(tree: MirTree; n: NodePosition): int {....raises: [], tags: [].}
Computes the number of child nodes for the given sub-tree node.   Source   Edit
proc mutatesGlobal(tree: MirTree; n: NodePosition): bool {.inline, ...raises: [],
    tags: [].}
Whether evaluating the call expression at n potentially mutates global state.   Source   Edit
func numArgs(tree: MirTree; n: NodePosition): int {....raises: [], tags: [].}
Counts and returns the number of call arguments in the call tree at n.   Source   Edit
func operand(tree: MirTree; n: NodePosition; i: Natural): OpValue {.inline,
    ...raises: [], tags: [].}
Returns the i-th operand to the sub-tree at n. It is expected that the operation has at least i + 1 operands.   Source   Edit
func operand(tree: MirTree; op: OpValue | NodePosition): OpValue
Returns the index (OpValue) of the operand for the single-operand operation at op.   Source   Edit
func parent(tree: MirTree; n: NodePosition): NodePosition {....raises: [], tags: [].}
  Source   Edit
func previous(tree: MirTree; n: NodePosition): NodePosition {....raises: [],
    tags: [].}
Computes the index of n's the preceding sibling node. If there is none, returns the index of the parent node. This is a slow operation, it should be used sparsely.   Source   Edit
func sibling(tree: MirTree; n: NodePosition): NodePosition {....raises: [],
    tags: [].}
Computes the index of the next node/sub-tree following the node at n.   Source   Edit
func skip(tree: MirTree; n: OpValue; kind: MirNodeKind): OpValue {....raises: [],
    tags: [].}
If n is of kind, return its operand node, n otherwise.   Source   Edit
func toConstId(id: DataId): ConstId {....raises: [], tags: [].}
Creates the ID for an anonymous constant with id as the content.   Source   Edit

Iterators

iterator arguments(tree: MirTree; n: NodePosition): (ArgKinds, EffectKind,
    OpValue) {....raises: [], tags: [].}
Returns the argument kinds together with the operand node (or tag tree).   Source   Edit
iterator lpairs[T](x: seq[T]): (int, lent T)
  Source   Edit
iterator pairs(tree: MirTree): (NodePosition, lent MirNode) {....raises: [],
    tags: [].}
  Source   Edit
iterator subNodes(tree: MirTree; n: NodePosition; start = 0): NodePosition {.
    ...raises: [], tags: [].}
Returns in order of apperance all direct child nodes of n, starting with start.   Source   Edit

Templates

template `+`(a: NodePosition; b: int): NodePosition
  Source   Edit
template `-`(a: NodePosition; b: int): NodePosition
  Source   Edit
template `[]`(tree: MirTree; i: NodePosition | OpValue): untyped
  Source   Edit
template dec(a: var NodePosition)
  Source   Edit
template inc(a: var NodePosition)
  Source   Edit
template indexLike(_: typedesc[SourceId])
  Source   Edit