vm.nim 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121
  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 sfImportc in prc.flags:
  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. let prcValue = c.globals.sons[prc.position-1]
  1028. if prcValue.kind == nkEmpty:
  1029. globalError(c.config, c.debug[pc], "cannot run " & prc.name.s)
  1030. var slots2: TNodeSeq
  1031. slots2.setLen(tos.slots.len)
  1032. for i in 0..<tos.slots.len:
  1033. slots2[i] = regToNode(tos.slots[i])
  1034. let newValue = callForeignFunction(c.config, prcValue, prc.typ, slots2,
  1035. rb+1, rc-1, c.debug[pc])
  1036. if newValue.kind != nkEmpty:
  1037. assert instr.opcode == opcIndCallAsgn
  1038. putIntoReg(regs[ra], newValue)
  1039. else:
  1040. globalError(c.config, c.debug[pc], "VM not built with FFI support")
  1041. elif prc.kind != skTemplate:
  1042. let newPc = compile(c, prc)
  1043. # tricky: a recursion is also a jump back, so we use the same
  1044. # logic as for loops:
  1045. if newPc < pc: handleJmpBack()
  1046. #echo "new pc ", newPc, " calling: ", prc.name.s
  1047. var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
  1048. newSeq(newFrame.slots, prc.offset+ord(isClosure))
  1049. if not isEmptyType(prc.typ.sons[0]):
  1050. putIntoReg(newFrame.slots[0], getNullValue(prc.typ.sons[0], prc.info, c.config))
  1051. for i in 1 .. rc-1:
  1052. newFrame.slots[i] = regs[rb+i]
  1053. if isClosure:
  1054. newFrame.slots[rc].kind = rkNode
  1055. newFrame.slots[rc].node = regs[rb].node.sons[1]
  1056. tos = newFrame
  1057. move(regs, newFrame.slots)
  1058. # -1 for the following 'inc pc'
  1059. pc = newPc-1
  1060. else:
  1061. # for 'getAst' support we need to support template expansion here:
  1062. let genSymOwner = if tos.next != nil and tos.next.prc != nil:
  1063. tos.next.prc
  1064. else:
  1065. c.module
  1066. var macroCall = newNodeI(nkCall, c.debug[pc])
  1067. macroCall.add(newSymNode(prc))
  1068. for i in 1 .. rc-1:
  1069. let node = regs[rb+i].regToNode
  1070. node.info = c.debug[pc]
  1071. macroCall.add(node)
  1072. var a = evalTemplate(macroCall, prc, genSymOwner, c.config)
  1073. if a.kind == nkStmtList and a.len == 1: a = a[0]
  1074. a.recSetFlagIsRef
  1075. ensureKind(rkNode)
  1076. regs[ra].node = a
  1077. of opcTJmp:
  1078. # jump Bx if A != 0
  1079. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1080. if regs[ra].intVal != 0:
  1081. inc pc, rbx
  1082. of opcFJmp:
  1083. # jump Bx if A == 0
  1084. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1085. if regs[ra].intVal == 0:
  1086. inc pc, rbx
  1087. of opcJmp:
  1088. # jump Bx
  1089. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1090. inc pc, rbx
  1091. of opcJmpBack:
  1092. let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1093. inc pc, rbx
  1094. handleJmpBack()
  1095. of opcBranch:
  1096. # we know the next instruction is a 'fjmp':
  1097. let branch = c.constants[instr.regBx-wordExcess]
  1098. var cond = false
  1099. for j in 0 .. sonsLen(branch) - 2:
  1100. if overlap(regs[ra].regToNode, branch.sons[j]):
  1101. cond = true
  1102. break
  1103. assert c.code[pc+1].opcode == opcFJmp
  1104. inc pc
  1105. # we skip this instruction so that the final 'inc(pc)' skips
  1106. # the following jump
  1107. if not cond:
  1108. let instr2 = c.code[pc]
  1109. let rbx = instr2.regBx - wordExcess - 1 # -1 for the following 'inc pc'
  1110. inc pc, rbx
  1111. of opcTry:
  1112. let rbx = instr.regBx - wordExcess
  1113. tos.pushSafePoint(pc + rbx)
  1114. assert c.code[pc+rbx].opcode in {opcExcept, opcFinally}
  1115. of opcExcept:
  1116. # This opcode is never executed, it only holds informations for the
  1117. # exception handling routines.
  1118. doAssert(false)
  1119. of opcFinally:
  1120. # Pop the last safepoint introduced by a opcTry. This opcode is only
  1121. # executed _iff_ no exception was raised in the body of the `try`
  1122. # statement hence the need to pop the safepoint here.
  1123. doAssert(savedPC < 0)
  1124. tos.popSafePoint()
  1125. of opcFinallyEnd:
  1126. # The control flow may not resume at the next instruction since we may be
  1127. # raising an exception or performing a cleanup.
  1128. if savedPC >= 0:
  1129. pc = savedPC - 1
  1130. savedPC = -1
  1131. if tos != savedFrame:
  1132. tos = savedFrame
  1133. move(regs, tos.slots)
  1134. of opcRaise:
  1135. let raised = regs[ra].node
  1136. c.currentExceptionA = raised
  1137. c.exceptionInstr = pc
  1138. var frame = tos
  1139. var jumpTo = findExceptionHandler(c, frame, raised)
  1140. while jumpTo.why == ExceptionGotoUnhandled and not frame.next.isNil:
  1141. frame = frame.next
  1142. jumpTo = findExceptionHandler(c, frame, raised)
  1143. case jumpTo.why:
  1144. of ExceptionGotoHandler:
  1145. # Jump to the handler, do nothing when the `finally` block ends.
  1146. savedPC = -1
  1147. pc = jumpTo.where - 1
  1148. if tos != frame:
  1149. tos = frame
  1150. move(regs, tos.slots)
  1151. of ExceptionGotoFinally:
  1152. # Jump to the `finally` block first then re-jump here to continue the
  1153. # traversal of the exception chain
  1154. savedPC = pc
  1155. savedFrame = tos
  1156. pc = jumpTo.where - 1
  1157. if tos != frame:
  1158. tos = frame
  1159. move(regs, tos.slots)
  1160. of ExceptionGotoUnhandled:
  1161. # Nobody handled this exception, error out.
  1162. bailOut(c, tos)
  1163. of opcNew:
  1164. ensureKind(rkNode)
  1165. let typ = c.types[instr.regBx - wordExcess]
  1166. regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
  1167. regs[ra].node.flags.incl nfIsRef
  1168. of opcNewSeq:
  1169. let typ = c.types[instr.regBx - wordExcess]
  1170. inc pc
  1171. ensureKind(rkNode)
  1172. let instr2 = c.code[pc]
  1173. let count = regs[instr2.regA].intVal.int
  1174. regs[ra].node = newNodeI(nkBracket, c.debug[pc])
  1175. regs[ra].node.typ = typ
  1176. newSeq(regs[ra].node.sons, count)
  1177. for i in 0 ..< count:
  1178. regs[ra].node.sons[i] = getNullValue(typ.sons[0], c.debug[pc], c.config)
  1179. of opcNewStr:
  1180. decodeB(rkNode)
  1181. regs[ra].node = newNodeI(nkStrLit, c.debug[pc])
  1182. regs[ra].node.strVal = newString(regs[rb].intVal.int)
  1183. of opcLdImmInt:
  1184. # dest = immediate value
  1185. decodeBx(rkInt)
  1186. regs[ra].intVal = rbx
  1187. of opcLdNull:
  1188. ensureKind(rkNode)
  1189. let typ = c.types[instr.regBx - wordExcess]
  1190. regs[ra].node = getNullValue(typ, c.debug[pc], c.config)
  1191. # opcLdNull really is the gist of the VM's problems: should it load
  1192. # a fresh null to regs[ra].node or to regs[ra].node[]? This really
  1193. # depends on whether regs[ra] represents the variable itself or wether
  1194. # it holds the indirection! Due to the way registers are re-used we cannot
  1195. # say for sure here! --> The codegen has to deal with it
  1196. # via 'genAsgnPatch'.
  1197. of opcLdNullReg:
  1198. let typ = c.types[instr.regBx - wordExcess]
  1199. if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
  1200. tyFloat..tyFloat128}:
  1201. ensureKind(rkFloat)
  1202. regs[ra].floatVal = 0.0
  1203. else:
  1204. ensureKind(rkInt)
  1205. regs[ra].intVal = 0
  1206. of opcLdConst:
  1207. let rb = instr.regBx - wordExcess
  1208. let cnst = c.constants.sons[rb]
  1209. if fitsRegister(cnst.typ):
  1210. myreset(regs[ra])
  1211. putIntoReg(regs[ra], cnst)
  1212. else:
  1213. ensureKind(rkNode)
  1214. regs[ra].node = cnst
  1215. of opcAsgnConst:
  1216. let rb = instr.regBx - wordExcess
  1217. let cnst = c.constants.sons[rb]
  1218. if fitsRegister(cnst.typ):
  1219. putIntoReg(regs[ra], cnst)
  1220. else:
  1221. ensureKind(rkNode)
  1222. regs[ra].node = cnst.copyTree
  1223. of opcLdGlobal:
  1224. let rb = instr.regBx - wordExcess - 1
  1225. ensureKind(rkNode)
  1226. regs[ra].node = c.globals.sons[rb]
  1227. of opcLdGlobalAddr:
  1228. let rb = instr.regBx - wordExcess - 1
  1229. ensureKind(rkNodeAddr)
  1230. regs[ra].nodeAddr = addr(c.globals.sons[rb])
  1231. of opcRepr:
  1232. decodeB(rkNode)
  1233. createStr regs[ra]
  1234. regs[ra].node.strVal = renderTree(regs[rb].regToNode, {renderNoComments, renderDocComments})
  1235. of opcQuit:
  1236. if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
  1237. message(c.config, c.debug[pc], hintQuitCalled)
  1238. msgQuit(int8(getOrdValue(regs[ra].regToNode)))
  1239. else:
  1240. return TFullReg(kind: rkNone)
  1241. of opcSetLenStr:
  1242. decodeB(rkNode)
  1243. #createStrKeepNode regs[ra]
  1244. regs[ra].node.strVal.setLen(regs[rb].intVal.int)
  1245. of opcOf:
  1246. decodeBC(rkInt)
  1247. let typ = c.types[regs[rc].intVal.int]
  1248. regs[ra].intVal = ord(inheritanceDiff(regs[rb].node.typ, typ) <= 0)
  1249. of opcIs:
  1250. decodeBC(rkInt)
  1251. let t1 = regs[rb].node.typ.skipTypes({tyTypeDesc})
  1252. let t2 = c.types[regs[rc].intVal.int]
  1253. # XXX: This should use the standard isOpImpl
  1254. let match = if t2.kind == tyUserTypeClass: true
  1255. else: sameType(t1, t2)
  1256. regs[ra].intVal = ord(match)
  1257. of opcSetLenSeq:
  1258. decodeB(rkNode)
  1259. let newLen = regs[rb].intVal.int
  1260. if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
  1261. else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
  1262. of opcNarrowS:
  1263. decodeB(rkInt)
  1264. let min = -(1.BiggestInt shl (rb-1))
  1265. let max = (1.BiggestInt shl (rb-1))-1
  1266. if regs[ra].intVal < min or regs[ra].intVal > max:
  1267. stackTrace(c, tos, pc, "unhandled exception: value out of range")
  1268. of opcNarrowU:
  1269. decodeB(rkInt)
  1270. regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1)
  1271. of opcSignExtend:
  1272. # like opcNarrowS, but no out of range possible
  1273. decodeB(rkInt)
  1274. let imm = 64 - rb
  1275. regs[ra].intVal = ashr(regs[ra].intVal shl imm, imm)
  1276. of opcIsNil:
  1277. decodeB(rkInt)
  1278. let node = regs[rb].node
  1279. regs[ra].intVal = ord(
  1280. # Note that `nfIsRef` + `nkNilLit` represents an allocated
  1281. # reference with the value `nil`, so `isNil` should be false!
  1282. (node.kind == nkNilLit and nfIsRef notin node.flags) or
  1283. (not node.typ.isNil and node.typ.kind == tyProc and
  1284. node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and
  1285. node.sons[1].kind == nkNilLit))
  1286. of opcNBindSym:
  1287. # cannot use this simple check
  1288. # if dynamicBindSym notin c.config.features:
  1289. # bindSym with static input
  1290. decodeBx(rkNode)
  1291. regs[ra].node = copyTree(c.constants.sons[rbx])
  1292. regs[ra].node.flags.incl nfIsRef
  1293. of opcNDynBindSym:
  1294. # experimental bindSym
  1295. let
  1296. rb = instr.regB
  1297. rc = instr.regC
  1298. idx = int(regs[rb+rc-1].intVal)
  1299. callback = c.callbacks[idx].value
  1300. args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
  1301. currentException: c.currentExceptionA,
  1302. currentLineInfo: c.debug[pc])
  1303. callback(args)
  1304. regs[ra].node.flags.incl nfIsRef
  1305. of opcNChild:
  1306. decodeBC(rkNode)
  1307. let idx = regs[rc].intVal.int
  1308. let src = regs[rb].node
  1309. if src.kind notin {nkEmpty..nkNilLit} and idx <% src.len:
  1310. regs[ra].node = src.sons[idx]
  1311. else:
  1312. stackTrace(c, tos, pc, formatErrorIndexBound(idx, src.len-1))
  1313. of opcNSetChild:
  1314. decodeBC(rkNode)
  1315. let idx = regs[rb].intVal.int
  1316. var dest = regs[ra].node
  1317. if dest.kind notin {nkEmpty..nkNilLit} and idx <% dest.len:
  1318. dest.sons[idx] = regs[rc].node
  1319. else:
  1320. stackTrace(c, tos, pc, formatErrorIndexBound(idx, dest.len-1))
  1321. of opcNAdd:
  1322. decodeBC(rkNode)
  1323. var u = regs[rb].node
  1324. if u.kind notin {nkEmpty..nkNilLit}:
  1325. u.add(regs[rc].node)
  1326. else:
  1327. stackTrace(c, tos, pc, "cannot add to node kind: " & $u.kind)
  1328. regs[ra].node = u
  1329. of opcNAddMultiple:
  1330. decodeBC(rkNode)
  1331. let x = regs[rc].node
  1332. var u = regs[rb].node
  1333. if u.kind notin {nkEmpty..nkNilLit}:
  1334. # XXX can be optimized:
  1335. for i in 0..<x.len: u.add(x.sons[i])
  1336. else:
  1337. stackTrace(c, tos, pc, "cannot add to node kind: " & $u.kind)
  1338. regs[ra].node = u
  1339. of opcNKind:
  1340. decodeB(rkInt)
  1341. regs[ra].intVal = ord(regs[rb].node.kind)
  1342. c.comesFromHeuristic = regs[rb].node.info
  1343. of opcNSymKind:
  1344. decodeB(rkInt)
  1345. let a = regs[rb].node
  1346. if a.kind == nkSym:
  1347. regs[ra].intVal = ord(a.sym.kind)
  1348. else:
  1349. stackTrace(c, tos, pc, "node is not a symbol")
  1350. c.comesFromHeuristic = regs[rb].node.info
  1351. of opcNIntVal:
  1352. decodeB(rkInt)
  1353. let a = regs[rb].node
  1354. if a.kind in {nkCharLit..nkUInt64Lit}:
  1355. regs[ra].intVal = a.intVal
  1356. elif a.kind == nkSym and a.sym.kind == skEnumField:
  1357. regs[ra].intVal = a.sym.position
  1358. else:
  1359. stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
  1360. of opcNFloatVal:
  1361. decodeB(rkFloat)
  1362. let a = regs[rb].node
  1363. case a.kind
  1364. of nkFloatLit..nkFloat64Lit: regs[ra].floatVal = a.floatVal
  1365. else: stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
  1366. of opcNSymbol:
  1367. decodeB(rkNode)
  1368. let a = regs[rb].node
  1369. if a.kind == nkSym:
  1370. regs[ra].node = copyNode(a)
  1371. else:
  1372. stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
  1373. of opcNIdent:
  1374. decodeB(rkNode)
  1375. let a = regs[rb].node
  1376. if a.kind == nkIdent:
  1377. regs[ra].node = copyNode(a)
  1378. else:
  1379. stackTrace(c, tos, pc, errFieldXNotFound & "ident")
  1380. of opcNGetType:
  1381. let rb = instr.regB
  1382. let rc = instr.regC
  1383. case rc
  1384. of 0:
  1385. # getType opcode:
  1386. ensureKind(rkNode)
  1387. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1388. regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1389. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1390. regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1391. else:
  1392. stackTrace(c, tos, pc, "node has no type")
  1393. of 1:
  1394. # typeKind opcode:
  1395. ensureKind(rkInt)
  1396. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1397. regs[ra].intVal = ord(regs[rb].node.typ.kind)
  1398. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1399. regs[ra].intVal = ord(regs[rb].node.sym.typ.kind)
  1400. #else:
  1401. # stackTrace(c, tos, pc, "node has no type")
  1402. of 2:
  1403. # getTypeInst opcode:
  1404. ensureKind(rkNode)
  1405. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1406. regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1407. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1408. regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1409. else:
  1410. stackTrace(c, tos, pc, "node has no type")
  1411. else:
  1412. # getTypeImpl opcode:
  1413. ensureKind(rkNode)
  1414. if regs[rb].kind == rkNode and regs[rb].node.typ != nil:
  1415. regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.typ, c.debug[pc])
  1416. elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil:
  1417. regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc])
  1418. else:
  1419. stackTrace(c, tos, pc, "node has no type")
  1420. of opcNGetSize:
  1421. decodeBImm(rkInt)
  1422. let n = regs[rb].node
  1423. case imm
  1424. of 0: # size
  1425. if n.typ == nil:
  1426. stackTrace(c, tos, pc, "node has no type")
  1427. else:
  1428. regs[ra].intVal = getSize(c.config, n.typ)
  1429. of 1: # align
  1430. if n.typ == nil:
  1431. stackTrace(c, tos, pc, "node has no type")
  1432. else:
  1433. regs[ra].intVal = getAlign(c.config, n.typ)
  1434. else: # offset
  1435. if n.kind != nkSym:
  1436. stackTrace(c, tos, pc, "node is not a symbol")
  1437. elif n.sym.kind != skField:
  1438. stackTrace(c, tos, pc, "symbol is not a field (nskField)")
  1439. else:
  1440. regs[ra].intVal = n.sym.offset
  1441. of opcNStrVal:
  1442. decodeB(rkNode)
  1443. createStr regs[ra]
  1444. let a = regs[rb].node
  1445. case a.kind
  1446. of nkStrLit..nkTripleStrLit:
  1447. regs[ra].node.strVal = a.strVal
  1448. of nkCommentStmt:
  1449. regs[ra].node.strVal = a.comment
  1450. of nkIdent:
  1451. regs[ra].node.strVal = a.ident.s
  1452. of nkSym:
  1453. regs[ra].node.strVal = a.sym.name.s
  1454. else:
  1455. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1456. of opcNSigHash:
  1457. decodeB(rkNode)
  1458. createStr regs[ra]
  1459. if regs[rb].node.kind != nkSym:
  1460. stackTrace(c, tos, pc, "node is not a symbol")
  1461. else:
  1462. regs[ra].node.strVal = $sigHash(regs[rb].node.sym)
  1463. of opcSlurp:
  1464. decodeB(rkNode)
  1465. createStr regs[ra]
  1466. regs[ra].node.strVal = opSlurp(regs[rb].node.strVal, c.debug[pc],
  1467. c.module, c.config)
  1468. of opcGorge:
  1469. when defined(nimcore):
  1470. decodeBC(rkNode)
  1471. inc pc
  1472. let rd = c.code[pc].regA
  1473. createStr regs[ra]
  1474. regs[ra].node.strVal = opGorge(regs[rb].node.strVal,
  1475. regs[rc].node.strVal, regs[rd].node.strVal,
  1476. c.debug[pc], c.config)[0]
  1477. else:
  1478. globalError(c.config, c.debug[pc], "VM is not built with 'gorge' support")
  1479. of opcNError, opcNWarning, opcNHint:
  1480. decodeB(rkNode)
  1481. let a = regs[ra].node
  1482. let b = regs[rb].node
  1483. let info = if b.kind == nkNilLit: c.debug[pc] else: b.info
  1484. if instr.opcode == opcNError:
  1485. stackTrace(c, tos, pc, a.strVal, info)
  1486. elif instr.opcode == opcNWarning:
  1487. message(c.config, info, warnUser, a.strVal)
  1488. elif instr.opcode == opcNHint:
  1489. message(c.config, info, hintUser, a.strVal)
  1490. of opcParseExprToAst:
  1491. decodeB(rkNode)
  1492. # c.debug[pc].line.int - countLines(regs[rb].strVal) ?
  1493. var error: string
  1494. let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
  1495. toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
  1496. proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
  1497. if error.len == 0 and msg <= errMax:
  1498. error = formatMsg(conf, info, msg, arg))
  1499. if error.len > 0:
  1500. c.errorFlag = error
  1501. elif sonsLen(ast) != 1:
  1502. c.errorFlag = formatMsg(c.config, c.debug[pc], errGenerated,
  1503. "expected expression, but got multiple statements")
  1504. else:
  1505. regs[ra].node = ast.sons[0]
  1506. of opcParseStmtToAst:
  1507. decodeB(rkNode)
  1508. var error: string
  1509. let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
  1510. toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
  1511. proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
  1512. if error.len == 0 and msg <= errMax:
  1513. error = formatMsg(conf, info, msg, arg))
  1514. if error.len > 0:
  1515. c.errorFlag = error
  1516. else:
  1517. regs[ra].node = ast
  1518. of opcQueryErrorFlag:
  1519. createStr regs[ra]
  1520. regs[ra].node.strVal = c.errorFlag
  1521. c.errorFlag.setLen 0
  1522. of opcCallSite:
  1523. ensureKind(rkNode)
  1524. if c.callsite != nil: regs[ra].node = c.callsite
  1525. else: stackTrace(c, tos, pc, errFieldXNotFound & "callsite")
  1526. of opcNGetLineInfo:
  1527. decodeBImm(rkNode)
  1528. let n = regs[rb].node
  1529. case imm
  1530. of 0: # getFile
  1531. regs[ra].node = newStrNode(nkStrLit, toFullPath(c.config, n.info))
  1532. of 1: # getLine
  1533. regs[ra].node = newIntNode(nkIntLit, n.info.line.int)
  1534. of 2: # getColumn
  1535. regs[ra].node = newIntNode(nkIntLit, n.info.col)
  1536. else:
  1537. internalAssert c.config, false
  1538. regs[ra].node.info = n.info
  1539. regs[ra].node.typ = n.typ
  1540. of opcNSetLineInfo:
  1541. decodeB(rkNode)
  1542. regs[ra].node.info = regs[rb].node.info
  1543. of opcEqIdent:
  1544. decodeBC(rkInt)
  1545. # aliases for shorter and easier to understand code below
  1546. let aNode = regs[rb].node
  1547. let bNode = regs[rc].node
  1548. # these are cstring to prevent string copy, and cmpIgnoreStyle from
  1549. # takes cstring arguments
  1550. var aStrVal: cstring = nil
  1551. var bStrVal: cstring = nil
  1552. # extract strVal from argument ``a``
  1553. case aNode.kind
  1554. of nkStrLit..nkTripleStrLit:
  1555. aStrVal = aNode.strVal.cstring
  1556. of nkIdent:
  1557. aStrVal = aNode.ident.s.cstring
  1558. of nkSym:
  1559. aStrVal = aNode.sym.name.s.cstring
  1560. of nkOpenSymChoice, nkClosedSymChoice:
  1561. aStrVal = aNode[0].sym.name.s.cstring
  1562. else:
  1563. discard
  1564. # extract strVal from argument ``b``
  1565. case bNode.kind
  1566. of nkStrLit..nkTripleStrLit:
  1567. bStrVal = bNode.strVal.cstring
  1568. of nkIdent:
  1569. bStrVal = bNode.ident.s.cstring
  1570. of nkSym:
  1571. bStrVal = bNode.sym.name.s.cstring
  1572. of nkOpenSymChoice, nkClosedSymChoice:
  1573. bStrVal = bNode[0].sym.name.s.cstring
  1574. else:
  1575. discard
  1576. # set result
  1577. regs[ra].intVal =
  1578. if aStrVal != nil and bStrVal != nil:
  1579. ord(idents.cmpIgnoreStyle(aStrVal, bStrVal, high(int)) == 0)
  1580. else:
  1581. 0
  1582. of opcStrToIdent:
  1583. decodeB(rkNode)
  1584. if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}:
  1585. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1586. else:
  1587. regs[ra].node = newNodeI(nkIdent, c.debug[pc])
  1588. regs[ra].node.ident = getIdent(c.cache, regs[rb].node.strVal)
  1589. regs[ra].node.flags.incl nfIsRef
  1590. of opcSetType:
  1591. let typ = c.types[instr.regBx - wordExcess]
  1592. if regs[ra].kind != rkNode:
  1593. let temp = regToNode(regs[ra])
  1594. ensureKind(rkNode)
  1595. regs[ra].node = temp
  1596. regs[ra].node.info = c.debug[pc]
  1597. regs[ra].node.typ = typ
  1598. of opcConv:
  1599. let rb = instr.regB
  1600. inc pc
  1601. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1602. inc pc
  1603. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1604. if opConv(c, regs[ra], regs[rb], desttyp, srctyp):
  1605. stackTrace(c, tos, pc,
  1606. errIllegalConvFromXtoY % [
  1607. typeToString(srctyp), typeToString(desttyp)])
  1608. of opcCast:
  1609. let rb = instr.regB
  1610. inc pc
  1611. let desttyp = c.types[c.code[pc].regBx - wordExcess]
  1612. inc pc
  1613. let srctyp = c.types[c.code[pc].regBx - wordExcess]
  1614. when hasFFI:
  1615. let dest = fficast(c.config, regs[rb].node, desttyp)
  1616. # todo: check whether this is correct
  1617. # asgnRef(regs[ra], dest)
  1618. putIntoReg(regs[ra], dest)
  1619. else:
  1620. globalError(c.config, c.debug[pc], "cannot evaluate cast")
  1621. of opcNSetIntVal:
  1622. decodeB(rkNode)
  1623. var dest = regs[ra].node
  1624. if dest.kind in {nkCharLit..nkUInt64Lit} and
  1625. regs[rb].kind in {rkInt}:
  1626. dest.intVal = regs[rb].intVal
  1627. elif dest.kind == nkSym and dest.sym.kind == skEnumField:
  1628. stackTrace(c, tos, pc, "`intVal` cannot be changed for an enum symbol.")
  1629. else:
  1630. stackTrace(c, tos, pc, errFieldXNotFound & "intVal")
  1631. of opcNSetFloatVal:
  1632. decodeB(rkNode)
  1633. var dest = regs[ra].node
  1634. if dest.kind in {nkFloatLit..nkFloat64Lit} and
  1635. regs[rb].kind in {rkFloat}:
  1636. dest.floatVal = regs[rb].floatVal
  1637. else:
  1638. stackTrace(c, tos, pc, errFieldXNotFound & "floatVal")
  1639. of opcNSetSymbol:
  1640. decodeB(rkNode)
  1641. var dest = regs[ra].node
  1642. if dest.kind == nkSym and regs[rb].node.kind == nkSym:
  1643. dest.sym = regs[rb].node.sym
  1644. else:
  1645. stackTrace(c, tos, pc, errFieldXNotFound & "symbol")
  1646. of opcNSetIdent:
  1647. decodeB(rkNode)
  1648. var dest = regs[ra].node
  1649. if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
  1650. dest.ident = regs[rb].node.ident
  1651. else:
  1652. stackTrace(c, tos, pc, errFieldXNotFound & "ident")
  1653. of opcNSetType:
  1654. decodeB(rkNode)
  1655. let b = regs[rb].node
  1656. internalAssert c.config, b.kind == nkSym and b.sym.kind == skType
  1657. internalAssert c.config, regs[ra].node != nil
  1658. regs[ra].node.typ = b.sym.typ
  1659. of opcNSetStrVal:
  1660. decodeB(rkNode)
  1661. var dest = regs[ra].node
  1662. if dest.kind in {nkStrLit..nkTripleStrLit} and
  1663. regs[rb].kind in {rkNode}:
  1664. dest.strVal = regs[rb].node.strVal
  1665. elif dest.kind == nkCommentStmt and regs[rb].kind in {rkNode}:
  1666. dest.comment = regs[rb].node.strVal
  1667. else:
  1668. stackTrace(c, tos, pc, errFieldXNotFound & "strVal")
  1669. of opcNNewNimNode:
  1670. decodeBC(rkNode)
  1671. var k = regs[rb].intVal
  1672. if k < 0 or k > ord(high(TNodeKind)):
  1673. internalError(c.config, c.debug[pc],
  1674. "request to create a NimNode of invalid kind")
  1675. let cc = regs[rc].node
  1676. let x = newNodeI(TNodeKind(int(k)),
  1677. if cc.kind != nkNilLit:
  1678. cc.info
  1679. elif c.comesFromHeuristic.line != 0'u16:
  1680. c.comesFromHeuristic
  1681. elif c.callsite != nil and c.callsite.safeLen > 1:
  1682. c.callsite[1].info
  1683. else:
  1684. c.debug[pc])
  1685. x.flags.incl nfIsRef
  1686. # prevent crashes in the compiler resulting from wrong macros:
  1687. if x.kind == nkIdent: x.ident = c.cache.emptyIdent
  1688. regs[ra].node = x
  1689. of opcNCopyNimNode:
  1690. decodeB(rkNode)
  1691. regs[ra].node = copyNode(regs[rb].node)
  1692. of opcNCopyNimTree:
  1693. decodeB(rkNode)
  1694. regs[ra].node = copyTree(regs[rb].node)
  1695. of opcNDel:
  1696. decodeBC(rkNode)
  1697. let bb = regs[rb].intVal.int
  1698. for i in 0 ..< regs[rc].intVal.int:
  1699. delSon(regs[ra].node, bb)
  1700. of opcGenSym:
  1701. decodeBC(rkNode)
  1702. let k = regs[rb].intVal
  1703. let name = if regs[rc].node.strVal.len == 0: ":tmp"
  1704. else: regs[rc].node.strVal
  1705. if k < 0 or k > ord(high(TSymKind)):
  1706. internalError(c.config, c.debug[pc], "request to create symbol of invalid kind")
  1707. var sym = newSym(k.TSymKind, getIdent(c.cache, name), c.module.owner, c.debug[pc])
  1708. incl(sym.flags, sfGenSym)
  1709. regs[ra].node = newSymNode(sym)
  1710. regs[ra].node.flags.incl nfIsRef
  1711. of opcNccValue:
  1712. decodeB(rkInt)
  1713. let destKey = regs[rb].node.strVal
  1714. regs[ra].intVal = getOrDefault(c.graph.cacheCounters, destKey)
  1715. of opcNccInc:
  1716. let g = c.graph
  1717. declBC()
  1718. let destKey = regs[rb].node.strVal
  1719. let by = regs[rc].intVal
  1720. let v = getOrDefault(g.cacheCounters, destKey)
  1721. g.cacheCounters[destKey] = v+by
  1722. recordInc(c, c.debug[pc], destKey, by)
  1723. of opcNcsAdd:
  1724. let g = c.graph
  1725. declBC()
  1726. let destKey = regs[rb].node.strVal
  1727. let val = regs[rc].node
  1728. if not contains(g.cacheSeqs, destKey):
  1729. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  1730. else:
  1731. g.cacheSeqs[destKey].add val
  1732. recordAdd(c, c.debug[pc], destKey, val)
  1733. of opcNcsIncl:
  1734. let g = c.graph
  1735. declBC()
  1736. let destKey = regs[rb].node.strVal
  1737. let val = regs[rc].node
  1738. if not contains(g.cacheSeqs, destKey):
  1739. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  1740. else:
  1741. block search:
  1742. for existing in g.cacheSeqs[destKey]:
  1743. if exprStructuralEquivalent(existing, val, strictSymEquality=true):
  1744. break search
  1745. g.cacheSeqs[destKey].add val
  1746. recordIncl(c, c.debug[pc], destKey, val)
  1747. of opcNcsLen:
  1748. let g = c.graph
  1749. decodeB(rkInt)
  1750. let destKey = regs[rb].node.strVal
  1751. regs[ra].intVal =
  1752. if contains(g.cacheSeqs, destKey): g.cacheSeqs[destKey].len else: 0
  1753. of opcNcsAt:
  1754. let g = c.graph
  1755. decodeBC(rkNode)
  1756. let idx = regs[rc].intVal
  1757. let destKey = regs[rb].node.strVal
  1758. if contains(g.cacheSeqs, destKey) and idx <% g.cacheSeqs[destKey].len:
  1759. regs[ra].node = g.cacheSeqs[destKey][idx.int]
  1760. else:
  1761. stackTrace(c, tos, pc, formatErrorIndexBound(idx, g.cacheSeqs[destKey].len-1))
  1762. of opcNctPut:
  1763. let g = c.graph
  1764. let destKey = regs[ra].node.strVal
  1765. let key = regs[instr.regB].node.strVal
  1766. let val = regs[instr.regC].node
  1767. if not contains(g.cacheTables, destKey):
  1768. g.cacheTables[destKey] = initBTree[string, PNode]()
  1769. if not contains(g.cacheTables[destKey], key):
  1770. g.cacheTables[destKey].add(key, val)
  1771. recordPut(c, c.debug[pc], destKey, key, val)
  1772. else:
  1773. stackTrace(c, tos, pc, "key already exists: " & key)
  1774. of opcNctLen:
  1775. let g = c.graph
  1776. decodeB(rkInt)
  1777. let destKey = regs[rb].node.strVal
  1778. regs[ra].intVal =
  1779. if contains(g.cacheTables, destKey): g.cacheTables[destKey].len else: 0
  1780. of opcNctGet:
  1781. let g = c.graph
  1782. decodeBC(rkNode)
  1783. let destKey = regs[rb].node.strVal
  1784. let key = regs[rc].node.strVal
  1785. if contains(g.cacheTables, destKey):
  1786. if contains(g.cacheTables[destKey], key):
  1787. regs[ra].node = getOrDefault(g.cacheTables[destKey], key)
  1788. else:
  1789. stackTrace(c, tos, pc, "key does not exist: " & key)
  1790. else:
  1791. stackTrace(c, tos, pc, "key does not exist: " & destKey)
  1792. of opcNctHasNext:
  1793. let g = c.graph
  1794. decodeBC(rkInt)
  1795. let destKey = regs[rb].node.strVal
  1796. regs[ra].intVal =
  1797. if g.cacheTables.contains(destKey):
  1798. ord(btrees.hasNext(g.cacheTables[destKey], regs[rc].intVal.int))
  1799. else:
  1800. 0
  1801. of opcNctNext:
  1802. let g = c.graph
  1803. decodeBC(rkNode)
  1804. let destKey = regs[rb].node.strVal
  1805. let index = regs[rc].intVal
  1806. if contains(g.cacheTables, destKey):
  1807. let (k, v, nextIndex) = btrees.next(g.cacheTables[destKey], index.int)
  1808. regs[ra].node = newTree(nkTupleConstr, newStrNode(k, c.debug[pc]), v,
  1809. newIntNode(nkIntLit, nextIndex))
  1810. else:
  1811. stackTrace(c, tos, pc, "key does not exist: " & destKey)
  1812. of opcTypeTrait:
  1813. # XXX only supports 'name' for now; we can use regC to encode the
  1814. # type trait operation
  1815. decodeB(rkNode)
  1816. var typ = regs[rb].node.typ
  1817. internalAssert c.config, typ != nil
  1818. while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
  1819. createStr regs[ra]
  1820. regs[ra].node.strVal = typ.typeToString(preferExported)
  1821. of opcMarshalLoad:
  1822. let ra = instr.regA
  1823. let rb = instr.regB
  1824. inc pc
  1825. let typ = c.types[c.code[pc].regBx - wordExcess]
  1826. putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ, c.cache, c.config))
  1827. of opcMarshalStore:
  1828. decodeB(rkNode)
  1829. inc pc
  1830. let typ = c.types[c.code[pc].regBx - wordExcess]
  1831. createStrKeepNode(regs[ra])
  1832. when not defined(nimNoNilSeqs):
  1833. if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
  1834. storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config)
  1835. inc pc
  1836. proc execute(c: PCtx, start: int): PNode =
  1837. var tos = PStackFrame(prc: nil, comesFrom: 0, next: nil)
  1838. newSeq(tos.slots, c.prc.maxSlots)
  1839. result = rawExecute(c, start, tos).regToNode
  1840. proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
  1841. if sym.kind in routineKinds:
  1842. if sym.typ.len-1 != args.len:
  1843. localError(c.config, sym.info,
  1844. "NimScript: expected $# arguments, but got $#" % [
  1845. $(sym.typ.len-1), $args.len])
  1846. else:
  1847. let start = genProc(c, sym)
  1848. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  1849. let maxSlots = sym.offset
  1850. newSeq(tos.slots, maxSlots)
  1851. # setup parameters:
  1852. if not isEmptyType(sym.typ.sons[0]) or sym.kind == skMacro:
  1853. putIntoReg(tos.slots[0], getNullValue(sym.typ.sons[0], sym.info, c.config))
  1854. # XXX We could perform some type checking here.
  1855. for i in 1..<sym.typ.len:
  1856. putIntoReg(tos.slots[i], args[i-1])
  1857. result = rawExecute(c, start, tos).regToNode
  1858. else:
  1859. localError(c.config, sym.info,
  1860. "NimScript: attempt to call non-routine: " & sym.name.s)
  1861. proc evalStmt*(c: PCtx, n: PNode) =
  1862. let n = transformExpr(c.graph, c.module, n, noDestructors = true)
  1863. let start = genStmt(c, n)
  1864. # execute new instructions; this redundant opcEof check saves us lots
  1865. # of allocations in 'execute':
  1866. if c.code[start].opcode != opcEof:
  1867. discard execute(c, start)
  1868. proc evalExpr*(c: PCtx, n: PNode): PNode =
  1869. let n = transformExpr(c.graph, c.module, n, noDestructors = true)
  1870. let start = genExpr(c, n)
  1871. assert c.code[start].opcode != opcEof
  1872. result = execute(c, start)
  1873. proc getGlobalValue*(c: PCtx; s: PSym): PNode =
  1874. internalAssert c.config, s.kind in {skLet, skVar} and sfGlobal in s.flags
  1875. result = c.globals.sons[s.position-1]
  1876. include vmops
  1877. proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) =
  1878. if graph.vm.isNil:
  1879. graph.vm = newCtx(module, graph.cache, graph)
  1880. registerAdditionalOps(PCtx graph.vm)
  1881. else:
  1882. refresh(PCtx graph.vm, module)
  1883. proc myOpen(graph: ModuleGraph; module: PSym): PPassContext =
  1884. #var c = newEvalContext(module, emRepl)
  1885. #c.features = {allowCast, allowInfiniteLoops}
  1886. #pushStackFrame(c, newStackFrame())
  1887. # XXX produce a new 'globals' environment here:
  1888. setupGlobalCtx(module, graph)
  1889. result = PCtx graph.vm
  1890. proc myProcess(c: PPassContext, n: PNode): PNode =
  1891. let c = PCtx(c)
  1892. # don't eval errornous code:
  1893. if c.oldErrorCount == c.config.errorCounter:
  1894. evalStmt(c, n)
  1895. result = newNodeI(nkEmpty, n.info)
  1896. else:
  1897. result = n
  1898. c.oldErrorCount = c.config.errorCounter
  1899. proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
  1900. myProcess(c, n)
  1901. const evalPass* = makePass(myOpen, myProcess, myClose)
  1902. proc evalConstExprAux(module: PSym;
  1903. g: ModuleGraph; prc: PSym, n: PNode,
  1904. mode: TEvalMode): PNode =
  1905. if g.config.errorCounter > 0: return n
  1906. let n = transformExpr(g, module, n, noDestructors = true)
  1907. setupGlobalCtx(module, g)
  1908. var c = PCtx g.vm
  1909. let oldMode = c.mode
  1910. defer: c.mode = oldMode
  1911. c.mode = mode
  1912. let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
  1913. if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
  1914. assert c.code[start].opcode != opcEof
  1915. when debugEchoCode: c.echoCode start
  1916. var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
  1917. newSeq(tos.slots, c.prc.maxSlots)
  1918. #for i in 0 ..< c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
  1919. result = rawExecute(c, start, tos).regToNode
  1920. if result.info.col < 0: result.info = n.info
  1921. proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode =
  1922. result = evalConstExprAux(module, g, nil, e, emConst)
  1923. proc evalStaticExpr*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym): PNode =
  1924. result = evalConstExprAux(module, g, prc, e, emStaticExpr)
  1925. proc evalStaticStmt*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym) =
  1926. discard evalConstExprAux(module, g, prc, e, emStaticStmt)
  1927. proc setupCompileTimeVar*(module: PSym; g: ModuleGraph; n: PNode) =
  1928. discard evalConstExprAux(module, g, nil, n, emStaticStmt)
  1929. proc prepareVMValue(arg: PNode): PNode =
  1930. ## strip nkExprColonExpr from tuple values recurively. That is how
  1931. ## they are expected to be stored in the VM.
  1932. # Early abort without copy. No transformation takes place.
  1933. if arg.kind in nkLiterals:
  1934. return arg
  1935. result = copyNode(arg)
  1936. if arg.kind == nkTupleConstr:
  1937. for child in arg:
  1938. if child.kind == nkExprColonExpr:
  1939. result.add prepareVMValue(child[1])
  1940. else:
  1941. result.add prepareVMValue(child)
  1942. else:
  1943. for child in arg:
  1944. result.add prepareVMValue(child)
  1945. proc setupMacroParam(x: PNode, typ: PType): TFullReg =
  1946. case typ.kind
  1947. of tyStatic:
  1948. putIntoReg(result, prepareVMValue(x))
  1949. else:
  1950. result.kind = rkNode
  1951. var n = x
  1952. if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
  1953. n = n.canonValue
  1954. n.flags.incl nfIsRef
  1955. n.typ = x.typ
  1956. result.node = n
  1957. iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
  1958. let gp = macroSym.ast[genericParamsPos]
  1959. for i in 0 ..< gp.len:
  1960. let genericParam = gp[i].sym
  1961. let posInCall = macroSym.typ.len + i
  1962. yield (genericParam, call[posInCall])
  1963. # to prevent endless recursion in macro instantiation
  1964. const evalMacroLimit = 1000
  1965. proc evalMacroCall*(module: PSym; g: ModuleGraph;
  1966. n, nOrig: PNode, sym: PSym): PNode =
  1967. # XXX globalError() is ugly here, but I don't know a better solution for now
  1968. inc(g.config.evalMacroCounter)
  1969. if g.config.evalMacroCounter > evalMacroLimit:
  1970. globalError(g.config, n.info, "macro instantiation too nested")
  1971. # immediate macros can bypass any type and arity checking so we check the
  1972. # arity here too:
  1973. if sym.typ.len > n.safeLen and sym.typ.len > 1:
  1974. globalError(g.config, n.info, "in call '$#' got $#, but expected $# argument(s)" % [
  1975. n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)])
  1976. setupGlobalCtx(module, g)
  1977. var c = PCtx g.vm
  1978. c.comesFromHeuristic.line = 0'u16
  1979. c.callsite = nOrig
  1980. let start = genProc(c, sym)
  1981. var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
  1982. let maxSlots = sym.offset
  1983. newSeq(tos.slots, maxSlots)
  1984. # setup arguments:
  1985. var L = n.safeLen
  1986. if L == 0: L = 1
  1987. # This is wrong for tests/reject/tind1.nim where the passed 'else' part
  1988. # doesn't end up in the parameter:
  1989. #InternalAssert tos.slots.len >= L
  1990. # return value:
  1991. tos.slots[0].kind = rkNode
  1992. tos.slots[0].node = newNodeI(nkEmpty, n.info)
  1993. # setup parameters:
  1994. for i in 1..<sym.typ.len:
  1995. tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
  1996. let gp = sym.ast[genericParamsPos]
  1997. for i in 0 ..< gp.len:
  1998. let idx = sym.typ.len + i
  1999. if idx < n.len:
  2000. tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
  2001. else:
  2002. dec(g.config.evalMacroCounter)
  2003. c.callsite = nil
  2004. localError(c.config, n.info, "expected " & $gp.len &
  2005. " generic parameter(s)")
  2006. # temporary storage:
  2007. #for i in L ..< maxSlots: tos.slots[i] = newNode(nkEmpty)
  2008. result = rawExecute(c, start, tos).regToNode
  2009. if result.info.line < 0: result.info = n.info
  2010. if cyclicTree(result): globalError(c.config, n.info, "macro produced a cyclic tree")
  2011. dec(g.config.evalMacroCounter)
  2012. c.callsite = nil