vm.nim 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294
  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. import ast except getstr
  12. import
  13. strutils, msgs, vmdef, vmgen, nimsets, types, passes,
  14. parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
  15. vmmarshal, gorgeimpl, lineinfos, tables, btrees, macrocacheimpl,
  16. modulegraphs, sighashes, int128, vmprofiler
  17. from semfold import leValueConv, ordinalValToString
  18. from evaltempl import evalTemplate
  19. const
  20. traceCode = defined(nimVMDebug)
  21. when hasFFI:
  22. import evalffi
  23. proc stackTraceAux(c: PCtx; x: PStackFrame; pc: int; recursionLimit=100) =
  24. if x != nil:
  25. if recursionLimit == 0:
  26. var calls = 0
  27. var x = x
  28. while x != nil:
  29. inc calls
  30. x = x.next
  31. msgWriteln(c.config, $calls & " calls omitted\n")
  32. return
  33. stackTraceAux(c, x.next, x.comesFrom, recursionLimit-1)
  34. var info = c.debug[pc]
  35. # we now use a format similar to the one in lib/system/excpt.nim
  36. var s = ""
  37. # todo: factor with quotedFilename
  38. if optExcessiveStackTrace in c.config.globalOptions:
  39. s = toFullPath(c.config, info)
  40. else:
  41. s = toFilename(c.config, info)
  42. var line = toLinenumber(info)
  43. var col = toColumn(info)
  44. if line > 0:
  45. s.add('(')
  46. s.add($line)
  47. s.add(", ")
  48. s.add($(col + ColOffset))
  49. s.add(')')
  50. if x.prc != nil:
  51. for k in 1..max(1, 25-s.len): s.add(' ')
  52. s.add(x.prc.name.s)
  53. msgWriteln(c.config, s)
  54. proc stackTraceImpl(c: PCtx, tos: PStackFrame, pc: int,
  55. msg: string, lineInfo: TLineInfo, infoOrigin: InstantiationInfo) {.noinline.} =
  56. # noinline to avoid code bloat
  57. msgWriteln(c.config, "stack trace: (most recent call last)")
  58. stackTraceAux(c, tos, pc)
  59. let action = if c.mode == emRepl: doRaise else: doNothing
  60. # XXX test if we want 'globalError' for every mode
  61. let lineInfo = if lineInfo == TLineInfo.default: c.debug[pc] else: lineInfo
  62. liMessage(c.config, lineInfo, errGenerated, msg, action, infoOrigin)
  63. template stackTrace(c: PCtx, tos: PStackFrame, pc: int,
  64. msg: string, lineInfo: TLineInfo = TLineInfo.default) =
  65. stackTraceImpl(c, tos, pc, msg, lineInfo, instantiationInfo(-2, fullPaths = true))
  66. return
  67. proc bailOut(c: PCtx; tos: PStackFrame) =
  68. stackTrace(c, tos, c.exceptionInstr, "unhandled exception: " &
  69. c.currentExceptionA[3].skipColon.strVal &
  70. " [" & c.currentExceptionA[2].skipColon.strVal & "]")
  71. when not defined(nimComputedGoto):
  72. {.pragma: computedGoto.}
  73. proc ensureKind(n: var TFullReg, kind: TRegisterKind) =
  74. if n.kind != kind:
  75. n = TFullReg(kind: kind)
  76. template ensureKind(k: untyped) {.dirty.} =
  77. ensureKind(regs[ra], k)
  78. template decodeB(k: untyped) {.dirty.} =
  79. let rb = instr.regB
  80. ensureKind(k)
  81. template decodeBC(k: untyped) {.dirty.} =
  82. let rb = instr.regB
  83. let rc = instr.regC
  84. ensureKind(k)
  85. template declBC() {.dirty.} =
  86. let rb = instr.regB
  87. let rc = instr.regC
  88. template decodeBImm(k: untyped) {.dirty.} =
  89. let rb = instr.regB
  90. let imm = instr.regC - byteExcess
  91. ensureKind(k)
  92. template decodeBx(k: untyped) {.dirty.} =
  93. let rbx = instr.regBx - wordExcess
  94. ensureKind(k)
  95. template move(a, b: untyped) {.dirty.} = system.shallowCopy(a, b)
  96. # XXX fix minor 'shallowCopy' overloading bug in compiler
  97. proc derefPtrToReg(address: BiggestInt, typ: PType, r: var TFullReg, isAssign: bool): bool =
  98. # nim bug: `isAssign: static bool` doesn't work, giving odd compiler error
  99. template fun(field, T, rkind) =
  100. if isAssign:
  101. cast[ptr T](address)[] = T(r.field)
  102. else:
  103. r.ensureKind(rkind)
  104. let val = cast[ptr T](address)[]
  105. when T is SomeInteger:
  106. r.field = BiggestInt(val)
  107. else:
  108. r.field = val
  109. return true
  110. ## see also typeinfo.getBiggestInt
  111. case typ.kind
  112. of tyInt: fun(intVal, int, rkInt)
  113. of tyInt8: fun(intVal, int8, rkInt)
  114. of tyInt16: fun(intVal, int16, rkInt)
  115. of tyInt32: fun(intVal, int32, rkInt)
  116. of tyInt64: fun(intVal, int64, rkInt)
  117. of tyUInt: fun(intVal, uint, rkInt)
  118. of tyUInt8: fun(intVal, uint8, rkInt)
  119. of tyUInt16: fun(intVal, uint16, rkInt)
  120. of tyUInt32: fun(intVal, uint32, rkInt)
  121. of tyUInt64: fun(intVal, uint64, rkInt) # note: differs from typeinfo.getBiggestInt
  122. of tyFloat: fun(floatVal, float, rkFloat)
  123. of tyFloat32: fun(floatVal, float32, rkFloat)
  124. of tyFloat64: fun(floatVal, float64, rkFloat)
  125. else: return false
  126. proc createStrKeepNode(x: var TFullReg; keepNode=true) =
  127. if x.node.isNil or not keepNode:
  128. x.node = newNode(nkStrLit)
  129. elif x.node.kind == nkNilLit and keepNode:
  130. when defined(useNodeIds):
  131. let id = x.node.id
  132. x.node[] = TNode(kind: nkStrLit)
  133. when defined(useNodeIds):
  134. x.node.id = id
  135. elif x.node.kind notin {nkStrLit..nkTripleStrLit} or
  136. nfAllConst in x.node.flags:
  137. # XXX this is hacky; tests/txmlgen triggers it:
  138. x.node = newNode(nkStrLit)
  139. # It not only hackey, it is also wrong for tgentemplate. The primary
  140. # cause of bugs like these is that the VM does not properly distinguish
  141. # between variable definitions (var foo = e) and variable updates (foo = e).
  142. include vmhooks
  143. template createStr(x) =
  144. x.node = newNode(nkStrLit)
  145. template createSet(x) =
  146. x.node = newNode(nkCurly)
  147. proc moveConst(x: var TFullReg, y: TFullReg) =
  148. x.ensureKind(y.kind)
  149. case x.kind
  150. of rkNone: discard
  151. of rkInt: x.intVal = y.intVal
  152. of rkFloat: x.floatVal = y.floatVal
  153. of rkNode: x.node = y.node
  154. of rkRegisterAddr: x.regAddr = y.regAddr
  155. of rkNodeAddr: x.nodeAddr = y.nodeAddr
  156. # this seems to be the best way to model the reference semantics
  157. # of system.NimNode:
  158. template asgnRef(x, y: untyped) = moveConst(x, y)
  159. proc copyValue(src: PNode): PNode =
  160. if src == nil or nfIsRef in src.flags:
  161. return src
  162. result = newNode(src.kind)
  163. result.info = src.info
  164. result.typ = src.typ
  165. result.flags = src.flags * PersistentNodeFlags
  166. result.comment = src.comment
  167. when defined(useNodeIds):
  168. if result.id == nodeIdToDebug:
  169. echo "COMES FROM ", src.id
  170. case src.kind
  171. of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
  172. of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
  173. of nkSym: result.sym = src.sym
  174. of nkIdent: result.ident = src.ident
  175. of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
  176. else:
  177. newSeq(result.sons, src.len)
  178. for i in 0..<src.len:
  179. result[i] = copyValue(src[i])
  180. proc asgnComplex(x: var TFullReg, y: TFullReg) =
  181. x.ensureKind(y.kind)
  182. case x.kind
  183. of rkNone: discard
  184. of rkInt: x.intVal = y.intVal
  185. of rkFloat: x.floatVal = y.floatVal
  186. of rkNode: x.node = copyValue(y.node)
  187. of rkRegisterAddr: x.regAddr = y.regAddr
  188. of rkNodeAddr: x.nodeAddr = y.nodeAddr
  189. proc fastAsgnComplex(x: var TFullReg, y: TFullReg) =
  190. x.ensureKind(y.kind)
  191. case x.kind
  192. of rkNone: discard
  193. of rkInt: x.intVal = y.intVal
  194. of rkFloat: x.floatVal = y.floatVal
  195. of rkNode: x.node = y.node
  196. of rkRegisterAddr: x.regAddr = y.regAddr
  197. of rkNodeAddr: x.nodeAddr = y.nodeAddr
  198. proc writeField(n: var PNode, x: TFullReg) =
  199. case x.kind
  200. of rkNone: discard
  201. of rkInt:
  202. if n.kind == nkNilLit:
  203. n[] = TNode(kind: nkIntLit) # ideally, `nkPtrLit`
  204. n.intVal = x.intVal
  205. of rkFloat: n.floatVal = x.floatVal
  206. of rkNode: n = copyValue(x.node)
  207. of rkRegisterAddr: writeField(n, x.regAddr[])
  208. of rkNodeAddr: n = x.nodeAddr[]
  209. proc putIntoReg(dest: var TFullReg; n: PNode) =
  210. case n.kind
  211. of nkStrLit..nkTripleStrLit:
  212. dest = TFullReg(kind: rkNode, node: newStrNode(nkStrLit, n.strVal))
  213. of nkIntLit: # use `nkPtrLit` once this is added
  214. if dest.kind == rkNode: dest.node = n
  215. elif n.typ != nil and n.typ.kind in PtrLikeKinds:
  216. dest = TFullReg(kind: rkNode, node: n)
  217. else:
  218. dest = TFullReg(kind: rkInt, intVal: n.intVal)
  219. of {nkCharLit..nkUInt64Lit} - {nkIntLit}:
  220. dest = TFullReg(kind: rkInt, intVal: n.intVal)
  221. of nkFloatLit..nkFloat128Lit:
  222. dest = TFullReg(kind: rkFloat, floatVal: n.floatVal)
  223. else:
  224. dest = TFullReg(kind: rkNode, node: n)
  225. proc regToNode(x: TFullReg): PNode =
  226. case x.kind
  227. of rkNone: result = newNode(nkEmpty)
  228. of rkInt: result = newNode(nkIntLit); result.intVal = x.intVal
  229. of rkFloat: result = newNode(nkFloatLit); result.floatVal = x.floatVal
  230. of rkNode: result = x.node
  231. of rkRegisterAddr: result = regToNode(x.regAddr[])
  232. of rkNodeAddr: result = x.nodeAddr[]
  233. template getstr(a: untyped): untyped =
  234. (if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal)))
  235. proc pushSafePoint(f: PStackFrame; pc: int) =
  236. when not defined(nimNoNilSeqs):
  237. if f.safePoints.isNil: f.safePoints = @[]
  238. f.safePoints.add(pc)
  239. proc popSafePoint(f: PStackFrame) =
  240. discard f.safePoints.pop()
  241. type
  242. ExceptionGoto = enum
  243. ExceptionGotoHandler,
  244. ExceptionGotoFinally,
  245. ExceptionGotoUnhandled
  246. proc findExceptionHandler(c: PCtx, f: PStackFrame, exc: PNode):
  247. tuple[why: ExceptionGoto, where: int] =
  248. let raisedType = exc.typ.skipTypes(abstractPtrs)
  249. while f.safePoints.len > 0:
  250. var pc = f.safePoints.pop()
  251. var matched = false
  252. var pcEndExcept = pc
  253. # Scan the chain of exceptions starting at pc.
  254. # The structure is the following:
  255. # pc - opcExcept, <end of this block>
  256. # - opcExcept, <pattern1>
  257. # - opcExcept, <pattern2>
  258. # ...
  259. # - opcExcept, <patternN>
  260. # - Exception handler body
  261. # - ... more opcExcept blocks may follow
  262. # - ... an optional opcFinally block may follow
  263. #
  264. # Note that the exception handler body already contains a jump to the
  265. # finally block or, if that's not present, to the point where the execution
  266. # should continue.
  267. # Also note that opcFinally blocks are the last in the chain.
  268. while c.code[pc].opcode == opcExcept:
  269. # Where this Except block ends
  270. pcEndExcept = pc + c.code[pc].regBx - wordExcess
  271. inc pc
  272. # A series of opcExcept follows for each exception type matched
  273. while c.code[pc].opcode == opcExcept:
  274. let excIndex = c.code[pc].regBx - wordExcess
  275. let exceptType =
  276. if excIndex > 0: c.types[excIndex].skipTypes(abstractPtrs)
  277. else: nil
  278. # echo typeToString(exceptType), " ", typeToString(raisedType)
  279. # Determine if the exception type matches the pattern
  280. if exceptType.isNil or inheritanceDiff(raisedType, exceptType) <= 0:
  281. matched = true
  282. break
  283. inc pc
  284. # Skip any further ``except`` pattern and find the first instruction of
  285. # the handler body
  286. while c.code[pc].opcode == opcExcept:
  287. inc pc
  288. if matched:
  289. break
  290. # If no handler in this chain is able to catch this exception we check if
  291. # the "parent" chains are able to. If this chain ends with a `finally`
  292. # block we must execute it before continuing.
  293. pc = pcEndExcept
  294. # Where the handler body starts
  295. let pcBody = pc
  296. if matched:
  297. return (ExceptionGotoHandler, pcBody)
  298. elif c.code[pc].opcode == opcFinally:
  299. # The +1 here is here because we don't want to execute it since we've
  300. # already pop'd this statepoint from the stack.
  301. return (ExceptionGotoFinally, pc + 1)
  302. return (ExceptionGotoUnhandled, 0)
  303. proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
  304. # Walk up the chain of safepoints and return the PC of the first `finally`
  305. # block we find or -1 if no such block is found.
  306. # Note that the safepoint is removed once the function returns!
  307. result = -1
  308. # Traverse the stack starting from the end in order to execute the blocks in
  309. # the intended order
  310. for i in 1..f.safePoints.len:
  311. var pc = f.safePoints[^i]
  312. # Skip the `except` blocks
  313. while c.code[pc].opcode == opcExcept:
  314. pc += c.code[pc].regBx - wordExcess
  315. if c.code[pc].opcode == opcFinally:
  316. discard f.safePoints.pop
  317. return pc + 1
  318. proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
  319. if desttyp.kind == tyString:
  320. dest.ensureKind(rkNode)
  321. dest.node = newNode(nkStrLit)
  322. let styp = srctyp.skipTypes(abstractRange)
  323. case styp.kind
  324. of tyEnum:
  325. let n = styp.n
  326. let x = src.intVal.int
  327. if x <% n.len and (let f = n[x].sym; f.position == x):
  328. dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
  329. else:
  330. for i in 0..<n.len:
  331. if n[i].kind != nkSym: internalError(c.config, "opConv for enum")
  332. let f = n[i].sym
  333. if f.position == x:
  334. dest.node.strVal = if f.ast.isNil: f.name.s else: f.ast.strVal
  335. return
  336. dest.node.strVal = styp.sym.name.s & " " & $x
  337. of tyInt..tyInt64:
  338. dest.node.strVal = $src.intVal
  339. of tyUInt..tyUInt64:
  340. dest.node.strVal = $uint64(src.intVal)
  341. of tyBool:
  342. dest.node.strVal = if src.intVal == 0: "false" else: "true"
  343. of tyFloat..tyFloat128:
  344. dest.node.strVal = $src.floatVal
  345. of tyString:
  346. dest.node.strVal = src.node.strVal
  347. of tyCString:
  348. if src.node.kind == nkBracket:
  349. # Array of chars
  350. var strVal = ""
  351. for son in src.node.sons:
  352. let c = char(son.intVal)
  353. if c == '\0': break
  354. strVal.add(c)
  355. dest.node.strVal = strVal
  356. else:
  357. dest.node.strVal = src.node.strVal
  358. of tyChar:
  359. dest.node.strVal = $chr(src.intVal)
  360. else:
  361. internalError(c.config, "cannot convert to string " & desttyp.typeToString)
  362. else:
  363. case skipTypes(desttyp, abstractVarRange).kind
  364. of tyInt..tyInt64:
  365. dest.ensureKind(rkInt)
  366. case skipTypes(srctyp, abstractRange).kind
  367. of tyFloat..tyFloat64:
  368. dest.intVal = int(src.floatVal)
  369. else:
  370. dest.intVal = src.intVal
  371. if toInt128(dest.intVal) < firstOrd(c.config, desttyp) or toInt128(dest.intVal) > lastOrd(c.config, desttyp):
  372. return true
  373. of tyUInt..tyUInt64:
  374. dest.ensureKind(rkInt)
  375. case skipTypes(srctyp, abstractRange).kind
  376. of tyFloat..tyFloat64:
  377. dest.intVal = int(src.floatVal)
  378. else:
  379. let srcDist = (sizeof(src.intVal) - srctyp.size) * 8
  380. let destDist = (sizeof(dest.intVal) - desttyp.size) * 8
  381. var value = cast[BiggestUInt](src.intVal)
  382. value = (value shl srcDist) shr srcDist
  383. value = (value shl destDist) shr destDist
  384. dest.intVal = cast[BiggestInt](value)
  385. of tyBool:
  386. dest.ensureKind(rkInt)
  387. dest.intVal =
  388. case skipTypes(srctyp, abstractRange).kind
  389. of tyFloat..tyFloat64: int(src.floatVal != 0.0)
  390. else: int(src.intVal != 0)
  391. of tyFloat..tyFloat64:
  392. dest.ensureKind(rkFloat)
  393. case skipTypes(srctyp, abstractRange).kind
  394. of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
  395. dest.floatVal = toBiggestFloat(src.intVal)
  396. else:
  397. dest.floatVal = src.floatVal
  398. of tyObject:
  399. if srctyp.skipTypes(abstractVarRange).kind != tyObject:
  400. internalError(c.config, "invalid object-to-object conversion")
  401. # A object-to-object conversion is essentially a no-op
  402. moveConst(dest, src)
  403. else:
  404. asgnComplex(dest, src)
  405. proc compile(c: PCtx, s: PSym): int =
  406. result = vmgen.genProc(c, s)
  407. when debugEchoCode: c.echoCode result
  408. #c.echoCode
  409. template handleJmpBack() {.dirty.} =
  410. if c.loopIterations <= 0:
  411. if allowInfiniteLoops in c.features:
  412. c.loopIterations = c.config.maxLoopIterationsVM
  413. else:
  414. msgWriteln(c.config, "stack trace: (most recent call last)")
  415. stackTraceAux(c, tos, pc)
  416. globalError(c.config, c.debug[pc], errTooManyIterations % $c.config.maxLoopIterationsVM)
  417. dec(c.loopIterations)
  418. proc recSetFlagIsRef(arg: PNode) =
  419. if arg.kind notin {nkStrLit..nkTripleStrLit}:
  420. arg.flags.incl(nfIsRef)
  421. for i in 0..<arg.safeLen:
  422. arg[i].recSetFlagIsRef
  423. proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
  424. let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
  425. let oldLen = node.len
  426. setLen(node.sons, newLen)
  427. if oldLen < newLen:
  428. for i in oldLen..<newLen:
  429. node[i] = getNullValue(typ[0], info, c.config)
  430. const
  431. errNilAccess = "attempt to access a nil address"
  432. errOverOrUnderflow = "over- or underflow"
  433. errConstantDivisionByZero = "division by zero"
  434. errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'"
  435. errTooManyIterations = "interpretation requires too many iterations; " &
  436. "if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
  437. errFieldXNotFound = "node lacks field: "
  438. template maybeHandlePtr(node2: PNode, reg: TFullReg, isAssign2: bool): bool =
  439. let node = node2 # prevent double evaluation
  440. if node.kind == nkNilLit:
  441. stackTrace(c, tos, pc, errNilAccess)
  442. let typ = node.typ
  443. if nfIsPtr in node.flags or (typ != nil and typ.kind == tyPtr):
  444. assert node.kind == nkIntLit, $(node.kind)
  445. assert typ != nil
  446. let typ2 = if typ.kind == tyPtr: typ[0] else: typ
  447. if not derefPtrToReg(node.intVal, typ2, reg, isAssign = isAssign2):
  448. # tyObject not supported in this context
  449. stackTrace(c, tos, pc, "deref unsupported ptr type: " & $(typeToString(typ), typ.kind))
  450. true
  451. else:
  452. false
  453. when not defined(nimHasSinkInference):
  454. {.pragma: nosinks.}
  455. proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
  456. var pc = start
  457. var tos = tos
  458. # Used to keep track of where the execution is resumed.
  459. var savedPC = -1
  460. var savedFrame: PStackFrame
  461. var regs: seq[TFullReg] # alias to tos.slots for performance
  462. move(regs, tos.slots)
  463. #echo "NEW RUN ------------------------"
  464. while true:
  465. #{.computedGoto.}
  466. let instr = c.code[pc]
  467. let ra = instr.regA
  468. when traceCode:
  469. template regDescr(name, r): string =
  470. let kind = if r < regs.len: $regs[r].kind else: ""
  471. let ret = name & ": " & $r & " " & $kind
  472. alignLeft(ret, 15)
  473. echo "PC:$pc $opcode $ra $rb $rc" % [
  474. "pc", $pc, "opcode", alignLeft($c.code[pc].opcode, 15),
  475. "ra", regDescr("ra", ra), "rb", regDescr("rb", instr.regB),
  476. "rc", regDescr("rc", instr.regC)]
  477. c.profiler.enter(c, tos)
  478. case instr.opcode
  479. of opcEof: return regs[ra]
  480. of opcRet:
  481. let newPc = c.cleanUpOnReturn(tos)
  482. # Perform any cleanup action before returning
  483. if newPc < 0:
  484. pc = tos.comesFrom
  485. tos = tos.next
  486. let retVal = regs[0]
  487. if tos.isNil:
  488. return retVal
  489. move(regs, tos.slots)
  490. assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
  491. if c.code[pc].opcode == opcIndCallAsgn:
  492. regs[c.code[pc].regA] = retVal
  493. else:
  494. savedPC = pc
  495. savedFrame = tos
  496. # The -1 is needed because at the end of the loop we increment `pc`
  497. pc = newPc - 1
  498. of opcYldYoid: assert false
  499. of opcYldVal: assert false
  500. of opcAsgnInt:
  501. decodeB(rkInt)
  502. regs[ra].intVal = regs[rb].intVal
  503. of opcAsgnFloat:
  504. decodeB(rkFloat)
  505. regs[ra].floatVal = regs[rb].floatVal
  506. of opcCastFloatToInt32:
  507. let rb = instr.regB
  508. ensureKind(rkInt)
  509. regs[ra].intVal = cast[int32](float32(regs[rb].floatVal))
  510. of opcCastFloatToInt64:
  511. let rb = instr.regB
  512. ensureKind(rkInt)
  513. regs[ra].intVal = cast[int64](regs[rb].floatVal)
  514. of opcCastIntToFloat32:
  515. let rb = instr.regB
  516. ensureKind(rkFloat)
  517. regs[ra].floatVal = cast[float32](regs[rb].intVal)
  518. of opcCastIntToFloat64:
  519. let rb = instr.regB
  520. ensureKind(rkFloat)
  521. regs[ra].floatVal = cast[float64](regs[rb].intVal)
  522. of opcCastPtrToInt: # RENAME opcCastPtrOrRefToInt
  523. decodeBImm(rkInt)
  524. case imm
  525. of 1: # PtrLikeKinds
  526. case regs[rb].kind
  527. of rkNode:
  528. regs[ra].intVal = cast[int](regs[rb].node.intVal)
  529. of rkNodeAddr:
  530. regs[ra].intVal = cast[int](regs[rb].nodeAddr)
  531. else:
  532. stackTrace(c, tos, pc, "opcCastPtrToInt: got " & $regs[rb].kind)
  533. of 2: # tyRef
  534. regs[ra].intVal = cast[int](regs[rb].node)
  535. else: assert false, $imm
  536. of opcCastIntToPtr:
  537. let rb = instr.regB
  538. let typ = regs[ra].node.typ
  539. let node2 = newNodeIT(nkIntLit, c.debug[pc], typ)
  540. case regs[rb].kind
  541. of rkInt: node2.intVal = regs[rb].intVal
  542. of rkNode:
  543. if regs[rb].node.typ.kind notin PtrLikeKinds:
  544. stackTrace(c, tos, pc, "opcCastIntToPtr: regs[rb].node.typ: " & $regs[rb].node.typ.kind)
  545. node2.intVal = regs[rb].node.intVal
  546. else: stackTrace(c, tos, pc, "opcCastIntToPtr: regs[rb].kind: " & $regs[rb].kind)
  547. regs[ra].node = node2
  548. of opcAsgnComplex:
  549. asgnComplex(regs[ra], regs[instr.regB])
  550. of opcFastAsgnComplex:
  551. fastAsgnComplex(regs[ra], regs[instr.regB])
  552. of opcAsgnRef:
  553. asgnRef(regs[ra], regs[instr.regB])
  554. of opcNodeToReg:
  555. let ra = instr.regA
  556. let rb = instr.regB
  557. # opcDeref might already have loaded it into a register. XXX Let's hope
  558. # this is still correct this way:
  559. if regs[rb].kind != rkNode:
  560. regs[ra] = regs[rb]
  561. else:
  562. assert regs[rb].kind == rkNode
  563. let nb = regs[rb].node
  564. case nb.kind
  565. of nkCharLit..nkUInt64Lit:
  566. ensureKind(rkInt)
  567. regs[ra].intVal = nb.intVal
  568. of nkFloatLit..nkFloat64Lit:
  569. ensureKind(rkFloat)
  570. regs[ra].floatVal = nb.floatVal
  571. else:
  572. ensureKind(rkNode)
  573. regs[ra].node = nb
  574. of opcLdArr:
  575. # a = b[c]
  576. decodeBC(rkNode)
  577. if regs[rc].intVal > high(int):
  578. stackTrace(c, tos, pc, formatErrorIndexBound(regs[rc].intVal, high(int)))
  579. let idx = regs[rc].intVal.int
  580. let src = regs[rb].node
  581. if src.kind in {nkStrLit..nkTripleStrLit}:
  582. if idx <% src.strVal.len:
  583. regs[ra].node = newNodeI(nkCharLit, c.debug[pc])
  584. regs[ra].node.intVal = src.strVal[idx].ord
  585. else:
  586. stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.strVal.len-1))
  587. elif src.kind notin {nkEmpty..nkFloat128Lit} and idx <% src.len:
  588. regs[ra].node = src[idx]
  589. else:
  590. stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.safeLen-1))
  591. of opcLdArrAddr:
  592. # a = addr(b[c])
  593. decodeBC(rkNodeAddr)
  594. if regs[rc].intVal > high(int):
  595. stackTrace(c, tos, pc, formatErrorIndexBound(regs[rc].intVal, high(int)))
  596. let idx = regs[rc].intVal.int
  597. let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[]
  598. if src.kind notin {nkEmpty..nkTripleStrLit} and idx <% src.len:
  599. regs[ra].nodeAddr = addr src.sons[idx]
  600. else:
  601. stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.safeLen-1))
  602. of opcLdStrIdx:
  603. decodeBC(rkInt)
  604. let idx = regs[rc].intVal.int
  605. let s = regs[rb].node.strVal
  606. if idx <% s.len:
  607. regs[ra].intVal = s[idx].ord
  608. else:
  609. stackTrace(c, tos, pc, formatErrorIndexBound(idx, s.len-1))
  610. of opcWrArr:
  611. # a[b] = c
  612. decodeBC(rkNode)
  613. let idx = regs[rb].intVal.int
  614. let arr = regs[ra].node
  615. if arr.kind in {nkStrLit..nkTripleStrLit}:
  616. if idx <% arr.strVal.len:
  617. arr.strVal[idx] = chr(regs[rc].intVal)
  618. else:
  619. stackTrace(c, tos, pc, formatErrorIndexBound(idx, arr.strVal.len-1))
  620. elif idx <% arr.len:
  621. writeField(arr[idx], regs[rc])
  622. else:
  623. stackTrace(c, tos, pc, formatErrorIndexBound(idx, arr.safeLen-1))
  624. of opcLdObj:
  625. # a = b.c
  626. decodeBC(rkNode)
  627. let src = regs[rb].node
  628. case src.kind
  629. of nkEmpty..nkNilLit:
  630. # for nkPtrLit, this could be supported in the future, use something like:
  631. # derefPtrToReg(src.intVal + offsetof(src.typ, rc), typ_field, regs[ra], isAssign = false)
  632. # where we compute the offset in bytes for field rc
  633. stackTrace(c, tos, pc, errNilAccess & " " & $("kind", src.kind, "typ", typeToString(src.typ), "rc", rc))
  634. of nkObjConstr:
  635. let n = src[rc + 1].skipColon
  636. regs[ra].node = n
  637. else:
  638. let n = src[rc]
  639. regs[ra].node = n
  640. of opcLdObjAddr:
  641. # a = addr(b.c)
  642. decodeBC(rkNodeAddr)
  643. let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[]
  644. case src.kind
  645. of nkEmpty..nkNilLit:
  646. stackTrace(c, tos, pc, errNilAccess)
  647. of nkObjConstr:
  648. let n = src.sons[rc + 1]
  649. if n.kind == nkExprColonExpr:
  650. regs[ra].nodeAddr = addr n.sons[1]
  651. else:
  652. regs[ra].nodeAddr = addr src.sons[rc + 1]
  653. else:
  654. regs[ra].nodeAddr = addr src.sons[rc]
  655. of opcWrObj:
  656. # a.b = c
  657. decodeBC(rkNode)
  658. assert regs[ra].node != nil
  659. let shiftedRb = rb + ord(regs[ra].node.kind == nkObjConstr)
  660. let dest = regs[ra].node
  661. if dest.kind == nkNilLit:
  662. stackTrace(c, tos, pc, errNilAccess)
  663. elif dest[shiftedRb].kind == nkExprColonExpr:
  664. writeField(dest[shiftedRb][1], regs[rc])
  665. else:
  666. writeField(dest[shiftedRb], regs[rc])
  667. of opcWrStrIdx:
  668. decodeBC(rkNode)
  669. let idx = regs[rb].intVal.int
  670. if idx <% regs[ra].node.strVal.len:
  671. regs[ra].node.strVal[idx] = chr(regs[rc].intVal)
  672. else:
  673. stackTrace(c, tos, pc, formatErrorIndexBound(idx, regs[ra].node.strVal.len-1))
  674. of opcAddrReg:
  675. decodeB(rkRegisterAddr)
  676. regs[ra].regAddr = addr(regs[rb])
  677. of opcAddrNode:
  678. decodeB(rkNodeAddr)
  679. if regs[rb].kind == rkNode:
  680. regs[ra].nodeAddr = addr(regs[rb].node)
  681. else:
  682. stackTrace(c, tos, pc, "limited VM support for 'addr'")
  683. of opcLdDeref:
  684. # a = b[]
  685. let ra = instr.regA
  686. let rb = instr.regB
  687. case regs[rb].kind
  688. of rkNodeAddr:
  689. ensureKind(rkNode)
  690. regs[ra].node = regs[rb].nodeAddr[]
  691. of rkRegisterAddr:
  692. ensureKind(regs[rb].regAddr.kind)
  693. regs[ra] = regs[rb].regAddr[]
  694. of rkNode:
  695. if regs[rb].node.kind == nkRefTy:
  696. regs[ra].node = regs[rb].node[0]
  697. elif not maybeHandlePtr(regs[rb].node, regs[ra], false):
  698. ## eg: typ.kind = tyObject
  699. ensureKind(rkNode)
  700. regs[ra].node = regs[rb].node
  701. else:
  702. stackTrace(c, tos, pc, errNilAccess & " kind: " & $regs[rb].kind)
  703. of opcWrDeref:
  704. # a[] = c; b unused
  705. let ra = instr.regA
  706. let rc = instr.regC
  707. case regs[ra].kind
  708. of rkNodeAddr:
  709. let n = regs[rc].regToNode
  710. # `var object` parameters are sent as rkNodeAddr. When they are mutated
  711. # vmgen generates opcWrDeref, which means that we must dereference
  712. # twice.
  713. # TODO: This should likely be handled differently in vmgen.
  714. if (nfIsRef notin regs[ra].nodeAddr[].flags and
  715. nfIsRef notin n.flags):
  716. regs[ra].nodeAddr[][] = n[]
  717. else:
  718. regs[ra].nodeAddr[] = n
  719. of rkRegisterAddr: regs[ra].regAddr[] = regs[rc]
  720. of rkNode:
  721. # xxx: also check for nkRefTy as in opcLdDeref?
  722. if not maybeHandlePtr(regs[ra].node, regs[rc], true):
  723. regs[ra].node[] = regs[rc].regToNode[]
  724. regs[ra].node.flags.incl nfIsRef
  725. else: stackTrace(c, tos, pc, errNilAccess)
  726. of opcAddInt:
  727. decodeBC(rkInt)
  728. let
  729. bVal = regs[rb].intVal
  730. cVal = regs[rc].intVal
  731. sum = bVal +% cVal
  732. if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
  733. regs[ra].intVal = sum
  734. else:
  735. stackTrace(c, tos, pc, errOverOrUnderflow)
  736. of opcAddImmInt:
  737. decodeBImm(rkInt)
  738. #message(c.config, c.debug[pc], warnUser, "came here")
  739. #debug regs[rb].node
  740. let
  741. bVal = regs[rb].intVal
  742. cVal = imm
  743. sum = bVal +% cVal
  744. if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
  745. regs[ra].intVal = sum
  746. else:
  747. stackTrace(c, tos, pc, errOverOrUnderflow)
  748. of opcSubInt:
  749. decodeBC(rkInt)
  750. let
  751. bVal = regs[rb].intVal
  752. cVal = regs[rc].intVal
  753. diff = bVal -% cVal
  754. if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
  755. regs[ra].intVal = diff
  756. else:
  757. stackTrace(c, tos, pc, errOverOrUnderflow)
  758. of opcSubImmInt:
  759. decodeBImm(rkInt)
  760. let
  761. bVal = regs[rb].intVal
  762. cVal = imm
  763. diff = bVal -% cVal
  764. if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
  765. regs[ra].intVal = diff
  766. else:
  767. stackTrace(c, tos, pc, errOverOrUnderflow)
  768. of opcLenSeq:
  769. decodeBImm(rkInt)
  770. #assert regs[rb].kind == nkBracket
  771. let high = (imm and 1) # discard flags
  772. if (imm and nimNodeFlag) != 0:
  773. # used by mNLen (NimNode.len)
  774. regs[ra].intVal = regs[rb].node.safeLen - high
  775. else:
  776. # safeArrLen also return string node len
  777. # used when string is passed as openArray in VM
  778. regs[ra].intVal = regs[rb].node.safeArrLen - high
  779. of opcLenStr:
  780. decodeBImm(rkInt)
  781. assert regs[rb].kind == rkNode
  782. regs[ra].intVal = regs[rb].node.strVal.len - imm
  783. of opcIncl:
  784. decodeB(rkNode)
  785. let b = regs[rb].regToNode
  786. if not inSet(regs[ra].node, b):
  787. regs[ra].node.add copyTree(b)
  788. of opcInclRange:
  789. decodeBC(rkNode)
  790. var r = newNode(nkRange)
  791. r.add regs[rb].regToNode
  792. r.add regs[rc].regToNode
  793. regs[ra].node.add r.copyTree
  794. of opcExcl:
  795. decodeB(rkNode)
  796. var b = newNodeIT(nkCurly, regs[ra].node.info, regs[ra].node.typ)
  797. b.add regs[rb].regToNode
  798. var r = diffSets(c.config, regs[ra].node, b)
  799. discardSons(regs[ra].node)
  800. for i in 0..<r.len: regs[ra].node.add r[i]
  801. of opcCard:
  802. decodeB(rkInt)
  803. regs[ra].intVal = nimsets.cardSet(c.config, regs[rb].node)
  804. of opcMulInt:
  805. decodeBC(rkInt)
  806. let
  807. bVal = regs[rb].intVal
  808. cVal = regs[rc].intVal
  809. product = bVal *% cVal
  810. floatProd = toBiggestFloat(bVal) * toBiggestFloat(cVal)
  811. resAsFloat = toBiggestFloat(product)
  812. if resAsFloat == floatProd:
  813. regs[ra].intVal = product
  814. elif 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
  815. regs[ra].intVal = product
  816. else:
  817. stackTrace(c, tos, pc, errOverOrUnderflow)
  818. of opcDivInt:
  819. decodeBC(rkInt)
  820. if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
  821. else: regs[ra].intVal = regs[rb].intVal div regs[rc].intVal
  822. of opcModInt:
  823. decodeBC(rkInt)
  824. if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
  825. else: regs[ra].intVal = regs[rb].intVal mod regs[rc].intVal
  826. of opcAddFloat:
  827. decodeBC(rkFloat)
  828. regs[ra].floatVal = regs[rb].floatVal + regs[rc].floatVal
  829. of opcSubFloat:
  830. decodeBC(rkFloat)
  831. regs[ra].floatVal = regs[rb].floatVal - regs[rc].floatVal
  832. of opcMulFloat:
  833. decodeBC(rkFloat)
  834. regs[ra].floatVal = regs[rb].floatVal * regs[rc].floatVal
  835. of opcDivFloat:
  836. decodeBC(rkFloat)
  837. regs[ra].floatVal = regs[rb].floatVal / regs[rc].floatVal
  838. of opcShrInt:
  839. decodeBC(rkInt)
  840. let b = cast[uint64](regs[rb].intVal)
  841. let c = cast[uint64](regs[rc].intVal)
  842. let a = cast[int64](b shr c)
  843. regs[ra].intVal = a
  844. of opcShlInt:
  845. decodeBC(rkInt)
  846. regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal
  847. of opcAshrInt:
  848. decodeBC(rkInt)
  849. regs[ra].intVal = ashr(regs[rb].intVal, regs[rc].intVal)
  850. of opcBitandInt:
  851. decodeBC(rkInt)
  852. regs[ra].intVal = regs[rb].intVal and regs[rc].intVal
  853. of opcBitorInt:
  854. decodeBC(rkInt)
  855. regs[ra].intVal = regs[rb].intVal or regs[rc].intVal
  856. of opcBitxorInt:
  857. decodeBC(rkInt)
  858. regs[ra].intVal = regs[rb].intVal xor regs[rc].intVal
  859. of opcAddu:
  860. decodeBC(rkInt)
  861. regs[ra].intVal = regs[rb].intVal +% regs[rc].intVal
  862. of opcSubu:
  863. decodeBC(rkInt)
  864. regs[ra].intVal = regs[rb].intVal -% regs[rc].intVal
  865. of opcMulu:
  866. decodeBC(rkInt)
  867. regs[ra].intVal = regs[rb].intVal *% regs[rc].intVal
  868. of opcDivu:
  869. decodeBC(rkInt)
  870. regs[ra].intVal = regs[rb].intVal /% regs[rc].intVal
  871. of opcModu:
  872. decodeBC(rkInt)
  873. regs[ra].intVal = regs[rb].intVal %% regs[rc].intVal
  874. of opcEqInt:
  875. decodeBC(rkInt)
  876. regs[ra].intVal = ord(regs[rb].intVal == regs[rc].intVal)
  877. of opcLeInt:
  878. decodeBC(rkInt)
  879. regs[ra].intVal = ord(regs[rb].intVal <= regs[rc].intVal)
  880. of opcLtInt:
  881. decodeBC(rkInt)
  882. regs[ra].intVal = ord(regs[rb].intVal < regs[rc].intVal)
  883. of opcEqFloat:
  884. decodeBC(rkInt)
  885. regs[ra].intVal = ord(regs[rb].floatVal == regs[rc].floatVal)
  886. of opcLeFloat:
  887. decodeBC(rkInt)
  888. regs[ra].intVal = ord(regs[rb].floatVal <= regs[rc].floatVal)
  889. of opcLtFloat:
  890. decodeBC(rkInt)
  891. regs[ra].intVal = ord(regs[rb].floatVal < regs[rc].floatVal)
  892. of opcLeu:
  893. decodeBC(rkInt)
  894. regs[ra].intVal = ord(regs[rb].intVal <=% regs[rc].intVal)
  895. of opcLtu:
  896. decodeBC(rkInt)
  897. regs[ra].intVal = ord(regs[rb].intVal <% regs[rc].intVal)
  898. of opcEqRef:
  899. var ret = false
  900. decodeBC(rkInt)
  901. template getTyp(n): untyped =
  902. n.typ.skipTypes(abstractInst)
  903. proc ptrEquality(n1: ptr PNode, n2: PNode): bool =
  904. ## true if n2.intVal represents a ptr equal to n1
  905. let p1 = cast[int](n1)
  906. case n2.kind
  907. of nkNilLit: return p1 == 0
  908. of nkIntLit: # TODO: nkPtrLit
  909. # for example, n1.kind == nkFloatLit (ptr float)
  910. # the problem is that n1.typ == nil so we can't compare n1.typ and n2.typ
  911. # this is the best we can do (pending making sure we assign a valid n1.typ to nodeAddr's)
  912. let t2 = n2.getTyp
  913. return t2.kind in PtrLikeKinds and n2.intVal == p1
  914. else: return false
  915. if regs[rb].kind == rkNodeAddr:
  916. if regs[rc].kind == rkNodeAddr:
  917. ret = regs[rb].nodeAddr == regs[rc].nodeAddr
  918. else:
  919. ret = ptrEquality(regs[rb].nodeAddr, regs[rc].node)
  920. elif regs[rc].kind == rkNodeAddr:
  921. ret = ptrEquality(regs[rc].nodeAddr, regs[rb].node)
  922. else:
  923. let nb = regs[rb].node
  924. let nc = regs[rc].node
  925. if nb.kind != nc.kind: discard
  926. elif (nb == nc) or (nb.kind == nkNilLit): ret = true
  927. elif nb.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit
  928. let tb = nb.getTyp
  929. let tc = nc.getTyp
  930. ret = tb.kind in PtrLikeKinds and tc.kind == tb.kind
  931. regs[ra].intVal = ord(ret)
  932. of opcEqNimNode:
  933. decodeBC(rkInt)
  934. regs[ra].intVal =
  935. ord(exprStructuralEquivalent(regs[rb].node, regs[rc].node,
  936. strictSymEquality=true))
  937. of opcSameNodeType:
  938. decodeBC(rkInt)
  939. regs[ra].intVal = ord(regs[rb].node.typ.sameTypeOrNil regs[rc].node.typ)
  940. of opcXor:
  941. decodeBC(rkInt)
  942. regs[ra].intVal = ord(regs[rb].intVal != regs[rc].intVal)
  943. of opcNot:
  944. decodeB(rkInt)
  945. assert regs[rb].kind == rkInt
  946. regs[ra].intVal = 1 - regs[rb].intVal
  947. of opcUnaryMinusInt:
  948. decodeB(rkInt)
  949. assert regs[rb].kind == rkInt
  950. let val = regs[rb].intVal
  951. if val != int64.low:
  952. regs[ra].intVal = -val
  953. else:
  954. stackTrace(c, tos, pc, errOverOrUnderflow)
  955. of opcUnaryMinusFloat:
  956. decodeB(rkFloat)
  957. assert regs[rb].kind == rkFloat
  958. regs[ra].floatVal = -regs[rb].floatVal
  959. of opcBitnotInt:
  960. decodeB(rkInt)
  961. assert regs[rb].kind == rkInt
  962. regs[ra].intVal = not regs[rb].intVal
  963. of opcEqStr:
  964. decodeBC(rkInt)
  965. regs[ra].intVal = ord(regs[rb].node.strVal == regs[rc].node.strVal)
  966. of opcLeStr:
  967. decodeBC(rkInt)
  968. regs[ra].intVal = ord(regs[rb].node.strVal <= regs[rc].node.strVal)
  969. of opcLtStr:
  970. decodeBC(rkInt)
  971. regs[ra].intVal = ord(regs[rb].node.strVal < regs[rc].node.strVal)
  972. of opcLeSet:
  973. decodeBC(rkInt)
  974. regs[ra].intVal = ord(containsSets(c.config, regs[rb].node, regs[rc].node))
  975. of opcEqSet:
  976. decodeBC(rkInt)
  977. regs[ra].intVal = ord(equalSets(c.config, regs[rb].node, regs[rc].node))
  978. of opcLtSet:
  979. decodeBC(rkInt)
  980. let a = regs[rb].node
  981. let b = regs[rc].node
  982. regs[ra].intVal = ord(containsSets(c.config, a, b) and not equalSets(c.config, a, b))
  983. of opcMulSet:
  984. decodeBC(rkNode)
  985. createSet(regs[ra])
  986. move(regs[ra].node.sons,
  987. nimsets.intersectSets(c.config, regs[rb].node, regs[rc].node).sons)
  988. of opcPlusSet:
  989. decodeBC(rkNode)
  990. createSet(regs[ra])
  991. move(regs[ra].node.sons,
  992. nimsets.unionSets(c.config, regs[rb].node, regs[rc].node).sons)
  993. of opcMinusSet:
  994. decodeBC(rkNode)
  995. createSet(regs[ra])
  996. move(regs[ra].node.sons,
  997. nimsets.diffSets(c.config, regs[rb].node, regs[rc].node).sons)
  998. of opcConcatStr:
  999. decodeBC(rkNode)
  1000. createStr regs[ra]
  1001. regs[ra].node.strVal = getstr(regs[rb])
  1002. for i in rb+1..rb+rc-1:
  1003. regs[ra].node.strVal.add getstr(regs[i])
  1004. of opcAddStrCh:
  1005. decodeB(rkNode)
  1006. regs[ra].node.strVal.add(regs[rb].intVal.chr)
  1007. of opcAddStrStr:
  1008. decodeB(rkNode)
  1009. regs[ra].node.strVal.add(regs[rb].node.strVal)
  1010. of opcAddSeqElem:
  1011. decodeB(rkNode)
  1012. if regs[ra].node.kind == nkBracket:
  1013. regs[ra].node.add(copyValue(regs[rb].regToNode))
  1014. else:
  1015. stackTrace(c, tos, pc, errNilAccess)
  1016. of opcGetImpl:
  1017. decodeB(rkNode)
  1018. var a = regs[rb].node
  1019. if a.kind == nkVarTy: a = a[0]
  1020. if a.kind == nkSym:
  1021. regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
  1022. else: copyTree(a.sym.ast)
  1023. regs[ra].node.flags.incl nfIsRef
  1024. else:
  1025. stackTrace(c, tos, pc, "node is not a symbol")
  1026. of opcGetImplTransf:
  1027. decodeB(rkNode)
  1028. let a = regs[rb].node
  1029. if a.kind == nkSym:
  1030. regs[ra].node =
  1031. if a.sym.ast.isNil:
  1032. newNode(nkNilLit)
  1033. else:
  1034. let ast = a.sym.ast.shallowCopy
  1035. for i in 0..<a.sym.ast.len:
  1036. ast[i] = a.sym.ast[i]
  1037. ast[bodyPos] = transformBody(c.graph, a.sym, cache=true)
  1038. ast.copyTree()
  1039. of opcSymOwner:
  1040. decodeB(rkNode)
  1041. let a = regs[rb].node
  1042. if a.kind == nkSym:
  1043. regs[ra].node = if a.sym.owner.isNil: newNode(nkNilLit)
  1044. else: newSymNode(a.sym.skipGenericOwner)
  1045. regs[ra].node.flags.incl nfIsRef
  1046. else:
  1047. stackTrace(c, tos, pc, "node is not a symbol")
  1048. of opcSymIsInstantiationOf:
  1049. decodeBC(rkInt)
  1050. let a = regs[rb].node
  1051. let b = regs[rc].node
  1052. if a.kind == nkSym and a.sym.kind in skProcKinds and
  1053. b.kind == nkSym and b.sym.kind in skProcKinds:
  1054. regs[ra].intVal =
  1055. if sfFromGeneric in a.sym.flags and a.sym.owner == b.sym: 1
  1056. else: 0
  1057. else:
  1058. stackTrace(c, tos, pc, "node is not a proc symbol")
  1059. of opcEcho:
  1060. let rb = instr.regB
  1061. if rb == 1:
  1062. msgWriteln(c.config, regs[ra].node.strVal, {msgStdout})
  1063. else:
  1064. var outp = ""
  1065. for i in ra..ra+rb-1:
  1066. #if regs[i].kind != rkNode: debug regs[i]
  1067. outp.add(regs[i].node.strVal)
  1068. msgWriteln(c.config, outp, {msgStdout})
  1069. of opcContainsSet:
  1070. decodeBC(rkInt)
  1071. regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
  1072. of opcSubStr:
  1073. decodeBC(rkNode)
  1074. inc pc
  1075. assert c.code[pc].opcode == opcSubStr
  1076. let rd = c.code[pc].regA
  1077. createStr regs[ra]
  1078. regs[ra].node.strVal = substr(regs[rb].node.strVal,
  1079. regs[rc].intVal.int, regs[rd].intVal.int)
  1080. of opcParseFloat:
  1081. decodeBC(rkInt)
  1082. inc pc
  1083. assert c.code[pc].opcode == opcParseFloat
  1084. let rd = c.code[pc].regA
  1085. var rcAddr = addr(regs[rc])
  1086. if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr
  1087. elif regs[rc].kind != rkFloat:
  1088. regs[rc] = TFullReg(kind: rkFloat)
  1089. regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal,
  1090. rcAddr.floatVal, regs[rd].intVal.int)
  1091. of opcRangeChck:
  1092. let rb = instr.regB
  1093. let rc = instr.regC
  1094. if not (leValueConv(regs[rb].regToNode, regs[ra].regToNode) and
  1095. leValueConv(regs[ra].regToNode, regs[rc].regToNode)):
  1096. stackTrace(c, tos, pc,
  1097. errIllegalConvFromXtoY % [
  1098. $regs[ra].regToNode, "[" & $regs[rb].regToNode & ".." & $regs[rc].regToNode & "]"])
  1099. of opcIndCall, opcIndCallAsgn:
  1100. # dest = call regStart, n; where regStart = fn, arg1, ...
  1101. let rb = instr.regB
  1102. let rc = instr.regC
  1103. let bb = regs[rb].node
  1104. let isClosure = bb.kind == nkTupleConstr
  1105. let prc = if not isClosure: bb.sym else: bb[0].sym
  1106. if prc.offset < -1:
  1107. # it's a callback:
  1108. c.callbacks[-prc.offset-2].value(
  1109. VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[ptr UncheckedArray[TFullReg]](addr regs[0]),
  1110. currentException: c.currentExceptionA,
  1111. currentLineInfo: c.debug[pc]))
  1112. elif importcCond(prc):
  1113. if compiletimeFFI notin c.config.features:
  1114. globalError(c.config, c.debug[pc], "VM not allowed to do FFI, see `compiletimeFFI`")
  1115. # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
  1116. # 'regs' in a register:
  1117. when hasFFI:
  1118. if prc.position - 1 < 0:
  1119. globalError(c.config, c.debug[pc],
  1120. "VM call invalid: prc.position: " & $prc.position)
  1121. let prcValue = c.globals[prc.position-1]
  1122. if prcValue.kind == nkEmpty:
  1123. globalError(c.config, c.debug[pc], "cannot run " & prc.name.s)
  1124. var slots2: TNodeSeq
  1125. slots2.setLen(tos.slots.len)
  1126. for i in 0..<tos.slots.len:
  1127. slots2[i] = regToNode(tos.slots[i])
  1128. let newValue = callForeignFunction(c.config, prcValue, prc.typ, slots2,
  1129. rb+1, rc-1, c.debug[pc])
  1130. if newValue.kind != nkEmpty:
  1131. assert instr.opcode == opcIndCallAsgn
  1132. putIntoReg(regs[ra], newValue)
  1133. else:
  1134. globalError(c.config, c.debug[pc], "VM not built with FFI support")
  1135. elif prc.kind != skTemplate:
  1136. let newPc = compile(c, prc)
  1137. # tricky: a recursion is also a jump back, so we use the same
  1138. # logic as for loops:
  1139. if newPc < pc: handleJmpBack()
  1140. #echo "new pc ", newPc, " calling: ", prc.name.s
  1141. var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
  1142. newSeq(newFrame.slots, prc.offset+ord(isClosure))
  1143. if not isEmptyType(prc.typ[0]):
  1144. putIntoReg(newFrame.slots[0], getNullValue(prc.typ[0], prc.info, c.config))
  1145. for i in 1..rc-1:
  1146. newFrame.slots[i] = regs[rb+i]
  1147. if isClosure:
  1148. newFrame.slots[rc] = TFullReg(kind: rkNode, node: regs[rb].node[1])
  1149. tos = newFrame
  1150. move(regs, newFrame.slots)
  1151. # -1 for the following 'inc pc'
  1152. pc = newPc-1
  1153. else:
  1154. # for 'getAst' support we need to support template expansion here:
  1155. let genSymOwner = if tos.next != nil and tos.next.prc != nil:
  1156. tos.next.prc
  1157. else:
  1158. c.module
  1159. var macroCall = newNodeI(nkCall, c.debug[pc])
  1160. macroCall.add(newSymNode(prc))
  1161. for i in 1..rc-1:
  1162. let node = regs[rb+i].regToNode
  1163. node.info = c.debug[pc]
  1164. macroCall.add(node)
  1165. var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter)
  1166. if a.kind == nkStmtList and a.len == 1: a = a[0]
  1167. a.recSetFlagIsRef
  1168. ensureKind(rkNode)
  1169. regs[ra].node = a
  1170. of opcTJmp:
  1171. # jump Bx if A != 0
  1172. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1173. if regs[ra].intVal != 0:
  1174. inc pc, rbx
  1175. of opcFJmp:
  1176. # jump Bx if A == 0
  1177. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1178. if regs[ra].intVal == 0:
  1179. inc pc, rbx
  1180. of opcJmp:
  1181. # jump Bx
  1182. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1183. inc pc, rbx
  1184. of opcJmpBack:
  1185. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1186. inc pc, rbx
  1187. handleJmpBack()
  1188. of opcBranch:
  1189. # we know the next instruction is a 'fjmp':
  1190. let branch = c.constants[instr.regBx-wordExcess]
  1191. var cond = false
  1192. for j in 0..<branch.len - 1:
  1193. if overlap(regs[ra].regToNode, branch[j]):
  1194. cond = true
  1195. break
  1196. assert c.code[pc+1].opcode == opcFJmp
  1197. inc pc
  1198. # we skip this instruction so that the final 'inc(pc)' skips
  1199. # the following jump
  1200. if not cond:
  1201. let instr2 = c.code[pc]
  1202. let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1203. inc pc, rbx
  1204. of opcTry:
  1205. let rbx = instr.regBx - wordExcess
  1206. tos.pushSafePoint(pc + rbx)
  1207. assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
  1208. of opcExcept:
  1209. # This opcode is never executed, it only holds information for the
  1210. # exception handling routines.
  1211. doAssert(false)
  1212. of opcFinally:
  1213. # Pop the last safepoint introduced by a opcTry. This opcode is only
  1214. # executed _iff_ no exception was raised in the body of the `try`
  1215. # statement hence the need to pop the safepoint here.
  1216. doAssert(savedPC < 0)
  1217. tos.popSafePoint()
  1218. of opcFinallyEnd:
  1219. # The control flow may not resume at the next instruction since we may be
  1220. # raising an exception or performing a cleanup.
  1221. if savedPC >= 0:
  1222. pc = savedPC - 1
  1223. savedPC = -1
  1224. if tos != savedFrame:
  1225. tos = savedFrame
  1226. move(regs, tos.slots)
  1227. of opcRaise:
  1228. let raised =
  1229. # Empty `raise` statement - reraise current exception
  1230. if regs[ra].kind == rkNone:
  1231. c.currentExceptionA
  1232. else:
  1233. regs[ra].node
  1234. c.currentExceptionA = raised
  1235. # Set the `name` field of the exception
  1236. c.currentExceptionA[2].skipColon.strVal = c.currentExceptionA.typ.sym.name.s
  1237. c.exceptionInstr = pc
  1238. var frame = tos
  1239. var jumpTo = findExceptionHandler(c, frame, raised)
  1240. while jumpTo.why == ExceptionGotoUnhandled and not frame.next.isNil:
  1241. frame = frame.next
  1242. jumpTo = findExceptionHandler(c, frame, raised)
  1243. case jumpTo.why:
  1244. of ExceptionGotoHandler:
  1245. # Jump to the handler, do nothing when the `finally` block ends.
  1246. savedPC = -1
  1247. pc = jumpTo.where - 1
  1248. if tos != frame:
  1249. tos = frame
  1250. move(regs, tos.slots)
  1251. of ExceptionGotoFinally:
  1252. # Jump to the `finally` block first then re-jump here to continue the
  1253. # traversal of the exception chain
  1254. savedPC = pc
  1255. savedFrame = tos
  1256. pc = jumpTo.where - 1
  1257. if tos != frame:
  1258. tos = frame
  1259. move(regs, tos.slots)
  1260. of ExceptionGotoUnhandled:
  1261. # Nobody handled this exception, error out.
  1262. bailOut(c, tos)
  1263. of opcNew:
  1264. ensureKind(rkNode)
  1265. let typ = c.types[instr.regBx - wordExcess]
  1266. regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
  1267. regs[ra].node.flags.incl nfIsRef
  1268. of opcNewSeq:
  1269. let typ = c.types[instr.regBx - wordExcess]
  1270. inc pc
  1271. ensureKind(rkNode)
  1272. let instr2 = c.code[pc]
  1273. let count = regs[instr2.regA].intVal.int
  1274. regs[ra].node = newNodeI(nkBracket, c.debug[pc])
  1275. regs[ra].node.typ = typ
  1276. newSeq(regs[ra].node.sons, count)
  1277. for i in 0..<count:
  1278. regs[ra].node[i] = getNullValue(typ[0], c.debug[pc], c.config)
  1279. of opcNewStr:
  1280. decodeB(rkNode)
  1281. regs[ra].node = newNodeI(nkStrLit, c.debug[pc])
  1282. regs[ra].node.strVal = newString(regs[rb].intVal.int)
  1283. of opcLdImmInt:
  1284. # dest = immediate value
  1285. decodeBx(rkInt)
  1286. regs[ra].intVal = rbx
  1287. of opcLdNull:
  1288. ensureKind(rkNode)
  1289. let typ = c.types[instr.regBx - wordExcess]
  1290. regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
  1291. # opcLdNull really is the gist of the VM's problems: should it load
  1292. # a fresh null to regs[ra].node or to regs[ra].node[]? This really
  1293. # depends on whether regs[ra] represents the variable itself or whether
  1294. # it holds the indirection! Due to the way registers are re-used we cannot
  1295. # say for sure here! --> The codegen has to deal with it
  1296. # via 'genAsgnPatch'.
  1297. of opcLdNullReg:
  1298. let typ = c.types[instr.regBx - wordExcess]
  1299. if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
  1300. tyFloat..tyFloat128}:
  1301. ensureKind(rkFloat)
  1302. regs[ra].floatVal = 0.0
  1303. else:
  1304. ensureKind(rkInt)
  1305. regs[ra].intVal = 0
  1306. of opcLdConst:
  1307. let rb = instr.regBx - wordExcess
  1308. let cnst = c.constants[rb]
  1309. if fitsRegister(cnst.typ):
  1310. reset(regs[ra])
  1311. putIntoReg(regs[ra], cnst)
  1312. else:
  1313. ensureKind(rkNode)
  1314. regs[ra].node = cnst
  1315. of opcAsgnConst:
  1316. let rb = instr.regBx - wordExcess
  1317. let cnst = c.constants[rb]
  1318. if fitsRegister(cnst.typ):
  1319. putIntoReg(regs[ra], cnst)
  1320. else:
  1321. ensureKind(rkNode)
  1322. regs[ra].node = cnst.copyTree
  1323. of opcLdGlobal:
  1324. let rb = instr.regBx - wordExcess - 1
  1325. ensureKind(rkNode)
  1326. regs[ra].node = c.globals[rb]
  1327. of opcLdGlobalDerefFFI:
  1328. let rb = instr.regBx - wordExcess - 1
  1329. let node = c.globals[rb]
  1330. let typ = node.typ
  1331. doAssert node.kind == nkIntLit, $(node.kind)
  1332. if typ.kind == tyPtr:
  1333. ensureKind(rkNode)
  1334. # use nkPtrLit once this is added
  1335. let node2 = newNodeIT(nkIntLit, c.debug[pc], typ)
  1336. node2.intVal = cast[ptr int](node.intVal)[]
  1337. node2.flags.incl nfIsPtr
  1338. regs[ra].node = node2
  1339. elif not derefPtrToReg(node.intVal, typ, regs[ra], isAssign = false):
  1340. stackTrace(c, tos, pc, "opcLdDeref unsupported type: " & $(typeToString(typ), typ[0].kind))
  1341. of opcLdGlobalAddrDerefFFI:
  1342. let rb = instr.regBx - wordExcess - 1
  1343. let node = c.globals[rb]
  1344. let typ = node.typ
  1345. var node2 = newNodeIT(nkIntLit, node.info, typ)
  1346. node2.intVal = node.intVal
  1347. node2.flags.incl nfIsPtr
  1348. ensureKind(rkNode)
  1349. regs[ra].node = node2
  1350. of opcLdGlobalAddr:
  1351. let rb = instr.regBx - wordExcess - 1
  1352. ensureKind(rkNodeAddr)
  1353. regs[ra].nodeAddr = addr(c.globals[rb])
  1354. of opcRepr:
  1355. decodeB(rkNode)
  1356. createStr regs[ra]
  1357. regs[ra].node.strVal = renderTree(regs[rb].regToNode, {renderNoComments, renderDocComments})
  1358. of opcQuit:
  1359. if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
  1360. message(c.config, c.debug[pc], hintQuitCalled)
  1361. msgQuit(int8(toInt(getOrdValue(regs[ra].regToNode, onError = toInt128(1)))))
  1362. else:
  1363. return TFullReg(kind: rkNone)
  1364. of opcInvalidField:
  1365. stackTrace(c, tos, pc, errFieldXNotFound & regs[ra].node.strVal)
  1366. of opcSetLenStr:
  1367. decodeB(rkNode)
  1368. #createStrKeepNode regs[ra]
  1369. regs[ra].node.strVal.setLen(regs[rb].intVal.int)
  1370. of opcOf:
  1371. decodeBC(rkInt)
  1372. let typ = c.types[regs[rc].intVal.int]
  1373. regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) <= 0)
  1374. of opcIs:
  1375. decodeBC(rkInt)
  1376. let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})
  1377. let t2 = c.types[regs[rc].intVal.int]
  1378. # XXX: This should use the standard isOpImpl
  1379. let match = if t2.kind == tyUserTypeClass: true
  1380. else: sameType(t1, t2)
  1381. regs[ra].intVal = ord(match)
  1382. of opcSetLenSeq:
  1383. decodeB(rkNode)
  1384. let newLen = regs[rb].intVal.int
  1385. if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
  1386. else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
  1387. of opcNarrowS:
  1388. decodeB(rkInt)
  1389. let min = -(1.BiggestInt shl (rb-1))
  1390. let max = (1.BiggestInt shl (rb-1))-1
  1391. if regs[ra].intVal < min or regs[ra].intVal > max:
  1392. stackTrace(c, tos, pc, "unhandled exception: value out of range")
  1393. of opcNarrowU:
  1394. decodeB(rkInt)
  1395. regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
  1396. of opcSignExtend:
  1397. # like opcNarrowS, but no out of range possible
  1398. decodeB(rkInt)
  1399. let imm = 64 - rb
  1400. regs[ra].intVal = ashr(regs[ra].intVal shl imm, imm)
  1401. of opcIsNil:
  1402. decodeB(rkInt)
  1403. let node = regs[rb].node
  1404. regs[ra].intVal = ord(
  1405. # Note that `nfIsRef` + `nkNilLit` represents an allocated
  1406. # reference with the value `nil`, so `isNil` should be false!
  1407. (node.kind == nkNilLit and nfIsRef notin node.flags) or
  1408. (not node.typ.isNil and node.typ.kind == tyProc and
  1409. node.typ.callConv == ccClosure and node[0].kind == nkNilLit and
  1410. node[1].kind == nkNilLit))
  1411. of opcNBindSym:
  1412. # cannot use this simple check
  1413. # if dynamicBindSym notin c.config.features:
  1414. # bindSym with static input
  1415. decodeBx(rkNode)
  1416. regs[ra].node = copyTree(c.constants[rbx])
  1417. regs[ra].node.flags.incl nfIsRef
  1418. of opcNDynBindSym:
  1419. # experimental bindSym
  1420. let
  1421. rb = instr.regB
  1422. rc = instr.regC
  1423. idx = int(regs[rb+rc-1].intVal)
  1424. callback = c.callbacks[idx].value
  1425. args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[ptr UncheckedArray[TFullReg]](addr regs[0]),
  1426. currentException: c.currentExceptionA,
  1427. currentLineInfo: c.debug[pc])
  1428. callback(args)
  1429. regs[ra].node.flags.incl nfIsRef
  1430. of opcNChild:
  1431. decodeBC(rkNode)
  1432. let idx = regs[rc].intVal.int
  1433. let src = regs[rb].node
  1434. if src.kind in {nkEmpty..nkNilLit}:
  1435. stackTrace(c, tos, pc, "cannot get child of node kind: n" & $src.kind)
  1436. elif idx >=% src.len:
  1437. stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.len-1))
  1438. else:
  1439. regs[ra].node = src[idx]
  1440. of opcNSetChild:
  1441. decodeBC(rkNode)
  1442. let idx = regs[rb].intVal.int
  1443. var dest = regs[ra].node
  1444. if nfSem in dest.flags and allowSemcheckedAstModification notin c.config.legacyFeatures:
  1445. stackTrace(c, tos, pc, "typechecked nodes may not be modified")
  1446. elif dest.kind in {nkEmpty..nkNilLit}:
  1447. stackTrace(c, tos, pc, "cannot set child of node kind: n" & $dest.kind)
  1448. elif idx >=% dest.len:
  1449. stackTrace(c, tos, pc, formatErrorIndexBound(idx, dest.len-1))
  1450. else:
  1451. dest[idx] = regs[rc].node
  1452. of opcNAdd:
  1453. decodeBC(rkNode)
  1454. var u = regs[rb].node
  1455. if nfSem in u.flags and allowSemcheckedAstModification notin c.config.legacyFeatures:
  1456. stackTrace(c, tos, pc, "typechecked nodes may not be modified")
  1457. elif u.kind in {nkEmpty..nkNilLit}:
  1458. stackTrace(c, tos, pc, "cannot add to node kind: n" & $u.kind)
  1459. else:
  1460. u.add(regs[rc].node)
  1461. regs[ra].node = u
  1462. of opcNAddMultiple:
  1463. decodeBC(rkNode)
  1464. let x = regs[rc].node
  1465. var u = regs[rb].node
  1466. if nfSem in u.flags and allowSemcheckedAstModification notin c.config.legacyFeatures:
  1467. stackTrace(c, tos, pc, "typechecked nodes may not be modified")
  1468. elif u.kind in {nkEmpty..nkNilLit}:
  1469. stackTrace(c, tos, pc, "cannot add to node kind: n" & $u.kind)
  1470. else:
  1471. for i in 0..<x.len: u.add(x[i])
  1472. regs[ra].node = u
  1473. of opcNKind:
  1474. decodeB(rkInt)
  1475. regs[ra].intVal = ord(regs[rb].node.kind)
  1476. c.comesFromHeuristic = regs[rb].node.info
  1477. of opcNSymKind:
  1478. decodeB(rkInt)
  1479. let a = regs[rb].node
  1480. if a.kind == nkSym:
  1481. regs[ra].intVal = ord(a.sym.kind)
  1482. else:
  1483. stackTrace(c, tos, pc, "node is not a symbol")
  1484. c.comesFromHeuristic = regs[rb].node.info
  1485. of opcNIntVal:
  1486. decodeB(rkInt)
  1487. let a = regs[rb].node
  1488. if a.kind in {nkCharLit..nkUInt64Lit}:
  1489. regs[ra].intVal = a.intVal
  1490. elif a.kind == nkSym and a.sym.kind == skEnumField:
  1491. regs[ra].intVal = a.sym.position
  1492. else:
  1493. stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
  1494. of opcNFloatVal:
  1495. decodeB(rkFloat)
  1496. let a = regs[rb].node
  1497. case a.kind
  1498. of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
  1499. else: stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
  1500. of opcNSymbol:
  1501. decodeB(rkNode)
  1502. let a = regs[rb].node
  1503. if a.kind == nkSym:
  1504. regs[ra].node = copyNode(a)
  1505. else:
  1506. stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
  1507. of opcNIdent:
  1508. decodeB(rkNode)
  1509. let a = regs[rb].node
  1510. if a.kind == nkIdent:
  1511. regs[ra].node = copyNode(a)
  1512. else:
  1513. stackTrace(c, tos, pc, errFieldXNotFound & "ident")
  1514. of opcNodeId:
  1515. decodeB(rkInt)
  1516. when defined(useNodeIds):
  1517. regs[ra].intVal = regs[rb].node.id
  1518. else:
  1519. regs[ra].intVal = -1
  1520. of opcNGetType:
  1521. let rb = instr.regB
  1522. let rc = instr.regC
  1523. case rc
  1524. of 0:
  1525. # getType opcode:
  1526. ensureKind(rkNode)
  1527. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1528. regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1529. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1530. regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1531. else:
  1532. stackTrace(c, tos, pc, "node has no type")
  1533. of 1:
  1534. # typeKind opcode:
  1535. ensureKind(rkInt)
  1536. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1537. regs[ra].intVal = ord(regs[rb].node.typ.kind)
  1538. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1539. regs[ra].intVal = ord(regs[rb].node.sym.typ.kind)
  1540. #else:
  1541. # stackTrace(c, tos, pc, "node has no type")
  1542. of 2:
  1543. # getTypeInst opcode:
  1544. ensureKind(rkNode)
  1545. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1546. regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1547. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1548. regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1549. else:
  1550. stackTrace(c, tos, pc, "node has no type")
  1551. else:
  1552. # getTypeImpl opcode:
  1553. ensureKind(rkNode)
  1554. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1555. regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1556. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1557. regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1558. else:
  1559. stackTrace(c, tos, pc, "node has no type")
  1560. of opcNGetSize:
  1561. decodeBImm(rkInt)
  1562. let n = regs[rb].node
  1563. case imm
  1564. of 0: # size
  1565. if n.typ == nil:
  1566. stackTrace(c, tos, pc, "node has no type")
  1567. else:
  1568. regs[ra].intVal = getSize(c.config, n.typ)
  1569. of 1: # align
  1570. if n.typ == nil:
  1571. stackTrace(c, tos, pc, "node has no type")
  1572. else:
  1573. regs[ra].intVal = getAlign(c.config, n.typ)
  1574. else: # offset
  1575. if n.kind != nkSym:
  1576. stackTrace(c, tos, pc, "node is not a symbol")
  1577. elif n.sym.kind != skField:
  1578. stackTrace(c, tos, pc, "symbol is not a field (nskField)")
  1579. else:
  1580. regs[ra].intVal = n.sym.offset
  1581. of opcNStrVal:
  1582. decodeB(rkNode)
  1583. createStr regs[ra]
  1584. let a = regs[rb].node
  1585. case a.kind
  1586. of nkStrLit..nkTripleStrLit:
  1587. regs[ra].node.strVal = a.strVal
  1588. of nkCommentStmt:
  1589. regs[ra].node.strVal = a.comment
  1590. of nkIdent:
  1591. regs[ra].node.strVal = a.ident.s
  1592. of nkSym:
  1593. regs[ra].node.strVal = a.sym.name.s
  1594. else:
  1595. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1596. of opcNSigHash:
  1597. decodeB(rkNode)
  1598. createStr regs[ra]
  1599. if regs[rb].node.kind != nkSym:
  1600. stackTrace(c, tos, pc, "node is not a symbol")
  1601. else:
  1602. regs[ra].node.strVal = $sigHash(regs[rb].node.sym)
  1603. of opcSlurp:
  1604. decodeB(rkNode)
  1605. createStr regs[ra]
  1606. regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
  1607. c.module, c.config)
  1608. of opcGorge:
  1609. decodeBC(rkNode)
  1610. inc pc
  1611. let rd = c.code[pc].regA
  1612. createStr regs[ra]
  1613. if defined(nimsuggest) or c.config.cmd == cmdCheck:
  1614. discard "don't run staticExec for 'nim suggest'"
  1615. regs[ra].node.strVal = ""
  1616. else:
  1617. when defined(nimcore):
  1618. regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
  1619. regs[rc].node.strVal, regs[rd].node.strVal,
  1620. c.debug[pc], c.config)[0]
  1621. else:
  1622. regs[ra].node.strVal = ""
  1623. globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
  1624. of opcNError, opcNWarning, opcNHint:
  1625. decodeB(rkNode)
  1626. let a = regs[ra].node
  1627. let b = regs[rb].node
  1628. let info = if b.kind == nkNilLit: c.debug[pc] else: b.info
  1629. if instr.opcode == opcNError:
  1630. stackTrace(c, tos, pc, a.strVal, info)
  1631. elif instr.opcode == opcNWarning:
  1632. message(c.config, info, warnUser, a.strVal)
  1633. elif instr.opcode == opcNHint:
  1634. message(c.config, info, hintUser, a.strVal)
  1635. of opcParseExprToAst:
  1636. decodeB(rkNode)
  1637. # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
  1638. var error: string
  1639. let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
  1640. toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
  1641. proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} =
  1642. if error.len == 0 and msg <= errMax:
  1643. error = formatMsg(conf, info, msg, arg))
  1644. if error.len > 0:
  1645. c.errorFlag = error
  1646. elif ast.len != 1:
  1647. c.errorFlag = formatMsg(c.config, c.debug[pc], errGenerated,
  1648. "expected expression, but got multiple statements")
  1649. else:
  1650. regs[ra].node = ast[0]
  1651. of opcParseStmtToAst:
  1652. decodeB(rkNode)
  1653. var error: string
  1654. let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
  1655. toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
  1656. proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) {.nosinks.} =
  1657. if error.len == 0 and msg <= errMax:
  1658. error = formatMsg(conf, info, msg, arg))
  1659. if error.len > 0:
  1660. c.errorFlag = error
  1661. else:
  1662. regs[ra].node = ast
  1663. of opcQueryErrorFlag:
  1664. createStr regs[ra]
  1665. regs[ra].node.strVal = c.errorFlag
  1666. c.errorFlag.setLen 0
  1667. of opcCallSite:
  1668. ensureKind(rkNode)
  1669. if c.callsite != nil: regs[ra].node = c.callsite
  1670. else: stackTrace(c, tos, pc, errFieldXNotFound & "callsite")
  1671. of opcNGetLineInfo:
  1672. decodeBImm(rkNode)
  1673. let n = regs[rb].node
  1674. case imm
  1675. of 0: # getFile
  1676. regs[ra].node = newStrNode(nkStrLit, toFullPath(c.config, n.info))
  1677. of 1: # getLine
  1678. regs[ra].node = newIntNode(nkIntLit, n.info.line.int)
  1679. of 2: # getColumn
  1680. regs[ra].node = newIntNode(nkIntLit, n.info.col)
  1681. else:
  1682. internalAssert c.config, false
  1683. regs[ra].node.info = n.info
  1684. regs[ra].node.typ = n.typ
  1685. of opcNSetLineInfo:
  1686. decodeB(rkNode)
  1687. regs[ra].node.info = regs[rb].node.info
  1688. of opcEqIdent:
  1689. decodeBC(rkInt)
  1690. # aliases for shorter and easier to understand code below
  1691. var aNode = regs[rb].node
  1692. var bNode = regs[rc].node
  1693. # Skipping both, `nkPostfix` and `nkAccQuoted` for both
  1694. # arguments. `nkPostfix` exists only to tag exported symbols
  1695. # and therefor it can be safely skipped. Nim has no postfix
  1696. # operator. `nkAccQuoted` is used to quote an identifier that
  1697. # wouldn't be allowed to use in an unquoted context.
  1698. if aNode.kind == nkPostfix:
  1699. aNode = aNode[1]
  1700. if aNode.kind == nkAccQuoted:
  1701. aNode = aNode[0]
  1702. if bNode.kind == nkPostfix:
  1703. bNode = bNode[1]
  1704. if bNode.kind == nkAccQuoted:
  1705. bNode = bNode[0]
  1706. # These vars are of type `cstring` to prevent unnecessary string copy.
  1707. var aStrVal: cstring = nil
  1708. var bStrVal: cstring = nil
  1709. # extract strVal from argument ``a``
  1710. case aNode.kind
  1711. of nkStrLit..nkTripleStrLit:
  1712. aStrVal = aNode.strVal.cstring
  1713. of nkIdent:
  1714. aStrVal = aNode.ident.s.cstring
  1715. of nkSym:
  1716. aStrVal = aNode.sym.name.s.cstring
  1717. of nkOpenSymChoice, nkClosedSymChoice:
  1718. aStrVal = aNode[0].sym.name.s.cstring
  1719. else:
  1720. discard
  1721. # extract strVal from argument ``b``
  1722. case bNode.kind
  1723. of nkStrLit..nkTripleStrLit:
  1724. bStrVal = bNode.strVal.cstring
  1725. of nkIdent:
  1726. bStrVal = bNode.ident.s.cstring
  1727. of nkSym:
  1728. bStrVal = bNode.sym.name.s.cstring
  1729. of nkOpenSymChoice, nkClosedSymChoice:
  1730. bStrVal = bNode[0].sym.name.s.cstring
  1731. else:
  1732. discard
  1733. regs[ra].intVal =
  1734. if aStrVal != nil and bStrVal != nil:
  1735. ord(idents.cmpIgnoreStyle(aStrVal, bStrVal, high(int)) == 0)
  1736. else:
  1737. 0
  1738. of opcStrToIdent:
  1739. decodeB(rkNode)
  1740. if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}:
  1741. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1742. else:
  1743. regs[ra].node = newNodeI(nkIdent, c.debug[pc])
  1744. regs[ra].node.ident = getIdent(c.cache, regs[rb].node.strVal)
  1745. regs[ra].node.flags.incl nfIsRef
  1746. of opcSetType:
  1747. let typ = c.types[instr.regBx - wordExcess]
  1748. if regs[ra].kind != rkNode:
  1749. let temp = regToNode(regs[ra])
  1750. ensureKind(rkNode)
  1751. regs[ra].node = temp
  1752. regs[ra].node.info = c.debug[pc]
  1753. regs[ra].node.typ = typ
  1754. of opcConv:
  1755. let rb = instr.regB
  1756. inc pc
  1757. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1758. inc pc
  1759. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1760. if opConv(c, regs[ra], regs[rb], desttyp, srctyp):
  1761. stackTrace(c, tos, pc,
  1762. errIllegalConvFromXtoY % [
  1763. typeToString(srctyp), typeToString(desttyp)])
  1764. of opcCast:
  1765. let rb = instr.regB
  1766. inc pc
  1767. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1768. inc pc
  1769. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1770. when hasFFI:
  1771. let dest = fficast(c.config, regs[rb].node, desttyp)
  1772. # todo: check whether this is correct
  1773. # asgnRef(regs[ra], dest)
  1774. putIntoReg(regs[ra], dest)
  1775. else:
  1776. globalError(c.config, c.debug[pc], "cannot evaluate cast")
  1777. of opcNSetIntVal:
  1778. decodeB(rkNode)
  1779. var dest = regs[ra].node
  1780. if dest.kind in {nkCharLit..nkUInt64Lit} and
  1781. regs[rb].kind in {rkInt}:
  1782. dest.intVal = regs[rb].intVal
  1783. elif dest.kind == nkSym and dest.sym.kind == skEnumField:
  1784. stackTrace(c, tos, pc, "`intVal` cannot be changed for an enum symbol.")
  1785. else:
  1786. stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
  1787. of opcNSetFloatVal:
  1788. decodeB(rkNode)
  1789. var dest = regs[ra].node
  1790. if dest.kind in {nkFloatLit..nkFloat64Lit} and
  1791. regs[rb].kind in {rkFloat}:
  1792. dest.floatVal = regs[rb].floatVal
  1793. else:
  1794. stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
  1795. of opcNSetSymbol:
  1796. decodeB(rkNode)
  1797. var dest = regs[ra].node
  1798. if dest.kind == nkSym and regs[rb].node.kind == nkSym:
  1799. dest.sym = regs[rb].node.sym
  1800. else:
  1801. stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
  1802. of opcNSetIdent:
  1803. decodeB(rkNode)
  1804. var dest = regs[ra].node
  1805. if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
  1806. dest.ident = regs[rb].node.ident
  1807. else:
  1808. stackTrace(c, tos, pc, errFieldXNotFound & "ident")
  1809. of opcNSetType:
  1810. decodeB(rkNode)
  1811. let b = regs[rb].node
  1812. internalAssert c.config, b.kind == nkSym and b.sym.kind == skType
  1813. internalAssert c.config, regs[ra].node != nil
  1814. regs[ra].node.typ = b.sym.typ
  1815. of opcNSetStrVal:
  1816. decodeB(rkNode)
  1817. var dest = regs[ra].node
  1818. if dest.kind in {nkStrLit..nkTripleStrLit} and
  1819. regs[rb].kind in {rkNode}:
  1820. dest.strVal = regs[rb].node.strVal
  1821. elif dest.kind == nkCommentStmt and regs[rb].kind in {rkNode}:
  1822. dest.comment = regs[rb].node.strVal
  1823. else:
  1824. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1825. of opcNNewNimNode:
  1826. decodeBC(rkNode)
  1827. var k = regs[rb].intVal
  1828. if k < 0 or k > ord(high(TNodeKind)):
  1829. internalError(c.config, c.debug[pc],
  1830. "request to create a NimNode of invalid kind")
  1831. let cc = regs[rc].node
  1832. let x = newNodeI(TNodeKind(int(k)),
  1833. if cc.kind != nkNilLit:
  1834. cc.info
  1835. elif c.comesFromHeuristic.line != 0'u16:
  1836. c.comesFromHeuristic
  1837. elif c.callsite != nil and c.callsite.safeLen > 1:
  1838. c.callsite[1].info
  1839. else:
  1840. c.debug[pc])
  1841. x.flags.incl nfIsRef
  1842. # prevent crashes in the compiler resulting from wrong macros:
  1843. if x.kind == nkIdent: x.ident = c.cache.emptyIdent
  1844. regs[ra].node = x
  1845. of opcNCopyNimNode:
  1846. decodeB(rkNode)
  1847. regs[ra].node = copyNode(regs[rb].node)
  1848. of opcNCopyNimTree:
  1849. decodeB(rkNode)
  1850. regs[ra].node = copyTree(regs[rb].node)
  1851. of opcNDel:
  1852. decodeBC(rkNode)
  1853. let bb = regs[rb].intVal.int
  1854. for i in 0..<regs[rc].intVal.int:
  1855. delSon(regs[ra].node, bb)
  1856. of opcGenSym:
  1857. decodeBC(rkNode)
  1858. let k = regs[rb].intVal
  1859. let name = if regs[rc].node.strVal.len == 0: ":tmp"
  1860. else: regs[rc].node.strVal
  1861. if k < 0 or k > ord(high(TSymKind)):
  1862. internalError(c.config, c.debug[pc], "request to create symbol of invalid kind")
  1863. var sym = newSym(k.TSymKind, getIdent(c.cache, name), c.module.owner, c.debug[pc])
  1864. incl(sym.flags, sfGenSym)
  1865. regs[ra].node = newSymNode(sym)
  1866. regs[ra].node.flags.incl nfIsRef
  1867. of opcNccValue:
  1868. decodeB(rkInt)
  1869. let destKey = regs[rb].node.strVal
  1870. regs[ra].intVal = getOrDefault(c.graph.cacheCounters, destKey)
  1871. of opcNccInc:
  1872. let g = c.graph
  1873. declBC()
  1874. let destKey = regs[rb].node.strVal
  1875. let by = regs[rc].intVal
  1876. let v = getOrDefault(g.cacheCounters, destKey)
  1877. g.cacheCounters[destKey] = v+by
  1878. recordInc(c, c.debug[pc], destKey, by)
  1879. of opcNcsAdd:
  1880. let g = c.graph
  1881. declBC()
  1882. let destKey = regs[rb].node.strVal
  1883. let val = regs[rc].node
  1884. if not contains(g.cacheSeqs, destKey):
  1885. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  1886. else:
  1887. g.cacheSeqs[destKey].add val
  1888. recordAdd(c, c.debug[pc], destKey, val)
  1889. of opcNcsIncl:
  1890. let g = c.graph
  1891. declBC()
  1892. let destKey = regs[rb].node.strVal
  1893. let val = regs[rc].node
  1894. if not contains(g.cacheSeqs, destKey):
  1895. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  1896. else:
  1897. block search:
  1898. for existing in g.cacheSeqs[destKey]:
  1899. if exprStructuralEquivalent(existing, val, strictSymEquality=true):
  1900. break search
  1901. g.cacheSeqs[destKey].add val
  1902. recordIncl(c, c.debug[pc], destKey, val)
  1903. of opcNcsLen:
  1904. let g = c.graph
  1905. decodeB(rkInt)
  1906. let destKey = regs[rb].node.strVal
  1907. regs[ra].intVal =
  1908. if contains(g.cacheSeqs, destKey): g.cacheSeqs[destKey].len else: 0
  1909. of opcNcsAt:
  1910. let g = c.graph
  1911. decodeBC(rkNode)
  1912. let idx = regs[rc].intVal
  1913. let destKey = regs[rb].node.strVal
  1914. if contains(g.cacheSeqs, destKey) and idx <% g.cacheSeqs[destKey].len:
  1915. regs[ra].node = g.cacheSeqs[destKey][idx.int]
  1916. else:
  1917. stackTrace(c, tos, pc, formatErrorIndexBound(idx, g.cacheSeqs[destKey].len-1))
  1918. of opcNctPut:
  1919. let g = c.graph
  1920. let destKey = regs[ra].node.strVal
  1921. let key = regs[instr.regB].node.strVal
  1922. let val = regs[instr.regC].node
  1923. if not contains(g.cacheTables, destKey):
  1924. g.cacheTables[destKey] = initBTree[string, PNode]()
  1925. if not contains(g.cacheTables[destKey], key):
  1926. g.cacheTables[destKey].add(key, val)
  1927. recordPut(c, c.debug[pc], destKey, key, val)
  1928. else:
  1929. stackTrace(c, tos, pc, "key already exists: " & key)
  1930. of opcNctLen:
  1931. let g = c.graph
  1932. decodeB(rkInt)
  1933. let destKey = regs[rb].node.strVal
  1934. regs[ra].intVal =
  1935. if contains(g.cacheTables, destKey): g.cacheTables[destKey].len else: 0
  1936. of opcNctGet:
  1937. let g = c.graph
  1938. decodeBC(rkNode)
  1939. let destKey = regs[rb].node.strVal
  1940. let key = regs[rc].node.strVal
  1941. if contains(g.cacheTables, destKey):
  1942. if contains(g.cacheTables[destKey], key):
  1943. regs[ra].node = getOrDefault(g.cacheTables[destKey], key)
  1944. else:
  1945. stackTrace(c, tos, pc, "key does not exist: " & key)
  1946. else:
  1947. stackTrace(c, tos, pc, "key does not exist: " & destKey)
  1948. of opcNctHasNext:
  1949. let g = c.graph
  1950. decodeBC(rkInt)
  1951. let destKey = regs[rb].node.strVal
  1952. regs[ra].intVal =
  1953. if g.cacheTables.contains(destKey):
  1954. ord(btrees.hasNext(g.cacheTables[destKey], regs[rc].intVal.int))
  1955. else:
  1956. 0
  1957. of opcNctNext:
  1958. let g = c.graph
  1959. decodeBC(rkNode)
  1960. let destKey = regs[rb].node.strVal
  1961. let index = regs[rc].intVal
  1962. if contains(g.cacheTables, destKey):
  1963. let (k, v, nextIndex) = btrees.next(g.cacheTables[destKey], index.int)
  1964. regs[ra].node = newTree(nkTupleConstr, newStrNode(k, c.debug[pc]), v,
  1965. newIntNode(nkIntLit, nextIndex))
  1966. else:
  1967. stackTrace(c, tos, pc, "key does not exist: " & destKey)
  1968. of opcTypeTrait:
  1969. # XXX only supports 'name' for now; we can use regC to encode the
  1970. # type trait operation
  1971. decodeB(rkNode)
  1972. var typ = regs[rb].node.typ
  1973. internalAssert c.config, typ != nil
  1974. while typ.kind == tyTypeDesc and typ.len > 0: typ = typ[0]
  1975. createStr regs[ra]
  1976. regs[ra].node.strVal = typ.typeToString(preferExported)
  1977. of opcMarshalLoad:
  1978. let ra = instr.regA
  1979. let rb = instr.regB
  1980. inc pc
  1981. let typ = c.types[c.code[pc].regBx - wordExcess]
  1982. putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ, c.cache, c.config))
  1983. of opcMarshalStore:
  1984. decodeB(rkNode)
  1985. inc pc
  1986. let typ = c.types[c.code[pc].regBx - wordExcess]
  1987. createStrKeepNode(regs[ra])
  1988. when not defined(nimNoNilSeqs):
  1989. if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
  1990. storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config)
  1991. c.profiler.leave(c)
  1992. inc pc
  1993. proc execute(c: PCtx, start: int): PNode =
  1994. var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
  1995. newSeq(tos.slots, c.prc.maxSlots)
  1996. result = rawExecute(c, start, tos).regToNode
  1997. proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
  1998. if sym.kind in routineKinds:
  1999. if sym.typ.len-1 != args.len:
  2000. localError(c.config, sym.info,
  2001. "NimScript: expected $# arguments, but got $#" % [
  2002. $(sym.typ.len-1), $args.len])
  2003. else:
  2004. let start = genProc(c, sym)
  2005. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  2006. let maxSlots = sym.offset
  2007. newSeq(tos.slots, maxSlots)
  2008. # setup parameters:
  2009. if not isEmptyType(sym.typ[0]) or sym.kind == skMacro:
  2010. putIntoReg(tos.slots[0], getNullValue(sym.typ[0], sym.info, c.config))
  2011. # XXX We could perform some type checking here.
  2012. for i in 1..<sym.typ.len:
  2013. putIntoReg(tos.slots[i], args[i-1])
  2014. result = rawExecute(c, start, tos).regToNode
  2015. else:
  2016. localError(c.config, sym.info,
  2017. "NimScript: attempt to call non-routine: " & sym.name.s)
  2018. proc evalStmt*(c: PCtx, n: PNode) =
  2019. let n = transformExpr(c.graph, c.module, n)
  2020. let start = genStmt(c, n)
  2021. # execute new instructions; this redundant opcEof check saves us lots
  2022. # of allocations in 'execute':
  2023. if c.code[start].opcode != opcEof:
  2024. discard execute(c, start)
  2025. proc evalExpr*(c: PCtx, n: PNode): PNode =
  2026. let n = transformExpr(c.graph, c.module, n)
  2027. let start = genExpr(c, n)
  2028. assert c.code[start].opcode != opcEof
  2029. result = execute(c, start)
  2030. proc getGlobalValue*(c: PCtx; s: PSym): PNode =
  2031. internalAssert c.config, s.kind in {skLet, skVar} and sfGlobal in s.flags
  2032. result = c.globals[s.position-1]
  2033. include vmops
  2034. proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) =
  2035. if graph.vm.isNil:
  2036. graph.vm = newCtx(module, graph.cache, graph)
  2037. registerAdditionalOps(PCtx graph.vm)
  2038. else:
  2039. refresh(PCtx graph.vm, module)
  2040. proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} =
  2041. #var c = newEvalContext(module, emRepl)
  2042. #c.features = {allowCast, allowInfiniteLoops}
  2043. #pushStackFrame(c, newStackFrame())
  2044. # XXX produce a new 'globals' environment here:
  2045. setupGlobalCtx(module, graph)
  2046. result = PCtx graph.vm
  2047. proc myProcess(c: PPassContext, n: PNode): PNode =
  2048. let c = PCtx(c)
  2049. # don't eval errornous code:
  2050. if c.oldErrorCount == c.config.errorCounter:
  2051. evalStmt(c, n)
  2052. result = newNodeI(nkEmpty, n.info)
  2053. else:
  2054. result = n
  2055. c.oldErrorCount = c.config.errorCounter
  2056. proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
  2057. myProcess(c, n)
  2058. const evalPass* = makePass(myOpen, myProcess, myClose)
  2059. proc evalConstExprAux(module: PSym;
  2060. g: ModuleGraph; prc: PSym, n: PNode,
  2061. mode: TEvalMode): PNode =
  2062. if g.config.errorCounter > 0: return n
  2063. let n = transformExpr(g, module, n)
  2064. setupGlobalCtx(module, g)
  2065. var c = PCtx g.vm
  2066. let oldMode = c.mode
  2067. c.mode = mode
  2068. let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
  2069. if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
  2070. assert c.code[start].opcode != opcEof
  2071. when debugEchoCode: c.echoCode start
  2072. var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
  2073. newSeq(tos.slots, c.prc.maxSlots)
  2074. #for i in 0..<c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
  2075. result = rawExecute(c, start, tos).regToNode
  2076. if result.info.col < 0: result.info = n.info
  2077. c.mode = oldMode
  2078. proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode =
  2079. result = evalConstExprAux(module, g, nil, e, emConst)
  2080. proc evalStaticExpr*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym): PNode =
  2081. result = evalConstExprAux(module, g, prc, e, emStaticExpr)
  2082. proc evalStaticStmt*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym) =
  2083. discard evalConstExprAux(module, g, prc, e, emStaticStmt)
  2084. proc setupCompileTimeVar*(module: PSym; g: ModuleGraph; n: PNode) =
  2085. discard evalConstExprAux(module, g, nil, n, emStaticStmt)
  2086. proc prepareVMValue(arg: PNode): PNode =
  2087. ## strip nkExprColonExpr from tuple values recurively. That is how
  2088. ## they are expected to be stored in the VM.
  2089. # Early abort without copy. No transformation takes place.
  2090. if arg.kind in nkLiterals:
  2091. return arg
  2092. result = copyNode(arg)
  2093. if arg.kind == nkTupleConstr:
  2094. for child in arg:
  2095. if child.kind == nkExprColonExpr:
  2096. result.add prepareVMValue(child[1])
  2097. else:
  2098. result.add prepareVMValue(child)
  2099. else:
  2100. for child in arg:
  2101. result.add prepareVMValue(child)
  2102. proc setupMacroParam(x: PNode, typ: PType): TFullReg =
  2103. case typ.kind
  2104. of tyStatic:
  2105. putIntoReg(result, prepareVMValue(x))
  2106. else:
  2107. var n = x
  2108. if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n[1]
  2109. n = n.canonValue
  2110. n.flags.incl nfIsRef
  2111. n.typ = x.typ
  2112. result = TFullReg(kind: rkNode, node: n)
  2113. iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
  2114. let gp = macroSym.ast[genericParamsPos]
  2115. for i in 0..<gp.len:
  2116. let genericParam = gp[i].sym
  2117. let posInCall = macroSym.typ.len + i
  2118. if posInCall < call.len:
  2119. yield (genericParam, call[posInCall])
  2120. # to prevent endless recursion in macro instantiation
  2121. const evalMacroLimit = 1000
  2122. proc errorNode(owner: PSym, n: PNode): PNode =
  2123. result = newNodeI(nkEmpty, n.info)
  2124. result.typ = newType(tyError, owner)
  2125. result.typ.flags.incl tfCheckedForDestructor
  2126. proc evalMacroCall*(module: PSym; g: ModuleGraph; templInstCounter: ref int;
  2127. n, nOrig: PNode, sym: PSym): PNode =
  2128. if g.config.errorCounter > 0: return errorNode(module, n)
  2129. # XXX globalError() is ugly here, but I don't know a better solution for now
  2130. inc(g.config.evalMacroCounter)
  2131. if g.config.evalMacroCounter > evalMacroLimit:
  2132. globalError(g.config, n.info, "macro instantiation too nested")
  2133. # immediate macros can bypass any type and arity checking so we check the
  2134. # arity here too:
  2135. if sym.typ.len > n.safeLen and sym.typ.len > 1:
  2136. globalError(g.config, n.info, "in call '$#' got $#, but expected $# argument(s)" % [
  2137. n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)])
  2138. setupGlobalCtx(module, g)
  2139. var c = PCtx g.vm
  2140. let oldMode = c.mode
  2141. c.mode = emStaticStmt
  2142. c.comesFromHeuristic.line = 0'u16
  2143. c.callsite = nOrig
  2144. c.templInstCounter = templInstCounter
  2145. let start = genProc(c, sym)
  2146. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  2147. let maxSlots = sym.offset
  2148. newSeq(tos.slots, maxSlots)
  2149. # setup arguments:
  2150. var L = n.safeLen
  2151. if L == 0: L = 1
  2152. # This is wrong for tests/reject/tind1.nim where the passed 'else' part
  2153. # doesn't end up in the parameter:
  2154. #InternalAssert tos.slots.len >= L
  2155. # return value:
  2156. tos.slots[0] = TFullReg(kind: rkNode, node: newNodeI(nkEmpty, n.info))
  2157. # setup parameters:
  2158. for i in 1..<sym.typ.len:
  2159. tos.slots[i] = setupMacroParam(n[i], sym.typ[i])
  2160. let gp = sym.ast[genericParamsPos]
  2161. for i in 0..<gp.len:
  2162. let idx = sym.typ.len + i
  2163. if idx < n.len:
  2164. tos.slots[idx] = setupMacroParam(n[idx], gp[i].sym.typ)
  2165. else:
  2166. dec(g.config.evalMacroCounter)
  2167. c.callsite = nil
  2168. localError(c.config, n.info, "expected " & $gp.len &
  2169. " generic parameter(s)")
  2170. # temporary storage:
  2171. #for i in L..<maxSlots: tos.slots[i] = newNode(nkEmpty)
  2172. result = rawExecute(c, start, tos).regToNode
  2173. if result.info.line < 0: result.info = n.info
  2174. if cyclicTree(result): globalError(c.config, n.info, "macro produced a cyclic tree")
  2175. dec(g.config.evalMacroCounter)
  2176. c.callsite = nil
  2177. c.mode = oldMode