vm.nim 84 KB

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