vmlayout

Source   Edit  

Memory layout of Nim types inside the VM. The VM works on "packed data": values are laid out exactly like the C backend lays them out, except that the host ABI is used (64 bit pointers and int), regardless of the target. sizeof & co are folded by sem using the target's layout; this module is only about how the VM itself stores values.

Differences to the C backend's layout:

  • NimNode, typedesc, typed and untyped values are NimNode handles stored in a pointer sized slot. A typedesc is represented as a nkType node.
  • Proc values are proc handles stored in a pointer sized slot; closures are (procHandle, env).
  • Fields with a bitsize are not packed into bit fields.
  • Zero length arrays occupy no storage.
  • Imported, incomplete structs are laid out from their declared fields.

Types

LayoutCache = object
Source   Edit  
MemKind = enum
  mkBlock,                  ## not a scalar: copied as a block of bytes
  mkI8, mkI16, mkI32, mkI64, mkU8, mkU16, mkU32, mkU64, mkF32, mkF64, mkPtr, ## pointer sized: ptr, ref, cstring, proc, handles
  mkNode                     ## a NimNode/typedesc handle
how a scalar is stored in memory; temporaries in the VM's registers are always widened to 64 bits. Source   Edit  
VmLayout = object
  size*: int
  align*: int
  fields*: seq[int]          ## objects: offset of the field with `position` i;
                             ## tuples: offset of the i-th element
Source   Edit  

Consts

BoxThreshold = 65536
a value bigger than this is held by its address in registers, see isBig Source   Edit  
FloatMemKinds = {mkF32, mkF64}
Source   Edit  
PayloadCapOffset = 0
cap field of a string or seq payload Source   Edit  
PayloadDataOffset = 8
first element of a string or seq payload Source   Edit  
ScalarMemKinds = {mkI8..mkNode}
Source   Edit  
SignedMemKinds = {mkI8..mkI64}
Source   Edit  
StrLenOffset = 0
len field of a string or seq Source   Edit  
StrPayloadOffset = 8
p field of a string or seq Source   Edit  
TypeHeaderSize = 8
size of the type field of an inheritable object Source   Edit  
UnsignedMemKinds = {mkU8..mkU64}
Source   Edit  
VmMaxAlign = 8
Source   Edit  
VmPtrSize = 8
size of a pointer, int, a handle in the VM Source   Edit  

Procs

proc alignTo(address, alignment: int): int {.inline, ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc elemOffset(c: var LayoutCache; conf: ConfigRef; tupType: PType; i: int): int {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
Byte offset of the i-th element of a tuple. Source   Edit  
proc elemSize(c: var LayoutCache; conf: ConfigRef; t: PType): int {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
Element size of an array-like type (array, seq, string, openArray, ...). Source   Edit  
proc fieldOffset(c: var LayoutCache; conf: ConfigRef; objType: PType;
                 field: PSym): int {....raises: [KeyError, OSError, Exception,
    ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect, ReadIOEffect,
    ReadDirEffect, RootEffect, WriteIOEffect], forbids: [].}
Byte offset of field within an object or named tuple of type objType. Source   Edit  
proc getLayout(c: var LayoutCache; conf: ConfigRef; t: PType): VmLayout {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
Source   Edit  
proc hasPayloads(t: PType): bool {....raises: [KeyError, OSError, Exception,
    ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect],
                                   forbids: [].}
Source   Edit  
proc hasTypeHeader(t: PType): bool {....raises: [KeyError, OSError, Exception,
    ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect],
                                     forbids: [].}
Inheritable root objects (RootObj and friends) start with a type field. Source   Edit  
proc isBig(c: var LayoutCache; conf: ConfigRef; t: PType): bool {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
a big value is not stored in registers: its register holds the address of the value instead. Results and parameters are passed by address then. Source   Edit  
proc memKind(conf: ConfigRef; t: PType): MemKind {....raises: [KeyError, OSError,
    Exception, ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect,
    ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect], forbids: [].}
How a value of type t is loaded from/stored to memory. Source   Edit  
proc memKindSize(k: MemKind): int {....raises: [], tags: [], forbids: [].}
Source   Edit  
proc setSize(conf: ConfigRef; t: PType): int {....raises: [KeyError, OSError,
    Exception, ValueError, IOError, ERecoverableError], tags: [ReadEnvEffect,
    ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect], forbids: [].}
Size of a set type in bytes. Sets of up to 64 elements are stored as an integer of the smallest fitting size, larger sets as a byte array. Invalid set types (with too many elements) have the size 0. Source   Edit  
proc skipForLayout(t: PType): PType {....raises: [KeyError, OSError, Exception,
    ValueError], tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect],
                                      forbids: [].}
Source   Edit  
proc vmAlignOf(c: var LayoutCache; conf: ConfigRef; t: PType): int {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
Source   Edit  
proc vmSizeOf(c: var LayoutCache; conf: ConfigRef; t: PType): int {....raises: [
    KeyError, OSError, Exception, ValueError, IOError, ERecoverableError], tags: [
    ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect, WriteIOEffect],
    forbids: [].}
Source   Edit