cir.nim 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  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. # We produce C code as a list of tokens.
  10. import std / [assertions, syncio, tables, intsets, formatfloat]
  11. from std / strutils import toOctal
  12. import .. / ic / [bitabs, rodfiles]
  13. import nirtypes, nirinsts, nirfiles
  14. import ../../dist/checksums/src/checksums/md5
  15. type
  16. Token = LitId # indexing into the tokens BiTable[string]
  17. PredefinedToken = enum
  18. IgnoreMe = "<unused>"
  19. EmptyToken = ""
  20. CurlyLe = "{"
  21. CurlyRi = "}"
  22. ParLe = "("
  23. ParRi = ")"
  24. BracketLe = "["
  25. BracketRi = "]"
  26. NewLine = "\n"
  27. Semicolon = ";"
  28. Comma = ", "
  29. Space = " "
  30. Colon = ": "
  31. Dot = "."
  32. Arrow = "->"
  33. Star = "*"
  34. Amp = "&"
  35. AsgnOpr = " = "
  36. ScopeOpr = "::"
  37. ConstKeyword = "const "
  38. StaticKeyword = "static "
  39. ExternKeyword = "extern "
  40. WhileKeyword = "while "
  41. IfKeyword = "if ("
  42. ElseKeyword = "else "
  43. SwitchKeyword = "switch "
  44. CaseKeyword = "case "
  45. DefaultKeyword = "default:"
  46. BreakKeyword = "break"
  47. NullPtr = "nullptr"
  48. IfNot = "if (!("
  49. ReturnKeyword = "return "
  50. TypedefStruct = "typedef struct "
  51. TypedefUnion = "typedef union "
  52. IncludeKeyword = "#include "
  53. proc fillTokenTable(tab: var BiTable[string]) =
  54. for e in EmptyToken..high(PredefinedToken):
  55. let id = tab.getOrIncl $e
  56. assert id == LitId(e), $(id, " ", ord(e))
  57. type
  58. GeneratedCode* = object
  59. m: NirModule
  60. includes: seq[LitId]
  61. includedHeaders: IntSet
  62. data: seq[LitId]
  63. protos: seq[LitId]
  64. code: seq[LitId]
  65. init: seq[LitId]
  66. tokens: BiTable[string]
  67. emittedStrings: IntSet
  68. needsPrefix: IntSet
  69. generatedTypes: IntSet
  70. mangledModules: Table[LitId, LitId]
  71. proc initGeneratedCode*(m: sink NirModule): GeneratedCode =
  72. result = GeneratedCode(m: m, code: @[], tokens: initBiTable[string]())
  73. fillTokenTable(result.tokens)
  74. proc add*(g: var GeneratedCode; t: PredefinedToken) {.inline.} =
  75. g.code.add Token(t)
  76. proc add*(g: var GeneratedCode; s: string) {.inline.} =
  77. g.code.add g.tokens.getOrIncl(s)
  78. proc mangleModuleName(c: var GeneratedCode; key: LitId): LitId =
  79. result = c.mangledModules.getOrDefault(key, LitId(0))
  80. if result == LitId(0):
  81. let u {.cursor.} = c.m.lit.strings[key]
  82. var last = u.len - len(".nim") - 1
  83. var start = last
  84. while start >= 0 and u[start] != '/': dec start
  85. var sum = getMD5(u)
  86. sum.setLen(8)
  87. let dest = u.substr(start+1, last) & sum
  88. result = c.tokens.getOrIncl(dest)
  89. c.mangledModules[key] = result
  90. type
  91. CppFile = object
  92. f: File
  93. proc write(f: var CppFile; s: string) = write(f.f, s)
  94. proc write(f: var CppFile; c: char) = write(f.f, c)
  95. proc writeTokenSeq(f: var CppFile; s: seq[Token]; c: GeneratedCode) =
  96. var indent = 0
  97. for i in 0..<s.len:
  98. let x = s[i]
  99. case x
  100. of Token(CurlyLe):
  101. inc indent
  102. write f, c.tokens[x]
  103. write f, "\n"
  104. for i in 1..indent*2: write f, ' '
  105. of Token(CurlyRi):
  106. dec indent
  107. write f, c.tokens[x]
  108. if i+1 < s.len and s[i+1] == Token(CurlyRi):
  109. discard
  110. else:
  111. write f, "\n"
  112. for i in 1..indent*2: write f, ' '
  113. of Token(Semicolon):
  114. write f, c.tokens[x]
  115. if i+1 < s.len and s[i+1] == Token(CurlyRi):
  116. discard "no newline before }"
  117. else:
  118. write f, "\n"
  119. for i in 1..indent*2: write f, ' '
  120. of Token(NewLine):
  121. write f, c.tokens[x]
  122. for i in 1..indent*2: write f, ' '
  123. else:
  124. write f, c.tokens[x]
  125. # Type graph
  126. type
  127. TypeList = object
  128. processed: IntSet
  129. s: seq[(TypeId, PredefinedToken)]
  130. proc add(dest: var TypeList; elem: TypeId; decl: PredefinedToken) =
  131. if not containsOrIncl(dest.processed, int(elem)):
  132. dest.s.add (elem, decl)
  133. type
  134. TypeOrder = object
  135. forwardedDecls, ordered: TypeList
  136. typeImpls: Table[string, TypeId]
  137. lookedAt: IntSet
  138. proc traverseObject(types: TypeGraph; lit: Literals; c: var TypeOrder; t: TypeId)
  139. proc recordDependency(types: TypeGraph; lit: Literals; c: var TypeOrder; parent, child: TypeId) =
  140. var ch = child
  141. var viaPointer = false
  142. while true:
  143. case types[ch].kind
  144. of APtrTy, UPtrTy, AArrayPtrTy, UArrayPtrTy:
  145. viaPointer = true
  146. ch = elementType(types, ch)
  147. of LastArrayTy:
  148. ch = elementType(types, ch)
  149. else:
  150. break
  151. case types[ch].kind
  152. of ObjectTy, UnionTy:
  153. let decl = if types[ch].kind == ObjectTy: TypedefStruct else: TypedefUnion
  154. let obj = c.typeImpls.getOrDefault(lit.strings[types[ch].litId])
  155. if viaPointer:
  156. c.forwardedDecls.add obj, decl
  157. else:
  158. if not containsOrIncl(c.lookedAt, obj.int):
  159. traverseObject(types, lit, c, obj)
  160. c.ordered.add obj, decl
  161. of ArrayTy:
  162. if viaPointer:
  163. c.forwardedDecls.add ch, TypedefStruct
  164. else:
  165. if not containsOrIncl(c.lookedAt, ch.int):
  166. traverseObject(types, lit, c, ch)
  167. c.ordered.add ch, TypedefStruct
  168. else:
  169. discard "uninteresting type as we only focus on the required struct declarations"
  170. proc traverseObject(types: TypeGraph; lit: Literals; c: var TypeOrder; t: TypeId) =
  171. for x in sons(types, t):
  172. case types[x].kind
  173. of FieldDecl:
  174. recordDependency types, lit, c, t, x.firstSon
  175. of ObjectTy:
  176. # inheritance
  177. recordDependency types, lit, c, t, x
  178. else: discard
  179. proc traverseTypes(types: TypeGraph; lit: Literals; c: var TypeOrder) =
  180. for t in allTypes(types):
  181. if types[t].kind in {ObjectDecl, UnionDecl}:
  182. assert types[t.firstSon].kind == NameVal
  183. c.typeImpls[lit.strings[types[t.firstSon].litId]] = t
  184. for t in allTypesIncludingInner(types):
  185. case types[t].kind
  186. of ObjectDecl, UnionDecl:
  187. traverseObject types, lit, c, t
  188. let decl = if types[t].kind == ObjectDecl: TypedefStruct else: TypedefUnion
  189. c.ordered.add t, decl
  190. of ArrayTy:
  191. traverseObject types, lit, c, t
  192. c.ordered.add t, TypedefStruct
  193. else: discard
  194. when false:
  195. template emitType(s: string) = c.types.add c.tokens.getOrIncl(s)
  196. template emitType(t: Token) = c.types.add t
  197. template emitType(t: PredefinedToken) = c.types.add Token(t)
  198. proc genType(g: var GeneratedCode; types: TypeGraph; lit: Literals; t: TypeId; name = "") =
  199. template maybeAddName =
  200. if name != "":
  201. g.add Space
  202. g.add name
  203. template atom(s: string) =
  204. g.add s
  205. maybeAddName()
  206. case types[t].kind
  207. of VoidTy: atom "void"
  208. of IntTy: atom "NI" & $types[t].integralBits
  209. of UIntTy: atom "NU" & $types[t].integralBits
  210. of FloatTy: atom "NF" & $types[t].integralBits
  211. of BoolTy: atom "NB" & $types[t].integralBits
  212. of CharTy: atom "NC" & $types[t].integralBits
  213. of ObjectTy, UnionTy, NameVal, AnnotationVal:
  214. atom lit.strings[types[t].litId]
  215. of VarargsTy:
  216. g.add "..."
  217. of APtrTy, UPtrTy, AArrayPtrTy, UArrayPtrTy:
  218. genType g, types, lit, elementType(types, t)
  219. g.add Star
  220. maybeAddName()
  221. of ArrayTy:
  222. genType g, types, lit, arrayName(types, t)
  223. maybeAddName()
  224. of LastArrayTy:
  225. genType g, types, lit, elementType(types, t)
  226. maybeAddName()
  227. g.add BracketLe
  228. g.add BracketRi
  229. of ProcTy:
  230. let (retType, callConv) = returnType(types, t)
  231. genType g, types, lit, retType
  232. g.add Space
  233. g.add ParLe
  234. genType g, types, lit, callConv
  235. g.add Star # "(*fn)"
  236. maybeAddName()
  237. g.add ParRi
  238. g.add ParLe
  239. var i = 0
  240. for ch in params(types, t):
  241. if i > 0: g.add Comma
  242. genType g, types, lit, ch
  243. inc i
  244. g.add ParRi
  245. of ObjectDecl, UnionDecl:
  246. atom lit.strings[types[t.firstSon].litId]
  247. of IntVal, SizeVal, AlignVal, OffsetVal, FieldDecl:
  248. #raiseAssert "did not expect: " & $types[t].kind
  249. g.add "BUG "
  250. atom $types[t].kind
  251. proc generateTypes(g: var GeneratedCode; types: TypeGraph; lit: Literals; c: TypeOrder) =
  252. for (t, declKeyword) in c.forwardedDecls.s:
  253. let name = if types[t].kind == ArrayTy: arrayName(types, t) else: t.firstSon
  254. let s {.cursor.} = lit.strings[types[name].litId]
  255. g.add declKeyword
  256. g.add s
  257. g.add Space
  258. g.add s
  259. g.add Semicolon
  260. for (t, declKeyword) in c.ordered.s:
  261. let name = if types[t].kind == ArrayTy: arrayName(types, t) else: t.firstSon
  262. let litId = types[name].litId
  263. if not g.generatedTypes.containsOrIncl(litId.int):
  264. let s {.cursor.} = lit.strings[litId]
  265. g.add declKeyword
  266. g.add CurlyLe
  267. if types[t].kind == ArrayTy:
  268. genType g, types, lit, elementType(types, t), "a"
  269. g.add BracketLe
  270. g.add $arrayLen(types, t)
  271. g.add BracketRi
  272. g.add Semicolon
  273. else:
  274. var i = 0
  275. for x in sons(types, t):
  276. case types[x].kind
  277. of FieldDecl:
  278. genType g, types, lit, x.firstSon, "F" & $i
  279. g.add Semicolon
  280. inc i
  281. of ObjectTy:
  282. genType g, types, lit, x, "P"
  283. g.add Semicolon
  284. else: discard
  285. g.add CurlyRi
  286. g.add s
  287. g.add Semicolon
  288. # Procs
  289. proc toCChar*(c: char; result: var string) {.inline.} =
  290. case c
  291. of '\0'..'\x1F', '\x7F'..'\xFF':
  292. result.add '\\'
  293. result.add toOctal(c)
  294. of '\'', '\"', '\\', '?':
  295. result.add '\\'
  296. result.add c
  297. else:
  298. result.add c
  299. proc makeCString(s: string): string =
  300. result = newStringOfCap(s.len + 10)
  301. result.add('"')
  302. for c in s: toCChar(c, result)
  303. result.add('"')
  304. template emitData(s: string) = c.data.add c.tokens.getOrIncl(s)
  305. template emitData(t: Token) = c.data.add t
  306. template emitData(t: PredefinedToken) = c.data.add Token(t)
  307. proc genStrLit(c: var GeneratedCode; lit: Literals; litId: LitId): Token =
  308. result = Token(c.tokens.getOrIncl "QStr" & $litId)
  309. if not containsOrIncl(c.emittedStrings, int(litId)):
  310. let s {.cursor.} = lit.strings[litId]
  311. emitData "static const struct "
  312. emitData CurlyLe
  313. emitData "NI cap"
  314. emitData Semicolon
  315. emitData "NC8 data"
  316. emitData BracketLe
  317. emitData $s.len
  318. emitData "+1"
  319. emitData BracketRi
  320. emitData Semicolon
  321. emitData CurlyRi
  322. emitData result
  323. emitData AsgnOpr
  324. emitData CurlyLe
  325. emitData $s.len
  326. emitData " | NIM_STRLIT_FLAG"
  327. emitData Comma
  328. emitData makeCString(s)
  329. emitData CurlyRi
  330. emitData Semicolon
  331. proc genIntLit(c: var GeneratedCode; lit: Literals; litId: LitId) =
  332. let i = lit.numbers[litId]
  333. if i > low(int32) and i <= high(int32):
  334. c.add $i
  335. elif i == low(int32):
  336. # Nim has the same bug for the same reasons :-)
  337. c.add "(-2147483647 -1)"
  338. elif i > low(int64):
  339. c.add "IL64("
  340. c.add $i
  341. c.add ")"
  342. else:
  343. c.add "(IL64(-9223372036854775807) - IL64(1))"
  344. proc gen(c: var GeneratedCode; t: Tree; n: NodePos)
  345. proc genDisplayName(c: var GeneratedCode; symId: SymId) =
  346. let displayName = c.m.symnames[symId]
  347. if displayName != LitId(0):
  348. c.add "/*"
  349. c.add c.m.lit.strings[displayName]
  350. c.add "*/"
  351. proc genSymDef(c: var GeneratedCode; t: Tree; n: NodePos) =
  352. if t[n].kind == SymDef:
  353. let symId = t[n].symId
  354. c.needsPrefix.incl symId.int
  355. genDisplayName c, symId
  356. gen c, t, n
  357. proc genGlobal(c: var GeneratedCode; t: Tree; name, typ: NodePos; annotation: string) =
  358. c.add annotation
  359. let m: string
  360. if t[name].kind == SymDef:
  361. let symId = t[name].symId
  362. m = c.tokens[mangleModuleName(c, c.m.namespace)] & "__" & $symId
  363. genDisplayName c, symId
  364. else:
  365. assert t[name].kind == ModuleSymUse
  366. let (x, y) = sons2(t, name)
  367. m = c.tokens[mangleModuleName(c, t[x].litId)] & "__" & $t[y].immediateVal
  368. genType c, c.m.types, c.m.lit, t[typ].typeId, m
  369. proc genLocal(c: var GeneratedCode; t: Tree; name, typ: NodePos; annotation: string) =
  370. assert t[name].kind == SymDef
  371. c.add annotation
  372. let symId = t[name].symId
  373. genType c, c.m.types, c.m.lit, t[typ].typeId, "q" & $symId
  374. genDisplayName c, symId
  375. proc genProcDecl(c: var GeneratedCode; t: Tree; n: NodePos; isExtern: bool) =
  376. let signatureBegin = c.code.len
  377. let name = n.firstSon
  378. var prc = n.firstSon
  379. next t, prc
  380. while true:
  381. case t[prc].kind
  382. of PragmaPair:
  383. let (x, y) = sons2(t, prc)
  384. let key = cast[PragmaKey](t[x].rawOperand)
  385. case key
  386. of HeaderImport:
  387. let lit = t[y].litId
  388. let headerAsStr {.cursor.} = c.m.lit.strings[lit]
  389. let header = c.tokens.getOrIncl(headerAsStr)
  390. # headerAsStr can be empty, this has the semantics of the `nodecl` pragma:
  391. if headerAsStr.len > 0 and not c.includedHeaders.containsOrIncl(int header):
  392. if headerAsStr[0] == '#':
  393. discard "skip the #include"
  394. else:
  395. c.includes.add Token(IncludeKeyword)
  396. c.includes.add header
  397. c.includes.add Token NewLine
  398. # do not generate code for importc'ed procs:
  399. return
  400. of DllImport:
  401. let lit = t[y].litId
  402. raiseAssert "cannot eval: " & c.m.lit.strings[lit]
  403. else: discard
  404. of PragmaId: discard
  405. else: break
  406. next t, prc
  407. var resultDeclPos = NodePos(-1)
  408. if t[prc].kind == SummonResult:
  409. resultDeclPos = prc
  410. gen c, t, prc.firstSon
  411. next t, prc
  412. else:
  413. c.add "void"
  414. c.add Space
  415. genSymDef c, t, name
  416. c.add ParLe
  417. var params = 0
  418. while t[prc].kind == SummonParam:
  419. if params > 0: c.add Comma
  420. let (typ, sym) = sons2(t, prc)
  421. genLocal c, t, sym, typ, ""
  422. next t, prc
  423. inc params
  424. if params == 0:
  425. c.add "void"
  426. c.add ParRi
  427. for i in signatureBegin ..< c.code.len:
  428. c.protos.add c.code[i]
  429. c.protos.add Token Semicolon
  430. if isExtern:
  431. c.code.setLen signatureBegin
  432. else:
  433. c.add CurlyLe
  434. if resultDeclPos.int >= 0:
  435. gen c, t, resultDeclPos
  436. for ch in sonsRest(t, n, prc):
  437. gen c, t, ch
  438. c.add CurlyRi
  439. template triop(opr) =
  440. let (typ, a, b) = sons3(t, n)
  441. c.add ParLe
  442. c.add ParLe
  443. gen c, t, typ
  444. c.add ParRi
  445. gen c, t, a
  446. c.add opr
  447. gen c, t, b
  448. c.add ParRi
  449. template cmpop(opr) =
  450. let (_, a, b) = sons3(t, n)
  451. c.add ParLe
  452. gen c, t, a
  453. c.add opr
  454. gen c, t, b
  455. c.add ParRi
  456. template binaryop(opr) =
  457. let (typ, a) = sons2(t, n)
  458. c.add ParLe
  459. c.add ParLe
  460. gen c, t, typ
  461. c.add ParRi
  462. c.add opr
  463. gen c, t, a
  464. c.add ParRi
  465. template checkedBinaryop(opr) =
  466. let (typ, labIdx, a, b) = sons4(t, n)
  467. let bits = integralBits(c.m.types[t[typ].typeId])
  468. let lab = t[labIdx].label
  469. c.add (opr & $bits)
  470. c.add ParLe
  471. c.gen t, a
  472. c.add Comma
  473. c.gen t, b
  474. c.add Comma
  475. c.add "L" & $lab.int
  476. c.add ParRi
  477. proc genNumberConv(c: var GeneratedCode; t: Tree; n: NodePos) =
  478. let (typ, arg) = sons2(t, n)
  479. if t[arg].kind == IntVal:
  480. let litId = t[arg].litId
  481. c.add ParLe
  482. c.add ParLe
  483. gen c, t, typ
  484. c.add ParRi
  485. case c.m.types[t[typ].typeId].kind
  486. of UIntTy:
  487. let x = cast[uint64](c.m.lit.numbers[litId])
  488. c.add $x
  489. of FloatTy:
  490. let x = cast[float64](c.m.lit.numbers[litId])
  491. c.add $x
  492. else:
  493. gen c, t, arg
  494. c.add ParRi
  495. else:
  496. binaryop ""
  497. template moveToDataSection(body: untyped) =
  498. let oldLen = c.code.len
  499. body
  500. for i in oldLen ..< c.code.len:
  501. c.data.add c.code[i]
  502. setLen c.code, oldLen
  503. proc gen(c: var GeneratedCode; t: Tree; n: NodePos) =
  504. case t[n].kind
  505. of Nop:
  506. discard "nothing to emit"
  507. of ImmediateVal:
  508. c.add $t[n].immediateVal
  509. of IntVal:
  510. genIntLit c, c.m.lit, t[n].litId
  511. of StrVal:
  512. c.code.add genStrLit(c, c.m.lit, t[n].litId)
  513. of Typed:
  514. genType c, c.m.types, c.m.lit, t[n].typeId
  515. of SymDef, SymUse:
  516. let s = t[n].symId
  517. if c.needsPrefix.contains(s.int):
  518. c.code.add mangleModuleName(c, c.m.namespace)
  519. c.add "__"
  520. c.add $s
  521. else:
  522. # XXX Use proper names here
  523. c.add "q"
  524. c.add $s
  525. of ModuleSymUse:
  526. let (x, y) = sons2(t, n)
  527. let u = mangleModuleName(c, t[x].litId)
  528. let s = t[y].immediateVal
  529. c.code.add u
  530. c.add "__"
  531. c.add $s
  532. of NilVal:
  533. c.add NullPtr
  534. of LoopLabel:
  535. c.add WhileKeyword
  536. c.add ParLe
  537. c.add "1"
  538. c.add ParRi
  539. c.add CurlyLe
  540. of GotoLoop:
  541. c.add CurlyRi
  542. of Label:
  543. let lab = t[n].label
  544. c.add "L"
  545. c.add $lab.int
  546. c.add Colon
  547. c.add Semicolon
  548. of Goto:
  549. let lab = t[n].label
  550. c.add "goto L"
  551. c.add $lab.int
  552. c.add Semicolon
  553. of CheckedGoto:
  554. discard "XXX todo"
  555. of ArrayConstr:
  556. c.add CurlyLe
  557. c.add ".a = "
  558. c.add CurlyLe
  559. var i = 0
  560. for ch in sonsFrom1(t, n):
  561. if i > 0: c.add Comma
  562. c.gen t, ch
  563. inc i
  564. c.add CurlyRi
  565. c.add CurlyRi
  566. of ObjConstr:
  567. c.add CurlyLe
  568. var i = 0
  569. for ch in sonsFrom1(t, n):
  570. if i mod 2 == 0:
  571. if i > 0: c.add Comma
  572. c.add ".F" & $t[ch].immediateVal
  573. c.add AsgnOpr
  574. else:
  575. c.gen t, ch
  576. inc i
  577. c.add CurlyRi
  578. of Ret:
  579. c.add ReturnKeyword
  580. c.gen t, n.firstSon
  581. c.add Semicolon
  582. of Select:
  583. c.add SwitchKeyword
  584. c.add ParLe
  585. let (_, selector) = sons2(t, n)
  586. c.gen t, selector
  587. c.add ParRi
  588. c.add CurlyLe
  589. for ch in sonsFromN(t, n, 2):
  590. c.gen t, ch
  591. c.add CurlyRi
  592. of SelectPair:
  593. let (le, ri) = sons2(t, n)
  594. c.gen t, le
  595. c.gen t, ri
  596. of SelectList:
  597. for ch in sons(t, n):
  598. c.gen t, ch
  599. of SelectValue:
  600. c.add CaseKeyword
  601. c.gen t, n.firstSon
  602. c.add Colon
  603. of SelectRange:
  604. let (le, ri) = sons2(t, n)
  605. c.add CaseKeyword
  606. c.gen t, le
  607. c.add " ... "
  608. c.gen t, ri
  609. c.add Colon
  610. of ForeignDecl:
  611. c.data.add LitId(ExternKeyword)
  612. c.gen t, n.firstSon
  613. of SummonGlobal:
  614. moveToDataSection:
  615. let (typ, sym) = sons2(t, n)
  616. c.genGlobal t, sym, typ, ""
  617. c.add Semicolon
  618. of SummonThreadLocal:
  619. moveToDataSection:
  620. let (typ, sym) = sons2(t, n)
  621. c.genGlobal t, sym, typ, "__thread "
  622. c.add Semicolon
  623. of SummonConst:
  624. moveToDataSection:
  625. let (typ, sym, val) = sons3(t, n)
  626. c.genGlobal t, sym, typ, "const "
  627. c.add AsgnOpr
  628. c.gen t, val
  629. c.add Semicolon
  630. of Summon, SummonResult:
  631. let (typ, sym) = sons2(t, n)
  632. c.genLocal t, sym, typ, ""
  633. c.add Semicolon
  634. of SummonParam:
  635. raiseAssert "SummonParam should have been handled in genProc"
  636. of Kill:
  637. discard "we don't care about Kill instructions"
  638. of AddrOf:
  639. let (_, arg) = sons2(t, n)
  640. c.add "&"
  641. gen c, t, arg
  642. of DerefArrayAt:
  643. let (_, a, i) = sons3(t, n)
  644. gen c, t, a
  645. c.add BracketLe
  646. gen c, t, i
  647. c.add BracketRi
  648. of ArrayAt:
  649. let (_, a, i) = sons3(t, n)
  650. gen c, t, a
  651. c.add Dot
  652. c.add "a"
  653. c.add BracketLe
  654. gen c, t, i
  655. c.add BracketRi
  656. of FieldAt:
  657. let (_, a, b) = sons3(t, n)
  658. gen c, t, a
  659. let field = t[b].immediateVal
  660. c.add Dot
  661. c.add "F" & $field
  662. of DerefFieldAt:
  663. let (_, a, b) = sons3(t, n)
  664. gen c, t, a
  665. let field = t[b].immediateVal
  666. c.add Arrow
  667. c.add "F" & $field
  668. of Load:
  669. let (_, arg) = sons2(t, n)
  670. c.add ParLe
  671. c.add "*"
  672. gen c, t, arg
  673. c.add ParRi
  674. of Store:
  675. raiseAssert "Assumption was that Store is unused!"
  676. of Asgn:
  677. let (_, dest, src) = sons3(t, n)
  678. gen c, t, dest
  679. c.add AsgnOpr
  680. gen c, t, src
  681. c.add Semicolon
  682. of CheckedRange:
  683. c.add "nimCheckRange"
  684. c.add ParLe
  685. let (_, gotoInstr, x, a, b) = sons5(t, n)
  686. gen c, t, x
  687. c.add Comma
  688. gen c, t, a
  689. c.add Comma
  690. gen c, t, b
  691. c.add Comma
  692. c.add "L" & $t[gotoInstr].label.int
  693. c.add ParRi
  694. of CheckedIndex:
  695. c.add "nimCheckIndex"
  696. c.add ParLe
  697. let (gotoInstr, x, a) = sons3(t, n)
  698. gen c, t, x
  699. c.add Comma
  700. gen c, t, a
  701. c.add Comma
  702. c.add "L" & $t[gotoInstr].label.int
  703. c.add ParRi
  704. of Call, IndirectCall:
  705. let (typ, fn) = sons2(t, n)
  706. gen c, t, fn
  707. c.add ParLe
  708. var i = 0
  709. for ch in sonsFromN(t, n, 2):
  710. if i > 0: c.add Comma
  711. gen c, t, ch
  712. inc i
  713. c.add ParRi
  714. if c.m.types[t[typ].typeId].kind == VoidTy:
  715. c.add Semicolon
  716. of CheckedCall, CheckedIndirectCall:
  717. let (typ, gotoInstr, fn) = sons3(t, n)
  718. gen c, t, fn
  719. c.add ParLe
  720. var i = 0
  721. for ch in sonsFromN(t, n, 3):
  722. if i > 0: c.add Comma
  723. gen c, t, ch
  724. inc i
  725. c.add ParRi
  726. if c.m.types[t[typ].typeId].kind == VoidTy:
  727. c.add Semicolon
  728. of CheckedAdd: checkedBinaryop "nimAddInt"
  729. of CheckedSub: checkedBinaryop "nimSubInt"
  730. of CheckedMul: checkedBinaryop "nimMulInt"
  731. of CheckedDiv: checkedBinaryop "nimDivInt"
  732. of CheckedMod: checkedBinaryop "nimModInt"
  733. of Add: triop " + "
  734. of Sub: triop " - "
  735. of Mul: triop " * "
  736. of Div: triop " / "
  737. of Mod: triop " % "
  738. of BitShl: triop " << "
  739. of BitShr: triop " >> "
  740. of BitAnd: triop " & "
  741. of BitOr: triop " | "
  742. of BitXor: triop " ^ "
  743. of BitNot: binaryop " ~ "
  744. of BoolNot: binaryop " !"
  745. of Eq: cmpop " == "
  746. of Le: cmpop " <= "
  747. of Lt: cmpop " < "
  748. of Cast: binaryop ""
  749. of NumberConv: genNumberConv c, t, n
  750. of CheckedObjConv: binaryop ""
  751. of ObjConv: binaryop ""
  752. of Emit: raiseAssert "cannot interpret: Emit"
  753. of ProcDecl: genProcDecl c, t, n, false
  754. of ForeignProcDecl: genProcDecl c, t, n, true
  755. of PragmaPair, PragmaId, TestOf, Yld, SetExc, TestExc:
  756. c.add "cannot interpret: " & $t[n].kind
  757. const
  758. Prelude = """
  759. /* GENERATED CODE. DO NOT EDIT. */
  760. #ifdef __cplusplus
  761. #define NB8 bool
  762. #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901)
  763. // see #13798: to avoid conflicts for code emitting `#include <stdbool.h>`
  764. #define NB8 _Bool
  765. #else
  766. typedef unsigned char NB8; // best effort
  767. #endif
  768. typedef unsigned char NC8;
  769. typedef float NF32;
  770. typedef double NF64;
  771. #if defined(__BORLANDC__) || defined(_MSC_VER)
  772. typedef signed char NI8;
  773. typedef signed short int NI16;
  774. typedef signed int NI32;
  775. typedef __int64 NI64;
  776. /* XXX: Float128? */
  777. typedef unsigned char NU8;
  778. typedef unsigned short int NU16;
  779. typedef unsigned int NU32;
  780. typedef unsigned __int64 NU64;
  781. #elif defined(HAVE_STDINT_H)
  782. #ifndef USE_NIM_NAMESPACE
  783. # include <stdint.h>
  784. #endif
  785. typedef int8_t NI8;
  786. typedef int16_t NI16;
  787. typedef int32_t NI32;
  788. typedef int64_t NI64;
  789. typedef uint8_t NU8;
  790. typedef uint16_t NU16;
  791. typedef uint32_t NU32;
  792. typedef uint64_t NU64;
  793. #elif defined(HAVE_CSTDINT)
  794. #ifndef USE_NIM_NAMESPACE
  795. # include <cstdint>
  796. #endif
  797. typedef std::int8_t NI8;
  798. typedef std::int16_t NI16;
  799. typedef std::int32_t NI32;
  800. typedef std::int64_t NI64;
  801. typedef std::uint8_t NU8;
  802. typedef std::uint16_t NU16;
  803. typedef std::uint32_t NU32;
  804. typedef std::uint64_t NU64;
  805. #else
  806. /* Unknown compiler/version, do our best */
  807. #ifdef __INT8_TYPE__
  808. typedef __INT8_TYPE__ NI8;
  809. #else
  810. typedef signed char NI8;
  811. #endif
  812. #ifdef __INT16_TYPE__
  813. typedef __INT16_TYPE__ NI16;
  814. #else
  815. typedef signed short int NI16;
  816. #endif
  817. #ifdef __INT32_TYPE__
  818. typedef __INT32_TYPE__ NI32;
  819. #else
  820. typedef signed int NI32;
  821. #endif
  822. #ifdef __INT64_TYPE__
  823. typedef __INT64_TYPE__ NI64;
  824. #else
  825. typedef long long int NI64;
  826. #endif
  827. /* XXX: Float128? */
  828. #ifdef __UINT8_TYPE__
  829. typedef __UINT8_TYPE__ NU8;
  830. #else
  831. typedef unsigned char NU8;
  832. #endif
  833. #ifdef __UINT16_TYPE__
  834. typedef __UINT16_TYPE__ NU16;
  835. #else
  836. typedef unsigned short int NU16;
  837. #endif
  838. #ifdef __UINT32_TYPE__
  839. typedef __UINT32_TYPE__ NU32;
  840. #else
  841. typedef unsigned int NU32;
  842. #endif
  843. #ifdef __UINT64_TYPE__
  844. typedef __UINT64_TYPE__ NU64;
  845. #else
  846. typedef unsigned long long int NU64;
  847. #endif
  848. #endif
  849. #ifdef NIM_INTBITS
  850. # if NIM_INTBITS == 64
  851. typedef NI64 NI;
  852. typedef NU64 NU;
  853. # elif NIM_INTBITS == 32
  854. typedef NI32 NI;
  855. typedef NU32 NU;
  856. # elif NIM_INTBITS == 16
  857. typedef NI16 NI;
  858. typedef NU16 NU;
  859. # elif NIM_INTBITS == 8
  860. typedef NI8 NI;
  861. typedef NU8 NU;
  862. # else
  863. # error "invalid bit width for int"
  864. # endif
  865. #endif
  866. #define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */
  867. #define nimAddInt64(a, b, L) ({long long int res; if(__builtin_saddll_overflow(a, b, &res)) goto L; res})
  868. #define nimSubInt64(a, b, L) ({long long int res; if(__builtin_ssubll_overflow(a, b, &res)) goto L; res})
  869. #define nimMulInt64(a, b, L) ({long long int res; if(__builtin_smulll_overflow(a, b, &res)) goto L; res})
  870. #define nimAddInt32(a, b, L) ({long int res; if(__builtin_sadd_overflow(a, b, &res)) goto L; res})
  871. #define nimSubInt32(a, b, L) ({long int res; if(__builtin_ssub_overflow(a, b, &res)) goto L; res})
  872. #define nimMulInt32(a, b, L) ({long int res; if(__builtin_smul_overflow(a, b, &res)) goto L; res})
  873. #define nimCheckRange(x, a, b, L) ({if (x < a || x > b) goto L; x})
  874. #define nimCheckIndex(x, a, L) ({if (x >= a) goto L; x})
  875. """
  876. proc traverseCode(c: var GeneratedCode) =
  877. const AllowedInToplevelC = {SummonConst, SummonGlobal, SummonThreadLocal,
  878. ProcDecl, ForeignDecl, ForeignProcDecl}
  879. var i = NodePos(0)
  880. while i.int < c.m.code.len:
  881. let oldLen = c.code.len
  882. let moveToInitSection = c.m.code[NodePos(i)].kind notin AllowedInToplevelC
  883. gen c, c.m.code, NodePos(i)
  884. next c.m.code, i
  885. if moveToInitSection:
  886. for i in oldLen ..< c.code.len:
  887. c.init.add c.code[i]
  888. setLen c.code, oldLen
  889. proc generateCode*(inp, outp: string) =
  890. var c = initGeneratedCode(load(inp))
  891. var co = TypeOrder()
  892. traverseTypes(c.m.types, c.m.lit, co)
  893. generateTypes(c, c.m.types, c.m.lit, co)
  894. let typeDecls = move c.code
  895. traverseCode c
  896. var f = CppFile(f: open(outp, fmWrite))
  897. f.write "#define NIM_INTBITS " & $c.m.intbits & "\n"
  898. f.write Prelude
  899. writeTokenSeq f, c.includes, c
  900. writeTokenSeq f, typeDecls, c
  901. writeTokenSeq f, c.data, c
  902. writeTokenSeq f, c.protos, c
  903. writeTokenSeq f, c.code, c
  904. if c.init.len > 0:
  905. f.write "void __attribute__((constructor)) init(void) {"
  906. writeTokenSeq f, c.init, c
  907. f.write "}\n\n"
  908. f.f.close