This module contains the type definitions for the evaluation engine. It is a register based VM that works on "packed data": values are laid out in memory like the C backend lays them out (see vmlayout), all VM memory is managed by vmmem.
Registers are 8 byte slots of the current stack frame; register i lives at the frame pointer + 8*i. A scalar (integer, float, pointer, handle) that is held in a register is always widened to 64 bits; an aggregate value (object, tuple, array, string, seq, closure, ...) that is held in registers occupies ceil(size/8) consecutive slots and uses the packed memory layout. Memory outside of registers is always packed and is accessed via typed loads and stores that narrow and widen scalars.
An instruction is a 64 bit word: opcode, A, B, C (16 bits each). Operand sizes and kinds are encoded in the opcode (one opcode per MemKind for loads and stores) so that the interpreter does not dispatch on them at runtime. Some instructions are followed by an extra 64 bit word W that holds an immediate value.
Types
CallShape = object paramOffsets*: seq[int] paramTypes*: seq[PType] resultType*: PType resultSlots*: int callbackIdx*: int
- where the arguments of a call live, relative to the first argument slot Source Edit
LocalInfo = object slot*: int32 boxed*: bool inMemory*: bool ## a scalar whose address is taken is stored packed in ## its slot and must be accessed via the opcLdSlot*/opcStSlot* instructions
- Source Edit
PProc = ref object blocks*: seq[TBlock] tries*: seq[TryInfo] sym*: PSym regInfo*: seq[SlotUse] locals*: Table[ItemId, LocalInfo] addrTaken*: IntSet paramAddrTaken*: IntSet resultAddrTaken*: bool paramSlots*: seq[LocalInfo] resultInfo*: LocalInfo hasResult*: bool injected*: bool
- Source Edit
Profiler = object tEnter*: float tos*: PStackFrame
- Source Edit
PStackFrame = ref TStackFrame
- Source Edit
SlotUse = object inUse*: bool isTemp*: bool rangeLen*: int32
- per register bookkeeping of the code generator Source Edit
TCtx = object of TPassContext code*: seq[TInstr] lastEof*: int ## position of the last `opcEof`; -1 if there is none typeKindDefault*: int debug*: seq[TLineInfo] mem*: VmMemory layouts*: LayoutCache globalAddrs*: Table[ItemId, Address] constAddrs*: Table[ItemId, Address] branchTables*: seq[seq[(BiggestInt, BiggestInt)]] callShapes*: seq[CallShape] procShapes*: Table[ItemId, CallShape] excNames*: Table[int, Address] semCtx*: PPassContext emptyCStr*: Address currentExceptionA*, currentExceptionB*: Address exceptionInstr*: int prc*: PProc module*: PSym callsite*: PNode mode*: TEvalMode features*: TSandboxFlags traceActive*: bool loopIterations*, callDepth*: int comesFromHeuristic*: TLineInfo callbacks*: seq[VmCallback] callbackIndex*: Table[string, int] errorFlag*: string cache*: IdentCache config*: ConfigRef graph*: ModuleGraph oldErrorCount*: int profiler*: Profiler templInstCounter*: ref int vmstateDiff*: seq[(PSym, PNode)] procToCodePos*: Table[int, VmProcInfo] cannotEval*: bool when false: ffiSites*: seq[FfiSite] locals*: IntSet
- Source Edit
TEvalMode = enum emRepl, ## evaluate because in REPL mode emConst, ## evaluate for 'const' according to spec emOptimize, ## evaluate for optimization purposes (same as ## emConst?) emStaticExpr, ## evaluate for enforced compile time eval ## ('static' context) emStaticStmt ## 'static' as an expression
- reason for evaluation Source Edit
TInstr = distinct TInstrType
- Source Edit
TInstrType = uint64
- Source Edit
TOpcode = enum opcEof, opcRet, opcYldYoid, opcYldVal, opcMov, opcMovN, opcZeroN, opcLdImmInt, opcLdImm, opcAddrSlot, opcAddrOff, opcAddrOffW, opcLdI8, opcLdI16, opcLdI32, opcLdU8, opcLdU16, opcLdU32, opcLdF32, opcLd64, opcSt8, opcSt16, opcSt32, opcStF32, opcSt64, opcLdSlotI8, opcLdSlotI16, opcLdSlotI32, opcLdSlotU8, opcLdSlotU16, opcLdSlotU32, opcLdSlotF32, opcStSlot8, opcStSlot16, opcStSlot32, opcStSlotF32, opcCopyMem, opcZeroMem, opcIdxArr, opcIdxSeq, opcIdxOpenArr, opcIdxPtr, opcSlice, opcAddInt, opcAddImmInt, opcSubInt, opcSubImmInt, opcMulInt, opcDivInt, opcModInt, opcAddFloat, opcSubFloat, opcMulFloat, opcDivFloat, opcShrInt, opcShlInt, opcAshrInt, opcBitandInt, opcBitorInt, opcBitxorInt, opcAddu, opcSubu, opcMulu, opcDivu, opcModu, opcEqInt, opcLeInt, opcLtInt, opcEqFloat, opcLeFloat, opcLtFloat, opcLeu, opcLtu, opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt, opcIsNil, opcCastIntToFloat32, opcCastIntToFloat64, opcCastFloatToInt32, opcCastFloatToInt64, opcIntToFloat, opcUIntToFloat, opcFloatToInt, opcFloatToUInt, opcFloatToF32, opcNarrowS, opcNarrowU, opcSignExtend, opcRangeChck, opcRangeChckF, opcRangeChckSucc, opcToStr, opcParseFloat, opcSetIncl, opcSetExcl, opcSetInclRange, opcSetContains, opcSetCard, opcSetLe, opcSetLt, opcBSetIncl, opcBSetExcl, opcBSetInclRange, opcBSetContains, opcBSetCard, opcBSetUnion, opcBSetInter, opcBSetDiff, opcBSetXor, opcBSetEq, opcBSetLe, opcBSetLt, opcStrNew, opcStrSetLen, opcStrAddCh, opcStrAddStr, opcStrAsgn, opcStrEq, opcStrLe, opcStrLt, opcStrToCStr, opcCStrToStr, opcCStrLen, opcCStrEq, opcStrFromChars, opcSeqNew, opcSeqSetLen, opcSeqGrowOne, opcSeqData, opcPayloadFree, opcSamePayload, opcSeqCopyPayload, opcMakeUnique, opcUnshare, opcDestroyValue, opcCopyValue, opcSinkValue, opcNewRef, opcIncRef, opcNodeIncRef, opcNodeDecRef, opcDecRefIsLast, opcDisposeRef, opcDynDestructor, opcInitObj, opcOf, opcIs, opcAlloc, opcDealloc, opcRealloc, opcAllocTemp, opcMemMove, opcMemZero, opcMemCmp, opcRepr, opcQuit, opcInvalidField, opcNLen, opcToNode, opcFromNode, opcNAdd, opcNAddMultiple, opcNKind, opcNSymKind, opcNIntVal, opcNFloatVal, opcNSymbol, opcNIdent, opcNGetType, opcNTypeKind, opcNGetTypeInst, opcNGetTypeImpl, opcNGetTypeInstSkipAlias, opcNStrVal, opcNSigHash, opcNGetSize, opcNSetIntVal, opcNSetFloatVal, opcNSetSymbol, opcNSetIdent, opcNSetStrVal, opcNNewNimNode, opcNCopyNimNode, opcNCopyNimTree, opcNDel, opcGenSym, opcNccValue, opcNccInc, opcNcsAdd, opcNcsIncl, opcNcsLen, opcNcsAt, opcNctPut, opcNctLen, opcNctGet, opcNctHasNext, opcNctNext, opcNodeId, opcSlurp, opcGorge, opcParseExprToAst, opcParseExprToAstFile, opcParseStmtToAst, opcParseStmtToAstFile, opcQueryErrorFlag, opcNError, opcNWarning, opcNHint, opcNGetLineInfo, opcNCopyLineInfo, opcNSetLineInfoLine, opcNSetLineInfoColumn, opcNSetLineInfoFile, opcEqIdent, opcEqIdentSN, opcEqIdentNS, opcEqIdentSS, opcStrToIdent, opcGetImpl, opcGetImplTransf, opcEqNimNode, opcSameNodeType, opcTypeTrait, opcSymOwner, opcSymIsInstantiationOf, opcSymCustomPragmas, opcNBindSym, opcNDynBindSym, opcNChild, opcNSetChild, opcCallSite, opcEcho, opcIndCall, opcFfiCall, opcRaise, opcTJmp, opcFJmp, opcJmp, opcJmpBack, opcBranch, opcTry, opcExcept, opcFinally, opcFinallyEnd, opcTypeLit
- Source Edit
TSandboxFlag = enum allowCast, ## allow unsafe language feature: 'cast' allowInfiniteLoops, ## allow endless loops allowInfiniteRecursion ## allow infinite recursion
- what the evaluation engine should allow Source Edit
TSandboxFlags = set[TSandboxFlag]
- Source Edit
TStackFrame {.acyclic.} = object prc*: PSym fp*: Address mark*: StackMark next*: PStackFrame comesFrom*: int top*: StackMark resultDest*: Address resultSize*: int disposeOnReturn*: Address disposeAlign*: int safePoints*: seq[int]
- Source Edit
VmArgs = object ctxp*: pointer args*: Address res*: Address shape*: ptr CallShape currentException*: Address currentLineInfo*: TLineInfo
- the arguments of a callback. See vmhooks for how to access them. Source Edit
VmCallback = proc (args: VmArgs) {.closure.}
- Source Edit
VmProcInfo = object pc*: int32 frameSlots*: int32 resultSlots*: int32 paramSlots*: int32 envSlot*: int32 bigResult*: bool genericParamSlots*: seq[int32]
- Source Edit
Consts
byteExcess = 128
- Source Edit
firstABxInstr = opcTJmp
- Source Edit
largeInstrs = {opcLdImm, opcAddrOffW, opcCopyMem, opcZeroMem, opcIdxArr, opcIdxSeq, opcIdxOpenArr, opcIdxPtr, opcFloatToInt, opcToStr, opcBSetIncl, opcBSetExcl, opcBSetInclRange, opcBSetContains, opcBSetCard, opcBSetUnion, opcBSetInter, opcBSetDiff, opcBSetXor, opcBSetEq, opcBSetLe, opcBSetLt, opcSeqNew, opcSeqSetLen, opcSeqGrowOne, opcSeqData, opcSeqCopyPayload, opcNewRef, opcInitObj, opcOf, opcIs, opcRepr, opcSlice, opcNDynBindSym, opcToNode, opcFromNode, opcUnshare, opcAllocTemp, opcDestroyValue, opcCopyValue, opcSinkValue, opcNctNext, opcInvalidField, opcFfiCall}
- Source Edit
MaxFrameSlots = 65536
- Source Edit
NoVmProcInfo = (pc: 0'i32, frameSlots: -1'i32, resultSlots: 0'i32, paramSlots: 0'i32, envSlot: 0'i32, bigResult: false, genericParamSlots: [])
- Source Edit
regBxShift = 32'u64
- Source Edit
relativeJumps = {opcTJmp, opcFJmp, opcJmp, opcJmpBack}
- Source Edit
wordExcess = 8388608
- Source Edit
Procs
proc newCtx(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator): PCtx {. ...raises: [], tags: [], forbids: [].}
- Source Edit
proc registerCallback(c: PCtx; name: string; callback: VmCallback): int {. discardable, ...raises: [], tags: [], forbids: [].}
- Source Edit
Exports
-
BoxThreshold, ClosureEnvOffset, ClosureFnOffset, FloatMemKinds, LayoutCache, MemKind, OpenArrayDataOffset, OpenArrayLenOffset, PayloadCapOffset, PayloadDataOffset, ScalarMemKinds, SignedMemKinds, StrLenOffset, StrPayloadOffset, TypeHeaderSize, UnsignedMemKinds, VmLayout, VmMaxAlign, VmPtrSize, alignTo, elemOffset, elemSize, fieldOffset, getLayout, hasPayloads, hasTypeHeader, isBig, memKind, memKindSize, setSize, skipForLayout, vmAlignOf, vmSizeOf, +!, -!, Address, BlockAlign, BlockHeaderSize, RcImmortal, RefHeaderSize, Region, RegionKind, StackMark, StackSegmentSize, StrlitFlag, VmMemory, allocBox, allocConst, allocGlobal, blockSize, canRead, canWrite, decNodeRef, decRefIsLast, disposeRef, findRegion, getNode, getProc, getType, heapAlloc, heapDealloc, heapRealloc, incNodeRef, incRef, isConstMemory, isFreedBlock, isHeapBlock, isLiteralPayload, ld, ldInt, liveNodes, loadString, newConstPayload, newConstRef, newPayload, newRef, nodeHandle, payloadCap, payloadDataOffset, pinnedNodeHandle, popFrames, procAddress, pushFrame, refBlockOffset, refCount, registerForeign, st, stackMark, stInt, storeString, toAddr, toPtr, typeHandle, unregisterForeign