compiler/mir/mirgen_blocks

  Source   Edit

Subordinate module to mirgen. Implements the block and scope management required for translating the AST's high-level control-flow constructs to the MIR's goto-based ones. Injecting mnkDestroy operations is also implemented here, integrated with the scope management.

Types

Block = object
  id*: Option[LabelId] ## the block's label. Initialized on-demand, meaning that 'none'
                       ## indicates that the block is unused
  case kind*: BlockKind
  of bkBlock:
      label*: PSym           ## the symbol of the block's label. nil if it's an internal block
    
  of bkScope:
      numRegistered: int     ## number of entities registered for the scope in the to-destroy list
      scopeExits: seq[LabelId] ## unordered set of follow-up targets
    
  of bkTryFinally:
      doesntExit*: bool      ## whether structured control-flow doesn't reach the end of the finally
      errorOnly*: bool       ## whether only exceptional control-flow is intercepted
      exits*: seq[LabelId]   ## unordered set of follow-up targets
    
  of bkTryExcept, bkFinally, bkExcept:
      nil

  
Information about a block-like structure. This not only includes |NimSkull| blocks, but also try, finally, etc.   Source   Edit
BlockCtx = object
  blocks: seq[Block]         ## stack of enclosing try, finally, etc. blocks
  toDestroy: seq[tuple[entity: Value, label: Option[LabelId]]] ## all locals/globals/temporaries that need destruction, together
                                                               ## with the label of the finally that the destroy operation is part
                                                               ## of. Only the items where the `label` changes have an initialized
                                                               ## label
  currScope: int             ## block index of the current scope
  
Per-procedure block-related state.   Source   Edit
BlockKind = enum
  bkBlock, bkScope, bkTryExcept, bkTryFinally, bkFinally, bkExcept
  Source   Edit

Procs

proc blockExit(c; bu; targetBlock: int) {....raises: [], tags: [].}
Emits the jump target description for a jump to targetBlock.   Source   Edit
proc closeBlock(c; bu): bool {....raises: [], tags: [].}
Finishes the current block. If required for the block (because it is a block and broken out of), emits a join and returns true, false otherwise.   Source   Edit
proc closeScope(c; bu; nextScope: int; hasStructuredExit: bool) {....raises: [],
    tags: [].}

Pops the scope from the stack and emits the scope exit actions. hasStructuredExit tells whether structured control-flow reaches the end of the scope, affecting how the exit looks like.

next is the index of the scope index returns by the previous startScope call.

  Source   Edit
proc closest(c: BlockCtx): int {....raises: [], tags: [].}
Returns the index of the closest block.   Source   Edit
proc earlyExit(c; bu) {....raises: [], tags: [].}
Emits the destroy operations for when structured control-flow reaches the current scope's end. All entities for which a destroy operation is emitted are unregistered already.   Source   Edit
proc findBlock(c: BlockCtx; label: PSym): int {....raises: [], tags: [].}
Returns the index of the block with label label.   Source   Edit
proc labelNode(label: LabelId): MirNode {....raises: [], tags: [].}
  Source   Edit
proc raiseExit(c; bu) {....raises: [], tags: [].}
Emits the jump target description for a jump to the nearest enclosing exception handler.   Source   Edit
func register(c; loc: Value) {....raises: [], tags: [].}
Registers loc for destruction at the end of the current scope. Destruction happens in the reverse order the locations are registered in.   Source   Edit
proc startScope(c): int {....raises: [], tags: [].}
Starts a new scope and returns the index of the previous one.   Source   Edit

Templates

template add(c: var BlockCtx; b: Block)
  Source   Edit
template pop(c: var BlockCtx): Block
  Source   Edit