replayer.nim 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2020 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Module that contains code to replay global VM state changes and pragma
  10. ## state like ``{.compile: "foo.c".}``. For IC (= Incremental compilation)
  11. ## support.
  12. import ".." / [ast, modulegraphs, trees, extccomp, btrees,
  13. msgs, lineinfos, pathutils, options, cgmeth]
  14. import std/tables
  15. when defined(nimPreviewSlimSystem):
  16. import std/assertions
  17. import packed_ast, ic, bitabs
  18. proc replayStateChanges*(module: PSym; g: ModuleGraph) =
  19. let list = module.ast
  20. assert list != nil
  21. assert list.kind == nkStmtList
  22. for n in list:
  23. assert n.kind == nkReplayAction
  24. # Fortunately only a tiny subset of the available pragmas need to
  25. # be replayed here. This is always a subset of ``pragmas.stmtPragmas``.
  26. if n.len >= 2:
  27. internalAssert g.config, n[0].kind == nkStrLit and n[1].kind == nkStrLit
  28. case n[0].strVal
  29. of "hint": message(g.config, n.info, hintUser, n[1].strVal)
  30. of "warning": message(g.config, n.info, warnUser, n[1].strVal)
  31. of "error": localError(g.config, n.info, errUser, n[1].strVal)
  32. of "compile":
  33. internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit
  34. let cname = AbsoluteFile n[1].strVal
  35. var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
  36. obj: AbsoluteFile n[2].strVal,
  37. flags: {CfileFlag.External},
  38. customArgs: n[3].strVal)
  39. extccomp.addExternalFileToCompile(g.config, cf)
  40. of "link":
  41. extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal)
  42. of "passl":
  43. extccomp.addLinkOption(g.config, n[1].strVal)
  44. of "passc":
  45. extccomp.addCompileOption(g.config, n[1].strVal)
  46. of "localpassc":
  47. extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex))
  48. of "cppdefine":
  49. options.cppDefine(g.config, n[1].strVal)
  50. of "inc":
  51. let destKey = n[1].strVal
  52. let by = n[2].intVal
  53. let v = getOrDefault(g.cacheCounters, destKey)
  54. g.cacheCounters[destKey] = v+by
  55. of "put":
  56. let destKey = n[1].strVal
  57. let key = n[2].strVal
  58. let val = n[3]
  59. if not contains(g.cacheTables, destKey):
  60. g.cacheTables[destKey] = initBTree[string, PNode]()
  61. if not contains(g.cacheTables[destKey], key):
  62. g.cacheTables[destKey].add(key, val)
  63. else:
  64. internalError(g.config, n.info, "key already exists: " & key)
  65. of "incl":
  66. let destKey = n[1].strVal
  67. let val = n[2]
  68. if not contains(g.cacheSeqs, destKey):
  69. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  70. else:
  71. block search:
  72. for existing in g.cacheSeqs[destKey]:
  73. if exprStructuralEquivalent(existing, val, strictSymEquality=true):
  74. break search
  75. g.cacheSeqs[destKey].add val
  76. of "add":
  77. let destKey = n[1].strVal
  78. let val = n[2]
  79. if not contains(g.cacheSeqs, destKey):
  80. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  81. else:
  82. g.cacheSeqs[destKey].add val
  83. else:
  84. internalAssert g.config, false
  85. proc replayBackendProcs*(g: ModuleGraph; module: int) =
  86. for it in mitems(g.packed[module].fromDisk.attachedOps):
  87. let key = translateId(it[0], g.packed, module, g.config)
  88. let op = it[1]
  89. let tmp = translateId(it[2], g.packed, module, g.config)
  90. let symId = FullId(module: tmp.module, packed: it[2])
  91. g.attachedOps[op][key] = LazySym(id: symId, sym: nil)
  92. for it in mitems(g.packed[module].fromDisk.enumToStringProcs):
  93. let key = translateId(it[0], g.packed, module, g.config)
  94. let tmp = translateId(it[1], g.packed, module, g.config)
  95. let symId = FullId(module: tmp.module, packed: it[1])
  96. g.enumToStringProcs[key] = LazySym(id: symId, sym: nil)
  97. for it in mitems(g.packed[module].fromDisk.methodsPerType):
  98. let key = translateId(it[0], g.packed, module, g.config)
  99. let tmp = translateId(it[1], g.packed, module, g.config)
  100. let symId = FullId(module: tmp.module, packed: it[1])
  101. g.methodsPerType.mgetOrPut(key, @[]).add LazySym(id: symId, sym: nil)
  102. for it in mitems(g.packed[module].fromDisk.dispatchers):
  103. let tmp = translateId(it, g.packed, module, g.config)
  104. let symId = FullId(module: tmp.module, packed: it)
  105. g.dispatchers.add LazySym(id: symId, sym: nil)
  106. proc replayGenericCacheInformation*(g: ModuleGraph; module: int) =
  107. ## We remember the generic instantiations a module performed
  108. ## in order to to avoid the code bloat that generic code tends
  109. ## to imply. This is cheaper than deduplication of identical
  110. ## generic instantiations. However, deduplication is more
  111. ## powerful and general and I hope to implement it soon too
  112. ## (famous last words).
  113. assert g.packed[module].status == loaded
  114. for it in g.packed[module].fromDisk.typeInstCache:
  115. let key = translateId(it[0], g.packed, module, g.config)
  116. g.typeInstCache.mgetOrPut(key, @[]).add LazyType(id: FullId(module: module, packed: it[1]), typ: nil)
  117. for it in mitems(g.packed[module].fromDisk.procInstCache):
  118. let key = translateId(it.key, g.packed, module, g.config)
  119. let sym = translateId(it.sym, g.packed, module, g.config)
  120. var concreteTypes = newSeq[FullId](it.concreteTypes.len)
  121. for i in 0..high(it.concreteTypes):
  122. let tmp = translateId(it.concreteTypes[i], g.packed, module, g.config)
  123. concreteTypes[i] = FullId(module: tmp.module, packed: it.concreteTypes[i])
  124. g.procInstCache.mgetOrPut(key, @[]).add LazyInstantiation(
  125. module: module, sym: FullId(module: sym.module, packed: it.sym),
  126. concreteTypes: concreteTypes, inst: nil)
  127. for it in mitems(g.packed[module].fromDisk.methodsPerGenericType):
  128. let key = translateId(it[0], g.packed, module, g.config)
  129. let col = it[1]
  130. let tmp = translateId(it[2], g.packed, module, g.config)
  131. let symId = FullId(module: tmp.module, packed: it[2])
  132. g.methodsPerGenericType.mgetOrPut(key, @[]).add (col, LazySym(id: symId, sym: nil))
  133. replayBackendProcs(g, module)
  134. for it in mitems(g.packed[module].fromDisk.methods):
  135. let sym = loadSymFromId(g.config, g.cache, g.packed, module,
  136. PackedItemId(module: LitId(0), item: it))
  137. methodDef(g, g.idgen, sym)
  138. when false:
  139. # not used anymore:
  140. for it in mitems(g.packed[module].fromDisk.compilerProcs):
  141. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it[1]))
  142. g.lazyCompilerprocs[g.packed[module].fromDisk.sh.strings[it[0]]] = symId
  143. for it in mitems(g.packed[module].fromDisk.converters):
  144. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  145. g.ifaces[module].converters.add LazySym(id: symId, sym: nil)
  146. for it in mitems(g.packed[module].fromDisk.trmacros):
  147. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  148. g.ifaces[module].patterns.add LazySym(id: symId, sym: nil)
  149. for it in mitems(g.packed[module].fromDisk.pureEnums):
  150. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  151. g.ifaces[module].pureEnums.add LazySym(id: symId, sym: nil)