ast2ir.nim 89 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2023 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. import std / [assertions, tables, sets]
  10. import ".." / [ast, astalgo, types, options, lineinfos, msgs, magicsys,
  11. modulegraphs, renderer, transf, bitsets, trees, nimsets,
  12. expanddefaults]
  13. from ".." / lowerings import lowerSwap, lowerTupleUnpacking
  14. from ".." / pathutils import customPath
  15. import .. / ic / bitabs
  16. import nirtypes, nirinsts, nirlineinfos, nirslots, types2ir, nirfiles
  17. when defined(nimCompilerStacktraceHints):
  18. import std/stackframes
  19. type
  20. ModuleCon* = ref object
  21. nirm*: ref NirModule
  22. types: TypesCon
  23. module*: PSym
  24. graph*: ModuleGraph
  25. nativeIntId, nativeUIntId: TypeId
  26. strPayloadId: (TypeId, TypeId)
  27. idgen: IdGenerator
  28. processedProcs, pendingProcsAsSet: HashSet[ItemId]
  29. pendingProcs: seq[PSym] # procs we still need to generate code for
  30. pendingVarsAsSet: HashSet[ItemId]
  31. pendingVars: seq[PSym]
  32. noModularity*: bool
  33. inProc: int
  34. toSymId: Table[ItemId, SymId]
  35. symIdCounter: int32
  36. ProcCon* = object
  37. config*: ConfigRef
  38. lit: Literals
  39. lastFileKey: FileIndex
  40. lastFileVal: LitId
  41. labelGen: int
  42. exitLabel: LabelId
  43. #code*: Tree
  44. blocks: seq[(PSym, LabelId)]
  45. sm: SlotManager
  46. idgen: IdGenerator
  47. m: ModuleCon
  48. prc: PSym
  49. options: TOptions
  50. template code(c: ProcCon): Tree = c.m.nirm.code
  51. proc initModuleCon*(graph: ModuleGraph; config: ConfigRef; idgen: IdGenerator; module: PSym;
  52. nirm: ref NirModule): ModuleCon =
  53. #let lit = Literals() # must be shared
  54. result = ModuleCon(graph: graph, types: initTypesCon(config), nirm: nirm,
  55. idgen: idgen, module: module)
  56. case config.target.intSize
  57. of 2:
  58. result.nativeIntId = Int16Id
  59. result.nativeUIntId = UInt16Id
  60. of 4:
  61. result.nativeIntId = Int32Id
  62. result.nativeUIntId = UInt16Id
  63. else:
  64. result.nativeIntId = Int64Id
  65. result.nativeUIntId = UInt16Id
  66. result.strPayloadId = strPayloadPtrType(result.types, result.nirm.types)
  67. nirm.namespace = nirm.lit.strings.getOrIncl(customPath(toFullPath(config, module.info)))
  68. nirm.intbits = uint32(config.target.intSize * 8)
  69. proc initProcCon*(m: ModuleCon; prc: PSym; config: ConfigRef): ProcCon =
  70. result = ProcCon(m: m, sm: initSlotManager({}), prc: prc, config: config,
  71. lit: m.nirm.lit, idgen: m.idgen,
  72. options: if prc != nil: prc.options
  73. else: config.options)
  74. result.exitLabel = newLabel(result.labelGen)
  75. proc toLineInfo(c: var ProcCon; i: TLineInfo): PackedLineInfo =
  76. var val: LitId
  77. if c.lastFileKey == i.fileIndex:
  78. val = c.lastFileVal
  79. else:
  80. val = c.lit.strings.getOrIncl(toFullPath(c.config, i.fileIndex))
  81. # remember the entry:
  82. c.lastFileKey = i.fileIndex
  83. c.lastFileVal = val
  84. result = pack(c.m.nirm.man, val, int32 i.line, int32 i.col)
  85. proc bestEffort(c: ProcCon): TLineInfo =
  86. if c.prc != nil:
  87. c.prc.info
  88. else:
  89. c.m.module.info
  90. proc popBlock(c: var ProcCon; oldLen: int) =
  91. c.blocks.setLen(oldLen)
  92. template withBlock(labl: PSym; info: PackedLineInfo; asmLabl: LabelId; body: untyped) {.dirty.} =
  93. var oldLen {.gensym.} = c.blocks.len
  94. c.blocks.add (labl, asmLabl)
  95. body
  96. popBlock(c, oldLen)
  97. type
  98. GenFlag = enum
  99. gfAddrOf # load the address of the expression
  100. gfToOutParam # the expression is passed to an `out` parameter
  101. GenFlags = set[GenFlag]
  102. proc gen(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags = {})
  103. proc genScope(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags = {}) =
  104. openScope c.sm
  105. gen c, n, d, flags
  106. closeScope c.sm
  107. proc freeTemp(c: var ProcCon; tmp: Value) =
  108. let s = extractTemp(tmp)
  109. if s != SymId(-1):
  110. freeTemp(c.sm, s)
  111. proc freeTemps(c: var ProcCon; tmps: openArray[Value]) =
  112. for t in tmps: freeTemp(c, t)
  113. proc typeToIr(m: ModuleCon; t: PType): TypeId =
  114. typeToIr(m.types, m.nirm.types, t)
  115. proc allocTemp(c: var ProcCon; t: TypeId): SymId =
  116. if c.m.noModularity:
  117. result = allocTemp(c.sm, t, c.m.symIdCounter)
  118. else:
  119. result = allocTemp(c.sm, t, c.idgen.symId)
  120. const
  121. ListSymId = -1
  122. proc toSymId(c: var ProcCon; s: PSym): SymId =
  123. if c.m.noModularity:
  124. result = c.m.toSymId.getOrDefault(s.itemId, SymId(-1))
  125. if result.int < 0:
  126. inc c.m.symIdCounter
  127. result = SymId(c.m.symIdCounter)
  128. c.m.toSymId[s.itemId] = result
  129. when ListSymId != -1:
  130. if result.int == ListSymId or s.name.s == "echoBinSafe":
  131. echo result.int, " is ", s.name.s, " ", c.m.graph.config $ s.info, " ", s.flags
  132. writeStackTrace()
  133. else:
  134. result = SymId(s.itemId.item)
  135. proc getTemp(c: var ProcCon; n: PNode): Value =
  136. let info = toLineInfo(c, n.info)
  137. let t = typeToIr(c.m, n.typ)
  138. let tmp = allocTemp(c, t)
  139. c.code.addSummon info, tmp, t
  140. result = localToValue(info, tmp)
  141. proc getTemp(c: var ProcCon; t: TypeId; info: PackedLineInfo): Value =
  142. let tmp = allocTemp(c, t)
  143. c.code.addSummon info, tmp, t
  144. result = localToValue(info, tmp)
  145. proc gen(c: var ProcCon; n: PNode; flags: GenFlags = {}) =
  146. var tmp = default(Value)
  147. gen(c, n, tmp, flags)
  148. freeTemp c, tmp
  149. proc genScope(c: var ProcCon; n: PNode; flags: GenFlags = {}) =
  150. openScope c.sm
  151. gen c, n, flags
  152. closeScope c.sm
  153. proc genx(c: var ProcCon; n: PNode; flags: GenFlags = {}): Value =
  154. result = default(Value)
  155. gen(c, n, result, flags)
  156. assert Tree(result).len > 0, $n
  157. proc clearDest(c: var ProcCon; n: PNode; d: var Value) {.inline.} =
  158. when false:
  159. if n.typ.isNil or n.typ.kind == tyVoid:
  160. let s = extractTemp(d)
  161. if s != SymId(-1):
  162. freeLoc(c.sm, s)
  163. proc isNotOpr(n: PNode): bool =
  164. n.kind in nkCallKinds and n[0].kind == nkSym and n[0].sym.magic == mNot
  165. proc jmpBack(c: var ProcCon; n: PNode; lab: LabelId) =
  166. c.code.gotoLabel toLineInfo(c, n.info), GotoLoop, lab
  167. type
  168. JmpKind = enum opcFJmp, opcTJmp
  169. proc xjmp(c: var ProcCon; n: PNode; jk: JmpKind; v: Value): LabelId =
  170. result = newLabel(c.labelGen)
  171. let info = toLineInfo(c, n.info)
  172. buildTyped c.code, info, Select, Bool8Id:
  173. c.code.copyTree Tree(v)
  174. build c.code, info, SelectPair:
  175. build c.code, info, SelectValue:
  176. c.code.boolVal(c.lit.numbers, info, jk == opcTJmp)
  177. c.code.gotoLabel info, Goto, result
  178. proc patch(c: var ProcCon; n: PNode; L: LabelId) =
  179. addLabel c.code, toLineInfo(c, n.info), Label, L
  180. proc genWhile(c: var ProcCon; n: PNode) =
  181. # lab1:
  182. # cond, tmp
  183. # fjmp tmp, lab2
  184. # body
  185. # jmp lab1
  186. # lab2:
  187. let info = toLineInfo(c, n.info)
  188. let lab1 = c.code.addNewLabel(c.labelGen, info, LoopLabel)
  189. withBlock(nil, info, lab1):
  190. if isTrue(n[0]):
  191. c.gen(n[1])
  192. c.jmpBack(n, lab1)
  193. elif isNotOpr(n[0]):
  194. var tmp = c.genx(n[0][1])
  195. let lab2 = c.xjmp(n, opcTJmp, tmp)
  196. c.freeTemp(tmp)
  197. c.gen(n[1])
  198. c.jmpBack(n, lab1)
  199. c.patch(n, lab2)
  200. else:
  201. var tmp = c.genx(n[0])
  202. let lab2 = c.xjmp(n, opcFJmp, tmp)
  203. c.freeTemp(tmp)
  204. c.gen(n[1])
  205. c.jmpBack(n, lab1)
  206. c.patch(n, lab2)
  207. proc genBlock(c: var ProcCon; n: PNode; d: var Value) =
  208. openScope c.sm
  209. let info = toLineInfo(c, n.info)
  210. let lab1 = newLabel(c.labelGen)
  211. withBlock(n[0].sym, info, lab1):
  212. c.gen(n[1], d)
  213. c.code.addLabel(info, Label, lab1)
  214. closeScope c.sm
  215. c.clearDest(n, d)
  216. proc jumpTo(c: var ProcCon; n: PNode; L: LabelId) =
  217. c.code.addLabel(toLineInfo(c, n.info), Goto, L)
  218. proc genBreak(c: var ProcCon; n: PNode) =
  219. if n[0].kind == nkSym:
  220. for i in countdown(c.blocks.len-1, 0):
  221. if c.blocks[i][0] == n[0].sym:
  222. c.jumpTo n, c.blocks[i][1]
  223. return
  224. localError(c.config, n.info, "NIR problem: cannot find 'break' target")
  225. else:
  226. c.jumpTo n, c.blocks[c.blocks.high][1]
  227. proc genIf(c: var ProcCon; n: PNode; d: var Value) =
  228. # if (!expr1) goto lab1;
  229. # thenPart
  230. # goto LEnd
  231. # lab1:
  232. # if (!expr2) goto lab2;
  233. # thenPart2
  234. # goto LEnd
  235. # lab2:
  236. # elsePart
  237. # Lend:
  238. if isEmpty(d) and not isEmptyType(n.typ): d = getTemp(c, n)
  239. var ending = newLabel(c.labelGen)
  240. for i in 0..<n.len:
  241. var it = n[i]
  242. if it.len == 2:
  243. let info = toLineInfo(c, it[0].info)
  244. var elsePos: LabelId
  245. if isNotOpr(it[0]):
  246. let tmp = c.genx(it[0][1])
  247. elsePos = c.xjmp(it[0][1], opcTJmp, tmp) # if true
  248. c.freeTemp tmp
  249. else:
  250. let tmp = c.genx(it[0])
  251. elsePos = c.xjmp(it[0], opcFJmp, tmp) # if false
  252. c.freeTemp tmp
  253. c.clearDest(n, d)
  254. if isEmptyType(it[1].typ): # maybe noreturn call, don't touch `d`
  255. c.genScope(it[1])
  256. else:
  257. c.genScope(it[1], d) # then part
  258. if i < n.len-1:
  259. c.jumpTo it[1], ending
  260. c.patch(it, elsePos)
  261. else:
  262. c.clearDest(n, d)
  263. if isEmptyType(it[0].typ): # maybe noreturn call, don't touch `d`
  264. c.genScope(it[0])
  265. else:
  266. c.genScope(it[0], d)
  267. c.patch(n, ending)
  268. c.clearDest(n, d)
  269. proc tempToDest(c: var ProcCon; n: PNode; d: var Value; tmp: Value) =
  270. if isEmpty(d):
  271. d = tmp
  272. else:
  273. let info = toLineInfo(c, n.info)
  274. buildTyped c.code, info, Asgn, typeToIr(c.m, n.typ):
  275. c.code.copyTree d
  276. c.code.copyTree tmp
  277. freeTemp(c, tmp)
  278. proc genAndOr(c: var ProcCon; n: PNode; opc: JmpKind; d: var Value) =
  279. # asgn d, a
  280. # tjmp|fjmp lab1
  281. # asgn d, b
  282. # lab1:
  283. var tmp = getTemp(c, n)
  284. c.gen(n[1], tmp)
  285. let lab1 = c.xjmp(n, opc, tmp)
  286. c.gen(n[2], tmp)
  287. c.patch(n, lab1)
  288. tempToDest c, n, d, tmp
  289. proc unused(c: var ProcCon; n: PNode; x: Value) {.inline.} =
  290. if hasValue(x):
  291. #debug(n)
  292. localError(c.config, n.info, "not unused")
  293. proc caseValue(c: var ProcCon; n: PNode) =
  294. let info = toLineInfo(c, n.info)
  295. build c.code, info, SelectValue:
  296. let x = genx(c, n)
  297. c.code.copyTree x
  298. freeTemp(c, x)
  299. proc caseRange(c: var ProcCon; n: PNode) =
  300. let info = toLineInfo(c, n.info)
  301. build c.code, info, SelectRange:
  302. let x = genx(c, n[0])
  303. let y = genx(c, n[1])
  304. c.code.copyTree x
  305. c.code.copyTree y
  306. freeTemp(c, y)
  307. freeTemp(c, x)
  308. proc addUseCodegenProc(c: var ProcCon; dest: var Tree; name: string; info: PackedLineInfo) =
  309. let cp = getCompilerProc(c.m.graph, name)
  310. let theProc = c.genx newSymNode(cp)
  311. copyTree c.code, theProc
  312. template buildCond(useNegation: bool; cond: typed; body: untyped) =
  313. let lab = newLabel(c.labelGen)
  314. buildTyped c.code, info, Select, Bool8Id:
  315. c.code.copyTree cond
  316. build c.code, info, SelectPair:
  317. build c.code, info, SelectValue:
  318. c.code.boolVal(c.lit.numbers, info, useNegation)
  319. c.code.gotoLabel info, Goto, lab
  320. body
  321. c.code.addLabel info, Label, lab
  322. template buildIf(cond: typed; body: untyped) =
  323. buildCond false, cond, body
  324. template buildIfNot(cond: typed; body: untyped) =
  325. buildCond true, cond, body
  326. template buildIfThenElse(cond: typed; then, otherwise: untyped) =
  327. let lelse = newLabel(c.labelGen)
  328. let lend = newLabel(c.labelGen)
  329. buildTyped c.code, info, Select, Bool8Id:
  330. c.code.copyTree cond
  331. build c.code, info, SelectPair:
  332. build c.code, info, SelectValue:
  333. c.code.boolVal(c.lit.numbers, info, false)
  334. c.code.gotoLabel info, Goto, lelse
  335. then()
  336. c.code.gotoLabel info, Goto, lend
  337. c.code.addLabel info, Label, lelse
  338. otherwise()
  339. c.code.addLabel info, Label, lend
  340. include stringcases
  341. proc genCase(c: var ProcCon; n: PNode; d: var Value) =
  342. if not isEmptyType(n.typ):
  343. if isEmpty(d): d = getTemp(c, n)
  344. else:
  345. unused(c, n, d)
  346. if n[0].typ.skipTypes(abstractInst).kind == tyString:
  347. genStringCase(c, n, d)
  348. return
  349. var sections = newSeqOfCap[LabelId](n.len-1)
  350. let ending = newLabel(c.labelGen)
  351. let info = toLineInfo(c, n.info)
  352. let tmp = c.genx(n[0])
  353. buildTyped c.code, info, Select, typeToIr(c.m, n[0].typ):
  354. c.code.copyTree tmp
  355. for i in 1..<n.len:
  356. let section = newLabel(c.labelGen)
  357. sections.add section
  358. let it = n[i]
  359. let itinfo = toLineInfo(c, it.info)
  360. build c.code, itinfo, SelectPair:
  361. build c.code, itinfo, SelectList:
  362. for j in 0..<it.len-1:
  363. if it[j].kind == nkRange:
  364. caseRange c, it[j]
  365. else:
  366. caseValue c, it[j]
  367. c.code.addLabel itinfo, Goto, section
  368. c.freeTemp tmp
  369. for i in 1..<n.len:
  370. let it = n[i]
  371. let itinfo = toLineInfo(c, it.info)
  372. c.code.addLabel itinfo, Label, sections[i-1]
  373. c.gen it.lastSon
  374. if i != n.len-1:
  375. c.code.addLabel itinfo, Goto, ending
  376. c.code.addLabel info, Label, ending
  377. proc rawCall(c: var ProcCon; info: PackedLineInfo; opc: Opcode; t: TypeId; args: var openArray[Value]) =
  378. buildTyped c.code, info, opc, t:
  379. if opc in {CheckedCall, CheckedIndirectCall}:
  380. c.code.addLabel info, CheckedGoto, c.exitLabel
  381. for a in mitems(args):
  382. c.code.copyTree a
  383. freeTemp c, a
  384. proc canRaiseDisp(c: ProcCon; n: PNode): bool =
  385. # we assume things like sysFatal cannot raise themselves
  386. if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
  387. result = false
  388. elif optPanics in c.config.globalOptions or
  389. (n.kind == nkSym and sfSystemModule in getModule(n.sym).flags and
  390. sfSystemRaisesDefect notin n.sym.flags):
  391. # we know we can be strict:
  392. result = canRaise(n)
  393. else:
  394. # we have to be *very* conservative:
  395. result = canRaiseConservative(n)
  396. proc genCall(c: var ProcCon; n: PNode; d: var Value) =
  397. let canRaise = canRaiseDisp(c, n[0])
  398. let opc = if n[0].kind == nkSym and n[0].sym.kind in routineKinds:
  399. (if canRaise: CheckedCall else: Call)
  400. else:
  401. (if canRaise: CheckedIndirectCall else: IndirectCall)
  402. let info = toLineInfo(c, n.info)
  403. # In the IR we cannot nest calls. Thus we use two passes:
  404. var args: seq[Value] = @[]
  405. var t = n[0].typ
  406. if t != nil: t = t.skipTypes(abstractInst)
  407. args.add genx(c, n[0])
  408. for i in 1..<n.len:
  409. if t != nil and i < t.len:
  410. if isCompileTimeOnly(t[i]): discard
  411. elif isOutParam(t[i]): args.add genx(c, n[i], {gfToOutParam})
  412. else: args.add genx(c, n[i])
  413. else:
  414. args.add genx(c, n[i])
  415. let tb = typeToIr(c.m, n.typ)
  416. if not isEmptyType(n.typ):
  417. if isEmpty(d): d = getTemp(c, n)
  418. # XXX Handle problematic aliasing here: `a = f_canRaise(a)`.
  419. buildTyped c.code, info, Asgn, tb:
  420. c.code.copyTree d
  421. rawCall c, info, opc, tb, args
  422. else:
  423. rawCall c, info, opc, tb, args
  424. freeTemps c, args
  425. proc genRaise(c: var ProcCon; n: PNode) =
  426. let info = toLineInfo(c, n.info)
  427. let tb = typeToIr(c.m, n[0].typ)
  428. let d = genx(c, n[0])
  429. buildTyped c.code, info, SetExc, tb:
  430. c.code.copyTree d
  431. c.freeTemp(d)
  432. c.code.addLabel info, Goto, c.exitLabel
  433. proc genReturn(c: var ProcCon; n: PNode) =
  434. if n[0].kind != nkEmpty:
  435. gen(c, n[0])
  436. # XXX Block leave actions?
  437. let info = toLineInfo(c, n.info)
  438. c.code.addLabel info, Goto, c.exitLabel
  439. proc genTry(c: var ProcCon; n: PNode; d: var Value) =
  440. if isEmpty(d) and not isEmptyType(n.typ): d = getTemp(c, n)
  441. var endings: seq[LabelId] = @[]
  442. let ehPos = newLabel(c.labelGen)
  443. let oldExitLab = c.exitLabel
  444. c.exitLabel = ehPos
  445. if isEmptyType(n[0].typ): # maybe noreturn call, don't touch `d`
  446. c.gen(n[0])
  447. else:
  448. c.gen(n[0], d)
  449. c.clearDest(n, d)
  450. # Add a jump past the exception handling code
  451. let jumpToFinally = newLabel(c.labelGen)
  452. c.jumpTo n, jumpToFinally
  453. # This signals where the body ends and where the exception handling begins
  454. c.patch(n, ehPos)
  455. c.exitLabel = oldExitLab
  456. for i in 1..<n.len:
  457. let it = n[i]
  458. if it.kind != nkFinally:
  459. # first opcExcept contains the end label of the 'except' block:
  460. let endExcept = newLabel(c.labelGen)
  461. for j in 0..<it.len - 1:
  462. assert(it[j].kind == nkType)
  463. let typ = it[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
  464. let itinfo = toLineInfo(c, it[j].info)
  465. build c.code, itinfo, TestExc:
  466. c.code.addTyped itinfo, typeToIr(c.m, typ)
  467. if it.len == 1:
  468. let itinfo = toLineInfo(c, it.info)
  469. build c.code, itinfo, TestExc:
  470. c.code.addTyped itinfo, VoidId
  471. let body = it.lastSon
  472. if isEmptyType(body.typ): # maybe noreturn call, don't touch `d`
  473. c.gen(body)
  474. else:
  475. c.gen(body, d)
  476. c.clearDest(n, d)
  477. if i < n.len:
  478. endings.add newLabel(c.labelGen)
  479. c.patch(it, endExcept)
  480. let fin = lastSon(n)
  481. # we always generate an 'opcFinally' as that pops the safepoint
  482. # from the stack if no exception is raised in the body.
  483. c.patch(fin, jumpToFinally)
  484. #c.gABx(fin, opcFinally, 0, 0)
  485. for endPos in endings: c.patch(n, endPos)
  486. if fin.kind == nkFinally:
  487. c.gen(fin[0])
  488. c.clearDest(n, d)
  489. #c.gABx(fin, opcFinallyEnd, 0, 0)
  490. template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
  491. proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)
  492. proc genField(c: var ProcCon; n: PNode; d: var Value) =
  493. var pos: int
  494. if n.kind != nkSym or n.sym.kind != skField:
  495. localError(c.config, n.info, "no field symbol")
  496. pos = 0
  497. else:
  498. pos = n.sym.position
  499. d.addImmediateVal toLineInfo(c, n.info), pos
  500. proc genIndex(c: var ProcCon; n: PNode; arr: PType; d: var Value) =
  501. let info = toLineInfo(c, n.info)
  502. if arr.skipTypes(abstractInst).kind == tyArray and
  503. (let offset = firstOrd(c.config, arr); offset != Zero):
  504. let x = c.genx(n)
  505. buildTyped d, info, Sub, c.m.nativeIntId:
  506. copyTree d.Tree, x
  507. d.addImmediateVal toLineInfo(c, n.info), toInt(offset)
  508. else:
  509. c.gen(n, d)
  510. if optBoundsCheck in c.options:
  511. let idx = move d
  512. build d, info, CheckedIndex:
  513. d.Tree.addLabel info, CheckedGoto, c.exitLabel
  514. copyTree d.Tree, idx
  515. let x = toInt64 lengthOrd(c.config, arr)
  516. d.addIntVal c.lit.numbers, info, c.m.nativeIntId, x
  517. proc rawGenNew(c: var ProcCon; d: Value; refType: PType; ninfo: TLineInfo; needsInit: bool) =
  518. assert refType.kind == tyRef
  519. let baseType = refType.elementType
  520. let info = toLineInfo(c, ninfo)
  521. let codegenProc = magicsys.getCompilerProc(c.m.graph,
  522. if needsInit: "nimNewObj" else: "nimNewObjUninit")
  523. let refTypeIr = typeToIr(c.m, refType)
  524. buildTyped c.code, info, Asgn, refTypeIr:
  525. copyTree c.code, d
  526. buildTyped c.code, info, Cast, refTypeIr:
  527. buildTyped c.code, info, Call, VoidPtrId:
  528. let theProc = c.genx newSymNode(codegenProc, ninfo)
  529. copyTree c.code, theProc
  530. c.code.addImmediateVal info, int(getSize(c.config, baseType))
  531. c.code.addImmediateVal info, int(getAlign(c.config, baseType))
  532. proc genNew(c: var ProcCon; n: PNode; needsInit: bool) =
  533. # If in doubt, always follow the blueprint of the C code generator for `mm:orc`.
  534. let refType = n[1].typ.skipTypes(abstractInstOwned)
  535. let d = genx(c, n[1])
  536. rawGenNew c, d, refType, n.info, needsInit
  537. freeTemp c, d
  538. proc genNewSeqOfCap(c: var ProcCon; n: PNode; d: var Value) =
  539. let info = toLineInfo(c, n.info)
  540. let seqtype = skipTypes(n.typ, abstractVarRange)
  541. let baseType = seqtype.elementType
  542. var a = c.genx(n[1])
  543. if isEmpty(d): d = getTemp(c, n)
  544. # $1.len = 0
  545. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  546. buildTyped c.code, info, FieldAt, typeToIr(c.m, seqtype):
  547. copyTree c.code, d
  548. c.code.addImmediateVal info, 0
  549. c.code.addImmediateVal info, 0
  550. # $1.p = ($4*) #newSeqPayloadUninit($2, sizeof($3), NIM_ALIGNOF($3))
  551. let payloadPtr = seqPayloadPtrType(c.m.types, c.m.nirm.types, seqtype)[0]
  552. buildTyped c.code, info, Asgn, payloadPtr:
  553. # $1.p
  554. buildTyped c.code, info, FieldAt, typeToIr(c.m, seqtype):
  555. copyTree c.code, d
  556. c.code.addImmediateVal info, 1
  557. # ($4*) #newSeqPayloadUninit($2, sizeof($3), NIM_ALIGNOF($3))
  558. buildTyped c.code, info, Cast, payloadPtr:
  559. buildTyped c.code, info, Call, VoidPtrId:
  560. let codegenProc = magicsys.getCompilerProc(c.m.graph, "newSeqPayloadUninit")
  561. let theProc = c.genx newSymNode(codegenProc, n.info)
  562. copyTree c.code, theProc
  563. copyTree c.code, a
  564. c.code.addImmediateVal info, int(getSize(c.config, baseType))
  565. c.code.addImmediateVal info, int(getAlign(c.config, baseType))
  566. freeTemp c, a
  567. proc genNewSeqPayload(c: var ProcCon; info: PackedLineInfo; d, b: Value; seqtype: PType) =
  568. let baseType = seqtype.elementType
  569. # $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3))
  570. let payloadPtr = seqPayloadPtrType(c.m.types, c.m.nirm.types, seqtype)[0]
  571. # $1.len = $2
  572. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  573. buildTyped c.code, info, FieldAt, typeToIr(c.m, seqtype):
  574. copyTree c.code, d
  575. c.code.addImmediateVal info, 0
  576. copyTree c.code, b
  577. buildTyped c.code, info, Asgn, payloadPtr:
  578. # $1.p
  579. buildTyped c.code, info, FieldAt, typeToIr(c.m, seqtype):
  580. copyTree c.code, d
  581. c.code.addImmediateVal info, 1
  582. # ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3))
  583. buildTyped c.code, info, Cast, payloadPtr:
  584. buildTyped c.code, info, Call, VoidPtrId:
  585. let codegenProc = magicsys.getCompilerProc(c.m.graph, "newSeqPayload")
  586. let theProc = c.genx newSymNode(codegenProc)
  587. copyTree c.code, theProc
  588. copyTree c.code, b
  589. c.code.addImmediateVal info, int(getSize(c.config, baseType))
  590. c.code.addImmediateVal info, int(getAlign(c.config, baseType))
  591. proc genNewSeq(c: var ProcCon; n: PNode) =
  592. let info = toLineInfo(c, n.info)
  593. let seqtype = skipTypes(n[1].typ, abstractVarRange)
  594. var d = c.genx(n[1])
  595. var b = c.genx(n[2])
  596. genNewSeqPayload(c, info, d, b, seqtype)
  597. freeTemp c, b
  598. freeTemp c, d
  599. template intoDest*(d: var Value; info: PackedLineInfo; typ: TypeId; body: untyped) =
  600. if typ == VoidId:
  601. body(c.code)
  602. elif isEmpty(d):
  603. body(Tree(d))
  604. else:
  605. buildTyped c.code, info, Asgn, typ:
  606. copyTree c.code, d
  607. body(c.code)
  608. template valueIntoDest(c: var ProcCon; info: PackedLineInfo; d: var Value; typ: PType; body: untyped) =
  609. if isEmpty(d):
  610. body(Tree d)
  611. else:
  612. buildTyped c.code, info, Asgn, typeToIr(c.m, typ):
  613. copyTree c.code, d
  614. body(c.code)
  615. template constrIntoDest(c: var ProcCon; info: PackedLineInfo; d: var Value; typ: PType; body: untyped) =
  616. var tmp = default(Value)
  617. body(Tree tmp)
  618. if isEmpty(d):
  619. d = tmp
  620. else:
  621. buildTyped c.code, info, Asgn, typeToIr(c.m, typ):
  622. copyTree c.code, d
  623. copyTree c.code, tmp
  624. proc genBinaryOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
  625. let info = toLineInfo(c, n.info)
  626. let tmp = c.genx(n[1])
  627. let tmp2 = c.genx(n[2])
  628. let t = typeToIr(c.m, n.typ)
  629. template body(target) =
  630. buildTyped target, info, opc, t:
  631. if opc in {CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedMod}:
  632. target.addLabel info, CheckedGoto, c.exitLabel
  633. copyTree target, tmp
  634. copyTree target, tmp2
  635. intoDest d, info, t, body
  636. c.freeTemp(tmp)
  637. c.freeTemp(tmp2)
  638. proc genCmpOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
  639. let info = toLineInfo(c, n.info)
  640. let tmp = c.genx(n[1])
  641. let tmp2 = c.genx(n[2])
  642. let t = typeToIr(c.m, n[1].typ)
  643. template body(target) =
  644. buildTyped target, info, opc, t:
  645. copyTree target, tmp
  646. copyTree target, tmp2
  647. intoDest d, info, Bool8Id, body
  648. c.freeTemp(tmp)
  649. c.freeTemp(tmp2)
  650. proc genUnaryOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
  651. let info = toLineInfo(c, n.info)
  652. let tmp = c.genx(n[1])
  653. let t = typeToIr(c.m, n.typ)
  654. template body(target) =
  655. buildTyped target, info, opc, t:
  656. copyTree target, tmp
  657. intoDest d, info, t, body
  658. c.freeTemp(tmp)
  659. proc genIncDec(c: var ProcCon; n: PNode; opc: Opcode) =
  660. let info = toLineInfo(c, n.info)
  661. let t = typeToIr(c.m, skipTypes(n[1].typ, abstractVar))
  662. let d = c.genx(n[1])
  663. let tmp = c.genx(n[2])
  664. # we produce code like: i = i + 1
  665. buildTyped c.code, info, Asgn, t:
  666. copyTree c.code, d
  667. buildTyped c.code, info, opc, t:
  668. if opc in {CheckedAdd, CheckedSub}:
  669. c.code.addLabel info, CheckedGoto, c.exitLabel
  670. copyTree c.code, d
  671. copyTree c.code, tmp
  672. c.freeTemp(tmp)
  673. #c.genNarrow(n[1], d)
  674. c.freeTemp(d)
  675. proc genArrayLen(c: var ProcCon; n: PNode; d: var Value) =
  676. #echo c.m.graph.config $ n.info, " ", n
  677. let info = toLineInfo(c, n.info)
  678. var a = n[1]
  679. #if a.kind == nkHiddenAddr: a = a[0]
  680. var typ = skipTypes(a.typ, abstractVar + tyUserTypeClasses)
  681. case typ.kind
  682. of tyOpenArray, tyVarargs:
  683. let xa = c.genx(a)
  684. template body(target) =
  685. buildTyped target, info, FieldAt, typeToIr(c.m, typ):
  686. copyTree target, xa
  687. target.addImmediateVal info, 1 # (p, len)-pair so len is at index 1
  688. intoDest d, info, c.m.nativeIntId, body
  689. of tyCstring:
  690. let xa = c.genx(a)
  691. if isEmpty(d): d = getTemp(c, n)
  692. buildTyped c.code, info, Call, c.m.nativeIntId:
  693. let codegenProc = magicsys.getCompilerProc(c.m.graph, "nimCStrLen")
  694. assert codegenProc != nil
  695. let theProc = c.genx newSymNode(codegenProc, n.info)
  696. copyTree c.code, theProc
  697. copyTree c.code, xa
  698. of tyString, tySequence:
  699. let xa = c.genx(a)
  700. if typ.kind == tySequence:
  701. # we go through a temporary here because people write bullshit code.
  702. if isEmpty(d): d = getTemp(c, n)
  703. template body(target) =
  704. buildTyped target, info, FieldAt, typeToIr(c.m, typ):
  705. copyTree target, xa
  706. target.addImmediateVal info, 0 # (len, p)-pair so len is at index 0
  707. intoDest d, info, c.m.nativeIntId, body
  708. of tyArray:
  709. template body(target) =
  710. target.addIntVal(c.lit.numbers, info, c.m.nativeIntId, toInt lengthOrd(c.config, typ))
  711. intoDest d, info, c.m.nativeIntId, body
  712. else: internalError(c.config, n.info, "genArrayLen()")
  713. proc genUnaryMinus(c: var ProcCon; n: PNode; d: var Value) =
  714. let info = toLineInfo(c, n.info)
  715. let tmp = c.genx(n[1])
  716. let t = typeToIr(c.m, n.typ)
  717. template body(target) =
  718. buildTyped target, info, Sub, t:
  719. # Little hack: This works because we know that `0.0` is all 0 bits:
  720. target.addIntVal(c.lit.numbers, info, t, 0)
  721. copyTree target, tmp
  722. intoDest d, info, t, body
  723. c.freeTemp(tmp)
  724. proc genHigh(c: var ProcCon; n: PNode; d: var Value) =
  725. let info = toLineInfo(c, n.info)
  726. let t = typeToIr(c.m, n.typ)
  727. var x = default(Value)
  728. genArrayLen(c, n, x)
  729. template body(target) =
  730. buildTyped target, info, Sub, t:
  731. copyTree target, x
  732. target.addIntVal(c.lit.numbers, info, t, 1)
  733. intoDest d, info, t, body
  734. c.freeTemp x
  735. proc genBinaryCp(c: var ProcCon; n: PNode; d: var Value; compilerProc: string) =
  736. let info = toLineInfo(c, n.info)
  737. let xa = c.genx(n[1])
  738. let xb = c.genx(n[2])
  739. if isEmpty(d) and not isEmptyType(n.typ): d = getTemp(c, n)
  740. let t = typeToIr(c.m, n.typ)
  741. template body(target) =
  742. buildTyped target, info, Call, t:
  743. let codegenProc = magicsys.getCompilerProc(c.m.graph, compilerProc)
  744. #assert codegenProc != nil, $n & " " & (c.m.graph.config $ n.info)
  745. let theProc = c.genx newSymNode(codegenProc, n.info)
  746. copyTree target, theProc
  747. copyTree target, xa
  748. copyTree target, xb
  749. intoDest d, info, t, body
  750. c.freeTemp xb
  751. c.freeTemp xa
  752. proc genUnaryCp(c: var ProcCon; n: PNode; d: var Value; compilerProc: string; argAt = 1) =
  753. let info = toLineInfo(c, n.info)
  754. let xa = c.genx(n[argAt])
  755. if isEmpty(d) and not isEmptyType(n.typ): d = getTemp(c, n)
  756. let t = typeToIr(c.m, n.typ)
  757. template body(target) =
  758. buildTyped target, info, Call, t:
  759. let codegenProc = magicsys.getCompilerProc(c.m.graph, compilerProc)
  760. let theProc = c.genx newSymNode(codegenProc, n.info)
  761. copyTree target, theProc
  762. copyTree target, xa
  763. intoDest d, info, t, body
  764. c.freeTemp xa
  765. proc genEnumToStr(c: var ProcCon; n: PNode; d: var Value) =
  766. let t = n[1].typ.skipTypes(abstractInst+{tyRange})
  767. let toStrProc = getToStringProc(c.m.graph, t)
  768. # XXX need to modify this logic for IC.
  769. var nb = copyTree(n)
  770. nb[0] = newSymNode(toStrProc)
  771. gen(c, nb, d)
  772. proc genOf(c: var ProcCon; n: PNode; d: var Value) =
  773. genUnaryOp c, n, d, TestOf
  774. template sizeOfLikeMsg(name): string =
  775. "'" & name & "' requires '.importc' types to be '.completeStruct'"
  776. proc genIsNil(c: var ProcCon; n: PNode; d: var Value) =
  777. let info = toLineInfo(c, n.info)
  778. let tmp = c.genx(n[1])
  779. let t = typeToIr(c.m, n[1].typ)
  780. template body(target) =
  781. buildTyped target, info, Eq, t:
  782. copyTree target, tmp
  783. addNilVal target, info, t
  784. intoDest d, info, Bool8Id, body
  785. c.freeTemp(tmp)
  786. proc fewCmps(conf: ConfigRef; s: PNode): bool =
  787. # this function estimates whether it is better to emit code
  788. # for constructing the set or generating a bunch of comparisons directly
  789. if s.kind != nkCurly:
  790. result = false
  791. elif (getSize(conf, s.typ) <= conf.target.intSize) and (nfAllConst in s.flags):
  792. result = false # it is better to emit the set generation code
  793. elif elemType(s.typ).kind in {tyInt, tyInt16..tyInt64}:
  794. result = true # better not emit the set if int is basetype!
  795. else:
  796. result = s.len <= 8 # 8 seems to be a good value
  797. proc genInBitset(c: var ProcCon; n: PNode; d: var Value) =
  798. let info = toLineInfo(c, n.info)
  799. let a = c.genx(n[1])
  800. let b = c.genx(n[2])
  801. let t = bitsetBasetype(c.m.types, c.m.nirm.types, n[1].typ)
  802. let setType = typeToIr(c.m, n[1].typ)
  803. let mask =
  804. case t
  805. of UInt8Id: 7
  806. of UInt16Id: 15
  807. of UInt32Id: 31
  808. else: 63
  809. let expansion = if t == UInt64Id: UInt64Id else: c.m.nativeUIntId
  810. # "(($1 &(1U<<((NU)($2)&7U)))!=0)" - or -
  811. # "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)"
  812. template body(target) =
  813. buildTyped target, info, BoolNot, Bool8Id:
  814. buildTyped target, info, Eq, t:
  815. buildTyped target, info, BitAnd, t:
  816. if c.m.nirm.types[setType].kind != ArrayTy:
  817. copyTree target, a
  818. else:
  819. buildTyped target, info, ArrayAt, setType:
  820. copyTree target, a
  821. buildTyped target, info, BitShr, t:
  822. buildTyped target, info, Cast, expansion:
  823. copyTree target, b
  824. addIntVal target, c.lit.numbers, info, expansion, 3
  825. buildTyped target, info, BitShl, t:
  826. addIntVal target, c.lit.numbers, info, t, 1
  827. buildTyped target, info, BitAnd, t:
  828. buildTyped target, info, Cast, expansion:
  829. copyTree target, b
  830. addIntVal target, c.lit.numbers, info, expansion, mask
  831. addIntVal target, c.lit.numbers, info, t, 0
  832. intoDest d, info, t, body
  833. c.freeTemp(b)
  834. c.freeTemp(a)
  835. proc genInSet(c: var ProcCon; n: PNode; d: var Value) =
  836. let g {.cursor.} = c.m.graph
  837. if n[1].kind == nkCurly and fewCmps(g.config, n[1]):
  838. # a set constructor but not a constant set:
  839. # do not emit the set, but generate a bunch of comparisons; and if we do
  840. # so, we skip the unnecessary range check: This is a semantical extension
  841. # that code now relies on. :-/ XXX
  842. let elem = if n[2].kind in {nkChckRange, nkChckRange64}: n[2][0]
  843. else: n[2]
  844. let curly = n[1]
  845. var ex: PNode = nil
  846. for it in curly:
  847. var test: PNode
  848. if it.kind == nkRange:
  849. test = newTree(nkCall, g.operators.opAnd.newSymNode,
  850. newTree(nkCall, g.operators.opLe.newSymNode, it[0], elem), # a <= elem
  851. newTree(nkCall, g.operators.opLe.newSymNode, elem, it[1])
  852. )
  853. else:
  854. test = newTree(nkCall, g.operators.opEq.newSymNode, elem, it)
  855. test.typ = getSysType(g, it.info, tyBool)
  856. if ex == nil: ex = test
  857. else: ex = newTree(nkCall, g.operators.opOr.newSymNode, ex, test)
  858. if ex == nil:
  859. let info = toLineInfo(c, n.info)
  860. template body(target) =
  861. boolVal target, c.lit.numbers, info, false
  862. intoDest d, info, Bool8Id, body
  863. else:
  864. gen c, ex, d
  865. else:
  866. genInBitset c, n, d
  867. proc genCard(c: var ProcCon; n: PNode; d: var Value) =
  868. let info = toLineInfo(c, n.info)
  869. let a = c.genx(n[1])
  870. let t = typeToIr(c.m, n.typ)
  871. let setType = typeToIr(c.m, n[1].typ)
  872. if isEmpty(d): d = getTemp(c, n)
  873. buildTyped c.code, info, Asgn, t:
  874. copyTree c.code, d
  875. buildTyped c.code, info, Call, t:
  876. if c.m.nirm.types[setType].kind == ArrayTy:
  877. let codegenProc = magicsys.getCompilerProc(c.m.graph, "cardSet")
  878. let theProc = c.genx newSymNode(codegenProc, n.info)
  879. copyTree c.code, theProc
  880. buildTyped c.code, info, AddrOf, ptrTypeOf(c.m.nirm.types, setType):
  881. copyTree c.code, a
  882. c.code.addImmediateVal info, int(getSize(c.config, n[1].typ))
  883. elif t == UInt64Id:
  884. let codegenProc = magicsys.getCompilerProc(c.m.graph, "countBits64")
  885. let theProc = c.genx newSymNode(codegenProc, n.info)
  886. copyTree c.code, theProc
  887. copyTree c.code, a
  888. else:
  889. let codegenProc = magicsys.getCompilerProc(c.m.graph, "countBits32")
  890. let theProc = c.genx newSymNode(codegenProc, n.info)
  891. copyTree c.code, theProc
  892. buildTyped c.code, info, Cast, UInt32Id:
  893. copyTree c.code, a
  894. freeTemp c, a
  895. proc genEqSet(c: var ProcCon; n: PNode; d: var Value) =
  896. let info = toLineInfo(c, n.info)
  897. let a = c.genx(n[1])
  898. let b = c.genx(n[2])
  899. let t = typeToIr(c.m, n.typ)
  900. let setType = typeToIr(c.m, n[1].typ)
  901. if c.m.nirm.types[setType].kind == ArrayTy:
  902. if isEmpty(d): d = getTemp(c, n)
  903. buildTyped c.code, info, Asgn, t:
  904. copyTree c.code, d
  905. buildTyped c.code, info, Eq, t:
  906. buildTyped c.code, info, Call, t:
  907. let codegenProc = magicsys.getCompilerProc(c.m.graph, "nimCmpMem")
  908. let theProc = c.genx newSymNode(codegenProc, n.info)
  909. copyTree c.code, theProc
  910. buildTyped c.code, info, AddrOf, ptrTypeOf(c.m.nirm.types, setType):
  911. copyTree c.code, a
  912. buildTyped c.code, info, AddrOf, ptrTypeOf(c.m.nirm.types, setType):
  913. copyTree c.code, b
  914. c.code.addImmediateVal info, int(getSize(c.config, n[1].typ))
  915. c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, 0
  916. else:
  917. template body(target) =
  918. buildTyped target, info, Eq, setType:
  919. copyTree target, a
  920. copyTree target, b
  921. intoDest d, info, Bool8Id, body
  922. freeTemp c, b
  923. freeTemp c, a
  924. proc beginCountLoop(c: var ProcCon; info: PackedLineInfo; first, last: int): (SymId, LabelId, LabelId) =
  925. let tmp = allocTemp(c, c.m.nativeIntId)
  926. c.code.addSummon info, tmp, c.m.nativeIntId
  927. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  928. c.code.addSymUse info, tmp
  929. c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, first
  930. let lab1 = c.code.addNewLabel(c.labelGen, info, LoopLabel)
  931. result = (tmp, lab1, newLabel(c.labelGen))
  932. buildTyped c.code, info, Select, Bool8Id:
  933. buildTyped c.code, info, Lt, c.m.nativeIntId:
  934. c.code.addSymUse info, tmp
  935. c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, last
  936. build c.code, info, SelectPair:
  937. build c.code, info, SelectValue:
  938. c.code.boolVal(c.lit.numbers, info, false)
  939. c.code.gotoLabel info, Goto, result[2]
  940. proc beginCountLoop(c: var ProcCon; info: PackedLineInfo; first, last: Value): (SymId, LabelId, LabelId) =
  941. let tmp = allocTemp(c, c.m.nativeIntId)
  942. c.code.addSummon info, tmp, c.m.nativeIntId
  943. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  944. c.code.addSymUse info, tmp
  945. copyTree c.code, first
  946. let lab1 = c.code.addNewLabel(c.labelGen, info, LoopLabel)
  947. result = (tmp, lab1, newLabel(c.labelGen))
  948. buildTyped c.code, info, Select, Bool8Id:
  949. buildTyped c.code, info, Le, c.m.nativeIntId:
  950. c.code.addSymUse info, tmp
  951. copyTree c.code, last
  952. build c.code, info, SelectPair:
  953. build c.code, info, SelectValue:
  954. c.code.boolVal(c.lit.numbers, info, false)
  955. c.code.gotoLabel info, Goto, result[2]
  956. proc endLoop(c: var ProcCon; info: PackedLineInfo; s: SymId; back, exit: LabelId) =
  957. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  958. c.code.addSymUse info, s
  959. buildTyped c.code, info, Add, c.m.nativeIntId:
  960. c.code.addSymUse info, s
  961. c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, 1
  962. c.code.addLabel info, GotoLoop, back
  963. c.code.addLabel info, Label, exit
  964. freeTemp(c.sm, s)
  965. proc genLeSet(c: var ProcCon; n: PNode; d: var Value) =
  966. let info = toLineInfo(c, n.info)
  967. let a = c.genx(n[1])
  968. let b = c.genx(n[2])
  969. let t = typeToIr(c.m, n.typ)
  970. let setType = typeToIr(c.m, n[1].typ)
  971. if c.m.nirm.types[setType].kind == ArrayTy:
  972. let elemType = bitsetBasetype(c.m.types, c.m.nirm.types, n[1].typ)
  973. if isEmpty(d): d = getTemp(c, n)
  974. # "for ($1 = 0; $1 < $2; $1++):"
  975. # " $3 = (($4[$1] & ~ $5[$1]) == 0)"
  976. # " if (!$3) break;"
  977. let (idx, backLabel, endLabel) = beginCountLoop(c, info, 0, int(getSize(c.config, n[1].typ)))
  978. buildTyped c.code, info, Asgn, Bool8Id:
  979. copyTree c.code, d
  980. buildTyped c.code, info, Eq, elemType:
  981. buildTyped c.code, info, BitAnd, elemType:
  982. buildTyped c.code, info, ArrayAt, setType:
  983. copyTree c.code, a
  984. c.code.addSymUse info, idx
  985. buildTyped c.code, info, BitNot, elemType:
  986. buildTyped c.code, info, ArrayAt, setType:
  987. copyTree c.code, b
  988. c.code.addSymUse info, idx
  989. c.code.addIntVal c.lit.numbers, info, elemType, 0
  990. # if !$3: break
  991. buildTyped c.code, info, Select, Bool8Id:
  992. c.code.copyTree d
  993. build c.code, info, SelectPair:
  994. build c.code, info, SelectValue:
  995. c.code.boolVal(c.lit.numbers, info, false)
  996. c.code.gotoLabel info, Goto, endLabel
  997. endLoop(c, info, idx, backLabel, endLabel)
  998. else:
  999. # "(($1 & ~ $2)==0)"
  1000. template body(target) =
  1001. buildTyped target, info, Eq, setType:
  1002. buildTyped target, info, BitAnd, setType:
  1003. copyTree target, a
  1004. buildTyped target, info, BitNot, setType:
  1005. copyTree target, b
  1006. target.addIntVal c.lit.numbers, info, setType, 0
  1007. intoDest d, info, Bool8Id, body
  1008. freeTemp c, b
  1009. freeTemp c, a
  1010. proc genLtSet(c: var ProcCon; n: PNode; d: var Value) =
  1011. localError(c.m.graph.config, n.info, "`<` for sets not implemented")
  1012. proc genBinarySet(c: var ProcCon; n: PNode; d: var Value; m: TMagic) =
  1013. let info = toLineInfo(c, n.info)
  1014. let a = c.genx(n[1])
  1015. let b = c.genx(n[2])
  1016. let t = typeToIr(c.m, n.typ)
  1017. let setType = typeToIr(c.m, n[1].typ)
  1018. if c.m.nirm.types[setType].kind == ArrayTy:
  1019. let elemType = bitsetBasetype(c.m.types, c.m.nirm.types, n[1].typ)
  1020. if isEmpty(d): d = getTemp(c, n)
  1021. # "for ($1 = 0; $1 < $2; $1++):"
  1022. # " $3 = (($4[$1] & ~ $5[$1]) == 0)"
  1023. # " if (!$3) break;"
  1024. let (idx, backLabel, endLabel) = beginCountLoop(c, info, 0, int(getSize(c.config, n[1].typ)))
  1025. buildTyped c.code, info, Asgn, elemType:
  1026. buildTyped c.code, info, ArrayAt, setType:
  1027. copyTree c.code, d
  1028. c.code.addSymUse info, idx
  1029. buildTyped c.code, info, (if m == mPlusSet: BitOr else: BitAnd), elemType:
  1030. buildTyped c.code, info, ArrayAt, setType:
  1031. copyTree c.code, a
  1032. c.code.addSymUse info, idx
  1033. if m == mMinusSet:
  1034. buildTyped c.code, info, BitNot, elemType:
  1035. buildTyped c.code, info, ArrayAt, setType:
  1036. copyTree c.code, b
  1037. c.code.addSymUse info, idx
  1038. else:
  1039. buildTyped c.code, info, ArrayAt, setType:
  1040. copyTree c.code, b
  1041. c.code.addSymUse info, idx
  1042. endLoop(c, info, idx, backLabel, endLabel)
  1043. else:
  1044. # "(($1 & ~ $2)==0)"
  1045. template body(target) =
  1046. buildTyped target, info, (if m == mPlusSet: BitOr else: BitAnd), setType:
  1047. copyTree target, a
  1048. if m == mMinusSet:
  1049. buildTyped target, info, BitNot, setType:
  1050. copyTree target, b
  1051. else:
  1052. copyTree target, b
  1053. intoDest d, info, setType, body
  1054. freeTemp c, b
  1055. freeTemp c, a
  1056. proc genInclExcl(c: var ProcCon; n: PNode; m: TMagic) =
  1057. let info = toLineInfo(c, n.info)
  1058. let a = c.genx(n[1])
  1059. let b = c.genx(n[2])
  1060. let setType = typeToIr(c.m, n[1].typ)
  1061. let t = bitsetBasetype(c.m.types, c.m.nirm.types, n[1].typ)
  1062. let mask =
  1063. case t
  1064. of UInt8Id: 7
  1065. of UInt16Id: 15
  1066. of UInt32Id: 31
  1067. else: 63
  1068. buildTyped c.code, info, Asgn, setType:
  1069. if c.m.nirm.types[setType].kind == ArrayTy:
  1070. if m == mIncl:
  1071. # $1[(NU)($2)>>3] |=(1U<<($2&7U))
  1072. buildTyped c.code, info, ArrayAt, setType:
  1073. copyTree c.code, a
  1074. buildTyped c.code, info, BitShr, t:
  1075. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1076. copyTree c.code, b
  1077. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1078. buildTyped c.code, info, BitOr, t:
  1079. buildTyped c.code, info, ArrayAt, setType:
  1080. copyTree c.code, a
  1081. buildTyped c.code, info, BitShr, t:
  1082. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1083. copyTree c.code, b
  1084. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1085. buildTyped c.code, info, BitShl, t:
  1086. c.code.addIntVal c.lit.numbers, info, t, 1
  1087. buildTyped c.code, info, BitAnd, t:
  1088. copyTree c.code, b
  1089. c.code.addIntVal c.lit.numbers, info, t, 7
  1090. else:
  1091. # $1[(NU)($2)>>3] &= ~(1U<<($2&7U))
  1092. buildTyped c.code, info, ArrayAt, setType:
  1093. copyTree c.code, a
  1094. buildTyped c.code, info, BitShr, t:
  1095. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1096. copyTree c.code, b
  1097. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1098. buildTyped c.code, info, BitAnd, t:
  1099. buildTyped c.code, info, ArrayAt, setType:
  1100. copyTree c.code, a
  1101. buildTyped c.code, info, BitShr, t:
  1102. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1103. copyTree c.code, b
  1104. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1105. buildTyped c.code, info, BitNot, t:
  1106. buildTyped c.code, info, BitShl, t:
  1107. c.code.addIntVal c.lit.numbers, info, t, 1
  1108. buildTyped c.code, info, BitAnd, t:
  1109. copyTree c.code, b
  1110. c.code.addIntVal c.lit.numbers, info, t, 7
  1111. else:
  1112. copyTree c.code, a
  1113. if m == mIncl:
  1114. # $1 |= ((NU8)1)<<(($2) & 7)
  1115. buildTyped c.code, info, BitOr, setType:
  1116. copyTree c.code, a
  1117. buildTyped c.code, info, BitShl, t:
  1118. c.code.addIntVal c.lit.numbers, info, t, 1
  1119. buildTyped c.code, info, BitAnd, t:
  1120. copyTree c.code, b
  1121. c.code.addIntVal c.lit.numbers, info, t, mask
  1122. else:
  1123. # $1 &= ~(((NU8)1) << (($2) & 7))
  1124. buildTyped c.code, info, BitAnd, setType:
  1125. copyTree c.code, a
  1126. buildTyped c.code, info, BitNot, t:
  1127. buildTyped c.code, info, BitShl, t:
  1128. c.code.addIntVal c.lit.numbers, info, t, 1
  1129. buildTyped c.code, info, BitAnd, t:
  1130. copyTree c.code, b
  1131. c.code.addIntVal c.lit.numbers, info, t, mask
  1132. freeTemp c, b
  1133. freeTemp c, a
  1134. proc genSetConstrDyn(c: var ProcCon; n: PNode; d: var Value) =
  1135. # example: { a..b, c, d, e, f..g }
  1136. # we have to emit an expression of the form:
  1137. # nimZeroMem(tmp, sizeof(tmp)); inclRange(tmp, a, b); incl(tmp, c);
  1138. # incl(tmp, d); incl(tmp, e); inclRange(tmp, f, g);
  1139. let info = toLineInfo(c, n.info)
  1140. let setType = typeToIr(c.m, n.typ)
  1141. let size = int(getSize(c.config, n.typ))
  1142. let t = bitsetBasetype(c.m.types, c.m.nirm.types, n.typ)
  1143. let mask =
  1144. case t
  1145. of UInt8Id: 7
  1146. of UInt16Id: 15
  1147. of UInt32Id: 31
  1148. else: 63
  1149. if isEmpty(d): d = getTemp(c, n)
  1150. if c.m.nirm.types[setType].kind != ArrayTy:
  1151. buildTyped c.code, info, Asgn, setType:
  1152. copyTree c.code, d
  1153. c.code.addIntVal c.lit.numbers, info, t, 0
  1154. for it in n:
  1155. if it.kind == nkRange:
  1156. let a = genx(c, it[0])
  1157. let b = genx(c, it[1])
  1158. let (idx, backLabel, endLabel) = beginCountLoop(c, info, a, b)
  1159. buildTyped c.code, info, Asgn, setType:
  1160. copyTree c.code, d
  1161. buildTyped c.code, info, BitAnd, setType:
  1162. copyTree c.code, d
  1163. buildTyped c.code, info, BitNot, t:
  1164. buildTyped c.code, info, BitShl, t:
  1165. c.code.addIntVal c.lit.numbers, info, t, 1
  1166. buildTyped c.code, info, BitAnd, t:
  1167. c.code.addSymUse info, idx
  1168. c.code.addIntVal c.lit.numbers, info, t, mask
  1169. endLoop(c, info, idx, backLabel, endLabel)
  1170. freeTemp c, b
  1171. freeTemp c, a
  1172. else:
  1173. let a = genx(c, it)
  1174. buildTyped c.code, info, Asgn, setType:
  1175. copyTree c.code, d
  1176. buildTyped c.code, info, BitAnd, setType:
  1177. copyTree c.code, d
  1178. buildTyped c.code, info, BitNot, t:
  1179. buildTyped c.code, info, BitShl, t:
  1180. c.code.addIntVal c.lit.numbers, info, t, 1
  1181. buildTyped c.code, info, BitAnd, t:
  1182. copyTree c.code, a
  1183. c.code.addIntVal c.lit.numbers, info, t, mask
  1184. freeTemp c, a
  1185. else:
  1186. # init loop:
  1187. let (idx, backLabel, endLabel) = beginCountLoop(c, info, 0, size)
  1188. buildTyped c.code, info, Asgn, t:
  1189. copyTree c.code, d
  1190. c.code.addIntVal c.lit.numbers, info, t, 0
  1191. endLoop(c, info, idx, backLabel, endLabel)
  1192. # incl elements:
  1193. for it in n:
  1194. if it.kind == nkRange:
  1195. let a = genx(c, it[0])
  1196. let b = genx(c, it[1])
  1197. let (idx, backLabel, endLabel) = beginCountLoop(c, info, a, b)
  1198. buildTyped c.code, info, Asgn, t:
  1199. buildTyped c.code, info, ArrayAt, setType:
  1200. copyTree c.code, d
  1201. buildTyped c.code, info, BitShr, t:
  1202. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1203. c.code.addSymUse info, idx
  1204. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1205. buildTyped c.code, info, BitOr, t:
  1206. buildTyped c.code, info, ArrayAt, setType:
  1207. copyTree c.code, d
  1208. buildTyped c.code, info, BitShr, t:
  1209. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1210. c.code.addSymUse info, idx
  1211. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1212. buildTyped c.code, info, BitShl, t:
  1213. c.code.addIntVal c.lit.numbers, info, t, 1
  1214. buildTyped c.code, info, BitAnd, t:
  1215. c.code.addSymUse info, idx
  1216. c.code.addIntVal c.lit.numbers, info, t, 7
  1217. endLoop(c, info, idx, backLabel, endLabel)
  1218. freeTemp c, b
  1219. freeTemp c, a
  1220. else:
  1221. let a = genx(c, it)
  1222. # $1[(NU)($2)>>3] |=(1U<<($2&7U))
  1223. buildTyped c.code, info, Asgn, t:
  1224. buildTyped c.code, info, ArrayAt, setType:
  1225. copyTree c.code, d
  1226. buildTyped c.code, info, BitShr, t:
  1227. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1228. copyTree c.code, a
  1229. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1230. buildTyped c.code, info, BitOr, t:
  1231. buildTyped c.code, info, ArrayAt, setType:
  1232. copyTree c.code, d
  1233. buildTyped c.code, info, BitShr, t:
  1234. buildTyped c.code, info, Cast, c.m.nativeUIntId:
  1235. copyTree c.code, a
  1236. addIntVal c.code, c.lit.numbers, info, c.m.nativeUIntId, 3
  1237. buildTyped c.code, info, BitShl, t:
  1238. c.code.addIntVal c.lit.numbers, info, t, 1
  1239. buildTyped c.code, info, BitAnd, t:
  1240. copyTree c.code, a
  1241. c.code.addIntVal c.lit.numbers, info, t, 7
  1242. freeTemp c, a
  1243. proc genSetConstr(c: var ProcCon; n: PNode; d: var Value) =
  1244. if isDeepConstExpr(n):
  1245. let info = toLineInfo(c, n.info)
  1246. let setType = typeToIr(c.m, n.typ)
  1247. let size = int(getSize(c.config, n.typ))
  1248. let cs = toBitSet(c.config, n)
  1249. if c.m.nirm.types[setType].kind != ArrayTy:
  1250. template body(target) =
  1251. target.addIntVal c.lit.numbers, info, setType, cast[BiggestInt](bitSetToWord(cs, size))
  1252. intoDest d, info, setType, body
  1253. else:
  1254. let t = bitsetBasetype(c.m.types, c.m.nirm.types, n.typ)
  1255. template body(target) =
  1256. buildTyped target, info, ArrayConstr, setType:
  1257. for i in 0..high(cs):
  1258. target.addIntVal c.lit.numbers, info, t, int64 cs[i]
  1259. intoDest d, info, setType, body
  1260. else:
  1261. genSetConstrDyn c, n, d
  1262. proc genStrConcat(c: var ProcCon; n: PNode; d: var Value) =
  1263. let info = toLineInfo(c, n.info)
  1264. # <Nim code>
  1265. # s = "Hello " & name & ", how do you feel?" & 'z'
  1266. #
  1267. # <generated code>
  1268. # {
  1269. # string tmp0;
  1270. # ...
  1271. # tmp0 = rawNewString(6 + 17 + 1 + s2->len);
  1272. # // we cannot generate s = rawNewString(...) here, because
  1273. # // ``s`` may be used on the right side of the expression
  1274. # appendString(tmp0, strlit_1);
  1275. # appendString(tmp0, name);
  1276. # appendString(tmp0, strlit_2);
  1277. # appendChar(tmp0, 'z');
  1278. # asgn(s, tmp0);
  1279. # }
  1280. var args: seq[Value] = @[]
  1281. var argsRuntimeLen: seq[Value] = @[]
  1282. var precomputedLen = 0
  1283. for i in 1 ..< n.len:
  1284. let it = n[i]
  1285. args.add genx(c, it)
  1286. if skipTypes(it.typ, abstractVarRange).kind == tyChar:
  1287. inc precomputedLen
  1288. elif it.kind in {nkStrLit..nkTripleStrLit}:
  1289. inc precomputedLen, it.strVal.len
  1290. else:
  1291. argsRuntimeLen.add args[^1]
  1292. # generate length computation:
  1293. var tmpLen = allocTemp(c, c.m.nativeIntId)
  1294. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  1295. c.code.addSymUse info, tmpLen
  1296. c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, precomputedLen
  1297. for a in mitems(argsRuntimeLen):
  1298. buildTyped c.code, info, Asgn, c.m.nativeIntId:
  1299. c.code.addSymUse info, tmpLen
  1300. buildTyped c.code, info, CheckedAdd, c.m.nativeIntId:
  1301. c.code.addLabel info, CheckedGoto, c.exitLabel
  1302. c.code.addSymUse info, tmpLen
  1303. buildTyped c.code, info, FieldAt, typeToIr(c.m, n.typ):
  1304. copyTree c.code, a
  1305. c.code.addImmediateVal info, 0 # (len, p)-pair so len is at index 0
  1306. var tmpStr = getTemp(c, n)
  1307. # ^ because of aliasing, we always go through a temporary
  1308. let t = typeToIr(c.m, n.typ)
  1309. buildTyped c.code, info, Asgn, t:
  1310. copyTree c.code, tmpStr
  1311. buildTyped c.code, info, Call, t:
  1312. let codegenProc = magicsys.getCompilerProc(c.m.graph, "rawNewString")
  1313. #assert codegenProc != nil, $n & " " & (c.m.graph.config $ n.info)
  1314. let theProc = c.genx newSymNode(codegenProc, n.info)
  1315. copyTree c.code, theProc
  1316. c.code.addSymUse info, tmpLen
  1317. freeTemp c.sm, tmpLen
  1318. for i in 1 ..< n.len:
  1319. let it = n[i]
  1320. let isChar = skipTypes(it.typ, abstractVarRange).kind == tyChar
  1321. buildTyped c.code, info, Call, VoidId:
  1322. let codegenProc = magicsys.getCompilerProc(c.m.graph,
  1323. (if isChar: "appendChar" else: "appendString"))
  1324. #assert codegenProc != nil, $n & " " & (c.m.graph.config $ n.info)
  1325. let theProc = c.genx newSymNode(codegenProc, n.info)
  1326. copyTree c.code, theProc
  1327. buildTyped c.code, info, AddrOf, ptrTypeOf(c.m.nirm.types, t):
  1328. copyTree c.code, tmpStr
  1329. copyTree c.code, args[i-1]
  1330. freeTemp c, args[i-1]
  1331. if isEmpty(d):
  1332. d = tmpStr
  1333. else:
  1334. # XXX Test that this does not cause memory leaks!
  1335. buildTyped c.code, info, Asgn, t:
  1336. copyTree c.code, d
  1337. copyTree c.code, tmpStr
  1338. proc genDefault(c: var ProcCon; n: PNode; d: var Value) =
  1339. let m = expandDefault(n.typ, n.info)
  1340. gen c, m, d
  1341. proc genWasMoved(c: var ProcCon; n: PNode) =
  1342. let n1 = n[1].skipAddr
  1343. # XXX We need a way to replicate this logic or better yet a better
  1344. # solution for injectdestructors.nim:
  1345. #if c.withinBlockLeaveActions > 0 and notYetAlive(n1):
  1346. var d = c.genx(n1)
  1347. assert not isEmpty(d)
  1348. let m = expandDefault(n1.typ, n1.info)
  1349. gen c, m, d
  1350. proc genMove(c: var ProcCon; n: PNode; d: var Value) =
  1351. let info = toLineInfo(c, n.info)
  1352. let n1 = n[1].skipAddr
  1353. var a = c.genx(n1)
  1354. if n.len == 4:
  1355. # generated by liftdestructors:
  1356. let src = c.genx(n[2])
  1357. # if ($1.p == $2.p) goto lab1
  1358. let lab1 = newLabel(c.labelGen)
  1359. let n1t = typeToIr(c.m, n1.typ)
  1360. let payloadType = seqPayloadPtrType(c.m.types, c.m.nirm.types, n1.typ)[0]
  1361. buildTyped c.code, info, Select, Bool8Id:
  1362. buildTyped c.code, info, Eq, payloadType:
  1363. buildTyped c.code, info, FieldAt, n1t:
  1364. copyTree c.code, a
  1365. c.code.addImmediateVal info, 1 # (len, p)-pair
  1366. buildTyped c.code, info, FieldAt, n1t:
  1367. copyTree c.code, src
  1368. c.code.addImmediateVal info, 1 # (len, p)-pair
  1369. build c.code, info, SelectPair:
  1370. build c.code, info, SelectValue:
  1371. c.code.boolVal(c.lit.numbers, info, true)
  1372. c.code.gotoLabel info, Goto, lab1
  1373. gen(c, n[3])
  1374. c.patch n, lab1
  1375. buildTyped c.code, info, Asgn, typeToIr(c.m, n1.typ):
  1376. copyTree c.code, a
  1377. copyTree c.code, src
  1378. else:
  1379. if isEmpty(d): d = getTemp(c, n)
  1380. buildTyped c.code, info, Asgn, typeToIr(c.m, n1.typ):
  1381. copyTree c.code, d
  1382. copyTree c.code, a
  1383. var op = getAttachedOp(c.m.graph, n.typ, attachedWasMoved)
  1384. if op == nil or skipTypes(n1.typ, abstractVar+{tyStatic}).kind in {tyOpenArray, tyVarargs}:
  1385. let m = expandDefault(n1.typ, n1.info)
  1386. gen c, m, a
  1387. else:
  1388. var opB = c.genx(newSymNode(op))
  1389. buildTyped c.code, info, Call, typeToIr(c.m, n.typ):
  1390. copyTree c.code, opB
  1391. buildTyped c.code, info, AddrOf, ptrTypeOf(c.m.nirm.types, typeToIr(c.m, n1.typ)):
  1392. copyTree c.code, a
  1393. template fieldAt(x: Value; i: int; t: TypeId): Tree =
  1394. var result = default(Tree)
  1395. buildTyped result, info, FieldAt, t:
  1396. copyTree result, x
  1397. result.addImmediateVal info, i
  1398. result
  1399. template eqNil(x: Tree; t: TypeId): Tree =
  1400. var result = default(Tree)
  1401. buildTyped result, info, Eq, t:
  1402. copyTree result, x
  1403. result.addNilVal info, t
  1404. result
  1405. template eqZero(x: Tree): Tree =
  1406. var result = default(Tree)
  1407. buildTyped result, info, Eq, c.m.nativeIntId:
  1408. copyTree result, x
  1409. result.addIntVal c.lit.numbers, info, c.m.nativeIntId, 0
  1410. result
  1411. template bitOp(x: Tree; opc: Opcode; y: int): Tree =
  1412. var result = default(Tree)
  1413. buildTyped result, info, opc, c.m.nativeIntId:
  1414. copyTree result, x
  1415. result.addIntVal c.lit.numbers, info, c.m.nativeIntId, y
  1416. result
  1417. proc genDestroySeq(c: var ProcCon; n: PNode; t: PType) =
  1418. let info = toLineInfo(c, n.info)
  1419. let strLitFlag = 1 shl (c.m.graph.config.target.intSize * 8 - 2) # see also NIM_STRLIT_FLAG
  1420. let x = c.genx(n[1])
  1421. let baseType = t.elementType
  1422. let seqType = typeToIr(c.m, t)
  1423. let p = fieldAt(x, 0, seqType)
  1424. # if $1.p != nil and ($1.p.cap and NIM_STRLIT_FLAG) == 0:
  1425. # alignedDealloc($1.p, NIM_ALIGNOF($2))
  1426. buildIfNot p.eqNil(seqType):
  1427. buildIf fieldAt(Value(p), 0, seqPayloadPtrType(c.m.types, c.m.nirm.types, t)[0]).bitOp(BitAnd, 0).eqZero():
  1428. let codegenProc = getCompilerProc(c.m.graph, "alignedDealloc")
  1429. buildTyped c.code, info, Call, VoidId:
  1430. let theProc = c.genx newSymNode(codegenProc, n.info)
  1431. copyTree c.code, theProc
  1432. copyTree c.code, p
  1433. c.code.addImmediateVal info, int(getAlign(c.config, baseType))
  1434. freeTemp c, x
  1435. proc genDestroy(c: var ProcCon; n: PNode) =
  1436. let t = n[1].typ.skipTypes(abstractInst)
  1437. case t.kind
  1438. of tyString:
  1439. var unused = default(Value)
  1440. genUnaryCp(c, n, unused, "nimDestroyStrV1")
  1441. of tySequence:
  1442. genDestroySeq(c, n, t)
  1443. else: discard "nothing to do"
  1444. type
  1445. IndexFor = enum
  1446. ForSeq, ForStr, ForOpenArray, ForArray
  1447. proc genIndexCheck(c: var ProcCon; n: PNode; a: Value; kind: IndexFor; arr: PType): Value =
  1448. if optBoundsCheck in c.options:
  1449. let info = toLineInfo(c, n.info)
  1450. result = default(Value)
  1451. let idx = genx(c, n)
  1452. build result, info, CheckedIndex:
  1453. result.Tree.addLabel info, CheckedGoto, c.exitLabel
  1454. copyTree result.Tree, idx
  1455. case kind
  1456. of ForSeq, ForStr:
  1457. buildTyped result, info, FieldAt, typeToIr(c.m, arr):
  1458. copyTree result.Tree, a
  1459. result.addImmediateVal info, 0 # (len, p)-pair
  1460. of ForOpenArray:
  1461. buildTyped result, info, FieldAt, typeToIr(c.m, arr):
  1462. copyTree result.Tree, a
  1463. result.addImmediateVal info, 1 # (p, len)-pair
  1464. of ForArray:
  1465. let x = toInt64 lengthOrd(c.config, arr)
  1466. result.addIntVal c.lit.numbers, info, c.m.nativeIntId, x
  1467. freeTemp c, idx
  1468. else:
  1469. result = genx(c, n)
  1470. proc addSliceFields(c: var ProcCon; target: var Tree; info: PackedLineInfo;
  1471. x: Value; n: PNode; arrType: PType) =
  1472. let elemType = arrayPtrTypeOf(c.m.nirm.types, typeToIr(c.m, arrType.elementType))
  1473. case arrType.kind
  1474. of tyString, tySequence:
  1475. let checkKind = if arrType.kind == tyString: ForStr else: ForSeq
  1476. let pay = if checkKind == ForStr: c.m.strPayloadId
  1477. else: seqPayloadPtrType(c.m.types, c.m.nirm.types, arrType)
  1478. let y = genIndexCheck(c, n[2], x, checkKind, arrType)
  1479. let z = genIndexCheck(c, n[3], x, checkKind, arrType)
  1480. buildTyped target, info, ObjConstr, typeToIr(c.m, n.typ):
  1481. target.addImmediateVal info, 0
  1482. buildTyped target, info, AddrOf, elemType:
  1483. buildTyped target, info, DerefArrayAt, pay[1]:
  1484. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1485. copyTree target, x
  1486. target.addImmediateVal info, 1 # (len, p)-pair
  1487. copyTree target, y
  1488. # len:
  1489. target.addImmediateVal info, 1
  1490. buildTyped target, info, Add, c.m.nativeIntId:
  1491. buildTyped target, info, Sub, c.m.nativeIntId:
  1492. copyTree target, z
  1493. copyTree target, y
  1494. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 1
  1495. freeTemp c, z
  1496. freeTemp c, y
  1497. of tyArray:
  1498. # XXX This evaluates the index check for `y` twice.
  1499. # This check is also still insufficient for non-zero based arrays.
  1500. let y = genIndexCheck(c, n[2], x, ForArray, arrType)
  1501. let z = genIndexCheck(c, n[3], x, ForArray, arrType)
  1502. buildTyped target, info, ObjConstr, typeToIr(c.m, n.typ):
  1503. target.addImmediateVal info, 0
  1504. buildTyped target, info, AddrOf, elemType:
  1505. buildTyped target, info, ArrayAt, typeToIr(c.m, arrType):
  1506. copyTree target, x
  1507. copyTree target, y
  1508. target.addImmediateVal info, 1
  1509. buildTyped target, info, Add, c.m.nativeIntId:
  1510. buildTyped target, info, Sub, c.m.nativeIntId:
  1511. copyTree target, z
  1512. copyTree target, y
  1513. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 1
  1514. freeTemp c, z
  1515. freeTemp c, y
  1516. of tyOpenArray:
  1517. # XXX This evaluates the index check for `y` twice.
  1518. let y = genIndexCheck(c, n[2], x, ForOpenArray, arrType)
  1519. let z = genIndexCheck(c, n[3], x, ForOpenArray, arrType)
  1520. let pay = openArrayPayloadType(c.m.types, c.m.nirm.types, arrType)
  1521. buildTyped target, info, ObjConstr, typeToIr(c.m, n.typ):
  1522. target.addImmediateVal info, 0
  1523. buildTyped target, info, AddrOf, elemType:
  1524. buildTyped target, info, DerefArrayAt, pay:
  1525. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1526. copyTree target, x
  1527. target.addImmediateVal info, 0 # (p, len)-pair
  1528. copyTree target, y
  1529. target.addImmediateVal info, 1
  1530. buildTyped target, info, Add, c.m.nativeIntId:
  1531. buildTyped target, info, Sub, c.m.nativeIntId:
  1532. copyTree target, z
  1533. copyTree target, y
  1534. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 1
  1535. freeTemp c, z
  1536. freeTemp c, y
  1537. else:
  1538. raiseAssert "addSliceFields: " & typeToString(arrType)
  1539. proc genSlice(c: var ProcCon; n: PNode; d: var Value) =
  1540. let info = toLineInfo(c, n.info)
  1541. let x = c.genx(n[1])
  1542. let arrType = n[1].typ.skipTypes(abstractVar)
  1543. template body(target) =
  1544. c.addSliceFields target, info, x, n, arrType
  1545. valueIntoDest c, info, d, arrType, body
  1546. freeTemp c, x
  1547. proc genMagic(c: var ProcCon; n: PNode; d: var Value; m: TMagic) =
  1548. case m
  1549. of mAnd: c.genAndOr(n, opcFJmp, d)
  1550. of mOr: c.genAndOr(n, opcTJmp, d)
  1551. of mPred, mSubI: c.genBinaryOp(n, d, if optOverflowCheck in c.options: CheckedSub else: Sub)
  1552. of mSucc, mAddI: c.genBinaryOp(n, d, if optOverflowCheck in c.options: CheckedAdd else: Add)
  1553. of mInc:
  1554. unused(c, n, d)
  1555. c.genIncDec(n, if optOverflowCheck in c.options: CheckedAdd else: Add)
  1556. of mDec:
  1557. unused(c, n, d)
  1558. c.genIncDec(n, if optOverflowCheck in c.options: CheckedSub else: Sub)
  1559. of mOrd, mChr, mUnown:
  1560. c.gen(n[1], d)
  1561. of generatedMagics:
  1562. genCall(c, n, d)
  1563. of mNew, mNewFinalize:
  1564. unused(c, n, d)
  1565. c.genNew(n, needsInit = true)
  1566. of mNewSeq:
  1567. unused(c, n, d)
  1568. c.genNewSeq(n)
  1569. of mNewSeqOfCap: c.genNewSeqOfCap(n, d)
  1570. of mNewString, mNewStringOfCap, mExit: c.genCall(n, d)
  1571. of mLengthOpenArray, mLengthArray, mLengthSeq, mLengthStr:
  1572. genArrayLen(c, n, d)
  1573. of mMulI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedMul else: Mul)
  1574. of mDivI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedDiv else: Div)
  1575. of mModI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedMod else: Mod)
  1576. of mAddF64: genBinaryOp(c, n, d, Add)
  1577. of mSubF64: genBinaryOp(c, n, d, Sub)
  1578. of mMulF64: genBinaryOp(c, n, d, Mul)
  1579. of mDivF64: genBinaryOp(c, n, d, Div)
  1580. of mShrI: genBinaryOp(c, n, d, BitShr)
  1581. of mShlI: genBinaryOp(c, n, d, BitShl)
  1582. of mAshrI: genBinaryOp(c, n, d, BitShr)
  1583. of mBitandI: genBinaryOp(c, n, d, BitAnd)
  1584. of mBitorI: genBinaryOp(c, n, d, BitOr)
  1585. of mBitxorI: genBinaryOp(c, n, d, BitXor)
  1586. of mAddU: genBinaryOp(c, n, d, Add)
  1587. of mSubU: genBinaryOp(c, n, d, Sub)
  1588. of mMulU: genBinaryOp(c, n, d, Mul)
  1589. of mDivU: genBinaryOp(c, n, d, Div)
  1590. of mModU: genBinaryOp(c, n, d, Mod)
  1591. of mEqI, mEqB, mEqEnum, mEqCh:
  1592. genCmpOp(c, n, d, Eq)
  1593. of mLeI, mLeEnum, mLeCh, mLeB:
  1594. genCmpOp(c, n, d, Le)
  1595. of mLtI, mLtEnum, mLtCh, mLtB:
  1596. genCmpOp(c, n, d, Lt)
  1597. of mEqF64: genCmpOp(c, n, d, Eq)
  1598. of mLeF64: genCmpOp(c, n, d, Le)
  1599. of mLtF64: genCmpOp(c, n, d, Lt)
  1600. of mLePtr, mLeU: genCmpOp(c, n, d, Le)
  1601. of mLtPtr, mLtU: genCmpOp(c, n, d, Lt)
  1602. of mEqProc, mEqRef:
  1603. genCmpOp(c, n, d, Eq)
  1604. of mXor: genBinaryOp(c, n, d, BitXor)
  1605. of mNot: genUnaryOp(c, n, d, BoolNot)
  1606. of mUnaryMinusI, mUnaryMinusI64:
  1607. genUnaryMinus(c, n, d)
  1608. #genNarrow(c, n, d)
  1609. of mUnaryMinusF64: genUnaryMinus(c, n, d)
  1610. of mUnaryPlusI, mUnaryPlusF64: gen(c, n[1], d)
  1611. of mBitnotI:
  1612. genUnaryOp(c, n, d, BitNot)
  1613. when false:
  1614. # XXX genNarrowU modified, do not narrow signed types
  1615. let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
  1616. let size = getSize(c.config, t)
  1617. if t.kind in {tyUInt8..tyUInt32} or (t.kind == tyUInt and size < 8):
  1618. c.gABC(n, opcNarrowU, d, TRegister(size*8))
  1619. of mStrToStr, mEnsureMove: c.gen n[1], d
  1620. of mBoolToStr: genUnaryCp(c, n, d, "nimBoolToStr")
  1621. of mCharToStr: genUnaryCp(c, n, d, "nimCharToStr")
  1622. of mCStrToStr: genUnaryCp(c, n, d, "cstrToNimstr")
  1623. of mEnumToStr: genEnumToStr(c, n, d)
  1624. of mEqStr: genBinaryCp(c, n, d, "eqStrings")
  1625. of mEqCString: genCall(c, n, d)
  1626. of mLeStr: genBinaryCp(c, n, d, "leStrings")
  1627. of mLtStr: genBinaryCp(c, n, d, "ltStrings")
  1628. of mSetLengthStr:
  1629. unused(c, n, d)
  1630. let nb = copyTree(n)
  1631. nb[1] = makeAddr(nb[1], c.m.idgen)
  1632. genBinaryCp(c, nb, d, "setLengthStrV2")
  1633. of mSetLengthSeq:
  1634. unused(c, n, d)
  1635. let nb = copyTree(n)
  1636. nb[1] = makeAddr(nb[1], c.m.idgen)
  1637. genCall(c, nb, d)
  1638. of mSwap:
  1639. unused(c, n, d)
  1640. c.gen(lowerSwap(c.m.graph, n, c.m.idgen,
  1641. if c.prc == nil: c.m.module else: c.prc), d)
  1642. of mParseBiggestFloat:
  1643. genCall c, n, d
  1644. of mHigh:
  1645. c.genHigh n, d
  1646. of mEcho:
  1647. unused(c, n, d)
  1648. genUnaryCp c, n, d, "echoBinSafe"
  1649. of mAppendStrCh:
  1650. unused(c, n, d)
  1651. let nb = copyTree(n)
  1652. nb[1] = makeAddr(nb[1], c.m.idgen)
  1653. genBinaryCp(c, nb, d, "nimAddCharV1")
  1654. of mMinI, mMaxI, mAbsI, mDotDot:
  1655. c.genCall(n, d)
  1656. of mSizeOf:
  1657. localError(c.config, n.info, sizeOfLikeMsg("sizeof"))
  1658. of mAlignOf:
  1659. localError(c.config, n.info, sizeOfLikeMsg("alignof"))
  1660. of mOffsetOf:
  1661. localError(c.config, n.info, sizeOfLikeMsg("offsetof"))
  1662. of mRunnableExamples:
  1663. discard "just ignore any call to runnableExamples"
  1664. of mOf: genOf(c, n, d)
  1665. of mAppendStrStr:
  1666. unused(c, n, d)
  1667. let nb = copyTree(n)
  1668. nb[1] = makeAddr(nb[1], c.m.idgen)
  1669. genBinaryCp(c, nb, d, "nimAddStrV1")
  1670. of mAppendSeqElem:
  1671. unused(c, n, d)
  1672. let nb = copyTree(n)
  1673. nb[1] = makeAddr(nb[1], c.m.idgen)
  1674. genCall(c, nb, d)
  1675. of mIsNil: genIsNil(c, n, d)
  1676. of mInSet: genInSet(c, n, d)
  1677. of mCard: genCard(c, n, d)
  1678. of mEqSet: genEqSet(c, n, d)
  1679. of mLeSet: genLeSet(c, n, d)
  1680. of mLtSet: genLtSet(c, n, d)
  1681. of mMulSet: genBinarySet(c, n, d, m)
  1682. of mPlusSet: genBinarySet(c, n, d, m)
  1683. of mMinusSet: genBinarySet(c, n, d, m)
  1684. of mIncl, mExcl:
  1685. unused(c, n, d)
  1686. genInclExcl(c, n, m)
  1687. of mConStrStr: genStrConcat(c, n, d)
  1688. of mDefault, mZeroDefault:
  1689. genDefault c, n, d
  1690. of mMove: genMove(c, n, d)
  1691. of mWasMoved:
  1692. unused(c, n, d)
  1693. genWasMoved(c, n)
  1694. of mDestroy: genDestroy(c, n)
  1695. #of mAccessEnv: unaryExpr(d, n, d, "$1.ClE_0")
  1696. #of mAccessTypeField: genAccessTypeField(c, n, d)
  1697. of mSlice: genSlice(c, n, d)
  1698. of mTrace: discard "no code to generate"
  1699. else:
  1700. # mGCref, mGCunref: unused by ORC
  1701. globalError(c.config, n.info, "cannot generate code for: " & $m)
  1702. proc canElimAddr(n: PNode; idgen: IdGenerator): PNode =
  1703. result = nil
  1704. case n[0].kind
  1705. of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
  1706. var m = n[0][0]
  1707. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1708. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1709. result = copyNode(n[0])
  1710. result.add m[0]
  1711. if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
  1712. result.typ = n.typ
  1713. elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
  1714. result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
  1715. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1716. var m = n[0][1]
  1717. if m.kind in {nkDerefExpr, nkHiddenDeref}:
  1718. # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
  1719. result = copyNode(n[0])
  1720. result.add n[0][0]
  1721. result.add m[0]
  1722. if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
  1723. result.typ = n.typ
  1724. elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
  1725. result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
  1726. else:
  1727. if n[0].kind in {nkDerefExpr, nkHiddenDeref}:
  1728. # addr ( deref ( x )) --> x
  1729. result = n[0][0]
  1730. proc genAddr(c: var ProcCon; n: PNode; d: var Value, flags: GenFlags) =
  1731. if (let m = canElimAddr(n, c.m.idgen); m != nil):
  1732. gen(c, m, d, flags)
  1733. return
  1734. let info = toLineInfo(c, n.info)
  1735. let tmp = c.genx(n[0], flags)
  1736. template body(target) =
  1737. buildTyped target, info, AddrOf, typeToIr(c.m, n.typ):
  1738. copyTree target, tmp
  1739. valueIntoDest c, info, d, n.typ, body
  1740. freeTemp c, tmp
  1741. proc genDeref(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
  1742. let info = toLineInfo(c, n.info)
  1743. let tmp = c.genx(n[0], flags)
  1744. template body(target) =
  1745. buildTyped target, info, Load, typeToIr(c.m, n.typ):
  1746. copyTree target, tmp
  1747. valueIntoDest c, info, d, n.typ, body
  1748. freeTemp c, tmp
  1749. proc addAddrOfFirstElem(c: var ProcCon; target: var Tree; info: PackedLineInfo; tmp: Value; typ: PType) =
  1750. let arrType = typ.skipTypes(abstractVar)
  1751. let elemType = arrayPtrTypeOf(c.m.nirm.types, typeToIr(c.m, arrType.elementType))
  1752. case arrType.kind
  1753. of tyString:
  1754. let t = typeToIr(c.m, typ)
  1755. target.addImmediateVal info, 0
  1756. buildTyped target, info, AddrOf, elemType:
  1757. buildTyped target, info, DerefArrayAt, c.m.strPayloadId[1]:
  1758. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1759. copyTree target, tmp
  1760. target.addImmediateVal info, 1 # (len, p)-pair
  1761. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 0
  1762. # len:
  1763. target.addImmediateVal info, 1
  1764. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1765. copyTree target, tmp
  1766. target.addImmediateVal info, 0 # (len, p)-pair so len is at index 0
  1767. of tySequence:
  1768. let t = typeToIr(c.m, typ)
  1769. target.addImmediateVal info, 0
  1770. buildTyped target, info, AddrOf, elemType:
  1771. buildTyped target, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, typ)[1]:
  1772. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1773. copyTree target, tmp
  1774. target.addImmediateVal info, 1 # (len, p)-pair
  1775. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 0
  1776. # len:
  1777. target.addImmediateVal info, 1
  1778. buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
  1779. copyTree target, tmp
  1780. target.addImmediateVal info, 0 # (len, p)-pair so len is at index 0
  1781. of tyArray:
  1782. let t = typeToIr(c.m, arrType)
  1783. target.addImmediateVal info, 0
  1784. buildTyped target, info, AddrOf, elemType:
  1785. buildTyped target, info, ArrayAt, t:
  1786. copyTree target, tmp
  1787. target.addIntVal c.lit.numbers, info, c.m.nativeIntId, 0
  1788. target.addImmediateVal info, 1
  1789. target.addIntVal(c.lit.numbers, info, c.m.nativeIntId, toInt lengthOrd(c.config, arrType))
  1790. else:
  1791. raiseAssert "addAddrOfFirstElem: " & typeToString(typ)
  1792. proc genToOpenArrayConv(c: var ProcCon; arg: PNode; d: var Value; flags: GenFlags; destType: PType) =
  1793. let info = toLineInfo(c, arg.info)
  1794. let tmp = c.genx(arg, flags)
  1795. let arrType = destType.skipTypes(abstractVar)
  1796. template body(target) =
  1797. buildTyped target, info, ObjConstr, typeToIr(c.m, arrType):
  1798. c.addAddrOfFirstElem target, info, tmp, arg.typ
  1799. valueIntoDest c, info, d, arrType, body
  1800. freeTemp c, tmp
  1801. proc genConv(c: var ProcCon; n, arg: PNode; d: var Value; flags: GenFlags; opc: Opcode) =
  1802. let targetType = n.typ.skipTypes({tyDistinct})
  1803. let argType = arg.typ.skipTypes({tyDistinct})
  1804. if sameBackendType(targetType, argType) or (
  1805. argType.kind == tyProc and targetType.kind == argType.kind):
  1806. # don't do anything for lambda lifting conversions:
  1807. gen c, arg, d
  1808. return
  1809. if opc != Cast and targetType.skipTypes({tyVar, tyLent}).kind in {tyOpenArray, tyVarargs} and
  1810. argType.skipTypes({tyVar, tyLent}).kind notin {tyOpenArray, tyVarargs}:
  1811. genToOpenArrayConv c, arg, d, flags, n.typ
  1812. return
  1813. let info = toLineInfo(c, n.info)
  1814. let tmp = c.genx(arg, flags)
  1815. template body(target) =
  1816. buildTyped target, info, opc, typeToIr(c.m, n.typ):
  1817. if opc == CheckedObjConv:
  1818. target.addLabel info, CheckedGoto, c.exitLabel
  1819. copyTree target, tmp
  1820. valueIntoDest c, info, d, n.typ, body
  1821. freeTemp c, tmp
  1822. proc genObjOrTupleConstr(c: var ProcCon; n: PNode; d: var Value; t: PType) =
  1823. # XXX x = (x.old, 22) produces wrong code ... stupid self assignments
  1824. let info = toLineInfo(c, n.info)
  1825. template body(target) =
  1826. buildTyped target, info, ObjConstr, typeToIr(c.m, t):
  1827. for i in ord(n.kind == nkObjConstr)..<n.len:
  1828. let it = n[i]
  1829. if it.kind == nkExprColonExpr:
  1830. genField(c, it[0], Value target)
  1831. let tmp = c.genx(it[1])
  1832. copyTree target, tmp
  1833. c.freeTemp(tmp)
  1834. else:
  1835. let tmp = c.genx(it)
  1836. target.addImmediateVal info, i
  1837. copyTree target, tmp
  1838. c.freeTemp(tmp)
  1839. if isException(t):
  1840. target.addImmediateVal info, 1 # "name" field is at position after the "parent". See system.nim
  1841. target.addStrVal c.lit.strings, info, t.skipTypes(abstractInst).sym.name.s
  1842. constrIntoDest c, info, d, t, body
  1843. proc genRefObjConstr(c: var ProcCon; n: PNode; d: var Value) =
  1844. if isEmpty(d): d = getTemp(c, n)
  1845. let info = toLineInfo(c, n.info)
  1846. let refType = n.typ.skipTypes(abstractInstOwned)
  1847. let objType = refType.elementType
  1848. rawGenNew(c, d, refType, n.info, needsInit = nfAllFieldsSet notin n.flags)
  1849. var deref = default(Value)
  1850. deref.buildTyped info, Load, typeToIr(c.m, objType):
  1851. deref.Tree.copyTree d
  1852. genObjOrTupleConstr c, n, deref, objType
  1853. proc genSeqConstr(c: var ProcCon; n: PNode; d: var Value) =
  1854. if isEmpty(d): d = getTemp(c, n)
  1855. let info = toLineInfo(c, n.info)
  1856. let seqtype = skipTypes(n.typ, abstractVarRange)
  1857. let baseType = seqtype.elementType
  1858. var b = default(Value)
  1859. b.addIntVal c.lit.numbers, info, c.m.nativeIntId, n.len
  1860. genNewSeqPayload(c, info, d, b, seqtype)
  1861. for i in 0..<n.len:
  1862. var dd = default(Value)
  1863. buildTyped dd, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, seqtype)[1]:
  1864. buildTyped dd, info, FieldAt, typeToIr(c.m, seqtype):
  1865. copyTree Tree(dd), d
  1866. dd.addImmediateVal info, 1 # (len, p)-pair
  1867. dd.addIntVal c.lit.numbers, info, c.m.nativeIntId, i
  1868. gen(c, n[i], dd)
  1869. freeTemp c, d
  1870. proc genArrayConstr(c: var ProcCon; n: PNode, d: var Value) =
  1871. let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
  1872. if seqType.kind == tySequence:
  1873. genSeqConstr(c, n, d)
  1874. return
  1875. let info = toLineInfo(c, n.info)
  1876. template body(target) =
  1877. buildTyped target, info, ArrayConstr, typeToIr(c.m, n.typ):
  1878. for i in 0..<n.len:
  1879. let tmp = c.genx(n[i])
  1880. copyTree target, tmp
  1881. c.freeTemp(tmp)
  1882. constrIntoDest c, info, d, n.typ, body
  1883. proc genAsgn2(c: var ProcCon; a, b: PNode) =
  1884. assert a != nil
  1885. assert b != nil
  1886. var d = c.genx(a)
  1887. c.gen b, d
  1888. proc irModule(c: var ProcCon; owner: PSym): string =
  1889. #if owner == c.m.module: "" else:
  1890. customPath(toFullPath(c.config, owner.info))
  1891. proc fromForeignModule(c: ProcCon; s: PSym): bool {.inline.} =
  1892. result = ast.originatingModule(s) != c.m.module and not c.m.noModularity
  1893. proc genForeignVar(c: var ProcCon; s: PSym) =
  1894. var opc: Opcode
  1895. if s.kind == skConst:
  1896. opc = SummonConst
  1897. elif sfThread in s.flags:
  1898. opc = SummonThreadLocal
  1899. else:
  1900. assert sfGlobal in s.flags
  1901. opc = SummonGlobal
  1902. let t = typeToIr(c.m, s.typ)
  1903. let info = toLineInfo(c, s.info)
  1904. build c.code, info, ForeignDecl:
  1905. buildTyped c.code, info, opc, t:
  1906. build c.code, info, ModuleSymUse:
  1907. c.code.addStrVal c.lit.strings, info, irModule(c, ast.originatingModule(s))
  1908. c.code.addImmediateVal info, s.itemId.item.int
  1909. proc genVarSection(c: var ProcCon; n: PNode) =
  1910. for a in n:
  1911. if a.kind == nkCommentStmt: continue
  1912. #assert(a[0].kind == nkSym) can happen for transformed vars
  1913. if a.kind == nkVarTuple:
  1914. c.gen(lowerTupleUnpacking(c.m.graph, a, c.m.idgen, c.prc))
  1915. else:
  1916. var vn = a[0]
  1917. if vn.kind == nkPragmaExpr: vn = vn[0]
  1918. if vn.kind == nkSym:
  1919. let s = vn.sym
  1920. if s.kind == skConst:
  1921. if dontInlineConstant(n, s.astdef):
  1922. let symId = toSymId(c, s)
  1923. c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
  1924. let val = c.genx(s.astdef)
  1925. let info = toLineInfo(c, a.info)
  1926. buildTyped c.code, info, SummonConst, typeToIr(c.m, s.typ):
  1927. c.code.addSymDef info, symId
  1928. c.code.copyTree val
  1929. freeTemp c, val
  1930. else:
  1931. var opc: Opcode
  1932. if sfThread in s.flags:
  1933. opc = SummonThreadLocal
  1934. elif sfGlobal in s.flags:
  1935. opc = SummonGlobal
  1936. else:
  1937. opc = Summon
  1938. #assert t.int >= 0, typeToString(s.typ) & (c.config $ n.info)
  1939. let symId = toSymId(c, s)
  1940. c.code.addSummon toLineInfo(c, a.info), symId, typeToIr(c.m, s.typ), opc
  1941. c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
  1942. if a[2].kind != nkEmpty:
  1943. genAsgn2(c, vn, a[2])
  1944. else:
  1945. if a[2].kind == nkEmpty:
  1946. genAsgn2(c, vn, expandDefault(vn.typ, vn.info))
  1947. else:
  1948. genAsgn2(c, vn, a[2])
  1949. proc genAsgn(c: var ProcCon; n: PNode) =
  1950. var d = c.genx(n[0])
  1951. c.gen n[1], d
  1952. proc convStrToCStr(c: var ProcCon; n: PNode; d: var Value) =
  1953. genUnaryCp(c, n, d, "nimToCStringConv", argAt = 0)
  1954. proc convCStrToStr(c: var ProcCon; n: PNode; d: var Value) =
  1955. genUnaryCp(c, n, d, "cstrToNimstr", argAt = 0)
  1956. proc genRdVar(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
  1957. let info = toLineInfo(c, n.info)
  1958. let s = n.sym
  1959. if fromForeignModule(c, s):
  1960. if s.kind in {skVar, skConst, skLet} and not c.m.pendingVarsAsSet.containsOrIncl(s.itemId):
  1961. c.m.pendingVars.add s
  1962. template body(target) =
  1963. build target, info, ModuleSymUse:
  1964. target.addStrVal c.lit.strings, info, irModule(c, ast.originatingModule(s))
  1965. target.addImmediateVal info, s.itemId.item.int
  1966. valueIntoDest c, info, d, s.typ, body
  1967. else:
  1968. template body(target) =
  1969. target.addSymUse info, toSymId(c, s)
  1970. valueIntoDest c, info, d, s.typ, body
  1971. proc genSym(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags = {}) =
  1972. let s = n.sym
  1973. case s.kind
  1974. of skConst:
  1975. if dontInlineConstant(n, s.astdef):
  1976. genRdVar(c, n, d, flags)
  1977. else:
  1978. gen(c, s.astdef, d, flags)
  1979. of skVar, skForVar, skTemp, skLet, skResult, skParam:
  1980. genRdVar(c, n, d, flags)
  1981. of skProc, skFunc, skConverter, skMethod, skIterator:
  1982. if not c.m.noModularity:
  1983. # anon and generic procs have no AST so we need to remember not to forget
  1984. # to emit these:
  1985. if not c.m.processedProcs.contains(s.itemId):
  1986. if not c.m.pendingProcsAsSet.containsOrIncl(s.itemId):
  1987. c.m.pendingProcs.add s
  1988. genRdVar(c, n, d, flags)
  1989. of skEnumField:
  1990. let info = toLineInfo(c, n.info)
  1991. template body(target) =
  1992. target.addIntVal c.lit.numbers, info, typeToIr(c.m, n.typ), s.position
  1993. valueIntoDest c, info, d, n.typ, body
  1994. else:
  1995. localError(c.config, n.info, "cannot generate code for: " & s.name.s)
  1996. proc genNumericLit(c: var ProcCon; n: PNode; d: var Value; bits: int64) =
  1997. let info = toLineInfo(c, n.info)
  1998. template body(target) =
  1999. target.addIntVal c.lit.numbers, info, typeToIr(c.m, n.typ), bits
  2000. valueIntoDest c, info, d, n.typ, body
  2001. proc genStringLit(c: var ProcCon; n: PNode; d: var Value) =
  2002. let info = toLineInfo(c, n.info)
  2003. template body(target) =
  2004. target.addStrVal c.lit.strings, info, n.strVal
  2005. valueIntoDest c, info, d, n.typ, body
  2006. proc genNilLit(c: var ProcCon; n: PNode; d: var Value) =
  2007. let info = toLineInfo(c, n.info)
  2008. template body(target) =
  2009. target.addNilVal info, typeToIr(c.m, n.typ)
  2010. valueIntoDest c, info, d, n.typ, body
  2011. proc genRangeCheck(c: var ProcCon; n: PNode; d: var Value) =
  2012. if optRangeCheck in c.options:
  2013. let info = toLineInfo(c, n.info)
  2014. let tmp = c.genx n[0]
  2015. let a = c.genx n[1]
  2016. let b = c.genx n[2]
  2017. template body(target) =
  2018. buildTyped target, info, CheckedRange, typeToIr(c.m, n.typ):
  2019. target.addLabel info, CheckedGoto, c.exitLabel
  2020. copyTree target, tmp
  2021. copyTree target, a
  2022. copyTree target, b
  2023. valueIntoDest c, info, d, n.typ, body
  2024. freeTemp c, tmp
  2025. freeTemp c, a
  2026. freeTemp c, b
  2027. else:
  2028. gen c, n[0], d
  2029. proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
  2030. let arrayType = n[0].typ.skipTypes(abstractVarRange-{tyTypeDesc})
  2031. let arrayKind = arrayType.kind
  2032. let info = toLineInfo(c, n.info)
  2033. case arrayKind
  2034. of tyString:
  2035. let a = genx(c, n[0], flags)
  2036. let b = genIndexCheck(c, n[1], a, ForStr, arrayType)
  2037. let t = typeToIr(c.m, n.typ)
  2038. template body(target) =
  2039. buildTyped target, info, DerefArrayAt, c.m.strPayloadId[1]:
  2040. buildTyped target, info, FieldAt, typeToIr(c.m, arrayType):
  2041. copyTree target, a
  2042. target.addImmediateVal info, 1 # (len, p)-pair
  2043. copyTree target, b
  2044. intoDest d, info, t, body
  2045. freeTemp c, b
  2046. freeTemp c, a
  2047. of tyCstring, tyPtr, tyUncheckedArray:
  2048. let a = genx(c, n[0], flags)
  2049. let b = genx(c, n[1])
  2050. template body(target) =
  2051. buildTyped target, info, DerefArrayAt, typeToIr(c.m, arrayType):
  2052. copyTree target, a
  2053. copyTree target, b
  2054. valueIntoDest c, info, d, n.typ, body
  2055. freeTemp c, b
  2056. freeTemp c, a
  2057. of tyTuple:
  2058. let a = genx(c, n[0], flags)
  2059. let b = int n[1].intVal
  2060. template body(target) =
  2061. buildTyped target, info, FieldAt, typeToIr(c.m, arrayType):
  2062. copyTree target, a
  2063. target.addImmediateVal info, b
  2064. valueIntoDest c, info, d, n.typ, body
  2065. freeTemp c, a
  2066. of tyOpenArray, tyVarargs:
  2067. let a = genx(c, n[0], flags)
  2068. let b = genIndexCheck(c, n[1], a, ForOpenArray, arrayType)
  2069. let t = typeToIr(c.m, n.typ)
  2070. template body(target) =
  2071. buildTyped target, info, DerefArrayAt, openArrayPayloadType(c.m.types, c.m.nirm.types, n[0].typ):
  2072. buildTyped target, info, FieldAt, typeToIr(c.m, arrayType):
  2073. copyTree target, a
  2074. target.addImmediateVal info, 0 # (p, len)-pair
  2075. copyTree target, b
  2076. intoDest d, info, t, body
  2077. freeTemp c, b
  2078. freeTemp c, a
  2079. of tyArray:
  2080. let a = genx(c, n[0], flags)
  2081. var b = default(Value)
  2082. genIndex(c, n[1], n[0].typ, b)
  2083. template body(target) =
  2084. buildTyped target, info, ArrayAt, typeToIr(c.m, arrayType):
  2085. copyTree target, a
  2086. copyTree target, b
  2087. valueIntoDest c, info, d, n.typ, body
  2088. freeTemp c, b
  2089. freeTemp c, a
  2090. of tySequence:
  2091. let a = genx(c, n[0], flags)
  2092. let b = genIndexCheck(c, n[1], a, ForSeq, arrayType)
  2093. let t = typeToIr(c.m, n.typ)
  2094. template body(target) =
  2095. buildTyped target, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, n[0].typ)[1]:
  2096. buildTyped target, info, FieldAt, t:
  2097. copyTree target, a
  2098. target.addImmediateVal info, 1 # (len, p)-pair
  2099. copyTree target, b
  2100. intoDest d, info, t, body
  2101. freeTemp c, b
  2102. freeTemp c, a
  2103. else:
  2104. localError c.config, n.info, "invalid type for nkBracketExpr: " & $arrayKind
  2105. proc genObjAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
  2106. let info = toLineInfo(c, n.info)
  2107. var n0 = n[0]
  2108. var opc = FieldAt
  2109. if n0.kind == nkDotExpr:
  2110. # obj[].a --> DerefFieldAt instead of FieldAt:
  2111. n0 = n[0]
  2112. opc = DerefFieldAt
  2113. let a = genx(c, n0, flags)
  2114. template body(target) =
  2115. buildTyped target, info, opc, typeToIr(c.m, n0.typ):
  2116. copyTree target, a
  2117. genField c, n[1], Value(target)
  2118. valueIntoDest c, info, d, n.typ, body
  2119. freeTemp c, a
  2120. proc genParams(c: var ProcCon; params: PNode; prc: PSym): PSym =
  2121. result = nil
  2122. if params.len > 0 and resultPos < prc.ast.len:
  2123. let resNode = prc.ast[resultPos]
  2124. result = resNode.sym # get result symbol
  2125. c.code.addSummon toLineInfo(c, result.info), toSymId(c, result),
  2126. typeToIr(c.m, result.typ), SummonResult
  2127. elif prc.typ.len > 0 and not isEmptyType(prc.typ.returnType) and not isCompileTimeOnly(prc.typ.returnType):
  2128. # happens for procs without bodies:
  2129. let t = typeToIr(c.m, prc.typ.returnType)
  2130. let tmp = allocTemp(c, t)
  2131. c.code.addSummon toLineInfo(c, params.info), tmp, t, SummonResult
  2132. for i in 1..<params.len:
  2133. let s = params[i].sym
  2134. if not isCompileTimeOnly(s.typ):
  2135. let t = typeToIr(c.m, s.typ)
  2136. assert t.int != -1, typeToString(s.typ)
  2137. let symId = toSymId(c, s)
  2138. c.code.addSummon toLineInfo(c, params[i].info), symId, t, SummonParam
  2139. c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
  2140. proc addCallConv(c: var ProcCon; info: PackedLineInfo; callConv: TCallingConvention) =
  2141. template ann(s: untyped) = c.code.addPragmaId info, s
  2142. case callConv
  2143. of ccNimCall, ccFastCall, ccClosure: ann FastCall
  2144. of ccStdCall: ann StdCall
  2145. of ccCDecl: ann CDeclCall
  2146. of ccSafeCall: ann SafeCall
  2147. of ccSysCall: ann SysCall
  2148. of ccInline: ann InlineCall
  2149. of ccNoInline: ann NoinlineCall
  2150. of ccThisCall: ann ThisCall
  2151. of ccNoConvention, ccMember: ann NoCall
  2152. proc genProc(cOuter: var ProcCon; prc: PSym) =
  2153. if prc.magic notin generatedMagics: return
  2154. if cOuter.m.processedProcs.containsOrIncl(prc.itemId):
  2155. return
  2156. #assert cOuter.m.inProc == 0, " in nested proc! " & prc.name.s
  2157. if cOuter.m.inProc > 0:
  2158. if not cOuter.m.pendingProcsAsSet.containsOrIncl(prc.itemId):
  2159. cOuter.m.pendingProcs.add prc
  2160. return
  2161. inc cOuter.m.inProc
  2162. var c = initProcCon(cOuter.m, prc, cOuter.m.graph.config)
  2163. let body =
  2164. if not fromForeignModule(c, prc):
  2165. transformBody(c.m.graph, c.m.idgen, prc, {useCache, keepOpenArrayConversions})
  2166. else:
  2167. nil
  2168. let info = toLineInfo(c, prc.info)
  2169. build c.code, info, (if body != nil: ProcDecl else: ForeignProcDecl):
  2170. if body != nil:
  2171. let symId = toSymId(c, prc)
  2172. addSymDef c.code, info, symId
  2173. c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(prc.name.s)
  2174. else:
  2175. build c.code, info, ModuleSymUse:
  2176. c.code.addStrVal c.lit.strings, info, irModule(c, ast.originatingModule(prc))
  2177. c.code.addImmediateVal info, prc.itemId.item.int
  2178. addCallConv c, info, prc.typ.callConv
  2179. if sfCompilerProc in prc.flags:
  2180. build c.code, info, PragmaPair:
  2181. c.code.addPragmaId info, CoreName
  2182. c.code.addStrVal c.lit.strings, info, prc.name.s
  2183. if {sfImportc, sfExportc} * prc.flags != {}:
  2184. build c.code, info, PragmaPair:
  2185. c.code.addPragmaId info, ExternName
  2186. c.code.addStrVal c.lit.strings, info, prc.loc.r
  2187. if sfImportc in prc.flags:
  2188. if lfHeader in prc. loc.flags:
  2189. assert(prc. annex != nil)
  2190. let str = getStr(prc. annex.path)
  2191. build c.code, info, PragmaPair:
  2192. c.code.addPragmaId info, HeaderImport
  2193. c.code.addStrVal c.lit.strings, info, str
  2194. elif lfDynamicLib in prc. loc.flags:
  2195. assert(prc. annex != nil)
  2196. let str = getStr(prc. annex.path)
  2197. build c.code, info, PragmaPair:
  2198. c.code.addPragmaId info, DllImport
  2199. c.code.addStrVal c.lit.strings, info, str
  2200. elif sfExportc in prc.flags:
  2201. if lfDynamicLib in prc. loc.flags:
  2202. c.code.addPragmaId info, DllExport
  2203. else:
  2204. c.code.addPragmaId info, ObjExport
  2205. let resultSym = genParams(c, prc.typ.n, prc)
  2206. if body != nil:
  2207. gen(c, body)
  2208. patch c, body, c.exitLabel
  2209. if resultSym != nil:
  2210. build c.code, info, Ret:
  2211. c.code.addSymUse info, toSymId(c, resultSym)
  2212. else:
  2213. build c.code, info, Ret:
  2214. c.code.addNop info
  2215. #copyTree cOuter.code, c.code
  2216. dec cOuter.m.inProc
  2217. proc genProc(cOuter: var ProcCon; n: PNode) =
  2218. if n.len == 0 or n[namePos].kind != nkSym: return
  2219. let prc = n[namePos].sym
  2220. if isGenericRoutineStrict(prc) or isCompileTimeProc(prc) or sfForward in prc.flags: return
  2221. genProc cOuter, prc
  2222. proc genClosureCall(c: var ProcCon; n: PNode; d: var Value) =
  2223. let typ = skipTypes(n[0].typ, abstractInstOwned)
  2224. if tfIterator in typ.flags:
  2225. const PatIter = "$1.ClP_0($3, $1.ClE_0)" # we know the env exists
  2226. else:
  2227. const PatProc = "$1.ClE_0? $1.ClP_0($3, $1.ClE_0):(($4)($1.ClP_0))($2)"
  2228. proc genComplexCall(c: var ProcCon; n: PNode; d: var Value) =
  2229. if n[0].typ != nil and n[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
  2230. # XXX genClosureCall p, n, d
  2231. genCall c, n, d
  2232. else:
  2233. genCall c, n, d
  2234. proc gen(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags = {}) =
  2235. when defined(nimCompilerStacktraceHints):
  2236. setFrameMsg c.config$n.info & " " & $n.kind & " " & $flags
  2237. case n.kind
  2238. of nkSym: genSym(c, n, d, flags)
  2239. of nkCallKinds:
  2240. if n[0].kind == nkSym:
  2241. let s = n[0].sym
  2242. if s.magic != mNone:
  2243. genMagic(c, n, d, s.magic)
  2244. elif s.kind == skMethod:
  2245. localError(c.config, n.info, "cannot call method " & s.name.s &
  2246. " at compile time")
  2247. else:
  2248. genComplexCall(c, n, d)
  2249. else:
  2250. genComplexCall(c, n, d)
  2251. of nkCharLit..nkInt64Lit, nkUIntLit..nkUInt64Lit:
  2252. genNumericLit(c, n, d, n.intVal)
  2253. of nkFloatLit..nkFloat128Lit:
  2254. genNumericLit(c, n, d, cast[int64](n.floatVal))
  2255. of nkStrLit..nkTripleStrLit:
  2256. genStringLit(c, n, d)
  2257. of nkNilLit:
  2258. if not n.typ.isEmptyType: genNilLit(c, n, d)
  2259. else: unused(c, n, d)
  2260. of nkAsgn, nkFastAsgn, nkSinkAsgn:
  2261. unused(c, n, d)
  2262. genAsgn(c, n)
  2263. of nkDotExpr: genObjAccess(c, n, d, flags)
  2264. of nkCheckedFieldExpr: genObjAccess(c, n[0], d, flags)
  2265. of nkBracketExpr: genArrAccess(c, n, d, flags)
  2266. of nkDerefExpr, nkHiddenDeref: genDeref(c, n, d, flags)
  2267. of nkAddr, nkHiddenAddr: genAddr(c, n, d, flags)
  2268. of nkIfStmt, nkIfExpr: genIf(c, n, d)
  2269. of nkWhenStmt:
  2270. # This is "when nimvm" node. Chose the first branch.
  2271. gen(c, n[0][1], d)
  2272. of nkCaseStmt: genCase(c, n, d)
  2273. of nkWhileStmt:
  2274. unused(c, n, d)
  2275. genWhile(c, n)
  2276. of nkBlockExpr, nkBlockStmt: genBlock(c, n, d)
  2277. of nkReturnStmt: genReturn(c, n)
  2278. of nkRaiseStmt: genRaise(c, n)
  2279. of nkBreakStmt: genBreak(c, n)
  2280. of nkTryStmt, nkHiddenTryStmt: genTry(c, n, d)
  2281. of nkStmtList:
  2282. #unused(c, n, d)
  2283. # XXX Fix this bug properly, lexim triggers it
  2284. for x in n: gen(c, x)
  2285. of nkStmtListExpr:
  2286. for i in 0..<n.len-1: gen(c, n[i])
  2287. gen(c, n[^1], d, flags)
  2288. of nkPragmaBlock:
  2289. gen(c, n.lastSon, d, flags)
  2290. of nkDiscardStmt:
  2291. unused(c, n, d)
  2292. gen(c, n[0], d)
  2293. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  2294. genConv(c, n, n[1], d, flags, NumberConv) # misnomer?
  2295. of nkObjDownConv:
  2296. genConv(c, n, n[0], d, flags, ObjConv)
  2297. of nkObjUpConv:
  2298. genConv(c, n, n[0], d, flags, CheckedObjConv)
  2299. of nkVarSection, nkLetSection, nkConstSection:
  2300. unused(c, n, d)
  2301. genVarSection(c, n)
  2302. of nkLambdaKinds:
  2303. #let s = n[namePos].sym
  2304. #discard genProc(c, s)
  2305. gen(c, newSymNode(n[namePos].sym), d)
  2306. of nkChckRangeF, nkChckRange64, nkChckRange:
  2307. genRangeCheck(c, n, d)
  2308. of declarativeDefs - {nkIteratorDef}:
  2309. unused(c, n, d)
  2310. genProc(c, n)
  2311. of nkEmpty, nkCommentStmt, nkTypeSection, nkPragma,
  2312. nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt,
  2313. nkMixinStmt, nkBindStmt, nkMacroDef, nkIteratorDef:
  2314. unused(c, n, d)
  2315. of nkStringToCString: convStrToCStr(c, n, d)
  2316. of nkCStringToString: convCStrToStr(c, n, d)
  2317. of nkBracket: genArrayConstr(c, n, d)
  2318. of nkCurly: genSetConstr(c, n, d)
  2319. of nkObjConstr:
  2320. if n.typ.skipTypes(abstractInstOwned).kind == tyRef:
  2321. genRefObjConstr(c, n, d)
  2322. else:
  2323. genObjOrTupleConstr(c, n, d, n.typ)
  2324. of nkPar, nkClosure, nkTupleConstr:
  2325. genObjOrTupleConstr(c, n, d, n.typ)
  2326. of nkCast:
  2327. genConv(c, n, n[1], d, flags, Cast)
  2328. of nkComesFrom:
  2329. discard "XXX to implement for better stack traces"
  2330. #of nkState: genState(c, n)
  2331. #of nkGotoState: genGotoState(c, n)
  2332. #of nkBreakState: genBreakState(c, n, d)
  2333. else:
  2334. localError(c.config, n.info, "cannot generate IR code for " & $n)
  2335. proc genPendingProcs(c: var ProcCon) =
  2336. while c.m.pendingProcs.len > 0 or c.m.pendingVars.len > 0:
  2337. let procs = move(c.m.pendingProcs)
  2338. for v in procs:
  2339. genProc(c, v)
  2340. let vars = move(c.m.pendingVars)
  2341. for v in vars:
  2342. genForeignVar(c, v)
  2343. proc genStmt*(c: var ProcCon; n: PNode): NodePos =
  2344. result = NodePos c.code.len
  2345. var d = default(Value)
  2346. c.gen(n, d)
  2347. unused c, n, d
  2348. genPendingProcs c
  2349. proc genExpr*(c: var ProcCon; n: PNode, requiresValue = true): int =
  2350. result = c.code.len
  2351. var d = default(Value)
  2352. c.gen(n, d)
  2353. genPendingProcs c
  2354. if isEmpty d:
  2355. if requiresValue:
  2356. globalError(c.config, n.info, "VM problem: d register is not set")