summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-11-30 21:05:45 +0800
committerGitHub <noreply@github.com>2023-11-30 14:05:45 +0100
commitb5f5b74fc8308593f04e3bc11f7c5ead24b73eb5 (patch)
treee373a39deab03649a8fbc4bed9a9c0582f48ba64 /compiler
parent9140f8e2212c91347704cec0f98c0345ddf0ea1e (diff)
downloadNim-b5f5b74fc8308593f04e3bc11f7c5ead24b73eb5.tar.gz
enable vtable implementation for C++ and make it an experimental feature (#23004)
follow up https://github.com/nim-lang/Nim/pull/22991

- [x] turning it into an experimental feature

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgtypes.nim22
-rw-r--r--compiler/cgen.nim3
-rw-r--r--compiler/cgmeth.nim2
-rw-r--r--compiler/condsyms.nim2
-rw-r--r--compiler/nim.cfg5
-rw-r--r--compiler/options.nim3
-rw-r--r--compiler/sem.nim4
7 files changed, 26 insertions, 15 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 2f304852b..462b08a43 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -1678,6 +1678,13 @@ proc genDisplay(m: BModule; t: PType, depth: int): Rope =
   result.add seqs[0]
   result.add "}"
 
+proc genVTable(seqs: seq[PSym]): string =
+  result = "{"
+  for i in 0..<seqs.len:
+    if i > 0: result.add ", "
+    result.add "(void *) " & seqs[i].loc.r
+  result.add "}"
+
 proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
   cgsym(m, "TNimTypeV2")
   m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
@@ -1714,18 +1721,19 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
     m.s[cfsVars].addf("static $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar), objDisplayStore, rope(objDepth+1), objDisplay])
     addf(typeEntry, "$1.display = $2;$n", [name, rope(objDisplayStore)])
 
+  let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
+  if dispatchMethods.len > 0:
+    let vTablePointerName = getTempName(m)
+    m.s[cfsVars].addf("static void* $1[$2] = $3;$n", [vTablePointerName, rope(dispatchMethods.len), genVTable(dispatchMethods)])
+    for i in dispatchMethods:
+      genProcPrototype(m, i)
+    addf(typeEntry, "$1.vTable = $2;$n", [name, vTablePointerName])
+
   m.s[cfsTypeInit3].add typeEntry
 
   if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
     discard genTypeInfoV1(m, t, info)
 
-proc genVTable(seqs: seq[PSym]): string =
-  result = "{"
-  for i in 0..<seqs.len:
-    if i > 0: result.add ", "
-    result.add "(void *) " & seqs[i].loc.r
-  result.add "}"
-
 proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineInfo) =
   cgsym(m, "TNimTypeV2")
   m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 5a331ae7c..d22a6bdc2 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -2234,8 +2234,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
         incl m.flags, objHasKidsValid
       if optMultiMethods in m.g.config.globalOptions or
           m.g.config.selectedGC notin {gcArc, gcOrc, gcAtomicArc} or
-          not m.g.config.isDefined("nimPreviewVtables") or
-          m.g.config.backend == backendCpp or sfCompileToCpp in m.module.flags:
+          vtables notin m.g.config.features:
         generateIfMethodDispatchers(graph, m.idgen)
 
 
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 3bbe7b3f4..833bb6fe5 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -157,7 +157,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
 
 proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym) =
   var witness: PSym = nil
-  if s.typ[1].owner.getModule != s.getModule and g.config.isDefined("nimPreviewVtables"):
+  if s.typ[1].owner.getModule != s.getModule and vtables in g.config.features and not g.config.isDefined("nimInternalNonVtablesTesting"):
     localError(g.config, s.info, errGenerated, "method `" & s.name.s &
           "` can be defined only in the same module with its type (" & s.typ[1].typeToString() & ")")
   for i in 0..<g.methods.len:
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index aa619c932..5865e5310 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -163,3 +163,5 @@ proc initDefines*(symbols: StringTableRef) =
 
   defineSymbol("nimHasCastExtendedVm")
   defineSymbol("nimHasWarnStdPrefix")
+
+  defineSymbol("nimHasVtables")
diff --git a/compiler/nim.cfg b/compiler/nim.cfg
index 43da7e3e0..ce5a22ad2 100644
--- a/compiler/nim.cfg
+++ b/compiler/nim.cfg
@@ -9,7 +9,6 @@ define:nimPreviewSlimSystem
 define:nimPreviewCstringConversion
 define:nimPreviewProcConversion
 define:nimPreviewRangeDefault
-define:nimPreviewVtables
 define:nimPreviewNonVarDestructor
 threads:off
 
@@ -58,3 +57,7 @@ define:useStdoutAsStdmsg
   warning[StdPrefix]:on
   warningAsError[StdPrefix]:on
 @end
+
+@if nimHasVtables:
+  experimental:vtables
+@end
diff --git a/compiler/options.nim b/compiler/options.nim
index 3731304c7..9282247c3 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -226,7 +226,8 @@ type
     flexibleOptionalParams,
     strictDefs,
     strictCaseObjects,
-    inferGenericTypes
+    inferGenericTypes,
+    vtables
 
   LegacyFeature* = enum
     allowSemcheckedAstModification,
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 2bdb1284f..03e599753 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -861,9 +861,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
   trackStmt(c, c.module, result, isTopLevel = true)
   if optMultiMethods notin c.config.globalOptions and
       c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
-      c.config.isDefined("nimPreviewVtables") and 
-      c.config.backend != backendCpp and
-      sfCompileToCpp notin c.module.flags:
+      Feature.vtables in c.config.features:
     sortVTableDispatchers(c.graph)
 
     if sfMainModule in c.module.flags: