vm.nim 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This file implements the new evaluation engine for Nim code.
  10. ## An instruction is 1-3 int32s in memory, it is a register based VM.
  11. const
  12. debugEchoCode = false
  13. traceCode = debugEchoCode
  14. import ast except getstr
  15. import
  16. strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes,
  17. parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
  18. vmmarshal
  19. from semfold import leValueConv, ordinalValToString
  20. from evaltempl import evalTemplate
  21. from modulegraphs import ModuleGraph
  22. when hasFFI:
  23. import evalffi
  24. type
  25. TRegisterKind = enum
  26. rkNone, rkNode, rkInt, rkFloat, rkRegisterAddr, rkNodeAddr
  27. TFullReg = object # with a custom mark proc, we could use the same
  28. # data representation as LuaJit (tagged NaNs).
  29. case kind: TRegisterKind
  30. of rkNone: nil
  31. of rkInt: intVal: BiggestInt
  32. of rkFloat: floatVal: BiggestFloat
  33. of rkNode: node: PNode
  34. of rkRegisterAddr: regAddr: ptr TFullReg
  35. of rkNodeAddr: nodeAddr: ptr PNode
  36. PStackFrame* = ref TStackFrame
  37. TStackFrame* = object
  38. prc: PSym # current prc; proc that is evaluated
  39. slots: seq[TFullReg] # parameters passed to the proc + locals;
  40. # parameters come first
  41. next: PStackFrame # for stacking
  42. comesFrom: int
  43. safePoints: seq[int] # used for exception handling
  44. # XXX 'break' should perform cleanup actions
  45. # What does the C backend do for it?
  46. proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
  47. if x != nil:
  48. if recursionLimit == 0:
  49. var calls = 0
  50. var x = x
  51. while x != nil:
  52. inc calls
  53. x = x.next
  54. msgWriteln($calls & " calls omitted\n")
  55. return
  56. stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
  57. var info = c.debug[pc]
  58. # we now use the same format as in system/except.nim
  59. var s = toFilename(info)
  60. var line = toLinenumber(info)
  61. if line > 0:
  62. add(s, '(')
  63. add(s, $line)
  64. add(s, ')')
  65. if x.prc != nil:
  66. for k in 1..max(1, 25-s.len): add(s, ' ')
  67. add(s, x.prc.name.s)
  68. msgWriteln(s)
  69. proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
  70. msg: TMsgKind, arg = "", n: PNode = nil) =
  71. msgWriteln("stack trace: (most recent call last)")
  72. stackTraceAux(c, tos, pc)
  73. # XXX test if we want 'globalError' for every mode
  74. let lineInfo = if n == nil: c.debug[pc] else: n.info
  75. if c.mode == emRepl: globalError(lineInfo, msg, arg)
  76. else: localError(lineInfo, msg, arg)
  77. proc bailOut(c: PCtx; tos: PStackFrame) =
  78. stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
  79. c.currentExceptionA.sons[3].skipColon.strVal)
  80. when not defined(nimComputedGoto):
  81. {.pragma: computedGoto.}
  82. proc myreset(n: var TFullReg) = reset(n)
  83. template ensureKind(k: untyped) {.dirty.} =
  84. if regs[ra].kind != k:
  85. myreset(regs[ra])
  86. regs[ra].kind = k
  87. template decodeB(k: untyped) {.dirty.} =
  88. let rb = instr.regB
  89. ensureKind(k)
  90. template decodeBC(k: untyped) {.dirty.} =
  91. let rb = instr.regB
  92. let rc = instr.regC
  93. ensureKind(k)
  94. template declBC() {.dirty.} =
  95. let rb = instr.regB
  96. let rc = instr.regC
  97. template decodeBImm(k: untyped) {.dirty.} =
  98. let rb = instr.regB
  99. let imm = instr.regC - byteExcess
  100. ensureKind(k)
  101. template decodeBx(k: untyped) {.dirty.} =
  102. let rbx = instr.regBx - wordExcess
  103. ensureKind(k)
  104. template move(a, b: untyped) {.dirty.} = system.shallowCopy(a, b)
  105. # XXX fix minor 'shallowCopy' overloading bug in compiler
  106. proc createStrKeepNode(x: var TFullReg; keepNode=true) =
  107. if x.node.isNil or not keepNode:
  108. x.node = newNode(nkStrLit)
  109. elif x.node.kind == nkNilLit and keepNode:
  110. when defined(useNodeIds):
  111. let id = x.node.id
  112. system.reset(x.node[])
  113. x.node.kind = nkStrLit
  114. when defined(useNodeIds):
  115. x.node.id = id
  116. elif x.node.kind notin {nkStrLit..nkTripleStrLit} or
  117. nfAllConst in x.node.flags:
  118. # XXX this is hacky; tests/txmlgen triggers it:
  119. x.node = newNode(nkStrLit)
  120. # It not only hackey, it is also wrong for tgentemplate. The primary
  121. # cause of bugs like these is that the VM does not properly distinguish
  122. # between variable defintions (var foo = e) and variable updates (foo = e).
  123. include vmhooks
  124. template createStr(x) =
  125. x.node = newNode(nkStrLit)
  126. template createSet(x) =
  127. x.node = newNode(nkCurly)
  128. proc moveConst(x: var TFullReg, y: TFullReg) =
  129. if x.kind != y.kind:
  130. myreset(x)
  131. x.kind = y.kind
  132. case x.kind
  133. of rkNone: discard
  134. of rkInt: x.intVal = y.intVal
  135. of rkFloat: x.floatVal = y.floatVal
  136. of rkNode: x.node = y.node
  137. of rkRegisterAddr: x.regAddr = y.regAddr
  138. of rkNodeAddr: x.nodeAddr = y.nodeAddr
  139. # this seems to be the best way to model the reference semantics
  140. # of system.NimNode:
  141. template asgnRef(x, y: untyped) = moveConst(x, y)
  142. proc copyValue(src: PNode): PNode =
  143. if src == nil or nfIsRef in src.flags:
  144. return src
  145. result = newNode(src.kind)
  146. result.info = src.info
  147. result.typ = src.typ
  148. result.flags = src.flags * PersistentNodeFlags
  149. result.comment = src.comment
  150. when defined(useNodeIds):
  151. if result.id == nodeIdToDebug:
  152. echo "COMES FROM ", src.id
  153. case src.kind
  154. of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
  155. of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
  156. of nkSym: result.sym = src.sym
  157. of nkIdent: result.ident = src.ident
  158. of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
  159. else:
  160. newSeq(result.sons, sonsLen(src))
  161. for i in countup(0, sonsLen(src) - 1):
  162. result.sons[i] = copyValue(src.sons[i])
  163. proc asgnComplex(x: var TFullReg, y: TFullReg) =
  164. if x.kind != y.kind:
  165. myreset(x)
  166. x.kind = y.kind
  167. case x.kind
  168. of rkNone: discard
  169. of rkInt: x.intVal = y.intVal
  170. of rkFloat: x.floatVal = y.floatVal
  171. of rkNode: x.node = copyValue(y.node)
  172. of rkRegisterAddr: x.regAddr = y.regAddr
  173. of rkNodeAddr: x.nodeAddr = y.nodeAddr
  174. proc putIntoNode(n: var PNode; x: TFullReg) =
  175. case x.kind
  176. of rkNone: discard
  177. of rkInt: n.intVal = x.intVal
  178. of rkFloat: n.floatVal = x.floatVal
  179. of rkNode:
  180. if nfIsRef in x.node.flags: n = x.node
  181. else: n[] = x.node[]
  182. of rkRegisterAddr: putIntoNode(n, x.regAddr[])
  183. of rkNodeAddr: n[] = x.nodeAddr[][]
  184. proc putIntoReg(dest: var TFullReg; n: PNode) =
  185. case n.kind
  186. of nkStrLit..nkTripleStrLit:
  187. dest.kind = rkNode
  188. createStr(dest)
  189. dest.node.strVal = n.strVal
  190. of nkCharLit..nkUInt64Lit:
  191. dest.kind = rkInt
  192. dest.intVal = n.intVal
  193. of nkFloatLit..nkFloat128Lit:
  194. dest.kind = rkFloat
  195. dest.floatVal = n.floatVal
  196. else:
  197. dest.kind = rkNode
  198. dest.node = n
  199. proc regToNode(x: TFullReg): PNode =
  200. case x.kind
  201. of rkNone: result = newNode(nkEmpty)
  202. of rkInt: result = newNode(nkIntLit); result.intVal = x.intVal
  203. of rkFloat: result = newNode(nkFloatLit); result.floatVal = x.floatVal
  204. of rkNode: result = x.node
  205. of rkRegisterAddr: result = regToNode(x.regAddr[])
  206. of rkNodeAddr: result = x.nodeAddr[]
  207. template getstr(a: untyped): untyped =
  208. (if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal)))
  209. proc pushSafePoint(f: PStackFrame; pc: int) =
  210. if f.safePoints.isNil: f.safePoints = @[]
  211. f.safePoints.add(pc)
  212. proc popSafePoint(f: PStackFrame) =
  213. # XXX this needs a proper fix!
  214. if f.safePoints.len > 0:
  215. discard f.safePoints.pop()
  216. proc cleanUpOnException(c: PCtx; tos: PStackFrame):
  217. tuple[pc: int, f: PStackFrame] =
  218. let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
  219. var f = tos
  220. while true:
  221. while f.safePoints.isNil or f.safePoints.len == 0:
  222. f = f.next
  223. if f.isNil: return (-1, nil)
  224. var pc2 = f.safePoints[f.safePoints.high]
  225. var nextExceptOrFinally = -1
  226. if c.code[pc2].opcode == opcExcept:
  227. nextExceptOrFinally = pc2 + c.code[pc2].regBx - wordExcess
  228. inc pc2
  229. while c.code[pc2].opcode == opcExcept:
  230. let excIndex = c.code[pc2].regBx-wordExcess
  231. let exceptType = if excIndex > 0: c.types[excIndex].skipTypes(
  232. abstractPtrs)
  233. else: nil
  234. #echo typeToString(exceptType), " ", typeToString(raisedType)
  235. if exceptType.isNil or inheritanceDiff(exceptType, raisedType) <= 0:
  236. # mark exception as handled but keep it in B for
  237. # the getCurrentException() builtin:
  238. c.currentExceptionB = c.currentExceptionA
  239. c.currentExceptionA = nil
  240. # execute the corresponding handler:
  241. while c.code[pc2].opcode == opcExcept: inc pc2
  242. discard f.safePoints.pop
  243. return (pc2, f)
  244. inc pc2
  245. if c.code[pc2].opcode != opcExcept and nextExceptOrFinally >= 0:
  246. # we're at the end of the *except list*, but maybe there is another
  247. # *except branch*?
  248. pc2 = nextExceptOrFinally+1
  249. if c.code[pc2].opcode == opcExcept:
  250. nextExceptOrFinally = pc2 + c.code[pc2].regBx - wordExcess
  251. if nextExceptOrFinally >= 0:
  252. pc2 = nextExceptOrFinally
  253. if c.code[pc2].opcode == opcFinally:
  254. # execute the corresponding handler, but don't quit walking the stack:
  255. discard f.safePoints.pop
  256. return (pc2+1, f)
  257. # not the right one:
  258. discard f.safePoints.pop
  259. proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
  260. if f.safePoints.isNil: return -1
  261. for s in f.safePoints:
  262. var pc = s
  263. while c.code[pc].opcode == opcExcept:
  264. pc = pc + c.code[pc].regBx - wordExcess
  265. if c.code[pc].opcode == opcFinally:
  266. return pc
  267. return -1
  268. proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
  269. if desttyp.kind == tyString:
  270. if dest.kind != rkNode:
  271. myreset(dest)
  272. dest.kind = rkNode
  273. dest.node = newNode(nkStrLit)
  274. let styp = srctyp.skipTypes(abstractRange)
  275. case styp.kind
  276. of tyEnum:
  277. let n = styp.n
  278. let x = src.intVal.int
  279. if x <% n.len and (let f = n.sons[x].sym; f.position == x):
  280. dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
  281. else:
  282. for i in 0.. <n.len:
  283. if n.sons[i].kind != nkSym: internalError("opConv for enum")
  284. let f = n.sons[i].sym
  285. if f.position == x:
  286. dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
  287. return
  288. dest.node.strVal = styp.sym.name.s & " " & $x
  289. of tyInt..tyInt64:
  290. dest.node.strVal = $src.intVal
  291. of tyUInt..tyUInt64:
  292. dest.node.strVal = $uint64(src.intVal)
  293. of tyBool:
  294. dest.node.strVal = if src.intVal == 0: "false" else: "true"
  295. of tyFloat..tyFloat128:
  296. dest.node.strVal = $src.floatVal
  297. of tyString:
  298. dest.node.strVal = src.node.strVal
  299. of tyCString:
  300. if src.node.kind == nkBracket:
  301. # Array of chars
  302. var strVal = ""
  303. for son in src.node.sons:
  304. let c = char(son.intVal)
  305. if c == '\0': break
  306. strVal.add(c)
  307. dest.node.strVal = strVal
  308. else:
  309. dest.node.strVal = src.node.strVal
  310. of tyChar:
  311. dest.node.strVal = $chr(src.intVal)
  312. else:
  313. internalError("cannot convert to string " & desttyp.typeToString)
  314. else:
  315. case skipTypes(desttyp, abstractRange).kind
  316. of tyInt..tyInt64:
  317. if dest.kind != rkInt:
  318. myreset(dest); dest.kind = rkInt
  319. case skipTypes(srctyp, abstractRange).kind
  320. of tyFloat..tyFloat64:
  321. dest.intVal = int(src.floatVal)
  322. else:
  323. dest.intVal = src.intVal
  324. if dest.intVal < firstOrd(desttyp) or dest.intVal > lastOrd(desttyp):
  325. return true
  326. of tyUInt..tyUInt64:
  327. if dest.kind != rkInt:
  328. myreset(dest); dest.kind = rkInt
  329. case skipTypes(srctyp, abstractRange).kind
  330. of tyFloat..tyFloat64:
  331. dest.intVal = int(src.floatVal)
  332. else:
  333. let srcDist = (sizeof(src.intVal) - srctyp.size) * 8
  334. let destDist = (sizeof(dest.intVal) - desttyp.size) * 8
  335. when system.cpuEndian == bigEndian:
  336. dest.intVal = (src.intVal shr srcDist) shl srcDist
  337. dest.intVal = (dest.intVal shr destDist) shl destDist
  338. else:
  339. dest.intVal = (src.intVal shl srcDist) shr srcDist
  340. dest.intVal = (dest.intVal shl destDist) shr destDist
  341. of tyFloat..tyFloat64:
  342. if dest.kind != rkFloat:
  343. myreset(dest); dest.kind = rkFloat
  344. case skipTypes(srctyp, abstractRange).kind
  345. of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
  346. dest.floatVal = toBiggestFloat(src.intVal)
  347. else:
  348. dest.floatVal = src.floatVal
  349. else:
  350. asgnComplex(dest, src)
  351. proc compile(c: PCtx, s: PSym): int =
  352. result = vmgen.genProc(c, s)
  353. when debugEchoCode: c.echoCode result
  354. #c.echoCode
  355. template handleJmpBack() {.dirty.} =
  356. if c.loopIterations <= 0:
  357. if allowInfiniteLoops in c.features:
  358. c.loopIterations = MaxLoopIterations
  359. else:
  360. msgWriteln("stack trace: (most recent call last)")
  361. stackTraceAux(c, tos, pc)
  362. globalError(c.debug[pc], errTooManyIterations)
  363. dec(c.loopIterations)
  364. proc recSetFlagIsRef(arg: PNode) =
  365. arg.flags.incl(nfIsRef)
  366. for i in 0 ..< arg.safeLen:
  367. arg.sons[i].recSetFlagIsRef
  368. proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
  369. # FIXME: this doesn't attempt to solve incomplete
  370. # support of tyPtr, tyRef in VM.
  371. let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
  372. let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
  373. let typeKind = case typeEntry.kind
  374. of tyUInt..tyUInt64: nkUIntLit
  375. of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
  376. of tyFloat..tyFloat128: nkFloatLit
  377. of tyString: nkStrLit
  378. of tyObject: nkObjConstr
  379. of tySequence: nkNilLit
  380. of tyProc, tyTuple: nkPar
  381. else: nkEmpty
  382. let oldLen = node.len
  383. setLen(node.sons, newLen)
  384. if oldLen < newLen:
  385. # TODO: This is still not correct for tyPtr, tyRef default value
  386. for i in oldLen .. <newLen:
  387. node.sons[i] = newNodeI(typeKind, info)
  388. proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
  389. var pc = start
  390. var tos = tos
  391. var regs: seq[TFullReg] # alias to tos.slots for performance
  392. move(regs, tos.slots)
  393. #echo "NEW RUN ------------------------"
  394. while true:
  395. #{.computedGoto.}
  396. let instr = c.code[pc]
  397. let ra = instr.regA
  398. #if c.traceActive:
  399. when traceCode:
  400. echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
  401. # message(c.debug[pc], warnUser, "Trace")
  402. case instr.opcode
  403. of opcEof: return regs[ra]
  404. of opcRet:
  405. # XXX perform any cleanup actions
  406. pc = tos.comesFrom
  407. tos = tos.next
  408. let retVal = regs[0]
  409. if tos.isNil:
  410. #echo "RET ", retVal.rendertree
  411. return retVal
  412. move(regs, tos.slots)
  413. assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
  414. if c.code[pc].opcode == opcIndCallAsgn:
  415. regs[c.code[pc].regA] = retVal
  416. #echo "RET2 ", retVal.rendertree, " ", c.code[pc].regA
  417. of opcYldYoid: assert false
  418. of opcYldVal: assert false
  419. of opcAsgnInt:
  420. decodeB(rkInt)
  421. regs[ra].intVal = regs[rb].intVal
  422. of opcAsgnStr:
  423. decodeBC(rkNode)
  424. createStrKeepNode regs[ra], rc != 0
  425. regs[ra].node.strVal = regs[rb].node.strVal
  426. of opcAsgnFloat:
  427. decodeB(rkFloat)
  428. regs[ra].floatVal = regs[rb].floatVal
  429. of opcAsgnComplex:
  430. asgnComplex(regs[ra], regs[instr.regB])
  431. of opcAsgnRef:
  432. asgnRef(regs[ra], regs[instr.regB])
  433. of opcRegToNode:
  434. decodeB(rkNode)
  435. putIntoNode(regs[ra].node, regs[rb])
  436. of opcNodeToReg:
  437. let ra = instr.regA
  438. let rb = instr.regB
  439. # opcDeref might already have loaded it into a register. XXX Let's hope
  440. # this is still correct this way:
  441. if regs[rb].kind != rkNode:
  442. regs[ra] = regs[rb]
  443. else:
  444. assert regs[rb].kind == rkNode
  445. let nb = regs[rb].node
  446. case nb.kind
  447. of nkCharLit..nkUInt64Lit:
  448. ensureKind(rkInt)
  449. regs[ra].intVal = nb.intVal
  450. of nkFloatLit..nkFloat64Lit:
  451. ensureKind(rkFloat)
  452. regs[ra].floatVal = nb.floatVal
  453. else:
  454. ensureKind(rkNode)
  455. regs[ra].node = nb
  456. of opcLdArr:
  457. # a = b[c]
  458. decodeBC(rkNode)
  459. if regs[rc].intVal > high(int):
  460. stackTrace(c, tos, pc, errIndexOutOfBounds)
  461. let idx = regs[rc].intVal.int
  462. let src = regs[rb].node
  463. if src.kind in {nkStrLit..nkTripleStrLit}:
  464. if idx <% src.strVal.len:
  465. regs[ra].node = newNodeI(nkCharLit, c.debug[pc])
  466. regs[ra].node.intVal = src.strVal[idx].ord
  467. else:
  468. stackTrace(c, tos, pc, errIndexOutOfBounds)
  469. elif src.kind notin {nkEmpty..nkFloat128Lit} and idx <% src.len:
  470. regs[ra].node = src.sons[idx]
  471. else:
  472. stackTrace(c, tos, pc, errIndexOutOfBounds)
  473. of opcLdStrIdx:
  474. decodeBC(rkInt)
  475. let idx = regs[rc].intVal.int
  476. let s = regs[rb].node.strVal
  477. if s.isNil:
  478. stackTrace(c, tos, pc, errNilAccess)
  479. elif idx <=% s.len:
  480. regs[ra].intVal = s[idx].ord
  481. else:
  482. stackTrace(c, tos, pc, errIndexOutOfBounds)
  483. of opcWrArr:
  484. # a[b] = c
  485. decodeBC(rkNode)
  486. let idx = regs[rb].intVal.int
  487. let arr = regs[ra].node
  488. if arr.kind in {nkStrLit..nkTripleStrLit}:
  489. if idx <% arr.strVal.len:
  490. arr.strVal[idx] = chr(regs[rc].intVal)
  491. else:
  492. stackTrace(c, tos, pc, errIndexOutOfBounds)
  493. elif idx <% arr.len:
  494. putIntoNode(arr.sons[idx], regs[rc])
  495. else:
  496. stackTrace(c, tos, pc, errIndexOutOfBounds)
  497. of opcLdObj:
  498. # a = b.c
  499. decodeBC(rkNode)
  500. let src = regs[rb].node
  501. if src.kind notin {nkEmpty..nkNilLit}:
  502. let n = src.sons[rc + ord(src.kind == nkObjConstr)].skipColon
  503. regs[ra].node = n
  504. else:
  505. stackTrace(c, tos, pc, errNilAccess)
  506. of opcWrObj:
  507. # a.b = c
  508. decodeBC(rkNode)
  509. let shiftedRb = rb + ord(regs[ra].node.kind == nkObjConstr)
  510. let dest = regs[ra].node
  511. if dest.kind == nkNilLit:
  512. stackTrace(c, tos, pc, errNilAccess)
  513. elif dest.sons[shiftedRb].kind == nkExprColonExpr:
  514. putIntoNode(dest.sons[shiftedRb].sons[1], regs[rc])
  515. else:
  516. putIntoNode(dest.sons[shiftedRb], regs[rc])
  517. of opcWrStrIdx:
  518. decodeBC(rkNode)
  519. let idx = regs[rb].intVal.int
  520. if idx <% regs[ra].node.strVal.len:
  521. regs[ra].node.strVal[idx] = chr(regs[rc].intVal)
  522. else:
  523. stackTrace(c, tos, pc, errIndexOutOfBounds)
  524. of opcAddrReg:
  525. decodeB(rkRegisterAddr)
  526. regs[ra].regAddr = addr(regs[rb])
  527. of opcAddrNode:
  528. decodeB(rkNodeAddr)
  529. if regs[rb].kind == rkNode:
  530. regs[ra].nodeAddr = addr(regs[rb].node)
  531. else:
  532. stackTrace(c, tos, pc, errGenerated, "limited VM support for 'addr'")
  533. of opcLdDeref:
  534. # a = b[]
  535. let ra = instr.regA
  536. let rb = instr.regB
  537. case regs[rb].kind
  538. of rkNodeAddr:
  539. ensureKind(rkNode)
  540. regs[ra].node = regs[rb].nodeAddr[]
  541. of rkRegisterAddr:
  542. ensureKind(regs[rb].regAddr.kind)
  543. regs[ra] = regs[rb].regAddr[]
  544. of rkNode:
  545. if regs[rb].node.kind == nkNilLit:
  546. stackTrace(c, tos, pc, errNilAccess)
  547. if regs[rb].node.kind == nkRefTy:
  548. regs[ra].node = regs[rb].node.sons[0]
  549. else:
  550. ensureKind(rkNode)
  551. regs[ra].node = regs[rb].node
  552. else:
  553. stackTrace(c, tos, pc, errNilAccess)
  554. of opcWrDeref:
  555. # a[] = c; b unused
  556. let ra = instr.regA
  557. let rc = instr.regC
  558. case regs[ra].kind
  559. of rkNodeAddr: putIntoNode(regs[ra].nodeAddr[], regs[rc])
  560. of rkRegisterAddr: regs[ra].regAddr[] = regs[rc]
  561. of rkNode: putIntoNode(regs[ra].node, regs[rc])
  562. else: stackTrace(c, tos, pc, errNilAccess)
  563. of opcAddInt:
  564. decodeBC(rkInt)
  565. let
  566. bVal = regs[rb].intVal
  567. cVal = regs[rc].intVal
  568. sum = bVal +% cVal
  569. if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
  570. regs[ra].intVal = sum
  571. else:
  572. stackTrace(c, tos, pc, errOverOrUnderflow)
  573. of opcAddImmInt:
  574. decodeBImm(rkInt)
  575. #message(c.debug[pc], warnUser, "came here")
  576. #debug regs[rb].node
  577. let
  578. bVal = regs[rb].intVal
  579. cVal = imm
  580. sum = bVal +% cVal
  581. if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
  582. regs[ra].intVal = sum
  583. else:
  584. stackTrace(c, tos, pc, errOverOrUnderflow)
  585. of opcSubInt:
  586. decodeBC(rkInt)
  587. let
  588. bVal = regs[rb].intVal
  589. cVal = regs[rc].intVal
  590. diff = bVal -% cVal
  591. if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
  592. regs[ra].intVal = diff
  593. else:
  594. stackTrace(c, tos, pc, errOverOrUnderflow)
  595. of opcSubImmInt:
  596. decodeBImm(rkInt)
  597. let
  598. bVal = regs[rb].intVal
  599. cVal = imm
  600. diff = bVal -% cVal
  601. if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
  602. regs[ra].intVal = diff
  603. else:
  604. stackTrace(c, tos, pc, errOverOrUnderflow)
  605. of opcLenSeq:
  606. decodeBImm(rkInt)
  607. #assert regs[rb].kind == nkBracket
  608. let high = (imm and 1) # discard flags
  609. if (imm and nimNodeFlag) != 0:
  610. # used by mNLen (NimNode.len)
  611. regs[ra].intVal = regs[rb].node.safeLen - high
  612. else:
  613. # safeArrLen also return string node len
  614. # used when string is passed as openArray in VM
  615. regs[ra].intVal = regs[rb].node.safeArrLen - high
  616. of opcLenStr:
  617. decodeBImm(rkInt)
  618. assert regs[rb].kind == rkNode
  619. regs[ra].intVal = regs[rb].node.strVal.len - imm
  620. of opcIncl:
  621. decodeB(rkNode)
  622. let b = regs[rb].regToNode
  623. if not inSet(regs[ra].node, b):
  624. addSon(regs[ra].node, copyTree(b))
  625. of opcInclRange:
  626. decodeBC(rkNode)
  627. var r = newNode(nkRange)
  628. r.add regs[rb].regToNode
  629. r.add regs[rc].regToNode
  630. addSon(regs[ra].node, r.copyTree)
  631. of opcExcl:
  632. decodeB(rkNode)
  633. var b = newNodeIT(nkCurly, regs[ra].node.info, regs[ra].node.typ)
  634. addSon(b, regs[rb].regToNode)
  635. var r = diffSets(regs[ra].node, b)
  636. discardSons(regs[ra].node)
  637. for i in countup(0, sonsLen(r) - 1): addSon(regs[ra].node, r.sons[i])
  638. of opcCard:
  639. decodeB(rkInt)
  640. regs[ra].intVal = nimsets.cardSet(regs[rb].node)
  641. of opcMulInt:
  642. decodeBC(rkInt)
  643. let
  644. bVal = regs[rb].intVal
  645. cVal = regs[rc].intVal
  646. product = bVal *% cVal
  647. floatProd = toBiggestFloat(bVal) * toBiggestFloat(cVal)
  648. resAsFloat = toBiggestFloat(product)
  649. if resAsFloat == floatProd:
  650. regs[ra].intVal = product
  651. elif 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
  652. regs[ra].intVal = product
  653. else:
  654. stackTrace(c, tos, pc, errOverOrUnderflow)
  655. of opcDivInt:
  656. decodeBC(rkInt)
  657. if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
  658. else: regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
  659. of opcModInt:
  660. decodeBC(rkInt)
  661. if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
  662. else: regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
  663. of opcAddFloat:
  664. decodeBC(rkFloat)
  665. regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
  666. of opcSubFloat:
  667. decodeBC(rkFloat)
  668. regs[ra].floatVal = regs[rb].floatVal - regs[rc].floatVal
  669. of opcMulFloat:
  670. decodeBC(rkFloat)
  671. regs[ra].floatVal = regs[rb].floatVal * regs[rc].floatVal
  672. of opcDivFloat:
  673. decodeBC(rkFloat)
  674. regs[ra].floatVal = regs[rb].floatVal / regs[rc].floatVal
  675. of opcShrInt:
  676. decodeBC(rkInt)
  677. regs[ra].intVal = regs[rb].intVal shr regs[rc].intVal
  678. of opcShlInt:
  679. decodeBC(rkInt)
  680. regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal
  681. of opcBitandInt:
  682. decodeBC(rkInt)
  683. regs[ra].intVal = regs[rb].intVal and regs[rc].intVal
  684. of opcBitorInt:
  685. decodeBC(rkInt)
  686. regs[ra].intVal = regs[rb].intVal or regs[rc].intVal
  687. of opcBitxorInt:
  688. decodeBC(rkInt)
  689. regs[ra].intVal = regs[rb].intVal xor regs[rc].intVal
  690. of opcAddu:
  691. decodeBC(rkInt)
  692. regs[ra].intVal = regs[rb].intVal +% regs[rc].intVal
  693. of opcSubu:
  694. decodeBC(rkInt)
  695. regs[ra].intVal = regs[rb].intVal -% regs[rc].intVal
  696. of opcMulu:
  697. decodeBC(rkInt)
  698. regs[ra].intVal = regs[rb].intVal *% regs[rc].intVal
  699. of opcDivu:
  700. decodeBC(rkInt)
  701. regs[ra].intVal = regs[rb].intVal /% regs[rc].intVal
  702. of opcModu:
  703. decodeBC(rkInt)
  704. regs[ra].intVal = regs[rb].intVal %% regs[rc].intVal
  705. of opcEqInt:
  706. decodeBC(rkInt)
  707. regs[ra].intVal = ord(regs[rb].intVal == regs[rc].intVal)
  708. of opcLeInt:
  709. decodeBC(rkInt)
  710. regs[ra].intVal = ord(regs[rb].intVal <= regs[rc].intVal)
  711. of opcLtInt:
  712. decodeBC(rkInt)
  713. regs[ra].intVal = ord(regs[rb].intVal < regs[rc].intVal)
  714. of opcEqFloat:
  715. decodeBC(rkInt)
  716. regs[ra].intVal = ord(regs[rb].floatVal == regs[rc].floatVal)
  717. of opcLeFloat:
  718. decodeBC(rkInt)
  719. regs[ra].intVal = ord(regs[rb].floatVal <= regs[rc].floatVal)
  720. of opcLtFloat:
  721. decodeBC(rkInt)
  722. regs[ra].intVal = ord(regs[rb].floatVal < regs[rc].floatVal)
  723. of opcLeu:
  724. decodeBC(rkInt)
  725. regs[ra].intVal = ord(regs[rb].intVal <=% regs[rc].intVal)
  726. of opcLtu:
  727. decodeBC(rkInt)
  728. regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
  729. of opcEqRef:
  730. decodeBC(rkInt)
  731. regs[ra].intVal = ord((regs[rb].node.kind == nkNilLit and
  732. regs[rc].node.kind == nkNilLit) or
  733. regs[rb].node == regs[rc].node)
  734. of opcEqNimrodNode:
  735. decodeBC(rkInt)
  736. regs[ra].intVal =
  737. ord(exprStructuralEquivalent(regs[rb].node, regs[rc].node,
  738. strictSymEquality=true))
  739. of opcSameNodeType:
  740. decodeBC(rkInt)
  741. regs[ra].intVal = ord(regs[rb].node.typ.sameTypeOrNil regs[rc].node.typ)
  742. of opcXor:
  743. decodeBC(rkInt)
  744. regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
  745. of opcNot:
  746. decodeB(rkInt)
  747. assert regs[rb].kind == rkInt
  748. regs[ra].intVal = 1 - regs[rb].intVal
  749. of opcUnaryMinusInt:
  750. decodeB(rkInt)
  751. assert regs[rb].kind == rkInt
  752. let val = regs[rb].intVal
  753. if val != int64.low:
  754. regs[ra].intVal = -val
  755. else:
  756. stackTrace(c, tos, pc, errOverOrUnderflow)
  757. of opcUnaryMinusFloat:
  758. decodeB(rkFloat)
  759. assert regs[rb].kind == rkFloat
  760. regs[ra].floatVal = -regs[rb].floatVal
  761. of opcBitnotInt:
  762. decodeB(rkInt)
  763. assert regs[rb].kind == rkInt
  764. regs[ra].intVal = not regs[rb].intVal
  765. of opcEqStr:
  766. decodeBC(rkInt)
  767. regs[ra].intVal = ord(regs[rb].node.strVal == regs[rc].node.strVal)
  768. of opcLeStr:
  769. decodeBC(rkInt)
  770. regs[ra].intVal = ord(regs[rb].node.strVal <= regs[rc].node.strVal)
  771. of opcLtStr:
  772. decodeBC(rkInt)
  773. regs[ra].intVal = ord(regs[rb].node.strVal < regs[rc].node.strVal)
  774. of opcLeSet:
  775. decodeBC(rkInt)
  776. regs[ra].intVal = ord(containsSets(regs[rb].node, regs[rc].node))
  777. of opcEqSet:
  778. decodeBC(rkInt)
  779. regs[ra].intVal = ord(equalSets(regs[rb].node, regs[rc].node))
  780. of opcLtSet:
  781. decodeBC(rkInt)
  782. let a = regs[rb].node
  783. let b = regs[rc].node
  784. regs[ra].intVal = ord(containsSets(a, b) and not equalSets(a, b))
  785. of opcMulSet:
  786. decodeBC(rkNode)
  787. createSet(regs[ra])
  788. move(regs[ra].node.sons,
  789. nimsets.intersectSets(regs[rb].node, regs[rc].node).sons)
  790. of opcPlusSet:
  791. decodeBC(rkNode)
  792. createSet(regs[ra])
  793. move(regs[ra].node.sons,
  794. nimsets.unionSets(regs[rb].node, regs[rc].node).sons)
  795. of opcMinusSet:
  796. decodeBC(rkNode)
  797. createSet(regs[ra])
  798. move(regs[ra].node.sons,
  799. nimsets.diffSets(regs[rb].node, regs[rc].node).sons)
  800. of opcSymdiffSet:
  801. decodeBC(rkNode)
  802. createSet(regs[ra])
  803. move(regs[ra].node.sons,
  804. nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)
  805. of opcConcatStr:
  806. decodeBC(rkNode)
  807. createStr regs[ra]
  808. regs[ra].node.strVal = getstr(regs[rb])
  809. for i in rb+1..rb+rc-1:
  810. regs[ra].node.strVal.add getstr(regs[i])
  811. of opcAddStrCh:
  812. decodeB(rkNode)
  813. #createStrKeepNode regs[ra]
  814. regs[ra].node.strVal.add(regs[rb].intVal.chr)
  815. of opcAddStrStr:
  816. decodeB(rkNode)
  817. #createStrKeepNode regs[ra]
  818. regs[ra].node.strVal.add(regs[rb].node.strVal)
  819. of opcAddSeqElem:
  820. decodeB(rkNode)
  821. if regs[ra].node.kind == nkBracket:
  822. regs[ra].node.add(copyValue(regs[rb].regToNode))
  823. else:
  824. stackTrace(c, tos, pc, errNilAccess)
  825. of opcGetImpl:
  826. decodeB(rkNode)
  827. let a = regs[rb].node
  828. if a.kind == nkSym:
  829. regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
  830. else: copyTree(a.sym.ast)
  831. else:
  832. stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
  833. of opcEcho:
  834. let rb = instr.regB
  835. if rb == 1:
  836. msgWriteln(regs[ra].node.strVal, {msgStdout})
  837. else:
  838. var outp = ""
  839. for i in ra..ra+rb-1:
  840. #if regs[i].kind != rkNode: debug regs[i]
  841. outp.add(regs[i].node.strVal)
  842. msgWriteln(outp, {msgStdout})
  843. of opcContainsSet:
  844. decodeBC(rkInt)
  845. regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
  846. of opcSubStr:
  847. decodeBC(rkNode)
  848. inc pc
  849. assert c.code[pc].opcode == opcSubStr
  850. let rd = c.code[pc].regA
  851. createStr regs[ra]
  852. regs[ra].node.strVal = substr(regs[rb].node.strVal,
  853. regs[rc].intVal.int, regs[rd].intVal.int)
  854. of opcParseFloat:
  855. decodeBC(rkInt)
  856. inc pc
  857. assert c.code[pc].opcode == opcParseFloat
  858. let rd = c.code[pc].regA
  859. var rcAddr = addr(regs[rc])
  860. if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr
  861. elif regs[rc].kind != rkFloat:
  862. myreset(regs[rc])
  863. regs[rc].kind = rkFloat
  864. regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal,
  865. rcAddr.floatVal, regs[rd].intVal.int)
  866. of opcRangeChck:
  867. let rb = instr.regB
  868. let rc = instr.regC
  869. if not (leValueConv(regs[rb].regToNode, regs[ra].regToNode) and
  870. leValueConv(regs[ra].regToNode, regs[rc].regToNode)):
  871. stackTrace(c, tos, pc, errGenerated,
  872. msgKindToString(errIllegalConvFromXtoY) % [
  873. $regs[ra].regToNode, "[" & $regs[rb].regToNode & ".." & $regs[rc].regToNode & "]"])
  874. of opcIndCall, opcIndCallAsgn:
  875. # dest = call regStart, n; where regStart = fn, arg1, ...
  876. let rb = instr.regB
  877. let rc = instr.regC
  878. let bb = regs[rb].node
  879. let isClosure = bb.kind == nkPar
  880. let prc = if not isClosure: bb.sym else: bb.sons[0].sym
  881. if prc.offset < -1:
  882. # it's a callback:
  883. c.callbacks[-prc.offset-2].value(
  884. VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
  885. currentException: c.currentExceptionB,
  886. currentLineInfo: c.debug[pc]))
  887. elif sfImportc in prc.flags:
  888. if allowFFI notin c.features:
  889. globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
  890. # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
  891. # 'regs' in a register:
  892. when hasFFI:
  893. let prcValue = c.globals.sons[prc.position-1]
  894. if prcValue.kind == nkEmpty:
  895. globalError(c.debug[pc], errGenerated, "canot run " & prc.name.s)
  896. let newValue = callForeignFunction(prcValue, prc.typ, tos.slots,
  897. rb+1, rc-1, c.debug[pc])
  898. if newValue.kind != nkEmpty:
  899. assert instr.opcode == opcIndCallAsgn
  900. putIntoReg(regs[ra], newValue)
  901. else:
  902. globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
  903. elif prc.kind != skTemplate:
  904. let newPc = compile(c, prc)
  905. # tricky: a recursion is also a jump back, so we use the same
  906. # logic as for loops:
  907. if newPc < pc: handleJmpBack()
  908. #echo "new pc ", newPc, " calling: ", prc.name.s
  909. var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
  910. newSeq(newFrame.slots, prc.offset+ord(isClosure))
  911. if not isEmptyType(prc.typ.sons[0]) or prc.kind == skMacro:
  912. putIntoReg(newFrame.slots[0], getNullValue(prc.typ.sons[0], prc.info))
  913. for i in 1 .. rc-1:
  914. newFrame.slots[i] = regs[rb+i]
  915. if isClosure:
  916. newFrame.slots[rc].kind = rkNode
  917. newFrame.slots[rc].node = regs[rb].node.sons[1]
  918. tos = newFrame
  919. move(regs, newFrame.slots)
  920. # -1 for the following 'inc pc'
  921. pc = newPc-1
  922. else:
  923. # for 'getAst' support we need to support template expansion here:
  924. let genSymOwner = if tos.next != nil and tos.next.prc != nil:
  925. tos.next.prc
  926. else:
  927. c.module
  928. var macroCall = newNodeI(nkCall, c.debug[pc])
  929. macroCall.add(newSymNode(prc))
  930. for i in 1 .. rc-1:
  931. let node = regs[rb+i].regToNode
  932. node.info = c.debug[pc]
  933. macroCall.add(node)
  934. let a = evalTemplate(macroCall, prc, genSymOwner)
  935. a.recSetFlagIsRef
  936. ensureKind(rkNode)
  937. regs[ra].node = a
  938. of opcTJmp:
  939. # jump Bx if A != 0
  940. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  941. if regs[ra].intVal != 0:
  942. inc pc, rbx
  943. of opcFJmp:
  944. # jump Bx if A == 0
  945. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  946. if regs[ra].intVal == 0:
  947. inc pc, rbx
  948. of opcJmp:
  949. # jump Bx
  950. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  951. inc pc, rbx
  952. of opcJmpBack:
  953. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  954. inc pc, rbx
  955. handleJmpBack()
  956. of opcBranch:
  957. # we know the next instruction is a 'fjmp':
  958. let branch = c.constants[instr.regBx-wordExcess]
  959. var cond = false
  960. for j in countup(0, sonsLen(branch) - 2):
  961. if overlap(regs[ra].regToNode, branch.sons[j]):
  962. cond = true
  963. break
  964. assert c.code[pc+1].opcode == opcFJmp
  965. inc pc
  966. # we skip this instruction so that the final 'inc(pc)' skips
  967. # the following jump
  968. if not cond:
  969. let instr2 = c.code[pc]
  970. let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  971. inc pc, rbx
  972. of opcTry:
  973. let rbx = instr.regBx - wordExcess
  974. tos.pushSafePoint(pc + rbx)
  975. assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
  976. of opcExcept:
  977. # just skip it; it's followed by a jump;
  978. # we'll execute in the 'raise' handler
  979. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  980. inc pc, rbx
  981. while c.code[pc+1].opcode == opcExcept:
  982. let rbx = c.code[pc+1].regBx - wordExcess - 1
  983. inc pc, rbx
  984. #assert c.code[pc+1].opcode in {opcExcept, opcFinally}
  985. if c.code[pc+1].opcode != opcFinally:
  986. # in an except handler there is no active safe point for the 'try':
  987. tos.popSafePoint()
  988. of opcFinally:
  989. # just skip it; it's followed by the code we need to execute anyway
  990. tos.popSafePoint()
  991. of opcFinallyEnd:
  992. if c.currentExceptionA != nil:
  993. # we are in a cleanup run:
  994. let (newPc, newTos) = cleanUpOnException(c, tos)
  995. if newPc-1 < 0:
  996. bailOut(c, tos)
  997. return
  998. pc = newPc-1
  999. if tos != newTos:
  1000. tos = newTos
  1001. move(regs, tos.slots)
  1002. of opcRaise:
  1003. let raised = regs[ra].node
  1004. c.currentExceptionA = raised
  1005. c.exceptionInstr = pc
  1006. let (newPc, newTos) = cleanUpOnException(c, tos)
  1007. # -1 because of the following 'inc'
  1008. if newPc-1 < 0:
  1009. bailOut(c, tos)
  1010. return
  1011. pc = newPc-1
  1012. if tos != newTos:
  1013. tos = newTos
  1014. move(regs, tos.slots)
  1015. of opcNew:
  1016. ensureKind(rkNode)
  1017. let typ = c.types[instr.regBx - wordExcess]
  1018. regs[ra].node = getNullValue(typ, c.debug[pc])
  1019. regs[ra].node.flags.incl nfIsRef
  1020. of opcNewSeq:
  1021. let typ = c.types[instr.regBx - wordExcess]
  1022. inc pc
  1023. ensureKind(rkNode)
  1024. let instr2 = c.code[pc]
  1025. let count = regs[instr2.regA].intVal.int
  1026. regs[ra].node = newNodeI(nkBracket, c.debug[pc])
  1027. regs[ra].node.typ = typ
  1028. newSeq(regs[ra].node.sons, count)
  1029. for i in 0 .. <count:
  1030. regs[ra].node.sons[i] = getNullValue(typ.sons[0], c.debug[pc])
  1031. of opcNewStr:
  1032. decodeB(rkNode)
  1033. regs[ra].node = newNodeI(nkStrLit, c.debug[pc])
  1034. regs[ra].node.strVal = newString(regs[rb].intVal.int)
  1035. of opcLdImmInt:
  1036. # dest = immediate value
  1037. decodeBx(rkInt)
  1038. regs[ra].intVal = rbx
  1039. of opcLdNull:
  1040. ensureKind(rkNode)
  1041. let typ = c.types[instr.regBx - wordExcess]
  1042. regs[ra].node = getNullValue(typ, c.debug[pc])
  1043. # opcLdNull really is the gist of the VM's problems: should it load
  1044. # a fresh null to regs[ra].node or to regs[ra].node[]? This really
  1045. # depends on whether regs[ra] represents the variable itself or wether
  1046. # it holds the indirection! Due to the way registers are re-used we cannot
  1047. # say for sure here! --> The codegen has to deal with it
  1048. # via 'genAsgnPatch'.
  1049. of opcLdNullReg:
  1050. let typ = c.types[instr.regBx - wordExcess]
  1051. if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
  1052. tyFloat..tyFloat128}:
  1053. ensureKind(rkFloat)
  1054. regs[ra].floatVal = 0.0
  1055. else:
  1056. ensureKind(rkInt)
  1057. regs[ra].intVal = 0
  1058. of opcLdConst:
  1059. let rb = instr.regBx - wordExcess
  1060. let cnst = c.constants.sons[rb]
  1061. if fitsRegister(cnst.typ):
  1062. myreset(regs[ra])
  1063. putIntoReg(regs[ra], cnst)
  1064. else:
  1065. ensureKind(rkNode)
  1066. regs[ra].node = cnst
  1067. of opcAsgnConst:
  1068. let rb = instr.regBx - wordExcess
  1069. let cnst = c.constants.sons[rb]
  1070. if fitsRegister(cnst.typ):
  1071. putIntoReg(regs[ra], cnst)
  1072. else:
  1073. ensureKind(rkNode)
  1074. regs[ra].node = cnst.copyTree
  1075. of opcLdGlobal:
  1076. let rb = instr.regBx - wordExcess - 1
  1077. ensureKind(rkNode)
  1078. regs[ra].node = c.globals.sons[rb]
  1079. of opcLdGlobalAddr:
  1080. let rb = instr.regBx - wordExcess - 1
  1081. ensureKind(rkNodeAddr)
  1082. regs[ra].nodeAddr = addr(c.globals.sons[rb])
  1083. of opcRepr:
  1084. decodeB(rkNode)
  1085. createStr regs[ra]
  1086. regs[ra].node.strVal = renderTree(regs[rb].regToNode, {renderNoComments, renderDocComments})
  1087. of opcQuit:
  1088. if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
  1089. message(c.debug[pc], hintQuitCalled)
  1090. msgQuit(int8(getOrdValue(regs[ra].regToNode)))
  1091. else:
  1092. return TFullReg(kind: rkNone)
  1093. of opcSetLenStr:
  1094. decodeB(rkNode)
  1095. #createStrKeepNode regs[ra]
  1096. regs[ra].node.strVal.setLen(regs[rb].intVal.int)
  1097. of opcOf:
  1098. decodeBC(rkInt)
  1099. let typ = c.types[regs[rc].intVal.int]
  1100. regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) >= 0)
  1101. of opcIs:
  1102. decodeBC(rkInt)
  1103. let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})
  1104. let t2 = c.types[regs[rc].intVal.int]
  1105. # XXX: This should use the standard isOpImpl
  1106. let match = if t2.kind == tyUserTypeClass: true
  1107. else: sameType(t1, t2)
  1108. regs[ra].intVal = ord(match)
  1109. of opcSetLenSeq:
  1110. decodeB(rkNode)
  1111. let newLen = regs[rb].intVal.int
  1112. if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
  1113. else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
  1114. of opcReset:
  1115. internalError(c.debug[pc], "too implement")
  1116. of opcNarrowS:
  1117. decodeB(rkInt)
  1118. let min = -(1.BiggestInt shl (rb-1))
  1119. let max = (1.BiggestInt shl (rb-1))-1
  1120. if regs[ra].intVal < min or regs[ra].intVal > max:
  1121. stackTrace(c, tos, pc, errGenerated,
  1122. msgKindToString(errUnhandledExceptionX) % "value out of range")
  1123. of opcNarrowU:
  1124. decodeB(rkInt)
  1125. regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
  1126. of opcIsNil:
  1127. decodeB(rkInt)
  1128. let node = regs[rb].node
  1129. regs[ra].intVal = ord(node.kind == nkNilLit or
  1130. (node.kind in {nkStrLit..nkTripleStrLit} and node.strVal.isNil))
  1131. of opcNBindSym:
  1132. decodeBx(rkNode)
  1133. regs[ra].node = copyTree(c.constants.sons[rbx])
  1134. of opcNChild:
  1135. decodeBC(rkNode)
  1136. let idx = regs[rc].intVal.int
  1137. let src = regs[rb].node
  1138. if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
  1139. regs[ra].node = src.sons[idx]
  1140. else:
  1141. stackTrace(c, tos, pc, errIndexOutOfBounds)
  1142. of opcNSetChild:
  1143. decodeBC(rkNode)
  1144. let idx = regs[rb].intVal.int
  1145. var dest = regs[ra].node
  1146. if dest.kind notin {nkEmpty..nkNilLit} and idx <% dest.len:
  1147. dest.sons[idx] = regs[rc].node
  1148. else:
  1149. stackTrace(c, tos, pc, errIndexOutOfBounds)
  1150. of opcNAdd:
  1151. decodeBC(rkNode)
  1152. var u = regs[rb].node
  1153. if u.kind notin {nkEmpty..nkNilLit}:
  1154. u.add(regs[rc].node)
  1155. else:
  1156. stackTrace(c, tos, pc, errGenerated, "cannot add to node kind: " & $u.kind)
  1157. regs[ra].node = u
  1158. of opcNAddMultiple:
  1159. decodeBC(rkNode)
  1160. let x = regs[rc].node
  1161. var u = regs[rb].node
  1162. if u.kind notin {nkEmpty..nkNilLit}:
  1163. # XXX can be optimized:
  1164. for i in 0.. <x.len: u.add(x.sons[i])
  1165. else:
  1166. stackTrace(c, tos, pc, errGenerated, "cannot add to node kind: " & $u.kind)
  1167. regs[ra].node = u
  1168. of opcNKind:
  1169. decodeB(rkInt)
  1170. regs[ra].intVal = ord(regs[rb].node.kind)
  1171. c.comesFromHeuristic = regs[rb].node.info
  1172. of opcNIntVal:
  1173. decodeB(rkInt)
  1174. let a = regs[rb].node
  1175. case a.kind
  1176. of nkCharLit..nkUInt64Lit: regs[ra].intVal = a.intVal
  1177. else: stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
  1178. of opcNFloatVal:
  1179. decodeB(rkFloat)
  1180. let a = regs[rb].node
  1181. case a.kind
  1182. of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
  1183. else: stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
  1184. of opcNSymbol:
  1185. decodeB(rkNode)
  1186. let a = regs[rb].node
  1187. if a.kind == nkSym:
  1188. regs[ra].node = copyNode(a)
  1189. else:
  1190. stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
  1191. of opcNIdent:
  1192. decodeB(rkNode)
  1193. let a = regs[rb].node
  1194. if a.kind == nkIdent:
  1195. regs[ra].node = copyNode(a)
  1196. else:
  1197. stackTrace(c, tos, pc, errFieldXNotFound, "ident")
  1198. of opcNGetType:
  1199. let rb = instr.regB
  1200. let rc = instr.regC
  1201. case rc:
  1202. of 0:
  1203. # getType opcode:
  1204. ensureKind(rkNode)
  1205. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1206. regs[ra].node = opMapTypeToAst(regs[rb].node.typ, c.debug[pc])
  1207. else:
  1208. stackTrace(c, tos, pc, errGenerated, "node has no type")
  1209. of 1:
  1210. # typeKind opcode:
  1211. ensureKind(rkInt)
  1212. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1213. regs[ra].intVal = ord(regs[rb].node.typ.kind)
  1214. #else:
  1215. # stackTrace(c, tos, pc, errGenerated, "node has no type")
  1216. of 2:
  1217. # getTypeInst opcode:
  1218. ensureKind(rkNode)
  1219. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1220. regs[ra].node = opMapTypeInstToAst(regs[rb].node.typ, c.debug[pc])
  1221. else:
  1222. stackTrace(c, tos, pc, errGenerated, "node has no type")
  1223. else:
  1224. # getTypeImpl opcode:
  1225. ensureKind(rkNode)
  1226. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1227. regs[ra].node = opMapTypeImplToAst(regs[rb].node.typ, c.debug[pc])
  1228. else:
  1229. stackTrace(c, tos, pc, errGenerated, "node has no type")
  1230. of opcNStrVal:
  1231. decodeB(rkNode)
  1232. createStr regs[ra]
  1233. let a = regs[rb].node
  1234. if a.kind in {nkStrLit..nkTripleStrLit}: regs[ra].node.strVal = a.strVal
  1235. elif a.kind == nkCommentStmt: regs[ra].node.strVal = a.comment
  1236. else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
  1237. of opcSlurp:
  1238. decodeB(rkNode)
  1239. createStr regs[ra]
  1240. regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
  1241. c.module)
  1242. of opcGorge:
  1243. decodeBC(rkNode)
  1244. inc pc
  1245. let rd = c.code[pc].regA
  1246. createStr regs[ra]
  1247. regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
  1248. regs[rc].node.strVal, regs[rd].node.strVal,
  1249. c.debug[pc])[0]
  1250. of opcNError:
  1251. decodeB(rkNode)
  1252. let a = regs[ra].node
  1253. let b = regs[rb].node
  1254. stackTrace(c, tos, pc, errUser, a.strVal, if b.kind == nkNilLit: nil else: b)
  1255. of opcNWarning:
  1256. message(c.debug[pc], warnUser, regs[ra].node.strVal)
  1257. of opcNHint:
  1258. message(c.debug[pc], hintUser, regs[ra].node.strVal)
  1259. of opcParseExprToAst:
  1260. decodeB(rkNode)
  1261. # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
  1262. var error: string
  1263. let ast = parseString(regs[rb].node.strVal, c.cache, c.debug[pc].toFullPath,
  1264. c.debug[pc].line.int,
  1265. proc (info: TLineInfo; msg: TMsgKind; arg: string) =
  1266. if error.isNil and msg <= msgs.errMax:
  1267. error = formatMsg(info, msg, arg))
  1268. if not error.isNil:
  1269. c.errorFlag = error
  1270. elif sonsLen(ast) != 1:
  1271. c.errorFlag = formatMsg(c.debug[pc], errExprExpected, "multiple statements")
  1272. else:
  1273. regs[ra].node = ast.sons[0]
  1274. of opcParseStmtToAst:
  1275. decodeB(rkNode)
  1276. var error: string
  1277. let ast = parseString(regs[rb].node.strVal, c.cache, c.debug[pc].toFullPath,
  1278. c.debug[pc].line.int,
  1279. proc (info: TLineInfo; msg: TMsgKind; arg: string) =
  1280. if error.isNil and msg <= msgs.errMax:
  1281. error = formatMsg(info, msg, arg))
  1282. if not error.isNil:
  1283. c.errorFlag = error
  1284. else:
  1285. regs[ra].node = ast
  1286. of opcQueryErrorFlag:
  1287. createStr regs[ra]
  1288. regs[ra].node.strVal = c.errorFlag
  1289. c.errorFlag.setLen 0
  1290. of opcCallSite:
  1291. ensureKind(rkNode)
  1292. if c.callsite != nil: regs[ra].node = c.callsite
  1293. else: stackTrace(c, tos, pc, errFieldXNotFound, "callsite")
  1294. of opcNGetFile:
  1295. decodeB(rkNode)
  1296. let n = regs[rb].node
  1297. regs[ra].node = newStrNode(nkStrLit, n.info.toFilename)
  1298. regs[ra].node.info = n.info
  1299. regs[ra].node.typ = n.typ
  1300. of opcNGetLine:
  1301. decodeB(rkNode)
  1302. let n = regs[rb].node
  1303. regs[ra].node = newIntNode(nkIntLit, n.info.line)
  1304. regs[ra].node.info = n.info
  1305. regs[ra].node.typ = n.typ
  1306. of opcNGetColumn:
  1307. decodeB(rkNode)
  1308. let n = regs[rb].node
  1309. regs[ra].node = newIntNode(nkIntLit, n.info.col)
  1310. regs[ra].node.info = n.info
  1311. regs[ra].node.typ = n.typ
  1312. of opcEqIdent:
  1313. decodeBC(rkInt)
  1314. if regs[rb].node.kind == nkIdent and regs[rc].node.kind == nkIdent:
  1315. regs[ra].intVal = ord(regs[rb].node.ident.id == regs[rc].node.ident.id)
  1316. else:
  1317. regs[ra].intVal = 0
  1318. of opcStrToIdent:
  1319. decodeB(rkNode)
  1320. if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}:
  1321. stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
  1322. else:
  1323. regs[ra].node = newNodeI(nkIdent, c.debug[pc])
  1324. regs[ra].node.ident = getIdent(regs[rb].node.strVal)
  1325. of opcIdentToStr:
  1326. decodeB(rkNode)
  1327. let a = regs[rb].node
  1328. createStr regs[ra]
  1329. regs[ra].node.info = c.debug[pc]
  1330. if a.kind == nkSym:
  1331. regs[ra].node.strVal = a.sym.name.s
  1332. elif a.kind == nkIdent:
  1333. regs[ra].node.strVal = a.ident.s
  1334. else:
  1335. stackTrace(c, tos, pc, errFieldXNotFound, "ident")
  1336. of opcSetType:
  1337. if regs[ra].kind != rkNode:
  1338. internalError(c.debug[pc], "cannot set type")
  1339. regs[ra].node.typ = c.types[instr.regBx - wordExcess]
  1340. of opcConv:
  1341. let rb = instr.regB
  1342. inc pc
  1343. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1344. inc pc
  1345. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1346. if opConv(regs[ra], regs[rb], desttyp, srctyp):
  1347. stackTrace(c, tos, pc, errGenerated,
  1348. msgKindToString(errIllegalConvFromXtoY) % [
  1349. typeToString(srctyp), typeToString(desttyp)])
  1350. of opcCast:
  1351. let rb = instr.regB
  1352. inc pc
  1353. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1354. inc pc
  1355. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1356. when hasFFI:
  1357. let dest = fficast(regs[rb], desttyp)
  1358. asgnRef(regs[ra], dest)
  1359. else:
  1360. globalError(c.debug[pc], "cannot evaluate cast")
  1361. of opcNSetIntVal:
  1362. decodeB(rkNode)
  1363. var dest = regs[ra].node
  1364. if dest.kind in {nkCharLit..nkUInt64Lit} and
  1365. regs[rb].kind in {rkInt}:
  1366. dest.intVal = regs[rb].intVal
  1367. else:
  1368. stackTrace(c, tos, pc, errFieldXNotFound, "intVal")
  1369. of opcNSetFloatVal:
  1370. decodeB(rkNode)
  1371. var dest = regs[ra].node
  1372. if dest.kind in {nkFloatLit..nkFloat64Lit} and
  1373. regs[rb].kind in {rkFloat}:
  1374. dest.floatVal = regs[rb].floatVal
  1375. else:
  1376. stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
  1377. of opcNSetSymbol:
  1378. decodeB(rkNode)
  1379. var dest = regs[ra].node
  1380. if dest.kind == nkSym and regs[rb].node.kind == nkSym:
  1381. dest.sym = regs[rb].node.sym
  1382. else:
  1383. stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
  1384. of opcNSetIdent:
  1385. decodeB(rkNode)
  1386. var dest = regs[ra].node
  1387. if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
  1388. dest.ident = regs[rb].node.ident
  1389. else:
  1390. stackTrace(c, tos, pc, errFieldXNotFound, "ident")
  1391. of opcNSetType:
  1392. decodeB(rkNode)
  1393. let b = regs[rb].node
  1394. internalAssert b.kind == nkSym and b.sym.kind == skType
  1395. internalAssert regs[ra].node != nil
  1396. regs[ra].node.typ = b.sym.typ
  1397. of opcNSetStrVal:
  1398. decodeB(rkNode)
  1399. var dest = regs[ra].node
  1400. if dest.kind in {nkStrLit..nkTripleStrLit} and
  1401. regs[rb].kind in {rkNode}:
  1402. dest.strVal = regs[rb].node.strVal
  1403. elif dest.kind == nkCommentStmt and regs[rb].kind in {rkNode}:
  1404. dest.comment = regs[rb].node.strVal
  1405. else:
  1406. stackTrace(c, tos, pc, errFieldXNotFound, "strVal")
  1407. of opcNNewNimNode:
  1408. decodeBC(rkNode)
  1409. var k = regs[rb].intVal
  1410. if k < 0 or k > ord(high(TNodeKind)):
  1411. internalError(c.debug[pc],
  1412. "request to create a NimNode of invalid kind")
  1413. let cc = regs[rc].node
  1414. regs[ra].node = newNodeI(TNodeKind(int(k)),
  1415. if cc.kind != nkNilLit:
  1416. cc.info
  1417. elif c.comesFromHeuristic.line > -1:
  1418. c.comesFromHeuristic
  1419. elif c.callsite != nil and c.callsite.safeLen > 1:
  1420. c.callsite[1].info
  1421. else:
  1422. c.debug[pc])
  1423. regs[ra].node.flags.incl nfIsRef
  1424. of opcNCopyNimNode:
  1425. decodeB(rkNode)
  1426. regs[ra].node = copyNode(regs[rb].node)
  1427. of opcNCopyNimTree:
  1428. decodeB(rkNode)
  1429. regs[ra].node = copyTree(regs[rb].node)
  1430. of opcNDel:
  1431. decodeBC(rkNode)
  1432. let bb = regs[rb].intVal.int
  1433. for i in countup(0, regs[rc].intVal.int-1):
  1434. delSon(regs[ra].node, bb)
  1435. of opcGenSym:
  1436. decodeBC(rkNode)
  1437. let k = regs[rb].intVal
  1438. let name = if regs[rc].node.strVal.len == 0: ":tmp"
  1439. else: regs[rc].node.strVal
  1440. if k < 0 or k > ord(high(TSymKind)):
  1441. internalError(c.debug[pc], "request to create symbol of invalid kind")
  1442. var sym = newSym(k.TSymKind, name.getIdent, c.module.owner, c.debug[pc])
  1443. incl(sym.flags, sfGenSym)
  1444. regs[ra].node = newSymNode(sym)
  1445. of opcTypeTrait:
  1446. # XXX only supports 'name' for now; we can use regC to encode the
  1447. # type trait operation
  1448. decodeB(rkNode)
  1449. var typ = regs[rb].node.typ
  1450. internalAssert typ != nil
  1451. while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
  1452. createStr regs[ra]
  1453. regs[ra].node.strVal = typ.typeToString(preferExported)
  1454. of opcMarshalLoad:
  1455. let ra = instr.regA
  1456. let rb = instr.regB
  1457. inc pc
  1458. let typ = c.types[c.code[pc].regBx - wordExcess]
  1459. putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ))
  1460. of opcMarshalStore:
  1461. decodeB(rkNode)
  1462. inc pc
  1463. let typ = c.types[c.code[pc].regBx - wordExcess]
  1464. createStrKeepNode(regs[ra])
  1465. if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
  1466. storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode)
  1467. of opcToNarrowInt:
  1468. decodeBC(rkInt)
  1469. let mask = (1'i64 shl rc) - 1 # 0xFF
  1470. let signbit = 1'i64 shl (rc - 1) # 0x80
  1471. let toggle = mask - signbit # 0x7F
  1472. # algorithm: -((i8 and 0xFF) xor 0x7F) + 0x7F
  1473. # mask off higher bits.
  1474. # uses two's complement to sign-extend integer.
  1475. # reajust integer into desired range.
  1476. regs[ra].intVal = -((regs[rb].intVal and mask) xor toggle) + toggle
  1477. inc pc
  1478. proc execute(c: PCtx, start: int): PNode =
  1479. var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
  1480. newSeq(tos.slots, c.prc.maxSlots)
  1481. result = rawExecute(c, start, tos).regToNode
  1482. proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
  1483. if sym.kind in routineKinds:
  1484. if sym.typ.len-1 != args.len:
  1485. localError(sym.info,
  1486. "NimScript: expected $# arguments, but got $#" % [
  1487. $(sym.typ.len-1), $args.len])
  1488. else:
  1489. let start = genProc(c, sym)
  1490. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  1491. let maxSlots = sym.offset
  1492. newSeq(tos.slots, maxSlots)
  1493. # setup parameters:
  1494. if not isEmptyType(sym.typ.sons[0]) or sym.kind == skMacro:
  1495. putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info))
  1496. # XXX We could perform some type checking here.
  1497. for i in 1.. <sym.typ.len:
  1498. putIntoReg(tos.slots[i], args[i-1])
  1499. result = rawExecute(c, start, tos).regToNode
  1500. else:
  1501. localError(sym.info,
  1502. "NimScript: attempt to call non-routine: " & sym.name.s)
  1503. proc evalStmt*(c: PCtx, n: PNode) =
  1504. let n = transformExpr(c.module, n)
  1505. let start = genStmt(c, n)
  1506. # execute new instructions; this redundant opcEof check saves us lots
  1507. # of allocations in 'execute':
  1508. if c.code[start].opcode != opcEof:
  1509. discard execute(c, start)
  1510. proc evalExpr*(c: PCtx, n: PNode): PNode =
  1511. let n = transformExpr(c.module, n)
  1512. let start = genExpr(c, n)
  1513. assert c.code[start].opcode != opcEof
  1514. result = execute(c, start)
  1515. proc getGlobalValue*(c: PCtx; s: PSym): PNode =
  1516. internalAssert s.kind in {skLet, skVar} and sfGlobal in s.flags
  1517. result = c.globals.sons[s.position-1]
  1518. include vmops
  1519. # for now we share the 'globals' environment. XXX Coming soon: An API for
  1520. # storing&loading the 'globals' environment to get what a component system
  1521. # requires.
  1522. var
  1523. globalCtx*: PCtx
  1524. proc setupGlobalCtx(module: PSym; cache: IdentCache) =
  1525. if globalCtx.isNil:
  1526. globalCtx = newCtx(module, cache)
  1527. registerAdditionalOps(globalCtx)
  1528. else:
  1529. refresh(globalCtx, module)
  1530. proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
  1531. #var c = newEvalContext(module, emRepl)
  1532. #c.features = {allowCast, allowFFI, allowInfiniteLoops}
  1533. #pushStackFrame(c, newStackFrame())
  1534. # XXX produce a new 'globals' environment here:
  1535. setupGlobalCtx(module, cache)
  1536. result = globalCtx
  1537. when hasFFI:
  1538. globalCtx.features = {allowFFI, allowCast}
  1539. var oldErrorCount: int
  1540. proc myProcess(c: PPassContext, n: PNode): PNode =
  1541. # don't eval errornous code:
  1542. if oldErrorCount == msgs.gErrorCounter:
  1543. evalStmt(PCtx(c), n)
  1544. result = emptyNode
  1545. else:
  1546. result = n
  1547. oldErrorCount = msgs.gErrorCounter
  1548. proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
  1549. myProcess(c, n)
  1550. const evalPass* = makePass(myOpen, nil, myProcess, myClose)
  1551. proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode,
  1552. mode: TEvalMode): PNode =
  1553. let n = transformExpr(module, n)
  1554. setupGlobalCtx(module, cache)
  1555. var c = globalCtx
  1556. let oldMode = c.mode
  1557. defer: c.mode = oldMode
  1558. c.mode = mode
  1559. let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
  1560. if c.code[start].opcode == opcEof: return emptyNode
  1561. assert c.code[start].opcode != opcEof
  1562. when debugEchoCode: c.echoCode start
  1563. var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
  1564. newSeq(tos.slots, c.prc.maxSlots)
  1565. #for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
  1566. result = rawExecute(c, start, tos).regToNode
  1567. if result.info.line < 0: result.info = n.info
  1568. proc evalConstExpr*(module: PSym; cache: IdentCache, e: PNode): PNode =
  1569. result = evalConstExprAux(module, cache, nil, e, emConst)
  1570. proc evalStaticExpr*(module: PSym; cache: IdentCache, e: PNode, prc: PSym): PNode =
  1571. result = evalConstExprAux(module, cache, prc, e, emStaticExpr)
  1572. proc evalStaticStmt*(module: PSym; cache: IdentCache, e: PNode, prc: PSym) =
  1573. discard evalConstExprAux(module, cache, prc, e, emStaticStmt)
  1574. proc setupCompileTimeVar*(module: PSym; cache: IdentCache, n: PNode) =
  1575. discard evalConstExprAux(module, cache, nil, n, emStaticStmt)
  1576. proc setupMacroParam(x: PNode, typ: PType): TFullReg =
  1577. case typ.kind
  1578. of tyStatic:
  1579. putIntoReg(result, x)
  1580. of tyTypeDesc:
  1581. putIntoReg(result, x)
  1582. else:
  1583. result.kind = rkNode
  1584. var n = x
  1585. if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
  1586. n = n.canonValue
  1587. n.flags.incl nfIsRef
  1588. n.typ = x.typ
  1589. result.node = n
  1590. iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
  1591. let gp = macroSym.ast[genericParamsPos]
  1592. for i in 0 .. <gp.len:
  1593. let genericParam = gp[i].sym
  1594. let posInCall = macroSym.typ.len + i
  1595. yield (genericParam, call[posInCall])
  1596. var evalMacroCounter: int
  1597. proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode,
  1598. sym: PSym): PNode =
  1599. # XXX globalError() is ugly here, but I don't know a better solution for now
  1600. inc(evalMacroCounter)
  1601. if evalMacroCounter > 100:
  1602. globalError(n.info, errTemplateInstantiationTooNested)
  1603. # immediate macros can bypass any type and arity checking so we check the
  1604. # arity here too:
  1605. if sym.typ.len > n.safeLen and sym.typ.len > 1:
  1606. globalError(n.info, "in call '$#' got $#, but expected $# argument(s)" % [
  1607. n.renderTree,
  1608. $ <n.safeLen, $ <sym.typ.len])
  1609. setupGlobalCtx(module, cache)
  1610. var c = globalCtx
  1611. c.comesFromHeuristic.line = -1
  1612. c.callsite = nOrig
  1613. let start = genProc(c, sym)
  1614. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  1615. let maxSlots = sym.offset
  1616. newSeq(tos.slots, maxSlots)
  1617. # setup arguments:
  1618. var L = n.safeLen
  1619. if L == 0: L = 1
  1620. # This is wrong for tests/reject/tind1.nim where the passed 'else' part
  1621. # doesn't end up in the parameter:
  1622. #InternalAssert tos.slots.len >= L
  1623. # return value:
  1624. tos.slots[0].kind = rkNode
  1625. tos.slots[0].node = newNodeI(nkEmpty, n.info)
  1626. # setup parameters:
  1627. for i in 1.. <sym.typ.len:
  1628. tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
  1629. let gp = sym.ast[genericParamsPos]
  1630. for i in 0 .. <gp.len:
  1631. if sfImmediate notin sym.flags:
  1632. let idx = sym.typ.len + i
  1633. if idx < n.len:
  1634. tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
  1635. else:
  1636. dec(evalMacroCounter)
  1637. c.callsite = nil
  1638. localError(n.info, "expected " & $gp.len &
  1639. " generic parameter(s)")
  1640. elif gp[i].sym.typ.kind in {tyStatic, tyTypeDesc}:
  1641. dec(evalMacroCounter)
  1642. c.callsite = nil
  1643. globalError(n.info, "static[T] or typedesc nor supported for .immediate macros")
  1644. # temporary storage:
  1645. #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
  1646. result = rawExecute(c, start, tos).regToNode
  1647. if result.info.line < 0: result.info = n.info
  1648. if cyclicTree(result): globalError(n.info, errCyclicTree)
  1649. dec(evalMacroCounter)
  1650. c.callsite = nil