vmgen.nim 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103
  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 module implements the code generator for the VM.
  10. # Important things to remember:
  11. # - The VM does not distinguish between definitions ('var x = y') and
  12. # assignments ('x = y'). For simple data types that fit into a register
  13. # this doesn't matter. However it matters for strings and other complex
  14. # types that use the 'node' field; the reason is that slots are
  15. # re-used in a register based VM. Example:
  16. #
  17. # .. code-block:: nim
  18. # let s = a & b # no matter what, create fresh node
  19. # s = a & b # no matter what, keep the node
  20. #
  21. # Also *stores* into non-temporary memory need to perform deep copies:
  22. # a.b = x.y
  23. # We used to generate opcAsgn for the *load* of 'x.y' but this is clearly
  24. # wrong! We need to produce opcAsgn (the copy) for the *store*. This also
  25. # solves the opcLdConst vs opcAsgnConst issue. Of course whether we need
  26. # this copy depends on the involved types.
  27. import
  28. strutils, ast, astalgo, types, msgs, renderer, vmdef,
  29. trees, intsets, magicsys, options, lowerings, lineinfos
  30. import platform
  31. from os import splitFile
  32. when hasFFI:
  33. import evalffi
  34. type
  35. TGenFlag = enum
  36. gfNode # Affects how variables are loaded - always loads as rkNode
  37. gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr
  38. TGenFlags = set[TGenFlag]
  39. proc debugInfo(c: PCtx; info: TLineInfo): string =
  40. result = toFilename(c.config, info).splitFile.name & ":" & $info.line
  41. proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
  42. # first iteration: compute all necessary labels:
  43. var jumpTargets = initIntSet()
  44. let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
  45. for i in start..last:
  46. let x = c.code[i]
  47. if x.opcode in relativeJumps:
  48. jumpTargets.incl(i+x.regBx-wordExcess)
  49. # for debugging purposes
  50. var i = start
  51. while i <= last:
  52. if i in jumpTargets: result.addf("L$1:\n", i)
  53. let x = c.code[i]
  54. result.add($i)
  55. let opc = opcode(x)
  56. if opc in {opcConv, opcCast}:
  57. let y = c.code[i+1]
  58. let z = c.code[i+2]
  59. result.addf("\t$#\tr$#, r$#, $#, $#", ($opc).substr(3), x.regA, x.regB,
  60. c.types[y.regBx-wordExcess].typeToString,
  61. c.types[z.regBx-wordExcess].typeToString)
  62. inc i, 2
  63. elif opc < firstABxInstr:
  64. result.addf("\t$#\tr$#, r$#, r$#", ($opc).substr(3), x.regA,
  65. x.regB, x.regC)
  66. elif opc in relativeJumps:
  67. result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA,
  68. i+x.regBx-wordExcess)
  69. elif opc in {opcLdConst, opcAsgnConst}:
  70. let idx = x.regBx-wordExcess
  71. result.addf("\t$#\tr$#, $# ($#)", ($opc).substr(3), x.regA,
  72. c.constants[idx].renderTree, $idx)
  73. elif opc in {opcMarshalLoad, opcMarshalStore}:
  74. let y = c.code[i+1]
  75. result.addf("\t$#\tr$#, r$#, $#", ($opc).substr(3), x.regA, x.regB,
  76. c.types[y.regBx-wordExcess].typeToString)
  77. inc i
  78. else:
  79. result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, x.regBx-wordExcess)
  80. result.add("\t#")
  81. result.add(debugInfo(c, c.debug[i]))
  82. result.add("\n")
  83. inc i
  84. proc echoCode*(c: PCtx; start=0; last = -1) {.deprecated.} =
  85. var buf = ""
  86. codeListing(c, buf, start, last)
  87. echo buf
  88. proc gABC(ctx: PCtx; n: PNode; opc: TOpcode; a, b, c: TRegister = 0) =
  89. ## Takes the registers `b` and `c`, applies the operation `opc` to them, and
  90. ## stores the result into register `a`
  91. ## The node is needed for debug information
  92. assert opc.ord < 255
  93. let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
  94. (b.uint32 shl 16'u32) or
  95. (c.uint32 shl 24'u32)).TInstr
  96. when false:
  97. if ctx.code.len == 43:
  98. writeStackTrace()
  99. echo "generating ", opc
  100. ctx.code.add(ins)
  101. ctx.debug.add(n.info)
  102. proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
  103. # Takes the `b` register and the immediate `imm`, appies the operation `opc`,
  104. # and stores the output value into `a`.
  105. # `imm` is signed and must be within [-128, 127]
  106. if imm >= -128 and imm <= 127:
  107. let ins = (opc.uint32 or (a.uint32 shl 8'u32) or
  108. (b.uint32 shl 16'u32) or
  109. (imm+byteExcess).uint32 shl 24'u32).TInstr
  110. c.code.add(ins)
  111. c.debug.add(n.info)
  112. else:
  113. localError(c.config, n.info,
  114. "VM: immediate value does not fit into an int8")
  115. proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
  116. # Applies `opc` to `bx` and stores it into register `a`
  117. # `bx` must be signed and in the range [-32768, 32767]
  118. when false:
  119. if c.code.len == 43:
  120. writeStackTrace()
  121. echo "generating ", opc
  122. if bx >= -32768 and bx <= 32767:
  123. let ins = (opc.uint32 or a.uint32 shl 8'u32 or
  124. (bx+wordExcess).uint32 shl 16'u32).TInstr
  125. c.code.add(ins)
  126. c.debug.add(n.info)
  127. else:
  128. localError(c.config, n.info,
  129. "VM: immediate value does not fit into an int16")
  130. proc xjmp(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0): TPosition =
  131. #assert opc in {opcJmp, opcFJmp, opcTJmp}
  132. result = TPosition(c.code.len)
  133. gABx(c, n, opc, a, 0)
  134. proc genLabel(c: PCtx): TPosition =
  135. result = TPosition(c.code.len)
  136. #c.jumpTargets.incl(c.code.len)
  137. proc jmpBack(c: PCtx, n: PNode, p = TPosition(0)) =
  138. let dist = p.int - c.code.len
  139. internalAssert(c.config, -0x7fff < dist and dist < 0x7fff)
  140. gABx(c, n, opcJmpBack, 0, dist)
  141. proc patch(c: PCtx, p: TPosition) =
  142. # patch with current index
  143. let p = p.int
  144. let diff = c.code.len - p
  145. #c.jumpTargets.incl(c.code.len)
  146. internalAssert(c.config, -0x7fff < diff and diff < 0x7fff)
  147. let oldInstr = c.code[p]
  148. # opcode and regA stay the same:
  149. c.code[p] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
  150. uint32(diff+wordExcess) shl 16'u32).TInstr
  151. proc getSlotKind(t: PType): TSlotKind =
  152. case t.skipTypes(abstractRange-{tyTypeDesc}).kind
  153. of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
  154. slotTempInt
  155. of tyString, tyCString:
  156. slotTempStr
  157. of tyFloat..tyFloat128:
  158. slotTempFloat
  159. else:
  160. slotTempComplex
  161. const
  162. HighRegisterPressure = 40
  163. proc bestEffort(c: PCtx): TLineInfo =
  164. (if c.prc == nil: c.module.info else: c.prc.sym.info)
  165. proc getTemp(cc: PCtx; tt: PType): TRegister =
  166. let typ = tt.skipTypesOrNil({tyStatic})
  167. let c = cc.prc
  168. # we prefer the same slot kind here for efficiency. Unfortunately for
  169. # discardable return types we may not know the desired type. This can happen
  170. # for e.g. mNAdd[Multiple]:
  171. let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
  172. for i in 0 .. c.maxSlots-1:
  173. if c.slots[i].kind == k and not c.slots[i].inUse:
  174. c.slots[i].inUse = true
  175. return TRegister(i)
  176. # if register pressure is high, we re-use more aggressively:
  177. if c.maxSlots >= HighRegisterPressure and false:
  178. for i in 0 .. c.maxSlots-1:
  179. if not c.slots[i].inUse:
  180. c.slots[i] = (inUse: true, kind: k)
  181. return TRegister(i)
  182. if c.maxSlots >= high(TRegister):
  183. globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
  184. result = TRegister(c.maxSlots)
  185. c.slots[c.maxSlots] = (inUse: true, kind: k)
  186. inc c.maxSlots
  187. proc freeTemp(c: PCtx; r: TRegister) =
  188. let c = c.prc
  189. if c.slots[r].kind in {slotSomeTemp..slotTempComplex}: c.slots[r].inUse = false
  190. proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
  191. # if register pressure is high, we re-use more aggressively:
  192. let c = cc.prc
  193. if c.maxSlots >= HighRegisterPressure or c.maxSlots+n >= high(TRegister):
  194. for i in 0 .. c.maxSlots-n:
  195. if not c.slots[i].inUse:
  196. block search:
  197. for j in i+1 .. i+n-1:
  198. if c.slots[j].inUse: break search
  199. result = TRegister(i)
  200. for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
  201. return
  202. if c.maxSlots+n >= high(TRegister):
  203. globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
  204. result = TRegister(c.maxSlots)
  205. inc c.maxSlots, n
  206. for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
  207. proc freeTempRange(c: PCtx; start: TRegister, n: int) =
  208. for i in start .. start+n-1: c.freeTemp(TRegister(i))
  209. template withTemp(tmp, typ, body: untyped) {.dirty.} =
  210. var tmp = getTemp(c, typ)
  211. body
  212. c.freeTemp(tmp)
  213. proc popBlock(c: PCtx; oldLen: int) =
  214. for f in c.prc.blocks[oldLen].fixups:
  215. c.patch(f)
  216. c.prc.blocks.setLen(oldLen)
  217. template withBlock(labl: PSym; body: untyped) {.dirty.} =
  218. var oldLen {.gensym.} = c.prc.blocks.len
  219. c.prc.blocks.add TBlock(label: labl, fixups: @[])
  220. body
  221. popBlock(c, oldLen)
  222. proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {})
  223. proc gen(c: PCtx; n: PNode; dest: TRegister; flags: TGenFlags = {}) =
  224. var d: TDest = dest
  225. gen(c, n, d, flags)
  226. #internalAssert c.config, d == dest # issue #7407
  227. proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
  228. var tmp: TDest = -1
  229. gen(c, n, tmp, flags)
  230. #if n.typ.isEmptyType: InternalAssert tmp < 0
  231. proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
  232. var tmp: TDest = -1
  233. gen(c, n, tmp, flags)
  234. #internalAssert c.config, tmp >= 0 # 'nim check' does not like this internalAssert.
  235. if tmp >= 0:
  236. result = TRegister(tmp)
  237. proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
  238. # stmt is different from 'void' in meta programming contexts.
  239. # So we only set dest to -1 if 'void':
  240. if dest >= 0 and (n.typ.isNil or n.typ.kind == tyVoid):
  241. c.freeTemp(dest)
  242. dest = -1
  243. proc isNotOpr(n: PNode): bool =
  244. n.kind in nkCallKinds and n.sons[0].kind == nkSym and
  245. n.sons[0].sym.magic == mNot
  246. proc isTrue(n: PNode): bool =
  247. n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or
  248. n.kind == nkIntLit and n.intVal != 0
  249. proc genWhile(c: PCtx; n: PNode) =
  250. # L1:
  251. # cond, tmp
  252. # fjmp tmp, L2
  253. # body
  254. # jmp L1
  255. # L2:
  256. let L1 = c.genLabel
  257. withBlock(nil):
  258. if isTrue(n.sons[0]):
  259. c.gen(n.sons[1])
  260. c.jmpBack(n, L1)
  261. elif isNotOpr(n.sons[0]):
  262. var tmp = c.genx(n.sons[0].sons[1])
  263. let L2 = c.xjmp(n, opcTJmp, tmp)
  264. c.freeTemp(tmp)
  265. c.gen(n.sons[1])
  266. c.jmpBack(n, L1)
  267. c.patch(L2)
  268. else:
  269. var tmp = c.genx(n.sons[0])
  270. let L2 = c.xjmp(n, opcFJmp, tmp)
  271. c.freeTemp(tmp)
  272. c.gen(n.sons[1])
  273. c.jmpBack(n, L1)
  274. c.patch(L2)
  275. proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
  276. withBlock(n.sons[0].sym):
  277. c.gen(n.sons[1], dest)
  278. c.clearDest(n, dest)
  279. proc genBreak(c: PCtx; n: PNode) =
  280. let L1 = c.xjmp(n, opcJmp)
  281. if n.sons[0].kind == nkSym:
  282. #echo cast[int](n.sons[0].sym)
  283. for i in countdown(c.prc.blocks.len-1, 0):
  284. if c.prc.blocks[i].label == n.sons[0].sym:
  285. c.prc.blocks[i].fixups.add L1
  286. return
  287. globalError(c.config, n.info, "VM problem: cannot find 'break' target")
  288. else:
  289. c.prc.blocks[c.prc.blocks.high].fixups.add L1
  290. proc genIf(c: PCtx, n: PNode; dest: var TDest) =
  291. # if (!expr1) goto L1;
  292. # thenPart
  293. # goto LEnd
  294. # L1:
  295. # if (!expr2) goto L2;
  296. # thenPart2
  297. # goto LEnd
  298. # L2:
  299. # elsePart
  300. # Lend:
  301. if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
  302. var endings: seq[TPosition] = @[]
  303. for i in countup(0, len(n) - 1):
  304. var it = n.sons[i]
  305. if it.len == 2:
  306. withTemp(tmp, it.sons[0].typ):
  307. var elsePos: TPosition
  308. if isNotOpr(it.sons[0]):
  309. c.gen(it.sons[0].sons[1], tmp)
  310. elsePos = c.xjmp(it.sons[0].sons[1], opcTJmp, tmp) # if true
  311. else:
  312. c.gen(it.sons[0], tmp)
  313. elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
  314. c.clearDest(n, dest)
  315. c.gen(it.sons[1], dest) # then part
  316. if i < sonsLen(n)-1:
  317. endings.add(c.xjmp(it.sons[1], opcJmp, 0))
  318. c.patch(elsePos)
  319. else:
  320. c.clearDest(n, dest)
  321. c.gen(it.sons[0], dest)
  322. for endPos in endings: c.patch(endPos)
  323. c.clearDest(n, dest)
  324. proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
  325. # asgn dest, a
  326. # tjmp|fjmp L1
  327. # asgn dest, b
  328. # L1:
  329. if dest < 0: dest = getTemp(c, n.typ)
  330. c.gen(n.sons[1], dest)
  331. let L1 = c.xjmp(n, opc, dest)
  332. c.gen(n.sons[2], dest)
  333. c.patch(L1)
  334. proc canonValue*(n: PNode): PNode =
  335. result = n
  336. proc rawGenLiteral(c: PCtx; n: PNode): int =
  337. result = c.constants.len
  338. #assert(n.kind != nkCall)
  339. n.flags.incl nfAllConst
  340. c.constants.add n.canonValue
  341. internalAssert c.config, result < 0x7fff
  342. proc sameConstant*(a, b: PNode): bool =
  343. result = false
  344. if a == b:
  345. result = true
  346. elif a != nil and b != nil and a.kind == b.kind:
  347. case a.kind
  348. of nkSym: result = a.sym == b.sym
  349. of nkIdent: result = a.ident.id == b.ident.id
  350. of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
  351. of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
  352. of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
  353. of nkType, nkNilLit: result = a.typ == b.typ
  354. of nkEmpty: result = true
  355. else:
  356. if sonsLen(a) == sonsLen(b):
  357. for i in countup(0, sonsLen(a) - 1):
  358. if not sameConstant(a.sons[i], b.sons[i]): return
  359. result = true
  360. proc genLiteral(c: PCtx; n: PNode): int =
  361. # types do not matter here:
  362. for i in 0 ..< c.constants.len:
  363. if sameConstant(c.constants[i], n): return i
  364. result = rawGenLiteral(c, n)
  365. proc unused(c: PCtx; n: PNode; x: TDest) {.inline.} =
  366. if x >= 0:
  367. #debug(n)
  368. globalError(c.config, n.info, "not unused")
  369. proc genCase(c: PCtx; n: PNode; dest: var TDest) =
  370. # if (!expr1) goto L1;
  371. # thenPart
  372. # goto LEnd
  373. # L1:
  374. # if (!expr2) goto L2;
  375. # thenPart2
  376. # goto LEnd
  377. # L2:
  378. # elsePart
  379. # Lend:
  380. if not isEmptyType(n.typ):
  381. if dest < 0: dest = getTemp(c, n.typ)
  382. else:
  383. unused(c, n, dest)
  384. var endings: seq[TPosition] = @[]
  385. withTemp(tmp, n.sons[0].typ):
  386. c.gen(n.sons[0], tmp)
  387. # branch tmp, codeIdx
  388. # fjmp elseLabel
  389. for i in 1 ..< n.len:
  390. let it = n.sons[i]
  391. if it.len == 1:
  392. # else stmt:
  393. c.gen(it.sons[0], dest)
  394. else:
  395. let b = rawGenLiteral(c, it)
  396. c.gABx(it, opcBranch, tmp, b)
  397. let elsePos = c.xjmp(it.lastSon, opcFJmp, tmp)
  398. c.gen(it.lastSon, dest)
  399. if i < sonsLen(n)-1:
  400. endings.add(c.xjmp(it.lastSon, opcJmp, 0))
  401. c.patch(elsePos)
  402. c.clearDest(n, dest)
  403. for endPos in endings: c.patch(endPos)
  404. proc genType(c: PCtx; typ: PType): int =
  405. for i, t in c.types:
  406. if sameType(t, typ): return i
  407. result = c.types.len
  408. c.types.add(typ)
  409. internalAssert(c.config, result <= 0x7fff)
  410. proc genTry(c: PCtx; n: PNode; dest: var TDest) =
  411. if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
  412. var endings: seq[TPosition] = @[]
  413. let elsePos = c.xjmp(n, opcTry, 0)
  414. c.gen(n.sons[0], dest)
  415. c.clearDest(n, dest)
  416. c.patch(elsePos)
  417. for i in 1 ..< n.len:
  418. let it = n.sons[i]
  419. if it.kind != nkFinally:
  420. var blen = len(it)
  421. # first opcExcept contains the end label of the 'except' block:
  422. let endExcept = c.xjmp(it, opcExcept, 0)
  423. for j in countup(0, blen - 2):
  424. assert(it.sons[j].kind == nkType)
  425. let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
  426. c.gABx(it, opcExcept, 0, c.genType(typ))
  427. if blen == 1:
  428. # general except section:
  429. c.gABx(it, opcExcept, 0, 0)
  430. c.gen(it.lastSon, dest)
  431. c.clearDest(n, dest)
  432. if i < sonsLen(n)-1:
  433. endings.add(c.xjmp(it, opcJmp, 0))
  434. c.patch(endExcept)
  435. for endPos in endings: c.patch(endPos)
  436. let fin = lastSon(n)
  437. # we always generate an 'opcFinally' as that pops the safepoint
  438. # from the stack
  439. c.gABx(fin, opcFinally, 0, 0)
  440. if fin.kind == nkFinally:
  441. c.gen(fin.sons[0])
  442. c.clearDest(n, dest)
  443. c.gABx(fin, opcFinallyEnd, 0, 0)
  444. proc genRaise(c: PCtx; n: PNode) =
  445. let dest = genx(c, n.sons[0])
  446. c.gABC(n, opcRaise, dest)
  447. c.freeTemp(dest)
  448. proc genReturn(c: PCtx; n: PNode) =
  449. if n.sons[0].kind != nkEmpty:
  450. gen(c, n.sons[0])
  451. c.gABC(n, opcRet)
  452. proc genLit(c: PCtx; n: PNode; dest: var TDest) =
  453. # opcLdConst is now always valid. We produce the necessary copy in the
  454. # assignments now:
  455. #var opc = opcLdConst
  456. if dest < 0: dest = c.getTemp(n.typ)
  457. #elif c.prc.slots[dest].kind == slotFixedVar: opc = opcAsgnConst
  458. let lit = genLiteral(c, n)
  459. c.gABx(n, opcLdConst, dest, lit)
  460. proc genCall(c: PCtx; n: PNode; dest: var TDest) =
  461. # it can happen that due to inlining we have a 'n' that should be
  462. # treated as a constant (see issue #537).
  463. #if n.typ != nil and n.typ.sym != nil and n.typ.sym.magic == mPNimrodNode:
  464. # genLit(c, n, dest)
  465. # return
  466. if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
  467. let x = c.getTempRange(n.len, slotTempUnknown)
  468. # varargs need 'opcSetType' for the FFI support:
  469. let fntyp = skipTypes(n.sons[0].typ, abstractInst)
  470. for i in 0..<n.len:
  471. #if i > 0 and i < sonsLen(fntyp):
  472. # let paramType = fntyp.n.sons[i]
  473. # if paramType.typ.isCompileTimeOnly: continue
  474. var r: TRegister = x+i
  475. c.gen(n.sons[i], r)
  476. if i >= fntyp.len:
  477. internalAssert c.config, tfVarargs in fntyp.flags
  478. c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
  479. if dest < 0:
  480. c.gABC(n, opcIndCall, 0, x, n.len)
  481. else:
  482. c.gABC(n, opcIndCallAsgn, dest, x, n.len)
  483. c.freeTempRange(x, n.len)
  484. template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
  485. proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
  486. proc needsAsgnPatch(n: PNode): bool =
  487. n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
  488. nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
  489. proc genField(c: PCtx; n: PNode): TRegister =
  490. if n.kind != nkSym or n.sym.kind != skField:
  491. globalError(c.config, n.info, "no field symbol")
  492. let s = n.sym
  493. if s.position > high(result):
  494. globalError(c.config, n.info,
  495. "too large offset! cannot generate code for: " & s.name.s)
  496. result = s.position
  497. proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister =
  498. if arr.skipTypes(abstractInst).kind == tyArray and (let x = firstOrd(c.config, arr);
  499. x != 0):
  500. let tmp = c.genx(n)
  501. # freeing the temporary here means we can produce: regA = regA - Imm
  502. c.freeTemp(tmp)
  503. result = c.getTemp(n.typ)
  504. c.gABI(n, opcSubImmInt, result, tmp, x.int)
  505. else:
  506. result = c.genx(n)
  507. proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
  508. case le.kind
  509. of nkBracketExpr:
  510. let dest = c.genx(le.sons[0], {gfNode})
  511. let idx = c.genIndex(le.sons[1], le.sons[0].typ)
  512. c.gABC(le, opcWrArr, dest, idx, value)
  513. c.freeTemp(dest)
  514. c.freeTemp(idx)
  515. of nkDotExpr, nkCheckedFieldExpr:
  516. # XXX field checks here
  517. let left = if le.kind == nkDotExpr: le else: le.sons[0]
  518. let dest = c.genx(left.sons[0], {gfNode})
  519. let idx = genField(c, left.sons[1])
  520. c.gABC(left, opcWrObj, dest, idx, value)
  521. c.freeTemp(dest)
  522. of nkDerefExpr, nkHiddenDeref:
  523. let dest = c.genx(le.sons[0], {gfNode})
  524. c.gABC(le, opcWrDeref, dest, 0, value)
  525. c.freeTemp(dest)
  526. of nkSym:
  527. if le.sym.isGlobal:
  528. let dest = c.genx(le, {gfNodeAddr})
  529. c.gABC(le, opcWrDeref, dest, 0, value)
  530. c.freeTemp(dest)
  531. else:
  532. discard
  533. proc genNew(c: PCtx; n: PNode) =
  534. let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
  535. else: c.genx(n.sons[1])
  536. # we use the ref's base type here as the VM conflates 'ref object'
  537. # and 'object' since internally we already have a pointer.
  538. c.gABx(n, opcNew, dest,
  539. c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
  540. c.genAsgnPatch(n.sons[1], dest)
  541. c.freeTemp(dest)
  542. proc genNewSeq(c: PCtx; n: PNode) =
  543. let t = n.sons[1].typ
  544. let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(t)
  545. else: c.genx(n.sons[1])
  546. let tmp = c.genx(n.sons[2])
  547. c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
  548. abstractVar-{tyTypeDesc})))
  549. c.gABx(n, opcNewSeq, tmp, 0)
  550. c.freeTemp(tmp)
  551. c.genAsgnPatch(n.sons[1], dest)
  552. c.freeTemp(dest)
  553. proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
  554. let t = n.typ
  555. let tmp = c.getTemp(n.sons[1].typ)
  556. c.gABx(n, opcLdNull, dest, c.genType(t))
  557. c.gABx(n, opcLdImmInt, tmp, 0)
  558. c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
  559. abstractVar-{tyTypeDesc})))
  560. c.gABx(n, opcNewSeq, tmp, 0)
  561. c.freeTemp(tmp)
  562. proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  563. let tmp = c.genx(n.sons[1])
  564. if dest < 0: dest = c.getTemp(n.typ)
  565. c.gABC(n, opc, dest, tmp)
  566. c.freeTemp(tmp)
  567. proc genUnaryABI(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; imm: BiggestInt=0) =
  568. let tmp = c.genx(n.sons[1])
  569. if dest < 0: dest = c.getTemp(n.typ)
  570. c.gABI(n, opc, dest, tmp, imm)
  571. c.freeTemp(tmp)
  572. proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  573. let
  574. tmp = c.genx(n.sons[1])
  575. tmp2 = c.genx(n.sons[2])
  576. if dest < 0: dest = c.getTemp(n.typ)
  577. c.gABC(n, opc, dest, tmp, tmp2)
  578. c.freeTemp(tmp)
  579. c.freeTemp(tmp2)
  580. proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  581. let
  582. tmp = c.genx(n.sons[1])
  583. tmp2 = c.genx(n.sons[2])
  584. tmp3 = c.genx(n.sons[3])
  585. if dest < 0: dest = c.getTemp(n.typ)
  586. c.gABC(n, opc, dest, tmp, tmp2)
  587. c.gABC(n, opc, tmp3)
  588. c.freeTemp(tmp)
  589. c.freeTemp(tmp2)
  590. c.freeTemp(tmp3)
  591. proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
  592. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  593. # uint is uint64 in the VM, we we only need to mask the result for
  594. # other unsigned types:
  595. if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
  596. c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
  597. elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8):
  598. c.gABC(n, opcNarrowS, dest, TRegister(t.size*8))
  599. proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
  600. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  601. # uint is uint64 in the VM, we we only need to mask the result for
  602. # other unsigned types:
  603. if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or
  604. (t.kind in {tyUInt, tyInt} and t.size < 8):
  605. c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
  606. proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  607. genBinaryABC(c, n, dest, opc)
  608. genNarrow(c, n, dest)
  609. proc genBinaryABCnarrowU(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  610. genBinaryABC(c, n, dest, opc)
  611. genNarrowU(c, n, dest)
  612. proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
  613. let t = skipTypes(n.typ, abstractInst-{tyTypeDesc})
  614. if t.kind == tySet:
  615. c.gABx(n, opcSetType, dest, c.genType(t))
  616. proc genBinarySet(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  617. let
  618. tmp = c.genx(n.sons[1])
  619. tmp2 = c.genx(n.sons[2])
  620. if dest < 0: dest = c.getTemp(n.typ)
  621. c.genSetType(n.sons[1], tmp)
  622. c.genSetType(n.sons[2], tmp2)
  623. c.gABC(n, opc, dest, tmp, tmp2)
  624. c.freeTemp(tmp)
  625. c.freeTemp(tmp2)
  626. proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
  627. let
  628. dest = c.genx(n.sons[1])
  629. tmp = c.genx(n.sons[2])
  630. c.gABC(n, opc, dest, tmp, 0)
  631. c.freeTemp(tmp)
  632. proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
  633. var x = n.sons[1]
  634. if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0]
  635. let
  636. dest = c.genx(x)
  637. tmp = c.genx(n.sons[2])
  638. c.gABC(n, opc, dest, tmp, 0)
  639. #c.genAsgnPatch(n.sons[1], dest)
  640. c.freeTemp(tmp)
  641. proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
  642. let tmp = c.genx(n.sons[1])
  643. c.gABC(n, opc, tmp, 0, 0)
  644. c.freeTemp(tmp)
  645. proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  646. if dest < 0: dest = getTemp(c, n.typ)
  647. var x = c.getTempRange(n.len-1, slotTempStr)
  648. for i in 1..n.len-1:
  649. var r: TRegister = x+i-1
  650. c.gen(n.sons[i], r)
  651. c.gABC(n, opc, dest, x, n.len-1)
  652. c.freeTempRange(x, n.len)
  653. proc isInt8Lit(n: PNode): bool =
  654. if n.kind in {nkCharLit..nkUInt64Lit}:
  655. result = n.intVal >= low(int8) and n.intVal <= high(int8)
  656. proc isInt16Lit(n: PNode): bool =
  657. if n.kind in {nkCharLit..nkUInt64Lit}:
  658. result = n.intVal >= low(int16) and n.intVal <= high(int16)
  659. proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  660. if n.sons[2].isInt8Lit:
  661. let tmp = c.genx(n.sons[1])
  662. if dest < 0: dest = c.getTemp(n.typ)
  663. c.gABI(n, succ(opc), dest, tmp, n.sons[2].intVal)
  664. c.freeTemp(tmp)
  665. else:
  666. genBinaryABC(c, n, dest, opc)
  667. c.genNarrow(n, dest)
  668. proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
  669. if n.typ.kind == arg.typ.kind and arg.typ.kind == tyProc:
  670. # don't do anything for lambda lifting conversions:
  671. gen(c, arg, dest)
  672. return
  673. let tmp = c.genx(arg)
  674. if dest < 0: dest = c.getTemp(n.typ)
  675. c.gABC(n, opc, dest, tmp)
  676. c.gABx(n, opc, 0, genType(c, n.typ.skipTypes({tyStatic})))
  677. c.gABx(n, opc, 0, genType(c, arg.typ.skipTypes({tyStatic})))
  678. c.freeTemp(tmp)
  679. proc genCard(c: PCtx; n: PNode; dest: var TDest) =
  680. let tmp = c.genx(n.sons[1])
  681. if dest < 0: dest = c.getTemp(n.typ)
  682. c.genSetType(n.sons[1], tmp)
  683. c.gABC(n, opcCard, dest, tmp)
  684. c.freeTemp(tmp)
  685. proc genIntCast(c: PCtx; n: PNode; dest: var TDest) =
  686. const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar}
  687. var signedIntegers = {tyInt8..tyInt32}
  688. var unsignedIntegers = {tyUInt8..tyUInt32, tyChar}
  689. let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
  690. let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
  691. let src_size = getSize(c.config, src)
  692. if c.config.target.intSize < 8:
  693. signedIntegers.incl(tyInt)
  694. unsignedIntegers.incl(tyUInt)
  695. if src_size == getSize(c.config, dst) and src.kind in allowedIntegers and
  696. dst.kind in allowedIntegers:
  697. let tmp = c.genx(n.sons[1])
  698. var tmp2 = c.getTemp(n.sons[1].typ)
  699. let tmp3 = c.getTemp(n.sons[1].typ)
  700. if dest < 0: dest = c.getTemp(n[0].typ)
  701. proc mkIntLit(ival: int): int =
  702. result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(c.graph, n.info, tyInt)))
  703. if src.kind in unsignedIntegers and dst.kind in signedIntegers:
  704. # cast unsigned to signed integer of same size
  705. # signedVal = (unsignedVal xor offset) -% offset
  706. let offset = 1 shl (src_size * 8 - 1)
  707. c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
  708. c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2)
  709. c.gABC(n, opcSubInt, dest, tmp3, tmp2)
  710. elif src.kind in signedIntegers and dst.kind in unsignedIntegers:
  711. # cast signed to unsigned integer of same size
  712. # unsignedVal = (offset +% signedVal +% 1) and offset
  713. let offset = (1 shl (src_size * 8)) - 1
  714. c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
  715. c.gABx(n, opcLdConst, dest, mkIntLit(offset+1))
  716. c.gABC(n, opcAddu, tmp3, tmp, dest)
  717. c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8))
  718. c.gABC(n, opcBitandInt, dest, tmp3, tmp2)
  719. else:
  720. c.gABC(n, opcAsgnInt, dest, tmp)
  721. c.freeTemp(tmp)
  722. c.freeTemp(tmp2)
  723. c.freeTemp(tmp3)
  724. else:
  725. globalError(c.config, n.info, "VM is only allowed to 'cast' between integers of same size")
  726. proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) =
  727. unused(c, n, dest)
  728. var
  729. tmp1 = c.genx(n[1])
  730. tmp2 = c.genx(n[2])
  731. tmp3 = c.genx(n[3])
  732. c.gABC(n, opcode, tmp1, tmp2, tmp3)
  733. c.freeTemp(tmp1)
  734. c.freeTemp(tmp2)
  735. c.freeTemp(tmp3)
  736. proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
  737. # nah, cannot use c.config.features because sempass context
  738. # can have local experimental switch
  739. # if dynamicBindSym notin c.config.features:
  740. if n.len == 2: # hmm, reliable?
  741. # bindSym with static input
  742. if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}:
  743. let idx = c.genLiteral(n[1])
  744. if dest < 0: dest = c.getTemp(n.typ)
  745. c.gABx(n, opcNBindSym, dest, idx)
  746. else:
  747. localError(c.config, n.info, "invalid bindSym usage")
  748. else:
  749. # experimental bindSym
  750. if dest < 0: dest = c.getTemp(n.typ)
  751. let x = c.getTempRange(n.len, slotTempUnknown)
  752. # callee symbol
  753. var tmp0 = TDest(x)
  754. c.genLit(n.sons[0], tmp0)
  755. # original parameters
  756. for i in 1..<n.len-2:
  757. var r = TRegister(x+i)
  758. c.gen(n.sons[i], r)
  759. # info node
  760. var tmp1 = TDest(x+n.len-2)
  761. c.genLit(n.sons[^2], tmp1)
  762. # payload idx
  763. var tmp2 = TDest(x+n.len-1)
  764. c.genLit(n.sons[^1], tmp2)
  765. c.gABC(n, opcNDynBindSym, dest, x, n.len)
  766. c.freeTempRange(x, n.len)
  767. proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
  768. case m
  769. of mAnd: c.genAndOr(n, opcFJmp, dest)
  770. of mOr: c.genAndOr(n, opcTJmp, dest)
  771. of mUnaryLt:
  772. let tmp = c.genx(n.sons[1])
  773. if dest < 0: dest = c.getTemp(n.typ)
  774. c.gABI(n, opcSubImmInt, dest, tmp, 1)
  775. c.freeTemp(tmp)
  776. of mPred, mSubI:
  777. c.genAddSubInt(n, dest, opcSubInt)
  778. of mSucc, mAddI:
  779. c.genAddSubInt(n, dest, opcAddInt)
  780. of mInc, mDec:
  781. unused(c, n, dest)
  782. let opc = if m == mInc: opcAddInt else: opcSubInt
  783. let d = c.genx(n.sons[1])
  784. if n.sons[2].isInt8Lit:
  785. c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
  786. else:
  787. let tmp = c.genx(n.sons[2])
  788. c.gABC(n, opc, d, d, tmp)
  789. c.freeTemp(tmp)
  790. c.genNarrow(n.sons[1], d)
  791. c.genAsgnPatch(n.sons[1], d)
  792. c.freeTemp(d)
  793. of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest)
  794. of mNew, mNewFinalize:
  795. unused(c, n, dest)
  796. c.genNew(n)
  797. of mNewSeq:
  798. unused(c, n, dest)
  799. c.genNewSeq(n)
  800. of mNewSeqOfCap: c.genNewSeqOfCap(n, dest)
  801. of mNewString:
  802. genUnaryABC(c, n, dest, opcNewStr)
  803. # XXX buggy
  804. of mNewStringOfCap:
  805. # we ignore the 'cap' argument and translate it as 'newString(0)'.
  806. # eval n.sons[1] for possible side effects:
  807. c.freeTemp(c.genx(n.sons[1]))
  808. var tmp = c.getTemp(n.sons[1].typ)
  809. c.gABx(n, opcLdImmInt, tmp, 0)
  810. if dest < 0: dest = c.getTemp(n.typ)
  811. c.gABC(n, opcNewStr, dest, tmp)
  812. c.freeTemp(tmp)
  813. # XXX buggy
  814. of mLengthOpenArray, mLengthArray, mLengthSeq, mXLenSeq:
  815. genUnaryABI(c, n, dest, opcLenSeq)
  816. of mLengthStr, mXLenStr:
  817. genUnaryABI(c, n, dest, opcLenStr)
  818. of mIncl, mExcl:
  819. unused(c, n, dest)
  820. var d = c.genx(n.sons[1])
  821. var tmp = c.genx(n.sons[2])
  822. c.genSetType(n.sons[1], d)
  823. c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp)
  824. c.freeTemp(d)
  825. c.freeTemp(tmp)
  826. of mCard: genCard(c, n, dest)
  827. of mMulI: genBinaryABCnarrow(c, n, dest, opcMulInt)
  828. of mDivI: genBinaryABCnarrow(c, n, dest, opcDivInt)
  829. of mModI: genBinaryABCnarrow(c, n, dest, opcModInt)
  830. of mAddF64: genBinaryABC(c, n, dest, opcAddFloat)
  831. of mSubF64: genBinaryABC(c, n, dest, opcSubFloat)
  832. of mMulF64: genBinaryABC(c, n, dest, opcMulFloat)
  833. of mDivF64: genBinaryABC(c, n, dest, opcDivFloat)
  834. of mShrI:
  835. # the idea here is to narrow type if needed before executing right shift
  836. # inlined modified: genNarrowU(c, n, dest)
  837. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  838. # uint is uint64 in the VM, we we only need to mask the result for
  839. # other unsigned types:
  840. let tmp = c.genx(n.sons[1])
  841. if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}:
  842. c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
  843. # inlined modified: genBinaryABC(c, n, dest, opcShrInt)
  844. let tmp2 = c.genx(n.sons[2])
  845. if dest < 0: dest = c.getTemp(n.typ)
  846. c.gABC(n, opcShrInt, dest, tmp, tmp2)
  847. c.freeTemp(tmp)
  848. c.freeTemp(tmp2)
  849. of mShlI: genBinaryABCnarrowU(c, n, dest, opcShlInt)
  850. of mAshrI: genBinaryABCnarrow(c, n, dest, opcAshrInt)
  851. of mBitandI: genBinaryABCnarrowU(c, n, dest, opcBitandInt)
  852. of mBitorI: genBinaryABCnarrowU(c, n, dest, opcBitorInt)
  853. of mBitxorI: genBinaryABCnarrowU(c, n, dest, opcBitxorInt)
  854. of mAddU: genBinaryABCnarrowU(c, n, dest, opcAddu)
  855. of mSubU: genBinaryABCnarrowU(c, n, dest, opcSubu)
  856. of mMulU: genBinaryABCnarrowU(c, n, dest, opcMulu)
  857. of mDivU: genBinaryABCnarrowU(c, n, dest, opcDivu)
  858. of mModU: genBinaryABCnarrowU(c, n, dest, opcModu)
  859. of mEqI, mEqB, mEqEnum, mEqCh:
  860. genBinaryABC(c, n, dest, opcEqInt)
  861. of mLeI, mLeEnum, mLeCh, mLeB:
  862. genBinaryABC(c, n, dest, opcLeInt)
  863. of mLtI, mLtEnum, mLtCh, mLtB:
  864. genBinaryABC(c, n, dest, opcLtInt)
  865. of mEqF64: genBinaryABC(c, n, dest, opcEqFloat)
  866. of mLeF64: genBinaryABC(c, n, dest, opcLeFloat)
  867. of mLtF64: genBinaryABC(c, n, dest, opcLtFloat)
  868. of mLePtr, mLeU, mLeU64: genBinaryABC(c, n, dest, opcLeu)
  869. of mLtPtr, mLtU, mLtU64: genBinaryABC(c, n, dest, opcLtu)
  870. of mEqProc, mEqRef, mEqUntracedRef:
  871. genBinaryABC(c, n, dest, opcEqRef)
  872. of mXor: genBinaryABCnarrowU(c, n, dest, opcXor)
  873. of mNot: genUnaryABC(c, n, dest, opcNot)
  874. of mUnaryMinusI, mUnaryMinusI64:
  875. genUnaryABC(c, n, dest, opcUnaryMinusInt)
  876. genNarrow(c, n, dest)
  877. of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
  878. of mUnaryPlusI, mUnaryPlusF64: gen(c, n.sons[1], dest)
  879. of mBitnotI:
  880. genUnaryABC(c, n, dest, opcBitnotInt)
  881. genNarrowU(c, n, dest)
  882. of mToFloat, mToBiggestFloat, mToInt,
  883. mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
  884. mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
  885. genConv(c, n, n.sons[1], dest)
  886. of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
  887. #genNarrowU modified
  888. let t = skipTypes(n.sons[1].typ, abstractVar-{tyTypeDesc})
  889. let tmp = c.genx(n.sons[1])
  890. c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
  891. # assign result to dest register
  892. if dest < 0: dest = c.getTemp(n.typ)
  893. c.gABC(n, opcAsgnInt, dest, tmp)
  894. c.freeTemp(tmp)
  895. of mToU8, mToU16, mToU32:
  896. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  897. var tmp = c.genx(n.sons[1])
  898. if dest < 0: dest = c.getTemp(n.typ)
  899. c.gABC(n, opcToNarrowInt, dest, tmp, TRegister(t.size*8))
  900. c.freeTemp(tmp)
  901. of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
  902. of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
  903. of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
  904. of mEqSet: genBinarySet(c, n, dest, opcEqSet)
  905. of mLeSet: genBinarySet(c, n, dest, opcLeSet)
  906. of mLtSet: genBinarySet(c, n, dest, opcLtSet)
  907. of mMulSet: genBinarySet(c, n, dest, opcMulSet)
  908. of mPlusSet: genBinarySet(c, n, dest, opcPlusSet)
  909. of mMinusSet: genBinarySet(c, n, dest, opcMinusSet)
  910. of mSymDiffSet: genBinarySet(c, n, dest, opcSymdiffSet)
  911. of mConStrStr: genVarargsABC(c, n, dest, opcConcatStr)
  912. of mInSet: genBinarySet(c, n, dest, opcContainsSet)
  913. of mRepr: genUnaryABC(c, n, dest, opcRepr)
  914. of mExit:
  915. unused(c, n, dest)
  916. var tmp = c.genx(n.sons[1])
  917. c.gABC(n, opcQuit, tmp)
  918. c.freeTemp(tmp)
  919. of mSetLengthStr, mSetLengthSeq:
  920. unused(c, n, dest)
  921. var d = c.genx(n.sons[1])
  922. var tmp = c.genx(n.sons[2])
  923. c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
  924. c.genAsgnPatch(n.sons[1], d)
  925. c.freeTemp(tmp)
  926. of mSwap:
  927. unused(c, n, dest)
  928. c.gen(lowerSwap(c.graph, n, if c.prc == nil: c.module else: c.prc.sym))
  929. of mIsNil: genUnaryABC(c, n, dest, opcIsNil)
  930. of mCopyStr:
  931. if dest < 0: dest = c.getTemp(n.typ)
  932. var
  933. tmp1 = c.genx(n.sons[1])
  934. tmp2 = c.genx(n.sons[2])
  935. tmp3 = c.getTemp(n.sons[2].typ)
  936. c.gABC(n, opcLenStr, tmp3, tmp1)
  937. c.gABC(n, opcSubStr, dest, tmp1, tmp2)
  938. c.gABC(n, opcSubStr, tmp3)
  939. c.freeTemp(tmp1)
  940. c.freeTemp(tmp2)
  941. c.freeTemp(tmp3)
  942. of mCopyStrLast:
  943. if dest < 0: dest = c.getTemp(n.typ)
  944. var
  945. tmp1 = c.genx(n.sons[1])
  946. tmp2 = c.genx(n.sons[2])
  947. tmp3 = c.genx(n.sons[3])
  948. c.gABC(n, opcSubStr, dest, tmp1, tmp2)
  949. c.gABC(n, opcSubStr, tmp3)
  950. c.freeTemp(tmp1)
  951. c.freeTemp(tmp2)
  952. c.freeTemp(tmp3)
  953. of mParseBiggestFloat:
  954. if dest < 0: dest = c.getTemp(n.typ)
  955. var d2: TRegister
  956. # skip 'nkHiddenAddr':
  957. let d2AsNode = n.sons[2].sons[0]
  958. if needsAsgnPatch(d2AsNode):
  959. d2 = c.getTemp(getSysType(c.graph, n.info, tyFloat))
  960. else:
  961. d2 = c.genx(d2AsNode)
  962. var
  963. tmp1 = c.genx(n.sons[1])
  964. tmp3 = c.genx(n.sons[3])
  965. c.gABC(n, opcParseFloat, dest, tmp1, d2)
  966. c.gABC(n, opcParseFloat, tmp3)
  967. c.freeTemp(tmp1)
  968. c.freeTemp(tmp3)
  969. c.genAsgnPatch(d2AsNode, d2)
  970. c.freeTemp(d2)
  971. of mReset:
  972. unused(c, n, dest)
  973. var d = c.genx(n.sons[1])
  974. c.gABC(n, opcReset, d)
  975. of mOf, mIs:
  976. if dest < 0: dest = c.getTemp(n.typ)
  977. var tmp = c.genx(n.sons[1])
  978. var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
  979. var typ = n.sons[2].typ
  980. if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
  981. c.gABx(n, opcLdImmInt, idx, c.genType(typ))
  982. c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
  983. c.freeTemp(tmp)
  984. c.freeTemp(idx)
  985. of mSizeOf:
  986. globalError(c.config, n.info, "cannot run in the VM: " & renderTree(n))
  987. of mHigh:
  988. if dest < 0: dest = c.getTemp(n.typ)
  989. let tmp = c.genx(n.sons[1])
  990. case n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind:
  991. of tyString, tyCString:
  992. c.gABI(n, opcLenStr, dest, tmp, 1)
  993. else:
  994. c.gABI(n, opcLenSeq, dest, tmp, 1)
  995. c.freeTemp(tmp)
  996. of mEcho:
  997. unused(c, n, dest)
  998. let n = n[1].skipConv
  999. let x = c.getTempRange(n.len, slotTempUnknown)
  1000. internalAssert c.config, n.kind == nkBracket
  1001. for i in 0..<n.len:
  1002. var r: TRegister = x+i
  1003. c.gen(n.sons[i], r)
  1004. c.gABC(n, opcEcho, x, n.len)
  1005. c.freeTempRange(x, n.len)
  1006. of mAppendStrCh:
  1007. unused(c, n, dest)
  1008. genBinaryStmtVar(c, n, opcAddStrCh)
  1009. of mAppendStrStr:
  1010. unused(c, n, dest)
  1011. genBinaryStmtVar(c, n, opcAddStrStr)
  1012. of mAppendSeqElem:
  1013. unused(c, n, dest)
  1014. genBinaryStmtVar(c, n, opcAddSeqElem)
  1015. of mParseExprToAst:
  1016. genUnaryABC(c, n, dest, opcParseExprToAst)
  1017. of mParseStmtToAst:
  1018. genUnaryABC(c, n, dest, opcParseStmtToAst)
  1019. of mTypeTrait:
  1020. let tmp = c.genx(n.sons[1])
  1021. if dest < 0: dest = c.getTemp(n.typ)
  1022. c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
  1023. c.gABC(n, opcTypeTrait, dest, tmp)
  1024. c.freeTemp(tmp)
  1025. of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
  1026. of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
  1027. of mNLen: genUnaryABI(c, n, dest, opcLenSeq, nimNodeFlag)
  1028. of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
  1029. of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner)
  1030. of mNChild: genBinaryABC(c, n, dest, opcNChild)
  1031. of mNSetChild: genVoidABC(c, n, dest, opcNSetChild)
  1032. of mNDel: genVoidABC(c, n, dest, opcNDel)
  1033. of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
  1034. of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple)
  1035. of mNKind: genUnaryABC(c, n, dest, opcNKind)
  1036. of mNSymKind: genUnaryABC(c, n, dest, opcNSymKind)
  1037. of mNccValue: genUnaryABC(c, n, dest, opcNccValue)
  1038. of mNccInc: genBinaryABC(c, n, dest, opcNccInc)
  1039. of mNcsAdd: genBinaryABC(c, n, dest, opcNcsAdd)
  1040. of mNcsIncl: genBinaryABC(c, n, dest, opcNcsIncl)
  1041. of mNcsLen: genUnaryABC(c, n, dest, opcNcsLen)
  1042. of mNcsAt: genBinaryABC(c, n, dest, opcNcsAt)
  1043. of mNctPut: genVoidABC(c, n, dest, opcNctPut)
  1044. of mNctLen: genUnaryABC(c, n, dest, opcNctLen)
  1045. of mNctGet: genBinaryABC(c, n, dest, opcNctGet)
  1046. of mNctHasNext: genBinaryABC(c, n, dest, opcNctHasNext)
  1047. of mNctNext: genBinaryABC(c, n, dest, opcNctNext)
  1048. of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
  1049. of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
  1050. of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol)
  1051. of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
  1052. of mNGetType:
  1053. let tmp = c.genx(n.sons[1])
  1054. if dest < 0: dest = c.getTemp(n.typ)
  1055. let rc = case n[0].sym.name.s:
  1056. of "getType": 0
  1057. of "typeKind": 1
  1058. of "getTypeInst": 2
  1059. else: 3 # "getTypeImpl"
  1060. c.gABC(n, opcNGetType, dest, tmp, rc)
  1061. c.freeTemp(tmp)
  1062. #genUnaryABC(c, n, dest, opcNGetType)
  1063. of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
  1064. of mNSetIntVal:
  1065. unused(c, n, dest)
  1066. genBinaryStmt(c, n, opcNSetIntVal)
  1067. of mNSetFloatVal:
  1068. unused(c, n, dest)
  1069. genBinaryStmt(c, n, opcNSetFloatVal)
  1070. of mNSetSymbol:
  1071. unused(c, n, dest)
  1072. genBinaryStmt(c, n, opcNSetSymbol)
  1073. of mNSetIdent:
  1074. unused(c, n, dest)
  1075. genBinaryStmt(c, n, opcNSetIdent)
  1076. of mNSetType:
  1077. unused(c, n, dest)
  1078. genBinaryStmt(c, n, opcNSetType)
  1079. of mNSetStrVal:
  1080. unused(c, n, dest)
  1081. genBinaryStmt(c, n, opcNSetStrVal)
  1082. of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
  1083. of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
  1084. of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree)
  1085. of mNBindSym: genBindSym(c, n, dest)
  1086. of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
  1087. of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
  1088. of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimNode)
  1089. of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)
  1090. of mNLineInfo:
  1091. case n[0].sym.name.s
  1092. of "getFile": genUnaryABI(c, n, dest, opcNGetLineInfo, 0)
  1093. of "getLine": genUnaryABI(c, n, dest, opcNGetLineInfo, 1)
  1094. of "getColumn": genUnaryABI(c, n, dest, opcNGetLineInfo, 2)
  1095. of "copyLineInfo":
  1096. internalAssert c.config, n.len == 3
  1097. unused(c, n, dest)
  1098. genBinaryStmt(c, n, opcNSetLineInfo)
  1099. else: internalAssert c.config, false
  1100. of mNHint:
  1101. unused(c, n, dest)
  1102. genBinaryStmt(c, n, opcNHint)
  1103. of mNWarning:
  1104. unused(c, n, dest)
  1105. genBinaryStmt(c, n, opcNWarning)
  1106. of mNError:
  1107. if n.len <= 1:
  1108. # query error condition:
  1109. c.gABC(n, opcQueryErrorFlag, dest)
  1110. else:
  1111. # setter
  1112. unused(c, n, dest)
  1113. genBinaryStmt(c, n, opcNError)
  1114. of mNCallSite:
  1115. if dest < 0: dest = c.getTemp(n.typ)
  1116. c.gABC(n, opcCallSite, dest)
  1117. of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
  1118. of mMinI, mMaxI, mAbsF64, mMinF64, mMaxF64, mAbsI,
  1119. mDotDot:
  1120. c.genCall(n, dest)
  1121. of mExpandToAst:
  1122. if n.len != 2:
  1123. globalError(c.config, n.info, "expandToAst requires 1 argument")
  1124. let arg = n.sons[1]
  1125. if arg.kind in nkCallKinds:
  1126. #if arg[0].kind != nkSym or arg[0].sym.kind notin {skTemplate, skMacro}:
  1127. # "ExpandToAst: expanded symbol is no macro or template"
  1128. if dest < 0: dest = c.getTemp(n.typ)
  1129. c.genCall(arg, dest)
  1130. # do not call clearDest(n, dest) here as getAst has a meta-type as such
  1131. # produces a value
  1132. else:
  1133. globalError(c.config, n.info, "expandToAst requires a call expression")
  1134. of mRunnableExamples:
  1135. discard "just ignore any call to runnableExamples"
  1136. else:
  1137. # mGCref, mGCunref,
  1138. globalError(c.config, n.info, "cannot generate code for: " & $m)
  1139. proc genMarshalLoad(c: PCtx, n: PNode, dest: var TDest) =
  1140. ## Signature: proc to*[T](data: string): T
  1141. if dest < 0: dest = c.getTemp(n.typ)
  1142. var tmp = c.genx(n.sons[1])
  1143. c.gABC(n, opcMarshalLoad, dest, tmp)
  1144. c.gABx(n, opcMarshalLoad, 0, c.genType(n.typ))
  1145. c.freeTemp(tmp)
  1146. proc genMarshalStore(c: PCtx, n: PNode, dest: var TDest) =
  1147. ## Signature: proc `$$`*[T](x: T): string
  1148. if dest < 0: dest = c.getTemp(n.typ)
  1149. var tmp = c.genx(n.sons[1])
  1150. c.gABC(n, opcMarshalStore, dest, tmp)
  1151. c.gABx(n, opcMarshalStore, 0, c.genType(n.sons[1].typ))
  1152. c.freeTemp(tmp)
  1153. const
  1154. atomicTypes = {tyBool, tyChar,
  1155. tyExpr, tyStmt, tyTypeDesc, tyStatic,
  1156. tyEnum,
  1157. tyOrdinal,
  1158. tyRange,
  1159. tyProc,
  1160. tyPointer, tyOpenArray,
  1161. tyString, tyCString,
  1162. tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
  1163. tyFloat, tyFloat32, tyFloat64, tyFloat128,
  1164. tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
  1165. proc fitsRegister*(t: PType): bool =
  1166. assert t != nil
  1167. t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
  1168. tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
  1169. proc unneededIndirection(n: PNode): bool =
  1170. n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
  1171. proc canElimAddr(n: PNode): PNode =
  1172. case n.sons[0].kind
  1173. of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
  1174. var m = n.sons[0].sons[0]
  1175. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1176. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1177. result = copyNode(n.sons[0])
  1178. result.add m.sons[0]
  1179. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1180. var m = n.sons[0].sons[1]
  1181. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1182. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1183. result = copyNode(n.sons[0])
  1184. result.add m.sons[0]
  1185. else:
  1186. if n.sons[0].kind in {nkDerefExpr, nkHiddenDeref}:
  1187. # addr ( deref ( x )) --> x
  1188. result = n.sons[0].sons[0]
  1189. proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
  1190. if (let m = canElimAddr(n); m != nil):
  1191. gen(c, m, dest, flags)
  1192. return
  1193. let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode}
  1194. else: {gfNodeAddr}
  1195. let newflags = flags-{gfNode, gfNodeAddr}+af
  1196. if isGlobal(n.sons[0]):
  1197. gen(c, n.sons[0], dest, flags+af)
  1198. else:
  1199. let tmp = c.genx(n.sons[0], newflags)
  1200. if dest < 0: dest = c.getTemp(n.typ)
  1201. if c.prc.slots[tmp].kind >= slotTempUnknown:
  1202. gABC(c, n, opcAddrNode, dest, tmp)
  1203. # hack ahead; in order to fix bug #1781 we mark the temporary as
  1204. # permanent, so that it's not used for anything else:
  1205. c.prc.slots[tmp].kind = slotTempPerm
  1206. # XXX this is still a hack
  1207. #message(n.info, warnUser, "suspicious opcode used")
  1208. else:
  1209. gABC(c, n, opcAddrReg, dest, tmp)
  1210. c.freeTemp(tmp)
  1211. proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
  1212. if unneededIndirection(n.sons[0]):
  1213. gen(c, n.sons[0], dest, flags)
  1214. if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
  1215. c.gABC(n, opcNodeToReg, dest, dest)
  1216. else:
  1217. let tmp = c.genx(n.sons[0], flags)
  1218. if dest < 0: dest = c.getTemp(n.typ)
  1219. gABC(c, n, opcLdDeref, dest, tmp)
  1220. assert n.typ != nil
  1221. if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
  1222. c.gABC(n, opcNodeToReg, dest, dest)
  1223. proc whichAsgnOpc(n: PNode): TOpcode =
  1224. case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
  1225. of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
  1226. opcAsgnInt
  1227. of tyString, tyCString:
  1228. opcAsgnStr
  1229. of tyFloat..tyFloat128:
  1230. opcAsgnFloat
  1231. of tyRef, tyNil, tyVar, tyLent, tyPtr:
  1232. opcAsgnRef
  1233. else:
  1234. opcAsgnComplex
  1235. proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc
  1236. proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
  1237. let tmp = c.genx(ri)
  1238. assert dest >= 0
  1239. gABC(c, ri, whichAsgnOpc(ri), dest, tmp, 1-ord(requiresCopy))
  1240. c.freeTemp(tmp)
  1241. proc setSlot(c: PCtx; v: PSym) =
  1242. # XXX generate type initialization here?
  1243. if v.position == 0:
  1244. if c.prc.maxSlots == 0: c.prc.maxSlots = 1
  1245. if c.prc.maxSlots >= high(TRegister):
  1246. globalError(c.config, v.info, "cannot generate code; too many registers required")
  1247. v.position = c.prc.maxSlots
  1248. c.prc.slots[v.position] = (inUse: true,
  1249. kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
  1250. inc c.prc.maxSlots
  1251. proc cannotEval(c: PCtx; n: PNode) {.noinline.} =
  1252. globalError(c.config, n.info, "cannot evaluate at compile time: " &
  1253. n.renderTree)
  1254. proc isOwnedBy(a, b: PSym): bool =
  1255. var a = a.owner
  1256. while a != nil and a.kind != skModule:
  1257. if a == b: return true
  1258. a = a.owner
  1259. proc getOwner(c: PCtx): PSym =
  1260. result = c.prc.sym
  1261. if result.isNil: result = c.module
  1262. proc checkCanEval(c: PCtx; n: PNode) =
  1263. # we need to ensure that we don't evaluate 'x' here:
  1264. # proc foo() = var x ...
  1265. let s = n.sym
  1266. if {sfCompileTime, sfGlobal} <= s.flags: return
  1267. if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
  1268. not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
  1269. cannotEval(c, n)
  1270. elif s.kind in {skProc, skFunc, skConverter, skMethod,
  1271. skIterator} and sfForward in s.flags:
  1272. cannotEval(c, n)
  1273. proc isTemp(c: PCtx; dest: TDest): bool =
  1274. result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
  1275. template needsAdditionalCopy(n): untyped =
  1276. not c.isTemp(dest) and not fitsRegister(n.typ)
  1277. proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode;
  1278. dest, idx, value: TRegister) =
  1279. var cc = c.getTemp(n.typ)
  1280. c.gABC(n, whichAsgnOpc(n), cc, value, 0)
  1281. c.gABC(n, opc, dest, idx, cc)
  1282. c.freeTemp(cc)
  1283. proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
  1284. dest, idx, value: TRegister) =
  1285. # opcLdObj et al really means "load address". We sometimes have to create a
  1286. # copy in order to not introduce false aliasing:
  1287. # mylocal = a.b # needs a copy of the data!
  1288. assert n.typ != nil
  1289. if needsAdditionalCopy(n):
  1290. genAdditionalCopy(c, n, opc, dest, idx, value)
  1291. else:
  1292. c.gABC(n, opc, dest, idx, value)
  1293. proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
  1294. case le.kind
  1295. of nkBracketExpr:
  1296. let dest = c.genx(le.sons[0], {gfNode})
  1297. let idx = c.genIndex(le.sons[1], le.sons[0].typ)
  1298. let tmp = c.genx(ri)
  1299. if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
  1300. tyString, tyCString}:
  1301. c.preventFalseAlias(le, opcWrStrIdx, dest, idx, tmp)
  1302. else:
  1303. c.preventFalseAlias(le, opcWrArr, dest, idx, tmp)
  1304. c.freeTemp(tmp)
  1305. of nkDotExpr, nkCheckedFieldExpr:
  1306. # XXX field checks here
  1307. let left = if le.kind == nkDotExpr: le else: le.sons[0]
  1308. let dest = c.genx(left.sons[0], {gfNode})
  1309. let idx = genField(c, left.sons[1])
  1310. let tmp = c.genx(ri)
  1311. c.preventFalseAlias(left, opcWrObj, dest, idx, tmp)
  1312. c.freeTemp(tmp)
  1313. of nkDerefExpr, nkHiddenDeref:
  1314. let dest = c.genx(le.sons[0], {gfNode})
  1315. let tmp = c.genx(ri)
  1316. c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
  1317. c.freeTemp(tmp)
  1318. of nkSym:
  1319. let s = le.sym
  1320. checkCanEval(c, le)
  1321. if s.isGlobal:
  1322. withTemp(tmp, le.typ):
  1323. c.gen(le, tmp, {gfNodeAddr})
  1324. let val = c.genx(ri)
  1325. c.preventFalseAlias(le, opcWrDeref, tmp, 0, val)
  1326. c.freeTemp(val)
  1327. else:
  1328. if s.kind == skForVar: c.setSlot s
  1329. internalAssert c.config, s.position > 0 or (s.position == 0 and
  1330. s.kind in {skParam,skResult})
  1331. var dest: TRegister = s.position + ord(s.kind == skParam)
  1332. assert le.typ != nil
  1333. if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}:
  1334. var cc = c.getTemp(le.typ)
  1335. gen(c, ri, cc)
  1336. c.gABC(le, whichAsgnOpc(le), dest, cc, 1)
  1337. c.freeTemp(cc)
  1338. else:
  1339. gen(c, ri, dest)
  1340. else:
  1341. let dest = c.genx(le, {gfNodeAddr})
  1342. genAsgn(c, dest, ri, requiresCopy)
  1343. proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
  1344. var n = newNode(nkType)
  1345. n.typ = t
  1346. genLit(c, n, dest)
  1347. proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
  1348. when hasFFI:
  1349. if allowFFI in c.features:
  1350. c.globals.add(importcSymbol(s))
  1351. s.position = c.globals.len
  1352. else:
  1353. localError(c.config, info, "VM is not allowed to 'importc'")
  1354. else:
  1355. localError(c.config, info,
  1356. "cannot 'importc' variable at compile time")
  1357. proc getNullValue*(typ: PType, info: TLineInfo; conf: ConfigRef): PNode
  1358. proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
  1359. c.globals.add(getNullValue(s.typ, n.info, c.config))
  1360. s.position = c.globals.len
  1361. # This is rather hard to support, due to the laziness of the VM code
  1362. # generator. See tests/compile/tmacro2 for why this is necessary:
  1363. # var decls{.compileTime.}: seq[NimNode] = @[]
  1364. let dest = c.getTemp(s.typ)
  1365. c.gABx(n, opcLdGlobal, dest, s.position)
  1366. if s.ast != nil:
  1367. let tmp = c.genx(s.ast)
  1368. c.genAdditionalCopy(n, opcWrDeref, dest, 0, tmp)
  1369. c.freeTemp(dest)
  1370. c.freeTemp(tmp)
  1371. proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1372. # gfNodeAddr and gfNode are mutually exclusive
  1373. assert card(flags * {gfNodeAddr, gfNode}) < 2
  1374. let s = n.sym
  1375. if s.isGlobal:
  1376. if sfCompileTime in s.flags or c.mode == emRepl:
  1377. discard
  1378. elif s.position == 0:
  1379. cannotEval(c, n)
  1380. if s.position == 0:
  1381. if sfImportc in s.flags: c.importcSym(n.info, s)
  1382. else: genGlobalInit(c, n, s)
  1383. if dest < 0: dest = c.getTemp(n.typ)
  1384. assert s.typ != nil
  1385. if gfNodeAddr in flags:
  1386. c.gABx(n, opcLdGlobalAddr, dest, s.position)
  1387. elif fitsRegister(s.typ) and gfNode notin flags:
  1388. var cc = c.getTemp(n.typ)
  1389. c.gABx(n, opcLdGlobal, cc, s.position)
  1390. c.gABC(n, opcNodeToReg, dest, cc)
  1391. c.freeTemp(cc)
  1392. else:
  1393. c.gABx(n, opcLdGlobal, dest, s.position)
  1394. else:
  1395. if s.kind == skForVar and c.mode == emRepl: c.setSlot(s)
  1396. if s.position > 0 or (s.position == 0 and
  1397. s.kind in {skParam,skResult}):
  1398. if dest < 0:
  1399. dest = s.position + ord(s.kind == skParam)
  1400. internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp)
  1401. else:
  1402. # we need to generate an assignment:
  1403. genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
  1404. else:
  1405. # see tests/t99bott for an example that triggers it:
  1406. cannotEval(c, n)
  1407. template needsRegLoad(): untyped =
  1408. {gfNode, gfNodeAddr} * flags == {} and
  1409. fitsRegister(n.typ.skipTypes({tyVar, tyLent}))
  1410. proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
  1411. flags: TGenFlags) =
  1412. let a = c.genx(n.sons[0], flags)
  1413. let b = c.genIndex(n.sons[1], n.sons[0].typ)
  1414. if dest < 0: dest = c.getTemp(n.typ)
  1415. if needsRegLoad():
  1416. var cc = c.getTemp(n.typ)
  1417. c.gABC(n, opc, cc, a, b)
  1418. c.gABC(n, opcNodeToReg, dest, cc)
  1419. c.freeTemp(cc)
  1420. else:
  1421. #message(n.info, warnUser, "argh")
  1422. #echo "FLAGS ", flags, " ", fitsRegister(n.typ), " ", typeToString(n.typ)
  1423. c.gABC(n, opc, dest, a, b)
  1424. c.freeTemp(a)
  1425. c.freeTemp(b)
  1426. proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1427. let a = c.genx(n.sons[0], flags)
  1428. let b = genField(c, n.sons[1])
  1429. if dest < 0: dest = c.getTemp(n.typ)
  1430. if needsRegLoad():
  1431. var cc = c.getTemp(n.typ)
  1432. c.gABC(n, opcLdObj, cc, a, b)
  1433. c.gABC(n, opcNodeToReg, dest, cc)
  1434. c.freeTemp(cc)
  1435. else:
  1436. c.gABC(n, opcLdObj, dest, a, b)
  1437. c.freeTemp(a)
  1438. proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1439. # XXX implement field checks!
  1440. genObjAccess(c, n.sons[0], dest, flags)
  1441. proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1442. let arrayType = n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
  1443. if arrayType in {tyString, tyCString}:
  1444. genArrAccess2(c, n, dest, opcLdStrIdx, {})
  1445. elif arrayType == tyTypeDesc:
  1446. c.genTypeLit(n.typ, dest)
  1447. else:
  1448. genArrAccess2(c, n, dest, opcLdArr, flags)
  1449. proc getNullValueAux(obj: PNode, result: PNode; conf: ConfigRef) =
  1450. case obj.kind
  1451. of nkRecList:
  1452. for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result, conf)
  1453. of nkRecCase:
  1454. getNullValueAux(obj.sons[0], result, conf)
  1455. for i in countup(1, sonsLen(obj) - 1):
  1456. getNullValueAux(lastSon(obj.sons[i]), result, conf)
  1457. of nkSym:
  1458. let field = newNodeI(nkExprColonExpr, result.info)
  1459. field.add(obj)
  1460. field.add(getNullValue(obj.sym.typ, result.info, conf))
  1461. addSon(result, field)
  1462. else: globalError(conf, result.info, "cannot create null element for: " & $obj)
  1463. proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
  1464. var t = skipTypes(typ, abstractRange-{tyTypeDesc})
  1465. case t.kind
  1466. of tyBool, tyEnum, tyChar, tyInt..tyInt64:
  1467. result = newNodeIT(nkIntLit, info, t)
  1468. of tyUInt..tyUInt64:
  1469. result = newNodeIT(nkUIntLit, info, t)
  1470. of tyFloat..tyFloat128:
  1471. result = newNodeIT(nkFloatLit, info, t)
  1472. of tyCString, tyString:
  1473. result = newNodeIT(nkStrLit, info, t)
  1474. result.strVal = ""
  1475. of tyVar, tyLent, tyPointer, tyPtr, tyExpr,
  1476. tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
  1477. result = newNodeIT(nkNilLit, info, t)
  1478. of tyProc:
  1479. if t.callConv != ccClosure:
  1480. result = newNodeIT(nkNilLit, info, t)
  1481. else:
  1482. result = newNodeIT(nkTupleConstr, info, t)
  1483. result.add(newNodeIT(nkNilLit, info, t))
  1484. result.add(newNodeIT(nkNilLit, info, t))
  1485. of tyObject:
  1486. result = newNodeIT(nkObjConstr, info, t)
  1487. result.add(newNodeIT(nkEmpty, info, t))
  1488. # initialize inherited fields:
  1489. var base = t.sons[0]
  1490. while base != nil:
  1491. getNullValueAux(skipTypes(base, skipPtrs).n, result, conf)
  1492. base = base.sons[0]
  1493. getNullValueAux(t.n, result, conf)
  1494. of tyArray:
  1495. result = newNodeIT(nkBracket, info, t)
  1496. for i in countup(0, int(lengthOrd(conf, t)) - 1):
  1497. addSon(result, getNullValue(elemType(t), info, conf))
  1498. of tyTuple:
  1499. result = newNodeIT(nkTupleConstr, info, t)
  1500. for i in countup(0, sonsLen(t) - 1):
  1501. addSon(result, getNullValue(t.sons[i], info, conf))
  1502. of tySet:
  1503. result = newNodeIT(nkCurly, info, t)
  1504. of tyOpt:
  1505. result = newNodeIT(nkNilLit, info, t)
  1506. of tySequence:
  1507. result = newNodeIT(nkBracket, info, t)
  1508. else:
  1509. globalError(conf, info, "cannot create null element for: " & $t.kind)
  1510. result = newNodeI(nkEmpty, info)
  1511. proc ldNullOpcode(t: PType): TOpcode =
  1512. assert t != nil
  1513. if fitsRegister(t): opcLdNullReg else: opcLdNull
  1514. proc genVarSection(c: PCtx; n: PNode) =
  1515. for a in n:
  1516. if a.kind == nkCommentStmt: continue
  1517. #assert(a.sons[0].kind == nkSym) can happen for transformed vars
  1518. if a.kind == nkVarTuple:
  1519. for i in 0 .. a.len-3:
  1520. if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
  1521. checkCanEval(c, a[i])
  1522. c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner))
  1523. elif a.sons[0].kind == nkSym:
  1524. let s = a.sons[0].sym
  1525. checkCanEval(c, a.sons[0])
  1526. if s.isGlobal:
  1527. if s.position == 0:
  1528. if sfImportc in s.flags: c.importcSym(a.info, s)
  1529. else:
  1530. let sa = getNullValue(s.typ, a.info, c.config)
  1531. #if s.ast.isNil: getNullValue(s.typ, a.info)
  1532. #else: canonValue(s.ast)
  1533. assert sa.kind != nkCall
  1534. c.globals.add(sa)
  1535. s.position = c.globals.len
  1536. if a.sons[2].kind != nkEmpty:
  1537. let tmp = c.genx(a.sons[0], {gfNodeAddr})
  1538. let val = c.genx(a.sons[2])
  1539. c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
  1540. c.freeTemp(val)
  1541. c.freeTemp(tmp)
  1542. else:
  1543. setSlot(c, s)
  1544. if a.sons[2].kind == nkEmpty:
  1545. c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
  1546. else:
  1547. assert s.typ != nil
  1548. if not fitsRegister(s.typ):
  1549. c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
  1550. let le = a.sons[0]
  1551. assert le.typ != nil
  1552. if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
  1553. var cc = c.getTemp(le.typ)
  1554. gen(c, a.sons[2], cc)
  1555. c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc, 1)
  1556. c.freeTemp(cc)
  1557. else:
  1558. gen(c, a.sons[2], s.position.TRegister)
  1559. else:
  1560. # assign to a.sons[0]; happens for closures
  1561. if a.sons[2].kind == nkEmpty:
  1562. let tmp = genx(c, a.sons[0])
  1563. c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a.sons[0].typ))
  1564. c.freeTemp(tmp)
  1565. else:
  1566. genAsgn(c, a.sons[0], a.sons[2], true)
  1567. proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
  1568. if dest < 0: dest = c.getTemp(n.typ)
  1569. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1570. let intType = getSysType(c.graph, n.info, tyInt)
  1571. let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
  1572. if seqType.kind == tySequence:
  1573. var tmp = c.getTemp(intType)
  1574. c.gABx(n, opcLdImmInt, tmp, n.len)
  1575. c.gABx(n, opcNewSeq, dest, c.genType(seqType))
  1576. c.gABx(n, opcNewSeq, tmp, 0)
  1577. c.freeTemp(tmp)
  1578. if n.len > 0:
  1579. var tmp = getTemp(c, intType)
  1580. c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
  1581. for x in n:
  1582. let a = c.genx(x)
  1583. c.preventFalseAlias(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
  1584. c.gABI(n, opcAddImmInt, tmp, tmp, 1)
  1585. c.freeTemp(a)
  1586. c.freeTemp(tmp)
  1587. proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
  1588. if dest < 0: dest = c.getTemp(n.typ)
  1589. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1590. for x in n:
  1591. if x.kind == nkRange:
  1592. let a = c.genx(x.sons[0])
  1593. let b = c.genx(x.sons[1])
  1594. c.gABC(n, opcInclRange, dest, a, b)
  1595. c.freeTemp(b)
  1596. c.freeTemp(a)
  1597. else:
  1598. let a = c.genx(x)
  1599. c.gABC(n, opcIncl, dest, a)
  1600. c.freeTemp(a)
  1601. proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
  1602. if dest < 0: dest = c.getTemp(n.typ)
  1603. let t = n.typ.skipTypes(abstractRange-{tyTypeDesc})
  1604. if t.kind == tyRef:
  1605. c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
  1606. else:
  1607. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1608. for i in 1..<n.len:
  1609. let it = n.sons[i]
  1610. if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
  1611. let idx = genField(c, it.sons[0])
  1612. let tmp = c.genx(it.sons[1])
  1613. c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
  1614. dest, idx, tmp)
  1615. c.freeTemp(tmp)
  1616. else:
  1617. globalError(c.config, n.info, "invalid object constructor")
  1618. proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
  1619. if dest < 0: dest = c.getTemp(n.typ)
  1620. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1621. # XXX x = (x.old, 22) produces wrong code ... stupid self assignments
  1622. for i in 0..<n.len:
  1623. let it = n.sons[i]
  1624. if it.kind == nkExprColonExpr:
  1625. let idx = genField(c, it.sons[0])
  1626. let tmp = c.genx(it.sons[1])
  1627. c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
  1628. dest, idx, tmp)
  1629. c.freeTemp(tmp)
  1630. else:
  1631. let tmp = c.genx(it)
  1632. c.preventFalseAlias(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
  1633. c.freeTemp(tmp)
  1634. proc genProc*(c: PCtx; s: PSym): int
  1635. proc matches(s: PSym; x: string): bool =
  1636. let y = x.split('.')
  1637. var s = s
  1638. var L = y.len-1
  1639. while L >= 0:
  1640. if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
  1641. return false
  1642. s = s.owner
  1643. dec L
  1644. result = true
  1645. proc matches(s: PSym; y: varargs[string]): bool =
  1646. var s = s
  1647. var L = y.len-1
  1648. while L >= 0:
  1649. if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
  1650. return false
  1651. s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner
  1652. dec L
  1653. result = true
  1654. proc procIsCallback(c: PCtx; s: PSym): bool =
  1655. if s.offset < -1: return true
  1656. var i = -2
  1657. for key, value in items(c.callbacks):
  1658. if s.matches(key):
  1659. doAssert s.offset == -1
  1660. s.offset = i
  1661. return true
  1662. dec i
  1663. proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
  1664. case n.kind
  1665. of nkSym:
  1666. let s = n.sym
  1667. checkCanEval(c, n)
  1668. case s.kind
  1669. of skVar, skForVar, skTemp, skLet, skParam, skResult:
  1670. genRdVar(c, n, dest, flags)
  1671. of skProc, skFunc, skConverter, skMacro, skTemplate, skMethod, skIterator:
  1672. # 'skTemplate' is only allowed for 'getAst' support:
  1673. if procIsCallback(c, s): discard
  1674. elif sfImportc in s.flags: c.importcSym(n.info, s)
  1675. genLit(c, n, dest)
  1676. of skConst:
  1677. let constVal = if s.ast != nil: s.ast else: s.typ.n
  1678. gen(c, constVal, dest)
  1679. of skEnumField:
  1680. # we never reach this case - as of the time of this comment,
  1681. # skEnumField is folded to an int in semfold.nim, but this code
  1682. # remains for robustness
  1683. if dest < 0: dest = c.getTemp(n.typ)
  1684. if s.position >= low(int16) and s.position <= high(int16):
  1685. c.gABx(n, opcLdImmInt, dest, s.position)
  1686. else:
  1687. var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
  1688. c.gABx(n, opcLdConst, dest, lit)
  1689. of skType:
  1690. genTypeLit(c, s.typ, dest)
  1691. of skGenericParam:
  1692. if c.prc.sym != nil and c.prc.sym.kind == skMacro:
  1693. genRdVar(c, n, dest, flags)
  1694. else:
  1695. globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
  1696. else:
  1697. globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
  1698. of nkCallKinds:
  1699. if n.sons[0].kind == nkSym:
  1700. let s = n.sons[0].sym
  1701. if s.magic != mNone:
  1702. genMagic(c, n, dest, s.magic)
  1703. elif s.kind == skMethod:
  1704. localError(c.config, n.info, "cannot call method " & s.name.s &
  1705. " at compile time")
  1706. elif matches(s, "stdlib", "marshal", "to"):
  1707. # XXX marshal load&store should not be opcodes, but use the
  1708. # general callback mechanisms.
  1709. genMarshalLoad(c, n, dest)
  1710. elif matches(s, "stdlib", "marshal", "$$"):
  1711. genMarshalStore(c, n, dest)
  1712. else:
  1713. genCall(c, n, dest)
  1714. clearDest(c, n, dest)
  1715. else:
  1716. genCall(c, n, dest)
  1717. clearDest(c, n, dest)
  1718. of nkCharLit..nkInt64Lit:
  1719. if isInt16Lit(n):
  1720. if dest < 0: dest = c.getTemp(n.typ)
  1721. c.gABx(n, opcLdImmInt, dest, n.intVal.int)
  1722. else:
  1723. genLit(c, n, dest)
  1724. of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
  1725. of nkNilLit:
  1726. if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info, c.config), dest)
  1727. else: unused(c, n, dest)
  1728. of nkAsgn, nkFastAsgn:
  1729. unused(c, n, dest)
  1730. genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
  1731. of nkDotExpr: genObjAccess(c, n, dest, flags)
  1732. of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
  1733. of nkBracketExpr: genArrAccess(c, n, dest, flags)
  1734. of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags)
  1735. of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags)
  1736. of nkIfStmt, nkIfExpr: genIf(c, n, dest)
  1737. of nkWhenStmt:
  1738. # This is "when nimvm" node. Chose the first branch.
  1739. gen(c, n.sons[0].sons[1], dest)
  1740. of nkCaseStmt: genCase(c, n, dest)
  1741. of nkWhileStmt:
  1742. unused(c, n, dest)
  1743. genWhile(c, n)
  1744. of nkBlockExpr, nkBlockStmt: genBlock(c, n, dest)
  1745. of nkReturnStmt:
  1746. unused(c, n, dest)
  1747. genReturn(c, n)
  1748. of nkRaiseStmt:
  1749. genRaise(c, n)
  1750. of nkBreakStmt:
  1751. unused(c, n, dest)
  1752. genBreak(c, n)
  1753. of nkTryStmt: genTry(c, n, dest)
  1754. of nkStmtList:
  1755. #unused(c, n, dest)
  1756. # XXX Fix this bug properly, lexim triggers it
  1757. for x in n: gen(c, x)
  1758. of nkStmtListExpr:
  1759. let L = n.len-1
  1760. for i in 0 ..< L: gen(c, n.sons[i])
  1761. gen(c, n.sons[L], dest, flags)
  1762. of nkPragmaBlock:
  1763. gen(c, n.lastSon, dest, flags)
  1764. of nkDiscardStmt:
  1765. unused(c, n, dest)
  1766. gen(c, n.sons[0])
  1767. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1768. genConv(c, n, n.sons[1], dest)
  1769. of nkObjDownConv:
  1770. genConv(c, n, n.sons[0], dest)
  1771. of nkVarSection, nkLetSection:
  1772. unused(c, n, dest)
  1773. genVarSection(c, n)
  1774. of declarativeDefs, nkMacroDef:
  1775. unused(c, n, dest)
  1776. of nkLambdaKinds:
  1777. #let s = n.sons[namePos].sym
  1778. #discard genProc(c, s)
  1779. genLit(c, newSymNode(n.sons[namePos].sym), dest)
  1780. of nkChckRangeF, nkChckRange64, nkChckRange:
  1781. let
  1782. tmp0 = c.genx(n.sons[0])
  1783. tmp1 = c.genx(n.sons[1])
  1784. tmp2 = c.genx(n.sons[2])
  1785. c.gABC(n, opcRangeChck, tmp0, tmp1, tmp2)
  1786. c.freeTemp(tmp1)
  1787. c.freeTemp(tmp2)
  1788. if dest >= 0:
  1789. gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1)
  1790. c.freeTemp(tmp0)
  1791. else:
  1792. dest = tmp0
  1793. of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
  1794. nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
  1795. unused(c, n, dest)
  1796. of nkStringToCString, nkCStringToString:
  1797. gen(c, n.sons[0], dest)
  1798. of nkBracket: genArrayConstr(c, n, dest)
  1799. of nkCurly: genSetConstr(c, n, dest)
  1800. of nkObjConstr: genObjConstr(c, n, dest)
  1801. of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
  1802. of nkCast:
  1803. if allowCast in c.features:
  1804. genConv(c, n, n.sons[1], dest, opcCast)
  1805. else:
  1806. genIntCast(c, n, dest)
  1807. of nkTypeOfExpr:
  1808. genTypeLit(c, n.typ, dest)
  1809. of nkComesFrom:
  1810. discard "XXX to implement for better stack traces"
  1811. else:
  1812. globalError(c.config, n.info, "cannot generate VM code for " & $n)
  1813. proc removeLastEof(c: PCtx) =
  1814. let last = c.code.len-1
  1815. if last >= 0 and c.code[last].opcode == opcEof:
  1816. # overwrite last EOF:
  1817. assert c.code.len == c.debug.len
  1818. c.code.setLen(last)
  1819. c.debug.setLen(last)
  1820. proc genStmt*(c: PCtx; n: PNode): int =
  1821. c.removeLastEof
  1822. result = c.code.len
  1823. var d: TDest = -1
  1824. c.gen(n, d)
  1825. c.gABC(n, opcEof)
  1826. if d >= 0:
  1827. globalError(c.config, n.info, "VM problem: dest register is set")
  1828. proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
  1829. c.removeLastEof
  1830. result = c.code.len
  1831. var d: TDest = -1
  1832. c.gen(n, d)
  1833. if d < 0:
  1834. if requiresValue:
  1835. globalError(c.config, n.info, "VM problem: dest register is not set")
  1836. d = 0
  1837. c.gABC(n, opcEof, d)
  1838. #echo renderTree(n)
  1839. #c.echoCode(result)
  1840. proc genParams(c: PCtx; params: PNode) =
  1841. # res.sym.position is already 0
  1842. c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
  1843. for i in 1..<params.len:
  1844. c.prc.slots[i] = (inUse: true, kind: slotFixedLet)
  1845. c.prc.maxSlots = max(params.len, 1)
  1846. proc finalJumpTarget(c: PCtx; pc, diff: int) =
  1847. internalAssert(c.config, -0x7fff < diff and diff < 0x7fff)
  1848. let oldInstr = c.code[pc]
  1849. # opcode and regA stay the same:
  1850. c.code[pc] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
  1851. uint32(diff+wordExcess) shl 16'u32).TInstr
  1852. proc genGenericParams(c: PCtx; gp: PNode) =
  1853. var base = c.prc.maxSlots
  1854. for i in 0..<gp.len:
  1855. var param = gp.sons[i].sym
  1856. param.position = base + i # XXX: fix this earlier; make it consistent with templates
  1857. c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet)
  1858. c.prc.maxSlots = base + gp.len
  1859. proc optimizeJumps(c: PCtx; start: int) =
  1860. const maxIterations = 10
  1861. for i in start ..< c.code.len:
  1862. let opc = c.code[i].opcode
  1863. case opc
  1864. of opcTJmp, opcFJmp:
  1865. var reg = c.code[i].regA
  1866. var d = i + c.code[i].jmpDiff
  1867. for iters in countdown(maxIterations, 0):
  1868. case c.code[d].opcode
  1869. of opcJmp, opcJmpBack:
  1870. d = d + c.code[d].jmpDiff
  1871. of opcTJmp, opcFJmp:
  1872. if c.code[d].regA != reg: break
  1873. # tjmp x, 23
  1874. # ...
  1875. # tjmp x, 12
  1876. # -- we know 'x' is true, and so can jump to 12+13:
  1877. if c.code[d].opcode == opc:
  1878. d = d + c.code[d].jmpDiff
  1879. else:
  1880. # tjmp x, 23
  1881. # fjmp x, 22
  1882. # We know 'x' is true so skip to the next instruction:
  1883. d = d + 1
  1884. else: break
  1885. if d != i + c.code[i].jmpDiff:
  1886. c.finalJumpTarget(i, d - i)
  1887. of opcJmp, opcJmpBack:
  1888. var d = i + c.code[i].jmpDiff
  1889. var iters = maxIterations
  1890. while c.code[d].opcode == opcJmp and iters > 0:
  1891. d = d + c.code[d].jmpDiff
  1892. dec iters
  1893. if c.code[d].opcode == opcRet:
  1894. # optimize 'jmp to ret' to 'ret' here
  1895. c.code[i] = c.code[d]
  1896. elif d != i + c.code[i].jmpDiff:
  1897. c.finalJumpTarget(i, d - i)
  1898. else: discard
  1899. proc genProc(c: PCtx; s: PSym): int =
  1900. var x = s.ast.sons[miscPos]
  1901. if x.kind == nkEmpty or x[0].kind == nkEmpty:
  1902. #if s.name.s == "outterMacro" or s.name.s == "innerProc":
  1903. # echo "GENERATING CODE FOR ", s.name.s
  1904. let last = c.code.len-1
  1905. var eofInstr: TInstr
  1906. if last >= 0 and c.code[last].opcode == opcEof:
  1907. eofInstr = c.code[last]
  1908. c.code.setLen(last)
  1909. c.debug.setLen(last)
  1910. #c.removeLastEof
  1911. result = c.code.len+1 # skip the jump instruction
  1912. if x.kind == nkEmpty:
  1913. x = newTree(nkBracket, newIntNode(nkIntLit, result), x)
  1914. else:
  1915. x.sons[0] = newIntNode(nkIntLit, result)
  1916. s.ast.sons[miscPos] = x
  1917. # thanks to the jmp we can add top level statements easily and also nest
  1918. # procs easily:
  1919. let body = s.getBody
  1920. let procStart = c.xjmp(body, opcJmp, 0)
  1921. var p = PProc(blocks: @[], sym: s)
  1922. let oldPrc = c.prc
  1923. c.prc = p
  1924. # iterate over the parameters and allocate space for them:
  1925. genParams(c, s.typ.n)
  1926. # allocate additional space for any generically bound parameters
  1927. if s.kind == skMacro and
  1928. sfImmediate notin s.flags and
  1929. s.ast[genericParamsPos].kind != nkEmpty:
  1930. genGenericParams(c, s.ast[genericParamsPos])
  1931. if tfCapturesEnv in s.typ.flags:
  1932. #let env = s.ast.sons[paramsPos].lastSon.sym
  1933. #assert env.position == 2
  1934. c.prc.slots[c.prc.maxSlots] = (inUse: true, kind: slotFixedLet)
  1935. inc c.prc.maxSlots
  1936. gen(c, body)
  1937. # generate final 'return' statement:
  1938. c.gABC(body, opcRet)
  1939. c.patch(procStart)
  1940. c.gABC(body, opcEof, eofInstr.regA)
  1941. c.optimizeJumps(result)
  1942. s.offset = c.prc.maxSlots
  1943. #if s.name.s == "calc":
  1944. # echo renderTree(body)
  1945. # c.echoCode(result)
  1946. c.prc = oldPrc
  1947. else:
  1948. c.prc.maxSlots = s.offset
  1949. result = x[0].intVal.int