From 13b958eb45a3569acaa18f9381d28b8f37d42057 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 9 Apr 2021 06:59:25 +0200 Subject: [PATCH] IC: added basic test case for methods (#17679) * IC: added basic test case for methods * IC: better methods test --- compiler/ic/cbackend.nim | 35 ++++++++++++++++++++++++++++------- compiler/ic/ic.nim | 2 +- tests/ic/mbaseobj.nim | 7 +++++++ tests/ic/tmethods.nim | 28 ++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 tests/ic/mbaseobj.nim create mode 100644 tests/ic/tmethods.nim diff --git a/compiler/ic/cbackend.nim b/compiler/ic/cbackend.nim index 9282ac466..2f3910b32 100644 --- a/compiler/ic/cbackend.nim +++ b/compiler/ic/cbackend.nim @@ -30,12 +30,16 @@ proc unpackTree(g: ModuleGraph; thisModule: int; 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) = +proc setupBackendModule(g: ModuleGraph; m: var LoadedModule) = if g.backend == nil: g.backend = cgendata.newModuleList(g) - + assert g.backend != nil var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config) bmod.idgen = idgenFromLoadedModule(m) + +proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) = + var bmod = BModuleList(g.backend).modules[m.module.position] + assert bmod != nil bmod.flags.incl useAliveDataFromDce bmod.alive = move alive[m.module.position] @@ -118,6 +122,27 @@ proc generateCode*(g: ModuleGraph) = for i in 0..high(g.packed): echo i, " is of status ", g.packed[i].status, " ", toFullPath(g.config, FileIndex(i)) + # First pass: Setup all the backend modules for all the modules that have + # changed: + 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, stored: + assert false + of storing, outdated: + setupBackendModule(g, g.packed[i]) + 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): + g.packed[i].loadedButAliveSetChanged = true + setupBackendModule(g, g.packed[i]) + + # Second pass: Code generation. for i in 0..high(g.packed): # case statement here to enforce exhaustive checks. case g.packed[i].status @@ -130,11 +155,7 @@ proc generateCode*(g: ModuleGraph) = closeRodFile(g, g.packed[i].module) storeAliveSyms(g.config, g.packed[i].module.position, 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): + if g.packed[i].loadedButAliveSetChanged: generateCodeForModule(g, g.packed[i], alive) else: addFileToLink(g.config, g.packed[i].module) diff --git a/compiler/ic/ic.nim b/compiler/ic/ic.nim index b5fed7d4e..46bb63e07 100644 --- a/compiler/ic/ic.nim +++ b/compiler/ic/ic.nim @@ -666,7 +666,7 @@ type LoadedModule* = object status*: ModuleStatus - symsInit, typesInit: bool + symsInit, typesInit, loadedButAliveSetChanged*: bool fromDisk*: PackedModule syms: seq[PSym] # indexed by itemId types: seq[PType] diff --git a/tests/ic/mbaseobj.nim b/tests/ic/mbaseobj.nim new file mode 100644 index 000000000..0f4e4a90d --- /dev/null +++ b/tests/ic/mbaseobj.nim @@ -0,0 +1,7 @@ + +type + Base* = ref object of RootObj + s*: string + +method m*(b: Base) {.base.} = + echo "Base ", b.s diff --git a/tests/ic/tmethods.nim b/tests/ic/tmethods.nim new file mode 100644 index 000000000..251f26889 --- /dev/null +++ b/tests/ic/tmethods.nim @@ -0,0 +1,28 @@ +discard """ + output: '''Base abc''' +""" + +import mbaseobj + +var c = Base(s: "abc") +m c + +#!EDIT!# + +discard """ + output: '''Base abc +Inherited abc''' +""" + +import mbaseobj + +type + Inherited = ref object of Base + +method m(i: Inherited) = + procCall m(Base i) + echo "Inherited ", i.s + +var c = Inherited(s: "abc") +m c +