diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2021-01-23 08:06:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-23 08:06:15 +0100 |
commit | 8241e55023ee32c9ec0b5443723bbe91f4fe875f (patch) | |
tree | d14be71f134b1789db54028704748c4dbed46bfa /compiler/ic/cbackend.nim | |
parent | eae3bdf8fe554cdd334b8a53de63fd9bf10a7832 (diff) | |
download | Nim-8241e55023ee32c9ec0b5443723bbe91f4fe875f.tar.gz |
IC: next steps (#16729)
* IC: dead code elimination pass * preparations for a different codegen strategy * added documentation to the newly written code * IC: backend code * IC: backend adjustments * optimized the compiler a bit * IC: yet another massive refactoring * fixes regressions * cleanups
Diffstat (limited to 'compiler/ic/cbackend.nim')
-rw-r--r-- | compiler/ic/cbackend.nim | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/compiler/ic/cbackend.nim b/compiler/ic/cbackend.nim new file mode 100644 index 000000000..fbc2d401e --- /dev/null +++ b/compiler/ic/cbackend.nim @@ -0,0 +1,102 @@ +# +# +# The Nim Compiler +# (c) Copyright 2021 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## New entry point into our C/C++ code generator. Ideally +## somebody would rewrite the old backend (which is 8000 lines of crufty Nim code) +## to work on packed trees directly and produce the C code as an AST which can +## then be rendered to text in a very simple manner. Unfortunately nobody wrote +## this code. So instead we wrap the existing cgen.nim and its friends so that +## we call directly into the existing code generation logic but avoiding the +## naive, outdated `passes` design. Thus you will see some +## `useAliveDataFromDce in flags` checks in the old code -- the old code is +## also doing cross-module dependency tracking and DCE that we don't need +## anymore. DCE is now done as prepass over the entire packed module graph. + +import std / [intsets, algorithm] +import ".." / [ast, options, lineinfos, modulegraphs, cgendata, cgen, + pathutils, extccomp, msgs] + +import packed_ast, to_packed_ast, bitabs, dce, rodfiles + +proc unpackTree(g: ModuleGraph; thisModule: int; + tree: PackedTree; n: NodePos): PNode = + var decoder = initPackedDecoder(g.config, g.cache) + result = loadNodes(decoder, g.packed, thisModule, tree, n) + +proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) = + if g.backend == nil: + g.backend = cgendata.newModuleList(g) + + var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config) + bmod.idgen = idgenFromLoadedModule(m) + bmod.flags.incl useAliveDataFromDce + bmod.alive = move alive[m.module.position] + + for p in allNodes(m.fromDisk.topLevel): + let n = unpackTree(g, m.module.position, m.fromDisk.topLevel, p) + cgen.genTopLevelStmt(bmod, n) + + finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info)) + +proc addFileToLink(config: ConfigRef; m: PSym) = + let filename = AbsoluteFile toFullPath(config, m.position.FileIndex) + let ext = + if config.backend == backendCpp: ".nim.cpp" + elif config.backend == backendObjc: ".nim.m" + else: ".nim.c" + let cfile = changeFileExt(completeCfilePath(config, withPackageName(config, filename)), ext) + var cf = Cfile(nimname: m.name.s, cname: cfile, + obj: completeCfilePath(config, toObjFile(config, cfile)), + flags: {CfileFlag.Cached}) + addFileToCompile(config, cf) + +proc aliveSymsChanged(config: ConfigRef; position: int; alive: AliveSyms): bool = + let asymFile = toRodFile(config, AbsoluteFile toFullPath(config, position.FileIndex), ".alivesyms") + var s = newSeqOfCap[int32](alive[position].len) + for a in items(alive[position]): s.add int32(a) + sort(s) + var f2 = rodfiles.open(asymFile.string) + f2.loadHeader() + f2.loadSection aliveSymsSection + var oldData: seq[int32] + f2.loadSeq(oldData) + f2.close + if f2.err == ok and oldData == s: + result = false + else: + result = true + var f = rodfiles.create(asymFile.string) + f.storeHeader() + f.storeSection aliveSymsSection + f.storeSeq(s) + close f + +proc generateCode*(g: ModuleGraph) = + ## The single entry point, generate C(++) code for the entire + ## Nim program aka `ModuleGraph`. + var alive = computeAliveSyms(g.packed, g.config) + + for i in 0..high(g.packed): + # case statement here to enforce exhaustive checks. + case g.packed[i].status + of undefined: + discard "nothing to do" + of loading: + assert false + of storing, outdated: + generateCodeForModule(g, g.packed[i], alive) + of loaded: + # Even though this module didn't change, DCE might trigger a change. + # Consider this case: Module A uses symbol S from B and B does not use + # S itself. A is then edited not to use S either. Thus we have to + # recompile B in order to remove S from the final result. + if aliveSymsChanged(g.config, g.packed[i].module.position, alive): + generateCodeForModule(g, g.packed[i], alive) + else: + addFileToLink(g.config, g.packed[i].module) |