vm.nim 74 KB

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