summary refs log tree commit diff stats
diff options
context:
space:
mode:
authoralaviss <alaviss@users.noreply.github.com>2020-01-23 12:45:31 +0000
committerAndreas Rumpf <rumpf_a@web.de>2020-01-23 13:45:31 +0100
commitf500895efe84525c131beadd2e83b30caa6674a3 (patch)
tree2562499459cbbe87f50c9a1401c27f8a0177bbe9
parent3a5056dc70102e4d6dafaa0e0914ae48326c5f4a (diff)
downloadNim-f500895efe84525c131beadd2e83b30caa6674a3.tar.gz
Unexport even more symbols (#13214)
* system/gc: don't export markStackAndRegisters

* compiler/cgen: unexport internal symbols

As these functions are Nim-specific walkaround against C's optimization
schemes, they don't serve any purpose being exported.

* compiler/cgen: don't export global var unless marked

* compiler/ccgthreadvars: don't export threadvar unless marked

* tests/dll/visibility: also check for exports

This ensure that these changes don't break manual exports.

* compiler/cgen: hide all variables created for constants

* compiler/ccgtypes: don't export RTTI variables

* compiler/ccgexprs: make all complex const static

* nimbase.h: fix export for windows

* compiler/cgen, ccgthreadvars: export variables correctly

For C/C++ variables, `extern` means that the variable is defined in an
another unit. Added a new N_LIB_EXPORT_VAR to correctly export
variables.
-rw-r--r--compiler/ccgexprs.nim6
-rw-r--r--compiler/ccgthreadvars.nim2
-rw-r--r--compiler/ccgtypes.nim4
-rw-r--r--compiler/cgen.nim18
-rw-r--r--lib/nimbase.h6
-rw-r--r--lib/system/gc.nim2
-rw-r--r--tests/dll/visibility.nim36
7 files changed, 52 insertions, 22 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index fd4556687..d718eab42 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1325,7 +1325,7 @@ proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
   if id == p.module.labels:
     # expression not found in the cache:
     inc(p.module.labels)
-    p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
+    p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
           [getTypeDesc(p.module, t), d.r, genBracedInit(p, n, isConst = true)])
 
 proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
@@ -2508,7 +2508,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   if id == p.module.labels:
     # expression not found in the cache:
     inc(p.module.labels)
-    p.module.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
+    p.module.s[cfsData].addf("static NIM_CONST $1 $2 = $3;$n",
          [getTypeDesc(p.module, t), tmp, genBracedInit(p, n, isConst = true)])
 
   if d.k == locNone:
@@ -2896,7 +2896,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
   let base = t.skipTypes(abstractInst)[0]
 
   appcg(p.module, cfsData,
-        "$5 struct {$n" &
+        "static $5 struct {$n" &
         "  #TGenericSeq Sup;$n" &
         "  $1 data[$2];$n" &
         "} $3 = $4;$n", [
diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim
index cc72e3d37..3701f337d 100644
--- a/compiler/ccgthreadvars.nim
+++ b/compiler/ccgthreadvars.nim
@@ -33,6 +33,8 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
       m.g.nimtv.addf("$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
   else:
     if isExtern: m.s[cfsVars].add("extern ")
+    elif lfExportLib in s.loc.flags: m.s[cfsVars].add("N_LIB_EXPORT_VAR ")
+    else: m.s[cfsVars].add("N_LIB_PRIVATE ")
     if optThreads in m.config.globalOptions: m.s[cfsVars].add("NIM_THREADVAR ")
     m.s[cfsVars].add(getTypeDesc(m, s.loc.t))
     m.s[cfsVars].addf(" $1;$n", [s.loc.r])
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 59f47b02d..054aa2b7c 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -1026,7 +1026,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
     m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
          [name, getModuleDllPath(m, m.module)])
   else:
-    m.s[cfsData].addf("TNimType $1;$n", [name])
+    m.s[cfsData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
 
 proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
                     info: TLineInfo) =
@@ -1301,7 +1301,7 @@ proc genTypeInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo)
   else:
     typeName = rope("NIM_NIL")
 
-  m.s[cfsData].addf("TNimType $1;$n", [name])
+  m.s[cfsData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
   let destroyImpl = genHook(m, t, info, attachedDestructor)
   let traceImpl = genHook(m, t, info, attachedTrace)
   let disposeImpl = genHook(m, t, info, attachedDispose)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index a36b6aa29..706e8e3ee 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -549,6 +549,8 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
           decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
         if p.hcrOn: decl.add("static ")
         elif sfImportc in s.flags: decl.add("extern ")
+        elif lfExportLib in s.loc.flags: decl.add("N_LIB_EXPORT_VAR ")
+        else: decl.add("N_LIB_PRIVATE ")
         if s.kind == skLet and value != nil: decl.add("NIM_CONST ")
         decl.add(td)
         if p.hcrOn: decl.add("*")
@@ -1175,7 +1177,7 @@ proc requestConstImpl(p: BProc, sym: PSym) =
   var q = findPendingModule(m, sym)
   if q != nil and not containsOrIncl(q.declaredThings, sym.id):
     assert q.initProc.module == q
-    q.s[cfsData].addf("NIM_CONST $1 $2 = $3;$n",
+    q.s[cfsData].addf("N_LIB_PRIVATE NIM_CONST $1 $2 = $3;$n",
         [getTypeDesc(q, sym.typ), sym.loc.r, genBracedInit(q.initProc, sym.ast, isConst = true)])
   # declare header:
   if q != m and not containsOrIncl(m.declaredThings, sym.id):
@@ -1316,19 +1318,19 @@ proc genMainProc(m: BModule) =
   const
     # not a big deal if we always compile these 3 global vars... makes the HCR code easier
     PosixCmdLine =
-      "int cmdCount;$N" &
-      "char** cmdLine;$N" &
-      "char** gEnv;$N"
+      "N_LIB_PRIVATE int cmdCount;$N" &
+      "N_LIB_PRIVATE char** cmdLine;$N" &
+      "N_LIB_PRIVATE char** gEnv;$N"
 
     # The use of a volatile function pointer to call Pre/NimMainInner
     # prevents inlining of the NimMainInner function and dependent
     # functions, which might otherwise merge their stack frames.
     PreMainBody = "$N" &
-      "void PreMainInner(void) {$N" &
+      "N_LIB_PRIVATE void PreMainInner(void) {$N" &
       "$2" &
       "}$N$N" &
       PosixCmdLine &
-      "void PreMain(void) {$N" &
+      "N_LIB_PRIVATE void PreMain(void) {$N" &
       "\tvoid (*volatile inner)(void);$N" &
       "\tinner = PreMainInner;$N" &
       "$1" &
@@ -1341,7 +1343,7 @@ proc genMainProc(m: BModule) =
     MainProcsWithResult =
       MainProcs & ("\treturn $1nim_program_result;$N")
 
-    NimMainInner = "N_CDECL(void, NimMainInner)(void) {$N" &
+    NimMainInner = "N_LIB_PRIVATE N_CDECL(void, NimMainInner)(void) {$N" &
         "$1" &
       "}$N$N"
 
@@ -1388,7 +1390,7 @@ proc genMainProc(m: BModule) =
     PosixNimDllMain = WinNimDllMain
 
     PosixCDllMain =
-      "void NIM_POSIX_INIT NimMainInit(void) {$N" &
+      "N_LIB_PRIVATE void NIM_POSIX_INIT NimMainInit(void) {$N" &
         MainProcs &
       "}$N$N"
 
diff --git a/lib/nimbase.h b/lib/nimbase.h
index 39885c70c..004ba170b 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -182,10 +182,11 @@ __AVR__
 #  define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name)
 
 #  ifdef __cplusplus
-#    define N_LIB_EXPORT  extern "C" __declspec(dllexport)
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
 #  else
-#    define N_LIB_EXPORT  extern __declspec(dllexport)
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
 #  endif
+#  define N_LIB_EXPORT_VAR  __declspec(dllexport)
 #  define N_LIB_IMPORT  extern __declspec(dllimport)
 #else
 #  define N_LIB_PRIVATE __attribute__((visibility("hidden")))
@@ -215,6 +216,7 @@ __AVR__
 #    define N_SAFECALL_PTR(rettype, name) rettype (*name)
 #  endif
 #  define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default")))
+#  define N_LIB_EXPORT_VAR  __attribute__((visibility("default")))
 #  define N_LIB_IMPORT  extern
 #endif
 
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 0b22d1431..7be9f4b1f 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -682,7 +682,7 @@ proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   `CLANG_NO_SANITIZE_ADDRESS` in `lib/nimbase.h`.
  ]#
 proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl,
-    codegenDecl: "CLANG_NO_SANITIZE_ADDRESS $# $#$#".} =
+    codegenDecl: "CLANG_NO_SANITIZE_ADDRESS N_LIB_PRIVATE $# $#$#".} =
   forEachStackSlot(gch, gcMark)
 
 proc collectZCT(gch: var GcHeap): bool =
diff --git a/tests/dll/visibility.nim b/tests/dll/visibility.nim
index 7341e3311..ec15dad29 100644
--- a/tests/dll/visibility.nim
+++ b/tests/dll/visibility.nim
@@ -1,6 +1,5 @@
 discard """
-  output: "could not import: foo"
-  exitcode: 1
+  output: ""
 """
 
 const LibName {.used.} =
@@ -12,8 +11,33 @@ const LibName {.used.} =
     "libvisibility.so"
 
 when compileOption("app", "lib"):
-  proc foo() {.exportc.} =
-    echo "failed"
+  var
+    bar {.exportc.}: int
+    thr {.exportc, threadvar.}: int
+  proc foo() {.exportc.} = discard
+
+  var
+    exported {.exportc, dynlib.}: int
+    exported_thr {.exportc, threadvar, dynlib.}: int
+  proc exported_func() {.exportc, dynlib.} = discard
 elif isMainModule:
-  proc foo() {.importc, dynlib: LibName.}
-  foo()
+  import dynlib
+
+  let handle = loadLib(LibName)
+
+  template check(sym: untyped) =
+    const s = astToStr(sym)
+    if handle.symAddr(s) != nil:
+      echo s, " is exported"
+  template checkE(sym: untyped) =
+    const s = astToStr(sym)
+    if handle.symAddr(s) == nil:
+      echo s, " is not exported"
+
+  check foo
+  check bar
+  check thr
+
+  checkE exported
+  checkE exported_thr
+  checkE exported_func