vmgen.nim 75 KB

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