replayer.nim 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 tables
  15. import packed_ast, ic, bitabs
  16. proc replayStateChanges*(module: PSym; g: ModuleGraph) =
  17. let list = module.ast
  18. assert list != nil
  19. assert list.kind == nkStmtList
  20. for n in list:
  21. assert n.kind == nkReplayAction
  22. # Fortunately only a tiny subset of the available pragmas need to
  23. # be replayed here. This is always a subset of ``pragmas.stmtPragmas``.
  24. if n.len >= 2:
  25. internalAssert g.config, n[0].kind == nkStrLit and n[1].kind == nkStrLit
  26. case n[0].strVal
  27. of "hint": message(g.config, n.info, hintUser, n[1].strVal)
  28. of "warning": message(g.config, n.info, warnUser, n[1].strVal)
  29. of "error": localError(g.config, n.info, errUser, n[1].strVal)
  30. of "compile":
  31. internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit
  32. let cname = AbsoluteFile n[1].strVal
  33. var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
  34. obj: AbsoluteFile n[2].strVal,
  35. flags: {CfileFlag.External},
  36. customArgs: n[3].strVal)
  37. extccomp.addExternalFileToCompile(g.config, cf)
  38. of "link":
  39. extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal)
  40. of "passl":
  41. extccomp.addLinkOption(g.config, n[1].strVal)
  42. of "passc":
  43. extccomp.addCompileOption(g.config, n[1].strVal)
  44. of "localpassc":
  45. extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex))
  46. of "cppdefine":
  47. options.cppDefine(g.config, n[1].strVal)
  48. of "inc":
  49. let destKey = n[1].strVal
  50. let by = n[2].intVal
  51. let v = getOrDefault(g.cacheCounters, destKey)
  52. g.cacheCounters[destKey] = v+by
  53. of "put":
  54. let destKey = n[1].strVal
  55. let key = n[2].strVal
  56. let val = n[3]
  57. if not contains(g.cacheTables, destKey):
  58. g.cacheTables[destKey] = initBTree[string, PNode]()
  59. if not contains(g.cacheTables[destKey], key):
  60. g.cacheTables[destKey].add(key, val)
  61. else:
  62. internalError(g.config, n.info, "key already exists: " & key)
  63. of "incl":
  64. let destKey = n[1].strVal
  65. let val = n[2]
  66. if not contains(g.cacheSeqs, destKey):
  67. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  68. else:
  69. block search:
  70. for existing in g.cacheSeqs[destKey]:
  71. if exprStructuralEquivalent(existing, val, strictSymEquality=true):
  72. break search
  73. g.cacheSeqs[destKey].add val
  74. of "add":
  75. let destKey = n[1].strVal
  76. let val = n[2]
  77. if not contains(g.cacheSeqs, destKey):
  78. g.cacheSeqs[destKey] = newTree(nkStmtList, val)
  79. else:
  80. g.cacheSeqs[destKey].add val
  81. else:
  82. internalAssert g.config, false
  83. proc replayGenericCacheInformation*(g: ModuleGraph; module: int) =
  84. ## We remember the generic instantiations a module performed
  85. ## in order to to avoid the code bloat that generic code tends
  86. ## to imply. This is cheaper than deduplication of identical
  87. ## generic instantiations. However, deduplication is more
  88. ## powerful and general and I hope to implement it soon too
  89. ## (famous last words).
  90. assert g.packed[module].status == loaded
  91. for it in g.packed[module].fromDisk.typeInstCache:
  92. let key = translateId(it[0], g.packed, module, g.config)
  93. g.typeInstCache.mgetOrPut(key, @[]).add LazyType(id: FullId(module: module, packed: it[1]), typ: nil)
  94. for it in mitems(g.packed[module].fromDisk.procInstCache):
  95. let key = translateId(it.key, g.packed, module, g.config)
  96. let sym = translateId(it.sym, g.packed, module, g.config)
  97. var concreteTypes = newSeq[FullId](it.concreteTypes.len)
  98. for i in 0..high(it.concreteTypes):
  99. let tmp = translateId(it.concreteTypes[i], g.packed, module, g.config)
  100. concreteTypes[i] = FullId(module: tmp.module, packed: it.concreteTypes[i])
  101. g.procInstCache.mgetOrPut(key, @[]).add LazyInstantiation(
  102. module: module, sym: FullId(module: sym.module, packed: it.sym),
  103. concreteTypes: concreteTypes, inst: nil)
  104. for it in mitems(g.packed[module].fromDisk.methodsPerType):
  105. let key = translateId(it[0], g.packed, module, g.config)
  106. let col = it[1]
  107. let tmp = translateId(it[2], g.packed, module, g.config)
  108. let symId = FullId(module: tmp.module, packed: it[2])
  109. g.methodsPerType.mgetOrPut(key, @[]).add (col, LazySym(id: symId, sym: nil))
  110. for it in mitems(g.packed[module].fromDisk.enumToStringProcs):
  111. let key = translateId(it[0], g.packed, module, g.config)
  112. let tmp = translateId(it[1], g.packed, module, g.config)
  113. let symId = FullId(module: tmp.module, packed: it[1])
  114. g.enumToStringProcs[key] = LazySym(id: symId, sym: nil)
  115. for it in mitems(g.packed[module].fromDisk.methods):
  116. let sym = loadSymFromId(g.config, g.cache, g.packed, module,
  117. PackedItemId(module: LitId(0), item: it))
  118. methodDef(g, g.idgen, sym)
  119. when false:
  120. # not used anymore:
  121. for it in mitems(g.packed[module].fromDisk.compilerProcs):
  122. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it[1]))
  123. g.lazyCompilerprocs[g.packed[module].fromDisk.sh.strings[it[0]]] = symId
  124. for it in mitems(g.packed[module].fromDisk.converters):
  125. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  126. g.ifaces[module].converters.add LazySym(id: symId, sym: nil)
  127. for it in mitems(g.packed[module].fromDisk.trmacros):
  128. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  129. g.ifaces[module].patterns.add LazySym(id: symId, sym: nil)
  130. for it in mitems(g.packed[module].fromDisk.pureEnums):
  131. let symId = FullId(module: module, packed: PackedItemId(module: LitId(0), item: it))
  132. g.ifaces[module].pureEnums.add LazySym(id: symId, sym: nil)