vmgen.nim 73 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186
  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, transf
  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 genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags)
  508. proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
  509. case le.kind
  510. of nkBracketExpr:
  511. let dest = c.genx(le.sons[0], {gfNode})
  512. let idx = c.genIndex(le.sons[1], le.sons[0].typ)
  513. c.gABC(le, opcWrArr, dest, idx, value)
  514. c.freeTemp(dest)
  515. c.freeTemp(idx)
  516. of nkCheckedFieldExpr:
  517. var objR: TDest = -1
  518. genCheckedObjAccessAux(c, le, objR, {gfNode})
  519. let idx = genField(c, le[0].sons[1])
  520. c.gABC(le[0], opcWrObj, objR, idx, value)
  521. c.freeTemp(objR)
  522. of nkDotExpr:
  523. let dest = c.genx(le.sons[0], {gfNode})
  524. let idx = genField(c, le.sons[1])
  525. c.gABC(le, opcWrObj, dest, idx, value)
  526. c.freeTemp(dest)
  527. of nkDerefExpr, nkHiddenDeref:
  528. let dest = c.genx(le.sons[0], {gfNode})
  529. c.gABC(le, opcWrDeref, dest, 0, value)
  530. c.freeTemp(dest)
  531. of nkSym:
  532. if le.sym.isGlobal:
  533. let dest = c.genx(le, {gfNodeAddr})
  534. c.gABC(le, opcWrDeref, dest, 0, value)
  535. c.freeTemp(dest)
  536. else:
  537. discard
  538. proc genNew(c: PCtx; n: PNode) =
  539. let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
  540. else: c.genx(n.sons[1])
  541. # we use the ref's base type here as the VM conflates 'ref object'
  542. # and 'object' since internally we already have a pointer.
  543. c.gABx(n, opcNew, dest,
  544. c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
  545. c.genAsgnPatch(n.sons[1], dest)
  546. c.freeTemp(dest)
  547. proc genNewSeq(c: PCtx; n: PNode) =
  548. let t = n.sons[1].typ
  549. let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(t)
  550. else: c.genx(n.sons[1])
  551. let tmp = c.genx(n.sons[2])
  552. c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
  553. abstractVar-{tyTypeDesc})))
  554. c.gABx(n, opcNewSeq, tmp, 0)
  555. c.freeTemp(tmp)
  556. c.genAsgnPatch(n.sons[1], dest)
  557. c.freeTemp(dest)
  558. proc genNewSeqOfCap(c: PCtx; n: PNode; dest: var TDest) =
  559. let t = n.typ
  560. let tmp = c.getTemp(n.sons[1].typ)
  561. c.gABx(n, opcLdNull, dest, c.genType(t))
  562. c.gABx(n, opcLdImmInt, tmp, 0)
  563. c.gABx(n, opcNewSeq, dest, c.genType(t.skipTypes(
  564. abstractVar-{tyTypeDesc})))
  565. c.gABx(n, opcNewSeq, tmp, 0)
  566. c.freeTemp(tmp)
  567. proc genUnaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  568. let tmp = c.genx(n.sons[1])
  569. if dest < 0: dest = c.getTemp(n.typ)
  570. c.gABC(n, opc, dest, tmp)
  571. c.freeTemp(tmp)
  572. proc genUnaryABI(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; imm: BiggestInt=0) =
  573. let tmp = c.genx(n.sons[1])
  574. if dest < 0: dest = c.getTemp(n.typ)
  575. c.gABI(n, opc, dest, tmp, imm)
  576. c.freeTemp(tmp)
  577. proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  578. let
  579. tmp = c.genx(n.sons[1])
  580. tmp2 = c.genx(n.sons[2])
  581. if dest < 0: dest = c.getTemp(n.typ)
  582. c.gABC(n, opc, dest, tmp, tmp2)
  583. c.freeTemp(tmp)
  584. c.freeTemp(tmp2)
  585. proc genBinaryABCD(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  586. let
  587. tmp = c.genx(n.sons[1])
  588. tmp2 = c.genx(n.sons[2])
  589. tmp3 = c.genx(n.sons[3])
  590. if dest < 0: dest = c.getTemp(n.typ)
  591. c.gABC(n, opc, dest, tmp, tmp2)
  592. c.gABC(n, opc, tmp3)
  593. c.freeTemp(tmp)
  594. c.freeTemp(tmp2)
  595. c.freeTemp(tmp3)
  596. proc genNarrow(c: PCtx; n: PNode; dest: TDest) =
  597. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  598. # uint is uint64 in the VM, we we only need to mask the result for
  599. # other unsigned types:
  600. if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and t.size < 8):
  601. c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
  602. elif t.kind in {tyInt8..tyInt32} or (t.kind == tyInt and t.size < 8):
  603. c.gABC(n, opcNarrowS, dest, TRegister(t.size*8))
  604. proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
  605. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  606. # uint is uint64 in the VM, we we only need to mask the result for
  607. # other unsigned types:
  608. if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or
  609. (t.kind in {tyUInt, tyInt} and t.size < 8):
  610. c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
  611. proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  612. genBinaryABC(c, n, dest, opc)
  613. genNarrow(c, n, dest)
  614. proc genBinaryABCnarrowU(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  615. genBinaryABC(c, n, dest, opc)
  616. genNarrowU(c, n, dest)
  617. proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
  618. let t = skipTypes(n.typ, abstractInst-{tyTypeDesc})
  619. if t.kind == tySet:
  620. c.gABx(n, opcSetType, dest, c.genType(t))
  621. proc genBinarySet(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  622. let
  623. tmp = c.genx(n.sons[1])
  624. tmp2 = c.genx(n.sons[2])
  625. if dest < 0: dest = c.getTemp(n.typ)
  626. c.genSetType(n.sons[1], tmp)
  627. c.genSetType(n.sons[2], tmp2)
  628. c.gABC(n, opc, dest, tmp, tmp2)
  629. c.freeTemp(tmp)
  630. c.freeTemp(tmp2)
  631. proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
  632. let
  633. dest = c.genx(n.sons[1])
  634. tmp = c.genx(n.sons[2])
  635. c.gABC(n, opc, dest, tmp, 0)
  636. c.freeTemp(tmp)
  637. proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
  638. var x = n.sons[1]
  639. if x.kind in {nkAddr, nkHiddenAddr}: x = x.sons[0]
  640. let
  641. dest = c.genx(x)
  642. tmp = c.genx(n.sons[2])
  643. c.gABC(n, opc, dest, tmp, 0)
  644. #c.genAsgnPatch(n.sons[1], dest)
  645. c.freeTemp(tmp)
  646. proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
  647. let tmp = c.genx(n.sons[1])
  648. c.gABC(n, opc, tmp, 0, 0)
  649. c.freeTemp(tmp)
  650. proc genVarargsABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  651. if dest < 0: dest = getTemp(c, n.typ)
  652. var x = c.getTempRange(n.len-1, slotTempStr)
  653. for i in 1..n.len-1:
  654. var r: TRegister = x+i-1
  655. c.gen(n.sons[i], r)
  656. c.gABC(n, opc, dest, x, n.len-1)
  657. c.freeTempRange(x, n.len)
  658. proc isInt8Lit(n: PNode): bool =
  659. if n.kind in {nkCharLit..nkUInt64Lit}:
  660. result = n.intVal >= low(int8) and n.intVal <= high(int8)
  661. proc isInt16Lit(n: PNode): bool =
  662. if n.kind in {nkCharLit..nkUInt64Lit}:
  663. result = n.intVal >= low(int16) and n.intVal <= high(int16)
  664. proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
  665. if n.sons[2].isInt8Lit:
  666. let tmp = c.genx(n.sons[1])
  667. if dest < 0: dest = c.getTemp(n.typ)
  668. c.gABI(n, succ(opc), dest, tmp, n.sons[2].intVal)
  669. c.freeTemp(tmp)
  670. else:
  671. genBinaryABC(c, n, dest, opc)
  672. c.genNarrow(n, dest)
  673. proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
  674. if n.typ.kind == arg.typ.kind and arg.typ.kind == tyProc:
  675. # don't do anything for lambda lifting conversions:
  676. gen(c, arg, dest)
  677. return
  678. let tmp = c.genx(arg)
  679. if dest < 0: dest = c.getTemp(n.typ)
  680. c.gABC(n, opc, dest, tmp)
  681. c.gABx(n, opc, 0, genType(c, n.typ.skipTypes({tyStatic})))
  682. c.gABx(n, opc, 0, genType(c, arg.typ.skipTypes({tyStatic})))
  683. c.freeTemp(tmp)
  684. proc genCard(c: PCtx; n: PNode; dest: var TDest) =
  685. let tmp = c.genx(n.sons[1])
  686. if dest < 0: dest = c.getTemp(n.typ)
  687. c.genSetType(n.sons[1], tmp)
  688. c.gABC(n, opcCard, dest, tmp)
  689. c.freeTemp(tmp)
  690. proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
  691. const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar}
  692. var signedIntegers = {tyInt8..tyInt32}
  693. var unsignedIntegers = {tyUInt8..tyUInt32, tyChar}
  694. let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
  695. let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
  696. let src_size = getSize(c.config, src)
  697. let dst_size = getSize(c.config, dst)
  698. if c.config.target.intSize < 8:
  699. signedIntegers.incl(tyInt)
  700. unsignedIntegers.incl(tyUInt)
  701. if src_size == dst_size and src.kind in allowedIntegers and
  702. dst.kind in allowedIntegers:
  703. let tmp = c.genx(n.sons[1])
  704. var tmp2 = c.getTemp(n.sons[1].typ)
  705. let tmp3 = c.getTemp(n.sons[1].typ)
  706. if dest < 0: dest = c.getTemp(n[0].typ)
  707. proc mkIntLit(ival: int): int =
  708. result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(c.graph, n.info, tyInt)))
  709. if src.kind in unsignedIntegers and dst.kind in signedIntegers:
  710. # cast unsigned to signed integer of same size
  711. # signedVal = (unsignedVal xor offset) -% offset
  712. let offset = 1 shl (src_size * 8 - 1)
  713. c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
  714. c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2)
  715. c.gABC(n, opcSubInt, dest, tmp3, tmp2)
  716. elif src.kind in signedIntegers and dst.kind in unsignedIntegers:
  717. # cast signed to unsigned integer of same size
  718. # unsignedVal = (offset +% signedVal +% 1) and offset
  719. let offset = (1 shl (src_size * 8)) - 1
  720. c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
  721. c.gABx(n, opcLdConst, dest, mkIntLit(offset+1))
  722. c.gABC(n, opcAddu, tmp3, tmp, dest)
  723. c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8))
  724. c.gABC(n, opcBitandInt, dest, tmp3, tmp2)
  725. else:
  726. c.gABC(n, opcAsgnInt, dest, tmp)
  727. c.freeTemp(tmp)
  728. c.freeTemp(tmp2)
  729. c.freeTemp(tmp3)
  730. elif src_size == dst_size and src.kind in allowedIntegers and
  731. dst.kind in {tyFloat, tyFloat32, tyFloat64}:
  732. let tmp = c.genx(n[1])
  733. if dest < 0: dest = c.getTemp(n[0].typ)
  734. if dst.kind == tyFloat32:
  735. c.gABC(n, opcAsgnFloat32FromInt, dest, tmp)
  736. else:
  737. c.gABC(n, opcAsgnFloat64FromInt, dest, tmp)
  738. c.freeTemp(tmp)
  739. elif src_size == dst_size and src.kind in {tyFloat, tyFloat32, tyFloat64} and
  740. dst.kind in allowedIntegers:
  741. let tmp = c.genx(n[1])
  742. if dest < 0: dest = c.getTemp(n[0].typ)
  743. if src.kind == tyFloat32:
  744. c.gABC(n, opcAsgnIntFromFloat32, dest, tmp)
  745. else:
  746. c.gABC(n, opcAsgnIntFromFloat64, dest, tmp)
  747. c.freeTemp(tmp)
  748. else:
  749. globalError(c.config, n.info, "VM is only allowed to 'cast' between integers and/or floats of same size")
  750. proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) =
  751. unused(c, n, dest)
  752. var
  753. tmp1 = c.genx(n[1])
  754. tmp2 = c.genx(n[2])
  755. tmp3 = c.genx(n[3])
  756. c.gABC(n, opcode, tmp1, tmp2, tmp3)
  757. c.freeTemp(tmp1)
  758. c.freeTemp(tmp2)
  759. c.freeTemp(tmp3)
  760. proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
  761. # nah, cannot use c.config.features because sempass context
  762. # can have local experimental switch
  763. # if dynamicBindSym notin c.config.features:
  764. if n.len == 2: # hmm, reliable?
  765. # bindSym with static input
  766. if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}:
  767. let idx = c.genLiteral(n[1])
  768. if dest < 0: dest = c.getTemp(n.typ)
  769. c.gABx(n, opcNBindSym, dest, idx)
  770. else:
  771. localError(c.config, n.info, "invalid bindSym usage")
  772. else:
  773. # experimental bindSym
  774. if dest < 0: dest = c.getTemp(n.typ)
  775. let x = c.getTempRange(n.len, slotTempUnknown)
  776. # callee symbol
  777. var tmp0 = TDest(x)
  778. c.genLit(n.sons[0], tmp0)
  779. # original parameters
  780. for i in 1..<n.len-2:
  781. var r = TRegister(x+i)
  782. c.gen(n.sons[i], r)
  783. # info node
  784. var tmp1 = TDest(x+n.len-2)
  785. c.genLit(n.sons[^2], tmp1)
  786. # payload idx
  787. var tmp2 = TDest(x+n.len-1)
  788. c.genLit(n.sons[^1], tmp2)
  789. c.gABC(n, opcNDynBindSym, dest, x, n.len)
  790. c.freeTempRange(x, n.len)
  791. proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
  792. case m
  793. of mAnd: c.genAndOr(n, opcFJmp, dest)
  794. of mOr: c.genAndOr(n, opcTJmp, dest)
  795. of mUnaryLt:
  796. let tmp = c.genx(n.sons[1])
  797. if dest < 0: dest = c.getTemp(n.typ)
  798. c.gABI(n, opcSubImmInt, dest, tmp, 1)
  799. c.freeTemp(tmp)
  800. of mPred, mSubI:
  801. c.genAddSubInt(n, dest, opcSubInt)
  802. of mSucc, mAddI:
  803. c.genAddSubInt(n, dest, opcAddInt)
  804. of mInc, mDec:
  805. unused(c, n, dest)
  806. let opc = if m == mInc: opcAddInt else: opcSubInt
  807. let d = c.genx(n.sons[1])
  808. if n.sons[2].isInt8Lit:
  809. c.gABI(n, succ(opc), d, d, n.sons[2].intVal)
  810. else:
  811. let tmp = c.genx(n.sons[2])
  812. c.gABC(n, opc, d, d, tmp)
  813. c.freeTemp(tmp)
  814. c.genNarrow(n.sons[1], d)
  815. c.genAsgnPatch(n.sons[1], d)
  816. c.freeTemp(d)
  817. of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest)
  818. of mNew, mNewFinalize:
  819. unused(c, n, dest)
  820. c.genNew(n)
  821. of mNewSeq:
  822. unused(c, n, dest)
  823. c.genNewSeq(n)
  824. of mNewSeqOfCap: c.genNewSeqOfCap(n, dest)
  825. of mNewString:
  826. genUnaryABC(c, n, dest, opcNewStr)
  827. # XXX buggy
  828. of mNewStringOfCap:
  829. # we ignore the 'cap' argument and translate it as 'newString(0)'.
  830. # eval n.sons[1] for possible side effects:
  831. c.freeTemp(c.genx(n.sons[1]))
  832. var tmp = c.getTemp(n.sons[1].typ)
  833. c.gABx(n, opcLdImmInt, tmp, 0)
  834. if dest < 0: dest = c.getTemp(n.typ)
  835. c.gABC(n, opcNewStr, dest, tmp)
  836. c.freeTemp(tmp)
  837. # XXX buggy
  838. of mLengthOpenArray, mLengthArray, mLengthSeq, mXLenSeq:
  839. genUnaryABI(c, n, dest, opcLenSeq)
  840. of mLengthStr, mXLenStr:
  841. genUnaryABI(c, n, dest, opcLenStr)
  842. of mIncl, mExcl:
  843. unused(c, n, dest)
  844. var d = c.genx(n.sons[1])
  845. var tmp = c.genx(n.sons[2])
  846. c.genSetType(n.sons[1], d)
  847. c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp)
  848. c.freeTemp(d)
  849. c.freeTemp(tmp)
  850. of mCard: genCard(c, n, dest)
  851. of mMulI: genBinaryABCnarrow(c, n, dest, opcMulInt)
  852. of mDivI: genBinaryABCnarrow(c, n, dest, opcDivInt)
  853. of mModI: genBinaryABCnarrow(c, n, dest, opcModInt)
  854. of mAddF64: genBinaryABC(c, n, dest, opcAddFloat)
  855. of mSubF64: genBinaryABC(c, n, dest, opcSubFloat)
  856. of mMulF64: genBinaryABC(c, n, dest, opcMulFloat)
  857. of mDivF64: genBinaryABC(c, n, dest, opcDivFloat)
  858. of mShrI:
  859. # the idea here is to narrow type if needed before executing right shift
  860. # inlined modified: genNarrowU(c, n, dest)
  861. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  862. # uint is uint64 in the VM, we we only need to mask the result for
  863. # other unsigned types:
  864. let tmp = c.genx(n.sons[1])
  865. if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}:
  866. c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
  867. # inlined modified: genBinaryABC(c, n, dest, opcShrInt)
  868. let tmp2 = c.genx(n.sons[2])
  869. if dest < 0: dest = c.getTemp(n.typ)
  870. c.gABC(n, opcShrInt, dest, tmp, tmp2)
  871. c.freeTemp(tmp)
  872. c.freeTemp(tmp2)
  873. of mShlI: genBinaryABCnarrowU(c, n, dest, opcShlInt)
  874. of mAshrI: genBinaryABCnarrow(c, n, dest, opcAshrInt)
  875. of mBitandI: genBinaryABCnarrowU(c, n, dest, opcBitandInt)
  876. of mBitorI: genBinaryABCnarrowU(c, n, dest, opcBitorInt)
  877. of mBitxorI: genBinaryABCnarrowU(c, n, dest, opcBitxorInt)
  878. of mAddU: genBinaryABCnarrowU(c, n, dest, opcAddu)
  879. of mSubU: genBinaryABCnarrowU(c, n, dest, opcSubu)
  880. of mMulU: genBinaryABCnarrowU(c, n, dest, opcMulu)
  881. of mDivU: genBinaryABCnarrowU(c, n, dest, opcDivu)
  882. of mModU: genBinaryABCnarrowU(c, n, dest, opcModu)
  883. of mEqI, mEqB, mEqEnum, mEqCh:
  884. genBinaryABC(c, n, dest, opcEqInt)
  885. of mLeI, mLeEnum, mLeCh, mLeB:
  886. genBinaryABC(c, n, dest, opcLeInt)
  887. of mLtI, mLtEnum, mLtCh, mLtB:
  888. genBinaryABC(c, n, dest, opcLtInt)
  889. of mEqF64: genBinaryABC(c, n, dest, opcEqFloat)
  890. of mLeF64: genBinaryABC(c, n, dest, opcLeFloat)
  891. of mLtF64: genBinaryABC(c, n, dest, opcLtFloat)
  892. of mLePtr, mLeU, mLeU64: genBinaryABC(c, n, dest, opcLeu)
  893. of mLtPtr, mLtU, mLtU64: genBinaryABC(c, n, dest, opcLtu)
  894. of mEqProc, mEqRef, mEqUntracedRef:
  895. genBinaryABC(c, n, dest, opcEqRef)
  896. of mXor: genBinaryABCnarrowU(c, n, dest, opcXor)
  897. of mNot: genUnaryABC(c, n, dest, opcNot)
  898. of mUnaryMinusI, mUnaryMinusI64:
  899. genUnaryABC(c, n, dest, opcUnaryMinusInt)
  900. genNarrow(c, n, dest)
  901. of mUnaryMinusF64: genUnaryABC(c, n, dest, opcUnaryMinusFloat)
  902. of mUnaryPlusI, mUnaryPlusF64: gen(c, n.sons[1], dest)
  903. of mBitnotI:
  904. genUnaryABC(c, n, dest, opcBitnotInt)
  905. genNarrowU(c, n, dest)
  906. of mToFloat, mToBiggestFloat, mToInt,
  907. mToBiggestInt, mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr,
  908. mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
  909. genConv(c, n, n.sons[1], dest)
  910. of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
  911. #genNarrowU modified
  912. let t = skipTypes(n.sons[1].typ, abstractVar-{tyTypeDesc})
  913. let tmp = c.genx(n.sons[1])
  914. c.gABC(n, opcNarrowU, tmp, TRegister(t.size*8))
  915. # assign result to dest register
  916. if dest < 0: dest = c.getTemp(n.typ)
  917. c.gABC(n, opcAsgnInt, dest, tmp)
  918. c.freeTemp(tmp)
  919. of mToU8, mToU16, mToU32:
  920. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  921. var tmp = c.genx(n.sons[1])
  922. if dest < 0: dest = c.getTemp(n.typ)
  923. c.gABC(n, opcToNarrowInt, dest, tmp, TRegister(t.size*8))
  924. c.freeTemp(tmp)
  925. of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
  926. of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
  927. of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
  928. of mEqSet: genBinarySet(c, n, dest, opcEqSet)
  929. of mLeSet: genBinarySet(c, n, dest, opcLeSet)
  930. of mLtSet: genBinarySet(c, n, dest, opcLtSet)
  931. of mMulSet: genBinarySet(c, n, dest, opcMulSet)
  932. of mPlusSet: genBinarySet(c, n, dest, opcPlusSet)
  933. of mMinusSet: genBinarySet(c, n, dest, opcMinusSet)
  934. of mSymDiffSet: genBinarySet(c, n, dest, opcSymdiffSet)
  935. of mConStrStr: genVarargsABC(c, n, dest, opcConcatStr)
  936. of mInSet: genBinarySet(c, n, dest, opcContainsSet)
  937. of mRepr: genUnaryABC(c, n, dest, opcRepr)
  938. of mExit:
  939. unused(c, n, dest)
  940. var tmp = c.genx(n.sons[1])
  941. c.gABC(n, opcQuit, tmp)
  942. c.freeTemp(tmp)
  943. of mSetLengthStr, mSetLengthSeq:
  944. unused(c, n, dest)
  945. var d = c.genx(n.sons[1])
  946. var tmp = c.genx(n.sons[2])
  947. c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
  948. c.genAsgnPatch(n.sons[1], d)
  949. c.freeTemp(tmp)
  950. of mSwap:
  951. unused(c, n, dest)
  952. c.gen(lowerSwap(c.graph, n, if c.prc == nil: c.module else: c.prc.sym))
  953. of mIsNil: genUnaryABC(c, n, dest, opcIsNil)
  954. of mCopyStr:
  955. if dest < 0: dest = c.getTemp(n.typ)
  956. var
  957. tmp1 = c.genx(n.sons[1])
  958. tmp2 = c.genx(n.sons[2])
  959. tmp3 = c.getTemp(n.sons[2].typ)
  960. c.gABC(n, opcLenStr, tmp3, tmp1)
  961. c.gABC(n, opcSubStr, dest, tmp1, tmp2)
  962. c.gABC(n, opcSubStr, tmp3)
  963. c.freeTemp(tmp1)
  964. c.freeTemp(tmp2)
  965. c.freeTemp(tmp3)
  966. of mCopyStrLast:
  967. if dest < 0: dest = c.getTemp(n.typ)
  968. var
  969. tmp1 = c.genx(n.sons[1])
  970. tmp2 = c.genx(n.sons[2])
  971. tmp3 = c.genx(n.sons[3])
  972. c.gABC(n, opcSubStr, dest, tmp1, tmp2)
  973. c.gABC(n, opcSubStr, tmp3)
  974. c.freeTemp(tmp1)
  975. c.freeTemp(tmp2)
  976. c.freeTemp(tmp3)
  977. of mParseBiggestFloat:
  978. if dest < 0: dest = c.getTemp(n.typ)
  979. var d2: TRegister
  980. # skip 'nkHiddenAddr':
  981. let d2AsNode = n.sons[2].sons[0]
  982. if needsAsgnPatch(d2AsNode):
  983. d2 = c.getTemp(getSysType(c.graph, n.info, tyFloat))
  984. else:
  985. d2 = c.genx(d2AsNode)
  986. var
  987. tmp1 = c.genx(n.sons[1])
  988. tmp3 = c.genx(n.sons[3])
  989. c.gABC(n, opcParseFloat, dest, tmp1, d2)
  990. c.gABC(n, opcParseFloat, tmp3)
  991. c.freeTemp(tmp1)
  992. c.freeTemp(tmp3)
  993. c.genAsgnPatch(d2AsNode, d2)
  994. c.freeTemp(d2)
  995. of mReset:
  996. unused(c, n, dest)
  997. var d = c.genx(n.sons[1])
  998. c.gABC(n, opcReset, d)
  999. of mOf, mIs:
  1000. if dest < 0: dest = c.getTemp(n.typ)
  1001. var tmp = c.genx(n.sons[1])
  1002. var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
  1003. var typ = n.sons[2].typ
  1004. if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
  1005. c.gABx(n, opcLdImmInt, idx, c.genType(typ))
  1006. c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
  1007. c.freeTemp(tmp)
  1008. c.freeTemp(idx)
  1009. of mHigh:
  1010. if dest < 0: dest = c.getTemp(n.typ)
  1011. let tmp = c.genx(n.sons[1])
  1012. case n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind:
  1013. of tyString, tyCString:
  1014. c.gABI(n, opcLenStr, dest, tmp, 1)
  1015. else:
  1016. c.gABI(n, opcLenSeq, dest, tmp, 1)
  1017. c.freeTemp(tmp)
  1018. of mEcho:
  1019. unused(c, n, dest)
  1020. let n = n[1].skipConv
  1021. let x = c.getTempRange(n.len, slotTempUnknown)
  1022. internalAssert c.config, n.kind == nkBracket
  1023. for i in 0..<n.len:
  1024. var r: TRegister = x+i
  1025. c.gen(n.sons[i], r)
  1026. c.gABC(n, opcEcho, x, n.len)
  1027. c.freeTempRange(x, n.len)
  1028. of mAppendStrCh:
  1029. unused(c, n, dest)
  1030. genBinaryStmtVar(c, n, opcAddStrCh)
  1031. of mAppendStrStr:
  1032. unused(c, n, dest)
  1033. genBinaryStmtVar(c, n, opcAddStrStr)
  1034. of mAppendSeqElem:
  1035. unused(c, n, dest)
  1036. genBinaryStmtVar(c, n, opcAddSeqElem)
  1037. of mParseExprToAst:
  1038. genUnaryABC(c, n, dest, opcParseExprToAst)
  1039. of mParseStmtToAst:
  1040. genUnaryABC(c, n, dest, opcParseStmtToAst)
  1041. of mTypeTrait:
  1042. let tmp = c.genx(n.sons[1])
  1043. if dest < 0: dest = c.getTemp(n.typ)
  1044. c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ))
  1045. c.gABC(n, opcTypeTrait, dest, tmp)
  1046. c.freeTemp(tmp)
  1047. of mSlurp: genUnaryABC(c, n, dest, opcSlurp)
  1048. of mStaticExec: genBinaryABCD(c, n, dest, opcGorge)
  1049. of mNLen: genUnaryABI(c, n, dest, opcLenSeq, nimNodeFlag)
  1050. of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
  1051. of mGetImplTransf: genUnaryABC(c, n, dest, opcGetImplTransf)
  1052. of mSymOwner: genUnaryABC(c, n, dest, opcSymOwner)
  1053. of mNChild: genBinaryABC(c, n, dest, opcNChild)
  1054. of mNSetChild: genVoidABC(c, n, dest, opcNSetChild)
  1055. of mNDel: genVoidABC(c, n, dest, opcNDel)
  1056. of mNAdd: genBinaryABC(c, n, dest, opcNAdd)
  1057. of mNAddMultiple: genBinaryABC(c, n, dest, opcNAddMultiple)
  1058. of mNKind: genUnaryABC(c, n, dest, opcNKind)
  1059. of mNSymKind: genUnaryABC(c, n, dest, opcNSymKind)
  1060. of mNccValue: genUnaryABC(c, n, dest, opcNccValue)
  1061. of mNccInc: genBinaryABC(c, n, dest, opcNccInc)
  1062. of mNcsAdd: genBinaryABC(c, n, dest, opcNcsAdd)
  1063. of mNcsIncl: genBinaryABC(c, n, dest, opcNcsIncl)
  1064. of mNcsLen: genUnaryABC(c, n, dest, opcNcsLen)
  1065. of mNcsAt: genBinaryABC(c, n, dest, opcNcsAt)
  1066. of mNctPut: genVoidABC(c, n, dest, opcNctPut)
  1067. of mNctLen: genUnaryABC(c, n, dest, opcNctLen)
  1068. of mNctGet: genBinaryABC(c, n, dest, opcNctGet)
  1069. of mNctHasNext: genBinaryABC(c, n, dest, opcNctHasNext)
  1070. of mNctNext: genBinaryABC(c, n, dest, opcNctNext)
  1071. of mNIntVal: genUnaryABC(c, n, dest, opcNIntVal)
  1072. of mNFloatVal: genUnaryABC(c, n, dest, opcNFloatVal)
  1073. of mNSymbol: genUnaryABC(c, n, dest, opcNSymbol)
  1074. of mNIdent: genUnaryABC(c, n, dest, opcNIdent)
  1075. of mNGetType:
  1076. let tmp = c.genx(n.sons[1])
  1077. if dest < 0: dest = c.getTemp(n.typ)
  1078. let rc = case n[0].sym.name.s:
  1079. of "getType": 0
  1080. of "typeKind": 1
  1081. of "getTypeInst": 2
  1082. else: 3 # "getTypeImpl"
  1083. c.gABC(n, opcNGetType, dest, tmp, rc)
  1084. c.freeTemp(tmp)
  1085. #genUnaryABC(c, n, dest, opcNGetType)
  1086. of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
  1087. of mNSetIntVal:
  1088. unused(c, n, dest)
  1089. genBinaryStmt(c, n, opcNSetIntVal)
  1090. of mNSetFloatVal:
  1091. unused(c, n, dest)
  1092. genBinaryStmt(c, n, opcNSetFloatVal)
  1093. of mNSetSymbol:
  1094. unused(c, n, dest)
  1095. genBinaryStmt(c, n, opcNSetSymbol)
  1096. of mNSetIdent:
  1097. unused(c, n, dest)
  1098. genBinaryStmt(c, n, opcNSetIdent)
  1099. of mNSetType:
  1100. unused(c, n, dest)
  1101. genBinaryStmt(c, n, opcNSetType)
  1102. of mNSetStrVal:
  1103. unused(c, n, dest)
  1104. genBinaryStmt(c, n, opcNSetStrVal)
  1105. of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
  1106. of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
  1107. of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree)
  1108. of mNBindSym: genBindSym(c, n, dest)
  1109. of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
  1110. of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
  1111. of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimNode)
  1112. of mSameNodeType: genBinaryABC(c, n, dest, opcSameNodeType)
  1113. of mNLineInfo:
  1114. case n[0].sym.name.s
  1115. of "getFile": genUnaryABI(c, n, dest, opcNGetLineInfo, 0)
  1116. of "getLine": genUnaryABI(c, n, dest, opcNGetLineInfo, 1)
  1117. of "getColumn": genUnaryABI(c, n, dest, opcNGetLineInfo, 2)
  1118. of "copyLineInfo":
  1119. internalAssert c.config, n.len == 3
  1120. unused(c, n, dest)
  1121. genBinaryStmt(c, n, opcNSetLineInfo)
  1122. else: internalAssert c.config, false
  1123. of mNHint:
  1124. unused(c, n, dest)
  1125. genBinaryStmt(c, n, opcNHint)
  1126. of mNWarning:
  1127. unused(c, n, dest)
  1128. genBinaryStmt(c, n, opcNWarning)
  1129. of mNError:
  1130. if n.len <= 1:
  1131. # query error condition:
  1132. c.gABC(n, opcQueryErrorFlag, dest)
  1133. else:
  1134. # setter
  1135. unused(c, n, dest)
  1136. genBinaryStmt(c, n, opcNError)
  1137. of mNCallSite:
  1138. if dest < 0: dest = c.getTemp(n.typ)
  1139. c.gABC(n, opcCallSite, dest)
  1140. of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
  1141. of mMinI, mMaxI, mAbsF64, mMinF64, mMaxF64, mAbsI,
  1142. mDotDot:
  1143. c.genCall(n, dest)
  1144. of mExpandToAst:
  1145. if n.len != 2:
  1146. globalError(c.config, n.info, "expandToAst requires 1 argument")
  1147. let arg = n.sons[1]
  1148. if arg.kind in nkCallKinds:
  1149. #if arg[0].kind != nkSym or arg[0].sym.kind notin {skTemplate, skMacro}:
  1150. # "ExpandToAst: expanded symbol is no macro or template"
  1151. if dest < 0: dest = c.getTemp(n.typ)
  1152. c.genCall(arg, dest)
  1153. # do not call clearDest(n, dest) here as getAst has a meta-type as such
  1154. # produces a value
  1155. else:
  1156. globalError(c.config, n.info, "expandToAst requires a call expression")
  1157. of mSizeOf, mAlignOf:
  1158. globalError(c.config, n.info, "cannot evaluate 'sizeof/alignof' because its type is not defined completely")
  1159. of mRunnableExamples:
  1160. discard "just ignore any call to runnableExamples"
  1161. else:
  1162. # mGCref, mGCunref,
  1163. globalError(c.config, n.info, "cannot generate code for: " & $m)
  1164. proc genMarshalLoad(c: PCtx, n: PNode, dest: var TDest) =
  1165. ## Signature: proc to*[T](data: string): T
  1166. if dest < 0: dest = c.getTemp(n.typ)
  1167. var tmp = c.genx(n.sons[1])
  1168. c.gABC(n, opcMarshalLoad, dest, tmp)
  1169. c.gABx(n, opcMarshalLoad, 0, c.genType(n.typ))
  1170. c.freeTemp(tmp)
  1171. proc genMarshalStore(c: PCtx, n: PNode, dest: var TDest) =
  1172. ## Signature: proc `$$`*[T](x: T): string
  1173. if dest < 0: dest = c.getTemp(n.typ)
  1174. var tmp = c.genx(n.sons[1])
  1175. c.gABC(n, opcMarshalStore, dest, tmp)
  1176. c.gABx(n, opcMarshalStore, 0, c.genType(n.sons[1].typ))
  1177. c.freeTemp(tmp)
  1178. const
  1179. atomicTypes = {tyBool, tyChar,
  1180. tyExpr, tyStmt, tyTypeDesc, tyStatic,
  1181. tyEnum,
  1182. tyOrdinal,
  1183. tyRange,
  1184. tyProc,
  1185. tyPointer, tyOpenArray,
  1186. tyString, tyCString,
  1187. tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
  1188. tyFloat, tyFloat32, tyFloat64, tyFloat128,
  1189. tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
  1190. proc fitsRegister*(t: PType): bool =
  1191. assert t != nil
  1192. t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
  1193. tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
  1194. proc unneededIndirection(n: PNode): bool =
  1195. n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
  1196. proc canElimAddr(n: PNode): PNode =
  1197. case n.sons[0].kind
  1198. of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
  1199. var m = n.sons[0].sons[0]
  1200. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1201. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1202. result = copyNode(n.sons[0])
  1203. result.add m.sons[0]
  1204. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1205. var m = n.sons[0].sons[1]
  1206. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1207. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1208. result = copyNode(n.sons[0])
  1209. result.add m.sons[0]
  1210. else:
  1211. if n.sons[0].kind in {nkDerefExpr, nkHiddenDeref}:
  1212. # addr ( deref ( x )) --> x
  1213. result = n.sons[0].sons[0]
  1214. proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
  1215. if (let m = canElimAddr(n); m != nil):
  1216. gen(c, m, dest, flags)
  1217. return
  1218. let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode}
  1219. else: {gfNodeAddr}
  1220. let newflags = flags-{gfNode, gfNodeAddr}+af
  1221. if isGlobal(n.sons[0]):
  1222. gen(c, n.sons[0], dest, flags+af)
  1223. else:
  1224. let tmp = c.genx(n.sons[0], newflags)
  1225. if dest < 0: dest = c.getTemp(n.typ)
  1226. if c.prc.slots[tmp].kind >= slotTempUnknown:
  1227. gABC(c, n, opcAddrNode, dest, tmp)
  1228. # hack ahead; in order to fix bug #1781 we mark the temporary as
  1229. # permanent, so that it's not used for anything else:
  1230. c.prc.slots[tmp].kind = slotTempPerm
  1231. # XXX this is still a hack
  1232. #message(n.info, warnUser, "suspicious opcode used")
  1233. else:
  1234. gABC(c, n, opcAddrReg, dest, tmp)
  1235. c.freeTemp(tmp)
  1236. proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
  1237. if unneededIndirection(n.sons[0]):
  1238. gen(c, n.sons[0], dest, flags)
  1239. if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
  1240. c.gABC(n, opcNodeToReg, dest, dest)
  1241. else:
  1242. let tmp = c.genx(n.sons[0], flags)
  1243. if dest < 0: dest = c.getTemp(n.typ)
  1244. gABC(c, n, opcLdDeref, dest, tmp)
  1245. assert n.typ != nil
  1246. if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
  1247. c.gABC(n, opcNodeToReg, dest, dest)
  1248. proc whichAsgnOpc(n: PNode): TOpcode =
  1249. case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
  1250. of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
  1251. opcAsgnInt
  1252. of tyString, tyCString:
  1253. opcAsgnStr
  1254. of tyFloat..tyFloat128:
  1255. opcAsgnFloat
  1256. of tyRef, tyNil, tyVar, tyLent, tyPtr:
  1257. opcAsgnRef
  1258. else:
  1259. opcAsgnComplex
  1260. proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc
  1261. proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
  1262. let tmp = c.genx(ri)
  1263. assert dest >= 0
  1264. gABC(c, ri, whichAsgnOpc(ri), dest, tmp, 1-ord(requiresCopy))
  1265. c.freeTemp(tmp)
  1266. proc setSlot(c: PCtx; v: PSym) =
  1267. # XXX generate type initialization here?
  1268. if v.position == 0:
  1269. if c.prc.maxSlots == 0: c.prc.maxSlots = 1
  1270. if c.prc.maxSlots >= high(TRegister):
  1271. globalError(c.config, v.info, "cannot generate code; too many registers required")
  1272. v.position = c.prc.maxSlots
  1273. c.prc.slots[v.position] = (inUse: true,
  1274. kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
  1275. inc c.prc.maxSlots
  1276. proc cannotEval(c: PCtx; n: PNode) {.noinline.} =
  1277. globalError(c.config, n.info, "cannot evaluate at compile time: " &
  1278. n.renderTree)
  1279. proc isOwnedBy(a, b: PSym): bool =
  1280. var a = a.owner
  1281. while a != nil and a.kind != skModule:
  1282. if a == b: return true
  1283. a = a.owner
  1284. proc getOwner(c: PCtx): PSym =
  1285. result = c.prc.sym
  1286. if result.isNil: result = c.module
  1287. proc checkCanEval(c: PCtx; n: PNode) =
  1288. # we need to ensure that we don't evaluate 'x' here:
  1289. # proc foo() = var x ...
  1290. let s = n.sym
  1291. if {sfCompileTime, sfGlobal} <= s.flags: return
  1292. if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
  1293. not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
  1294. cannotEval(c, n)
  1295. elif s.kind in {skProc, skFunc, skConverter, skMethod,
  1296. skIterator} and sfForward in s.flags:
  1297. cannotEval(c, n)
  1298. proc isTemp(c: PCtx; dest: TDest): bool =
  1299. result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
  1300. template needsAdditionalCopy(n): untyped =
  1301. not c.isTemp(dest) and not fitsRegister(n.typ)
  1302. proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode;
  1303. dest, idx, value: TRegister) =
  1304. var cc = c.getTemp(n.typ)
  1305. c.gABC(n, whichAsgnOpc(n), cc, value, 0)
  1306. c.gABC(n, opc, dest, idx, cc)
  1307. c.freeTemp(cc)
  1308. proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
  1309. dest, idx, value: TRegister) =
  1310. # opcLdObj et al really means "load address". We sometimes have to create a
  1311. # copy in order to not introduce false aliasing:
  1312. # mylocal = a.b # needs a copy of the data!
  1313. assert n.typ != nil
  1314. if needsAdditionalCopy(n):
  1315. genAdditionalCopy(c, n, opc, dest, idx, value)
  1316. else:
  1317. c.gABC(n, opc, dest, idx, value)
  1318. proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
  1319. case le.kind
  1320. of nkBracketExpr:
  1321. let dest = c.genx(le.sons[0], {gfNode})
  1322. let idx = c.genIndex(le.sons[1], le.sons[0].typ)
  1323. let tmp = c.genx(ri)
  1324. if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
  1325. tyString, tyCString}:
  1326. c.preventFalseAlias(le, opcWrStrIdx, dest, idx, tmp)
  1327. else:
  1328. c.preventFalseAlias(le, opcWrArr, dest, idx, tmp)
  1329. c.freeTemp(tmp)
  1330. of nkCheckedFieldExpr:
  1331. var objR: TDest = -1
  1332. genCheckedObjAccessAux(c, le, objR, {gfNode})
  1333. let idx = genField(c, le[0].sons[1])
  1334. let tmp = c.genx(ri)
  1335. c.preventFalseAlias(le[0], opcWrObj, objR, idx, tmp)
  1336. c.freeTemp(tmp)
  1337. c.freeTemp(objR)
  1338. of nkDotExpr:
  1339. let dest = c.genx(le.sons[0], {gfNode})
  1340. let idx = genField(c, le.sons[1])
  1341. let tmp = c.genx(ri)
  1342. c.preventFalseAlias(le, opcWrObj, dest, idx, tmp)
  1343. c.freeTemp(tmp)
  1344. of nkDerefExpr, nkHiddenDeref:
  1345. let dest = c.genx(le.sons[0], {gfNode})
  1346. let tmp = c.genx(ri)
  1347. c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
  1348. c.freeTemp(tmp)
  1349. of nkSym:
  1350. let s = le.sym
  1351. checkCanEval(c, le)
  1352. if s.isGlobal:
  1353. withTemp(tmp, le.typ):
  1354. c.gen(le, tmp, {gfNodeAddr})
  1355. let val = c.genx(ri)
  1356. c.preventFalseAlias(le, opcWrDeref, tmp, 0, val)
  1357. c.freeTemp(val)
  1358. else:
  1359. if s.kind == skForVar: c.setSlot s
  1360. internalAssert c.config, s.position > 0 or (s.position == 0 and
  1361. s.kind in {skParam,skResult})
  1362. var dest: TRegister = s.position + ord(s.kind == skParam)
  1363. assert le.typ != nil
  1364. if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}:
  1365. var cc = c.getTemp(le.typ)
  1366. gen(c, ri, cc)
  1367. c.gABC(le, whichAsgnOpc(le), dest, cc, 1)
  1368. c.freeTemp(cc)
  1369. else:
  1370. gen(c, ri, dest)
  1371. else:
  1372. let dest = c.genx(le, {gfNodeAddr})
  1373. genAsgn(c, dest, ri, requiresCopy)
  1374. proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
  1375. var n = newNode(nkType)
  1376. n.typ = t
  1377. genLit(c, n, dest)
  1378. proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
  1379. when hasFFI:
  1380. if allowFFI in c.features:
  1381. c.globals.add(importcSymbol(s))
  1382. s.position = c.globals.len
  1383. else:
  1384. localError(c.config, info, "VM is not allowed to 'importc'")
  1385. else:
  1386. localError(c.config, info,
  1387. "cannot 'importc' variable at compile time")
  1388. proc getNullValue*(typ: PType, info: TLineInfo; conf: ConfigRef): PNode
  1389. proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
  1390. c.globals.add(getNullValue(s.typ, n.info, c.config))
  1391. s.position = c.globals.len
  1392. # This is rather hard to support, due to the laziness of the VM code
  1393. # generator. See tests/compile/tmacro2 for why this is necessary:
  1394. # var decls{.compileTime.}: seq[NimNode] = @[]
  1395. let dest = c.getTemp(s.typ)
  1396. c.gABx(n, opcLdGlobal, dest, s.position)
  1397. if s.ast != nil:
  1398. let tmp = c.genx(s.ast)
  1399. c.genAdditionalCopy(n, opcWrDeref, dest, 0, tmp)
  1400. c.freeTemp(dest)
  1401. c.freeTemp(tmp)
  1402. proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1403. # gfNodeAddr and gfNode are mutually exclusive
  1404. assert card(flags * {gfNodeAddr, gfNode}) < 2
  1405. let s = n.sym
  1406. if s.isGlobal:
  1407. if sfCompileTime in s.flags or c.mode == emRepl:
  1408. discard
  1409. elif s.position == 0:
  1410. cannotEval(c, n)
  1411. if s.position == 0:
  1412. if sfImportc in s.flags: c.importcSym(n.info, s)
  1413. else: genGlobalInit(c, n, s)
  1414. if dest < 0: dest = c.getTemp(n.typ)
  1415. assert s.typ != nil
  1416. if gfNodeAddr in flags:
  1417. c.gABx(n, opcLdGlobalAddr, dest, s.position)
  1418. elif fitsRegister(s.typ) and gfNode notin flags:
  1419. var cc = c.getTemp(n.typ)
  1420. c.gABx(n, opcLdGlobal, cc, s.position)
  1421. c.gABC(n, opcNodeToReg, dest, cc)
  1422. c.freeTemp(cc)
  1423. else:
  1424. c.gABx(n, opcLdGlobal, dest, s.position)
  1425. else:
  1426. if s.kind == skForVar and c.mode == emRepl: c.setSlot(s)
  1427. if s.position > 0 or (s.position == 0 and
  1428. s.kind in {skParam,skResult}):
  1429. if dest < 0:
  1430. dest = s.position + ord(s.kind == skParam)
  1431. internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp)
  1432. else:
  1433. # we need to generate an assignment:
  1434. genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
  1435. else:
  1436. # see tests/t99bott for an example that triggers it:
  1437. cannotEval(c, n)
  1438. template needsRegLoad(): untyped =
  1439. {gfNode, gfNodeAddr} * flags == {} and
  1440. fitsRegister(n.typ.skipTypes({tyVar, tyLent, tyStatic}))
  1441. proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
  1442. flags: TGenFlags) =
  1443. let a = c.genx(n.sons[0], flags)
  1444. let b = c.genIndex(n.sons[1], n.sons[0].typ)
  1445. if dest < 0: dest = c.getTemp(n.typ)
  1446. if needsRegLoad():
  1447. var cc = c.getTemp(n.typ)
  1448. c.gABC(n, opc, cc, a, b)
  1449. c.gABC(n, opcNodeToReg, dest, cc)
  1450. c.freeTemp(cc)
  1451. else:
  1452. #message(n.info, warnUser, "argh")
  1453. #echo "FLAGS ", flags, " ", fitsRegister(n.typ), " ", typeToString(n.typ)
  1454. c.gABC(n, opc, dest, a, b)
  1455. c.freeTemp(a)
  1456. c.freeTemp(b)
  1457. proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1458. let a = c.genx(n.sons[0], flags)
  1459. let b = genField(c, n.sons[1])
  1460. if dest < 0: dest = c.getTemp(n.typ)
  1461. if needsRegLoad():
  1462. var cc = c.getTemp(n.typ)
  1463. c.gABC(n, opcLdObj, cc, a, b)
  1464. c.gABC(n, opcNodeToReg, dest, cc)
  1465. c.freeTemp(cc)
  1466. else:
  1467. c.gABC(n, opcLdObj, dest, a, b)
  1468. c.freeTemp(a)
  1469. proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1470. internalAssert c.config, n.kind == nkCheckedFieldExpr
  1471. # nkDotExpr to access the requested field
  1472. let accessExpr = n[0]
  1473. # nkCall to check if the discriminant is valid
  1474. var checkExpr = n[1]
  1475. let negCheck = checkExpr[0].sym.magic == mNot
  1476. if negCheck:
  1477. checkExpr = checkExpr[^1]
  1478. # Discriminant symbol
  1479. let disc = checkExpr[2]
  1480. internalAssert c.config, disc.sym.kind == skField
  1481. # Load the object in `dest`
  1482. c.gen(accessExpr[0], dest, flags)
  1483. # Load the discriminant
  1484. var discVal = c.getTemp(disc.typ)
  1485. c.gABC(n, opcLdObj, discVal, dest, genField(c, disc))
  1486. # Check if its value is contained in the supplied set
  1487. let setLit = c.genx(checkExpr[1])
  1488. var rs = c.getTemp(getSysType(c.graph, n.info, tyBool))
  1489. c.gABC(n, opcContainsSet, rs, setLit, discVal)
  1490. c.freeTemp(setLit)
  1491. # If the check fails let the user know
  1492. let L1 = c.xjmp(n, if negCheck: opcFJmp else: opcTJmp, rs)
  1493. c.freeTemp(rs)
  1494. # Not ideal but will do for the moment
  1495. c.gABC(n, opcQuit)
  1496. c.patch(L1)
  1497. proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1498. var objR: TDest = -1
  1499. genCheckedObjAccessAux(c, n, objR, flags)
  1500. let accessExpr = n[0]
  1501. # Field symbol
  1502. var field = accessExpr[1]
  1503. internalAssert c.config, field.sym.kind == skField
  1504. # Load the content now
  1505. if dest < 0: dest = c.getTemp(n.typ)
  1506. let fieldPos = genField(c, field)
  1507. if needsRegLoad():
  1508. var cc = c.getTemp(accessExpr.typ)
  1509. c.gABC(n, opcLdObj, cc, objR, fieldPos)
  1510. c.gABC(n, opcNodeToReg, dest, cc)
  1511. c.freeTemp(cc)
  1512. else:
  1513. c.gABC(n, opcLdObj, dest, objR, fieldPos)
  1514. c.freeTemp(objR)
  1515. proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
  1516. let arrayType = n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
  1517. if arrayType in {tyString, tyCString}:
  1518. genArrAccess2(c, n, dest, opcLdStrIdx, {})
  1519. elif arrayType == tyTypeDesc:
  1520. c.genTypeLit(n.typ, dest)
  1521. else:
  1522. genArrAccess2(c, n, dest, opcLdArr, flags)
  1523. proc getNullValueAux(obj: PNode, result: PNode; conf: ConfigRef) =
  1524. case obj.kind
  1525. of nkRecList:
  1526. for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result, conf)
  1527. of nkRecCase:
  1528. getNullValueAux(obj.sons[0], result, conf)
  1529. for i in countup(1, sonsLen(obj) - 1):
  1530. getNullValueAux(lastSon(obj.sons[i]), result, conf)
  1531. of nkSym:
  1532. let field = newNodeI(nkExprColonExpr, result.info)
  1533. field.add(obj)
  1534. field.add(getNullValue(obj.sym.typ, result.info, conf))
  1535. addSon(result, field)
  1536. else: globalError(conf, result.info, "cannot create null element for: " & $obj)
  1537. proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
  1538. var t = skipTypes(typ, abstractRange+{tyStatic}-{tyTypeDesc})
  1539. case t.kind
  1540. of tyBool, tyEnum, tyChar, tyInt..tyInt64:
  1541. result = newNodeIT(nkIntLit, info, t)
  1542. of tyUInt..tyUInt64:
  1543. result = newNodeIT(nkUIntLit, info, t)
  1544. of tyFloat..tyFloat128:
  1545. result = newNodeIT(nkFloatLit, info, t)
  1546. of tyCString, tyString:
  1547. result = newNodeIT(nkStrLit, info, t)
  1548. result.strVal = ""
  1549. of tyVar, tyLent, tyPointer, tyPtr, tyExpr,
  1550. tyStmt, tyTypeDesc, tyRef, tyNil:
  1551. result = newNodeIT(nkNilLit, info, t)
  1552. of tyProc:
  1553. if t.callConv != ccClosure:
  1554. result = newNodeIT(nkNilLit, info, t)
  1555. else:
  1556. result = newNodeIT(nkTupleConstr, info, t)
  1557. result.add(newNodeIT(nkNilLit, info, t))
  1558. result.add(newNodeIT(nkNilLit, info, t))
  1559. of tyObject:
  1560. result = newNodeIT(nkObjConstr, info, t)
  1561. result.add(newNodeIT(nkEmpty, info, t))
  1562. # initialize inherited fields:
  1563. var base = t.sons[0]
  1564. while base != nil:
  1565. getNullValueAux(skipTypes(base, skipPtrs).n, result, conf)
  1566. base = base.sons[0]
  1567. getNullValueAux(t.n, result, conf)
  1568. of tyArray:
  1569. result = newNodeIT(nkBracket, info, t)
  1570. for i in countup(0, int(lengthOrd(conf, t)) - 1):
  1571. addSon(result, getNullValue(elemType(t), info, conf))
  1572. of tyTuple:
  1573. result = newNodeIT(nkTupleConstr, info, t)
  1574. for i in countup(0, sonsLen(t) - 1):
  1575. addSon(result, getNullValue(t.sons[i], info, conf))
  1576. of tySet:
  1577. result = newNodeIT(nkCurly, info, t)
  1578. of tyOpt:
  1579. result = newNodeIT(nkNilLit, info, t)
  1580. of tySequence:
  1581. result = newNodeIT(nkBracket, info, t)
  1582. else:
  1583. globalError(conf, info, "cannot create null element for: " & $t.kind)
  1584. result = newNodeI(nkEmpty, info)
  1585. proc ldNullOpcode(t: PType): TOpcode =
  1586. assert t != nil
  1587. if fitsRegister(t): opcLdNullReg else: opcLdNull
  1588. proc genVarSection(c: PCtx; n: PNode) =
  1589. for a in n:
  1590. if a.kind == nkCommentStmt: continue
  1591. #assert(a.sons[0].kind == nkSym) can happen for transformed vars
  1592. if a.kind == nkVarTuple:
  1593. for i in 0 .. a.len-3:
  1594. if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
  1595. checkCanEval(c, a[i])
  1596. c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner))
  1597. elif a.sons[0].kind == nkSym:
  1598. let s = a.sons[0].sym
  1599. checkCanEval(c, a.sons[0])
  1600. if s.isGlobal:
  1601. if s.position == 0:
  1602. if sfImportc in s.flags: c.importcSym(a.info, s)
  1603. else:
  1604. let sa = getNullValue(s.typ, a.info, c.config)
  1605. #if s.ast.isNil: getNullValue(s.typ, a.info)
  1606. #else: canonValue(s.ast)
  1607. assert sa.kind != nkCall
  1608. c.globals.add(sa)
  1609. s.position = c.globals.len
  1610. if a.sons[2].kind != nkEmpty:
  1611. let tmp = c.genx(a.sons[0], {gfNodeAddr})
  1612. let val = c.genx(a.sons[2])
  1613. c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
  1614. c.freeTemp(val)
  1615. c.freeTemp(tmp)
  1616. else:
  1617. setSlot(c, s)
  1618. if a.sons[2].kind == nkEmpty:
  1619. c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
  1620. else:
  1621. assert s.typ != nil
  1622. if not fitsRegister(s.typ):
  1623. c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
  1624. let le = a.sons[0]
  1625. assert le.typ != nil
  1626. if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
  1627. var cc = c.getTemp(le.typ)
  1628. gen(c, a.sons[2], cc)
  1629. c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc, 1)
  1630. c.freeTemp(cc)
  1631. else:
  1632. gen(c, a.sons[2], s.position.TRegister)
  1633. else:
  1634. # assign to a.sons[0]; happens for closures
  1635. if a.sons[2].kind == nkEmpty:
  1636. let tmp = genx(c, a.sons[0])
  1637. c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a.sons[0].typ))
  1638. c.freeTemp(tmp)
  1639. else:
  1640. genAsgn(c, a.sons[0], a.sons[2], true)
  1641. proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
  1642. if dest < 0: dest = c.getTemp(n.typ)
  1643. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1644. let intType = getSysType(c.graph, n.info, tyInt)
  1645. let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
  1646. if seqType.kind == tySequence:
  1647. var tmp = c.getTemp(intType)
  1648. c.gABx(n, opcLdImmInt, tmp, n.len)
  1649. c.gABx(n, opcNewSeq, dest, c.genType(seqType))
  1650. c.gABx(n, opcNewSeq, tmp, 0)
  1651. c.freeTemp(tmp)
  1652. if n.len > 0:
  1653. var tmp = getTemp(c, intType)
  1654. c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
  1655. for x in n:
  1656. let a = c.genx(x)
  1657. c.preventFalseAlias(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
  1658. c.gABI(n, opcAddImmInt, tmp, tmp, 1)
  1659. c.freeTemp(a)
  1660. c.freeTemp(tmp)
  1661. proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
  1662. if dest < 0: dest = c.getTemp(n.typ)
  1663. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1664. for x in n:
  1665. if x.kind == nkRange:
  1666. let a = c.genx(x.sons[0])
  1667. let b = c.genx(x.sons[1])
  1668. c.gABC(n, opcInclRange, dest, a, b)
  1669. c.freeTemp(b)
  1670. c.freeTemp(a)
  1671. else:
  1672. let a = c.genx(x)
  1673. c.gABC(n, opcIncl, dest, a)
  1674. c.freeTemp(a)
  1675. proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
  1676. if dest < 0: dest = c.getTemp(n.typ)
  1677. let t = n.typ.skipTypes(abstractRange-{tyTypeDesc})
  1678. if t.kind == tyRef:
  1679. c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
  1680. else:
  1681. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1682. for i in 1..<n.len:
  1683. let it = n.sons[i]
  1684. if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
  1685. let idx = genField(c, it.sons[0])
  1686. let tmp = c.genx(it.sons[1])
  1687. c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
  1688. dest, idx, tmp)
  1689. c.freeTemp(tmp)
  1690. else:
  1691. globalError(c.config, n.info, "invalid object constructor")
  1692. proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
  1693. if dest < 0: dest = c.getTemp(n.typ)
  1694. c.gABx(n, opcLdNull, dest, c.genType(n.typ))
  1695. # XXX x = (x.old, 22) produces wrong code ... stupid self assignments
  1696. for i in 0..<n.len:
  1697. let it = n.sons[i]
  1698. if it.kind == nkExprColonExpr:
  1699. let idx = genField(c, it.sons[0])
  1700. let tmp = c.genx(it.sons[1])
  1701. c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
  1702. dest, idx, tmp)
  1703. c.freeTemp(tmp)
  1704. else:
  1705. let tmp = c.genx(it)
  1706. c.preventFalseAlias(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
  1707. c.freeTemp(tmp)
  1708. proc genProc*(c: PCtx; s: PSym): int
  1709. proc matches(s: PSym; x: string): bool =
  1710. let y = x.split('.')
  1711. var s = s
  1712. var L = y.len-1
  1713. while L >= 0:
  1714. if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
  1715. return false
  1716. s = s.owner
  1717. dec L
  1718. result = true
  1719. proc matches(s: PSym; y: varargs[string]): bool =
  1720. var s = s
  1721. var L = y.len-1
  1722. while L >= 0:
  1723. if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"):
  1724. return false
  1725. s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner
  1726. dec L
  1727. result = true
  1728. proc procIsCallback(c: PCtx; s: PSym): bool =
  1729. if s.offset < -1: return true
  1730. var i = -2
  1731. for key, value in items(c.callbacks):
  1732. if s.matches(key):
  1733. doAssert s.offset == -1
  1734. s.offset = i
  1735. return true
  1736. dec i
  1737. proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
  1738. case n.kind
  1739. of nkSym:
  1740. let s = n.sym
  1741. checkCanEval(c, n)
  1742. case s.kind
  1743. of skVar, skForVar, skTemp, skLet, skParam, skResult:
  1744. genRdVar(c, n, dest, flags)
  1745. of skProc, skFunc, skConverter, skMacro, skTemplate, skMethod, skIterator:
  1746. # 'skTemplate' is only allowed for 'getAst' support:
  1747. if procIsCallback(c, s): discard
  1748. elif sfImportc in s.flags: c.importcSym(n.info, s)
  1749. genLit(c, n, dest)
  1750. of skConst:
  1751. let constVal = if s.ast != nil: s.ast else: s.typ.n
  1752. gen(c, constVal, dest)
  1753. of skEnumField:
  1754. # we never reach this case - as of the time of this comment,
  1755. # skEnumField is folded to an int in semfold.nim, but this code
  1756. # remains for robustness
  1757. if dest < 0: dest = c.getTemp(n.typ)
  1758. if s.position >= low(int16) and s.position <= high(int16):
  1759. c.gABx(n, opcLdImmInt, dest, s.position)
  1760. else:
  1761. var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
  1762. c.gABx(n, opcLdConst, dest, lit)
  1763. of skType:
  1764. genTypeLit(c, s.typ, dest)
  1765. of skGenericParam:
  1766. if c.prc.sym != nil and c.prc.sym.kind == skMacro:
  1767. genRdVar(c, n, dest, flags)
  1768. else:
  1769. globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
  1770. else:
  1771. globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
  1772. of nkCallKinds:
  1773. if n.sons[0].kind == nkSym:
  1774. let s = n.sons[0].sym
  1775. if s.magic != mNone:
  1776. genMagic(c, n, dest, s.magic)
  1777. elif s.kind == skMethod:
  1778. localError(c.config, n.info, "cannot call method " & s.name.s &
  1779. " at compile time")
  1780. elif matches(s, "stdlib", "marshal", "to"):
  1781. # XXX marshal load&store should not be opcodes, but use the
  1782. # general callback mechanisms.
  1783. genMarshalLoad(c, n, dest)
  1784. elif matches(s, "stdlib", "marshal", "$$"):
  1785. genMarshalStore(c, n, dest)
  1786. else:
  1787. genCall(c, n, dest)
  1788. clearDest(c, n, dest)
  1789. else:
  1790. genCall(c, n, dest)
  1791. clearDest(c, n, dest)
  1792. of nkCharLit..nkInt64Lit:
  1793. if isInt16Lit(n):
  1794. if dest < 0: dest = c.getTemp(n.typ)
  1795. c.gABx(n, opcLdImmInt, dest, n.intVal.int)
  1796. else:
  1797. genLit(c, n, dest)
  1798. of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
  1799. of nkNilLit:
  1800. if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info, c.config), dest)
  1801. else: unused(c, n, dest)
  1802. of nkAsgn, nkFastAsgn:
  1803. unused(c, n, dest)
  1804. genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
  1805. of nkDotExpr: genObjAccess(c, n, dest, flags)
  1806. of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
  1807. of nkBracketExpr: genArrAccess(c, n, dest, flags)
  1808. of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags)
  1809. of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags)
  1810. of nkIfStmt, nkIfExpr: genIf(c, n, dest)
  1811. of nkWhenStmt:
  1812. # This is "when nimvm" node. Chose the first branch.
  1813. gen(c, n.sons[0].sons[1], dest)
  1814. of nkCaseStmt: genCase(c, n, dest)
  1815. of nkWhileStmt:
  1816. unused(c, n, dest)
  1817. genWhile(c, n)
  1818. of nkBlockExpr, nkBlockStmt: genBlock(c, n, dest)
  1819. of nkReturnStmt:
  1820. unused(c, n, dest)
  1821. genReturn(c, n)
  1822. of nkRaiseStmt:
  1823. genRaise(c, n)
  1824. of nkBreakStmt:
  1825. unused(c, n, dest)
  1826. genBreak(c, n)
  1827. of nkTryStmt: genTry(c, n, dest)
  1828. of nkStmtList:
  1829. #unused(c, n, dest)
  1830. # XXX Fix this bug properly, lexim triggers it
  1831. for x in n: gen(c, x)
  1832. of nkStmtListExpr:
  1833. let L = n.len-1
  1834. for i in 0 ..< L: gen(c, n.sons[i])
  1835. gen(c, n.sons[L], dest, flags)
  1836. of nkPragmaBlock:
  1837. gen(c, n.lastSon, dest, flags)
  1838. of nkDiscardStmt:
  1839. unused(c, n, dest)
  1840. gen(c, n.sons[0])
  1841. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1842. genConv(c, n, n.sons[1], dest)
  1843. of nkObjDownConv:
  1844. genConv(c, n, n.sons[0], dest)
  1845. of nkVarSection, nkLetSection:
  1846. unused(c, n, dest)
  1847. genVarSection(c, n)
  1848. of declarativeDefs, nkMacroDef:
  1849. unused(c, n, dest)
  1850. of nkLambdaKinds:
  1851. #let s = n.sons[namePos].sym
  1852. #discard genProc(c, s)
  1853. genLit(c, newSymNode(n.sons[namePos].sym), dest)
  1854. of nkChckRangeF, nkChckRange64, nkChckRange:
  1855. let
  1856. tmp0 = c.genx(n.sons[0])
  1857. tmp1 = c.genx(n.sons[1])
  1858. tmp2 = c.genx(n.sons[2])
  1859. c.gABC(n, opcRangeChck, tmp0, tmp1, tmp2)
  1860. c.freeTemp(tmp1)
  1861. c.freeTemp(tmp2)
  1862. if dest >= 0:
  1863. gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1)
  1864. c.freeTemp(tmp0)
  1865. else:
  1866. dest = tmp0
  1867. of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
  1868. nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
  1869. unused(c, n, dest)
  1870. of nkStringToCString, nkCStringToString:
  1871. gen(c, n.sons[0], dest)
  1872. of nkBracket: genArrayConstr(c, n, dest)
  1873. of nkCurly: genSetConstr(c, n, dest)
  1874. of nkObjConstr: genObjConstr(c, n, dest)
  1875. of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest)
  1876. of nkCast:
  1877. if allowCast in c.features:
  1878. genConv(c, n, n.sons[1], dest, opcCast)
  1879. else:
  1880. genCastIntFloat(c, n, dest)
  1881. of nkTypeOfExpr:
  1882. genTypeLit(c, n.typ, dest)
  1883. of nkComesFrom:
  1884. discard "XXX to implement for better stack traces"
  1885. else:
  1886. globalError(c.config, n.info, "cannot generate VM code for " & $n)
  1887. proc removeLastEof(c: PCtx) =
  1888. let last = c.code.len-1
  1889. if last >= 0 and c.code[last].opcode == opcEof:
  1890. # overwrite last EOF:
  1891. assert c.code.len == c.debug.len
  1892. c.code.setLen(last)
  1893. c.debug.setLen(last)
  1894. proc genStmt*(c: PCtx; n: PNode): int =
  1895. c.removeLastEof
  1896. result = c.code.len
  1897. var d: TDest = -1
  1898. c.gen(n, d)
  1899. c.gABC(n, opcEof)
  1900. if d >= 0:
  1901. globalError(c.config, n.info, "VM problem: dest register is set")
  1902. proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
  1903. c.removeLastEof
  1904. result = c.code.len
  1905. var d: TDest = -1
  1906. c.gen(n, d)
  1907. if d < 0:
  1908. if requiresValue:
  1909. globalError(c.config, n.info, "VM problem: dest register is not set")
  1910. d = 0
  1911. c.gABC(n, opcEof, d)
  1912. #echo renderTree(n)
  1913. #c.echoCode(result)
  1914. proc genParams(c: PCtx; params: PNode) =
  1915. # res.sym.position is already 0
  1916. c.prc.slots[0] = (inUse: true, kind: slotFixedVar)
  1917. for i in 1..<params.len:
  1918. c.prc.slots[i] = (inUse: true, kind: slotFixedLet)
  1919. c.prc.maxSlots = max(params.len, 1)
  1920. proc finalJumpTarget(c: PCtx; pc, diff: int) =
  1921. internalAssert(c.config, -0x7fff < diff and diff < 0x7fff)
  1922. let oldInstr = c.code[pc]
  1923. # opcode and regA stay the same:
  1924. c.code[pc] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
  1925. uint32(diff+wordExcess) shl 16'u32).TInstr
  1926. proc genGenericParams(c: PCtx; gp: PNode) =
  1927. var base = c.prc.maxSlots
  1928. for i in 0..<gp.len:
  1929. var param = gp.sons[i].sym
  1930. param.position = base + i # XXX: fix this earlier; make it consistent with templates
  1931. c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet)
  1932. c.prc.maxSlots = base + gp.len
  1933. proc optimizeJumps(c: PCtx; start: int) =
  1934. const maxIterations = 10
  1935. for i in start ..< c.code.len:
  1936. let opc = c.code[i].opcode
  1937. case opc
  1938. of opcTJmp, opcFJmp:
  1939. var reg = c.code[i].regA
  1940. var d = i + c.code[i].jmpDiff
  1941. for iters in countdown(maxIterations, 0):
  1942. case c.code[d].opcode
  1943. of opcJmp, opcJmpBack:
  1944. d = d + c.code[d].jmpDiff
  1945. of opcTJmp, opcFJmp:
  1946. if c.code[d].regA != reg: break
  1947. # tjmp x, 23
  1948. # ...
  1949. # tjmp x, 12
  1950. # -- we know 'x' is true, and so can jump to 12+13:
  1951. if c.code[d].opcode == opc:
  1952. d = d + c.code[d].jmpDiff
  1953. else:
  1954. # tjmp x, 23
  1955. # fjmp x, 22
  1956. # We know 'x' is true so skip to the next instruction:
  1957. d = d + 1
  1958. else: break
  1959. if d != i + c.code[i].jmpDiff:
  1960. c.finalJumpTarget(i, d - i)
  1961. of opcJmp, opcJmpBack:
  1962. var d = i + c.code[i].jmpDiff
  1963. var iters = maxIterations
  1964. while c.code[d].opcode == opcJmp and iters > 0:
  1965. d = d + c.code[d].jmpDiff
  1966. dec iters
  1967. if c.code[d].opcode == opcRet:
  1968. # optimize 'jmp to ret' to 'ret' here
  1969. c.code[i] = c.code[d]
  1970. elif d != i + c.code[i].jmpDiff:
  1971. c.finalJumpTarget(i, d - i)
  1972. else: discard
  1973. proc genProc(c: PCtx; s: PSym): int =
  1974. var x = s.ast.sons[miscPos]
  1975. if x.kind == nkEmpty or x[0].kind == nkEmpty:
  1976. #if s.name.s == "outterMacro" or s.name.s == "innerProc":
  1977. # echo "GENERATING CODE FOR ", s.name.s
  1978. let last = c.code.len-1
  1979. var eofInstr: TInstr
  1980. if last >= 0 and c.code[last].opcode == opcEof:
  1981. eofInstr = c.code[last]
  1982. c.code.setLen(last)
  1983. c.debug.setLen(last)
  1984. #c.removeLastEof
  1985. result = c.code.len+1 # skip the jump instruction
  1986. if x.kind == nkEmpty:
  1987. x = newTree(nkBracket, newIntNode(nkIntLit, result), x)
  1988. else:
  1989. x.sons[0] = newIntNode(nkIntLit, result)
  1990. s.ast.sons[miscPos] = x
  1991. # thanks to the jmp we can add top level statements easily and also nest
  1992. # procs easily:
  1993. let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s))
  1994. let procStart = c.xjmp(body, opcJmp, 0)
  1995. var p = PProc(blocks: @[], sym: s)
  1996. let oldPrc = c.prc
  1997. c.prc = p
  1998. # iterate over the parameters and allocate space for them:
  1999. genParams(c, s.typ.n)
  2000. # allocate additional space for any generically bound parameters
  2001. if s.kind == skMacro and
  2002. sfImmediate notin s.flags and
  2003. s.ast[genericParamsPos].kind != nkEmpty:
  2004. genGenericParams(c, s.ast[genericParamsPos])
  2005. if tfCapturesEnv in s.typ.flags:
  2006. #let env = s.ast.sons[paramsPos].lastSon.sym
  2007. #assert env.position == 2
  2008. c.prc.slots[c.prc.maxSlots] = (inUse: true, kind: slotFixedLet)
  2009. inc c.prc.maxSlots
  2010. gen(c, body)
  2011. # generate final 'return' statement:
  2012. c.gABC(body, opcRet)
  2013. c.patch(procStart)
  2014. c.gABC(body, opcEof, eofInstr.regA)
  2015. c.optimizeJumps(result)
  2016. s.offset = c.prc.maxSlots
  2017. #if s.name.s == "calc":
  2018. # echo renderTree(body)
  2019. # c.echoCode(result)
  2020. c.prc = oldPrc
  2021. else:
  2022. c.prc.maxSlots = s.offset
  2023. result = x[0].intVal.int