From 7cf483ce264d148b39dad6e5f8a7557b19070871 Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 19 Jan 2020 16:38:37 -0600 Subject: [PATCH 01/10] system/gc: don't export markStackAndRegisters --- lib/system/gc.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 0b22d1431e92b..7be9f4b1fc4b5 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 = From ec507a4f07b215c45cced05103eb6018d8e8f44d Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 19 Jan 2020 17:13:55 -0600 Subject: [PATCH 02/10] 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.nim | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index a36b6aa298bae..9757b2bdd4ac2 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1316,19 +1316,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 +1341,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 +1388,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" From ea27abd9e64fc016de30768820cb11b883d1209f Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 19:46:37 -0600 Subject: [PATCH 03/10] compiler/cgen: don't export global var unless marked --- compiler/cgen.nim | 2 ++ tests/dll/visibility.nim | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 9757b2bdd4ac2..6e9b623f25762 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 ") + 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("*") diff --git a/tests/dll/visibility.nim b/tests/dll/visibility.nim index 7341e33112b5e..8f3e54b3b8a5d 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,18 @@ const LibName {.used.} = "libvisibility.so" when compileOption("app", "lib"): + var bar {.exportc.}: int proc foo() {.exportc.} = echo "failed" 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" + + check foo + check bar From 1e77b3844d93740bdf58378dffae7d50bec785a0 Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 20:13:52 -0600 Subject: [PATCH 04/10] compiler/ccgthreadvars: don't export threadvar unless marked --- compiler/ccgthreadvars.nim | 2 ++ tests/dll/visibility.nim | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index cc72e3d37e430..6c94548353fa2 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 ") + 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/tests/dll/visibility.nim b/tests/dll/visibility.nim index 8f3e54b3b8a5d..9fa03261e0337 100644 --- a/tests/dll/visibility.nim +++ b/tests/dll/visibility.nim @@ -11,7 +11,9 @@ const LibName {.used.} = "libvisibility.so" when compileOption("app", "lib"): - var bar {.exportc.}: int + var + bar {.exportc.}: int + thr {.exportc, threadvar.}: int proc foo() {.exportc.} = echo "failed" elif isMainModule: @@ -26,3 +28,4 @@ elif isMainModule: check foo check bar + check thr From a3985c057bc38f747eb05bace5e1a49fdc728d32 Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 20:23:39 -0600 Subject: [PATCH 05/10] tests/dll/visibility: also check for exports This ensure that these changes don't break manual exports. --- tests/dll/visibility.nim | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/dll/visibility.nim b/tests/dll/visibility.nim index 9fa03261e0337..ec15dad291dae 100644 --- a/tests/dll/visibility.nim +++ b/tests/dll/visibility.nim @@ -14,8 +14,12 @@ when compileOption("app", "lib"): var bar {.exportc.}: int thr {.exportc, threadvar.}: int - proc foo() {.exportc.} = - echo "failed" + proc foo() {.exportc.} = discard + + var + exported {.exportc, dynlib.}: int + exported_thr {.exportc, threadvar, dynlib.}: int + proc exported_func() {.exportc, dynlib.} = discard elif isMainModule: import dynlib @@ -25,7 +29,15 @@ elif isMainModule: 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 From e180977716b9d996adb995e270dbae2f597410eb Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 21:04:47 -0600 Subject: [PATCH 06/10] compiler/cgen: hide all variables created for constants --- compiler/cgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 6e9b623f25762..302cc37b9cb1e 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1177,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): From 0d0005120f702cb26e440c6c4fe0bfca7d713764 Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 21:30:09 -0600 Subject: [PATCH 07/10] compiler/ccgtypes: don't export RTTI variables --- compiler/ccgtypes.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 59f47b02d0aa6..054aa2b7cda7f 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) From fc9f49c58204e52f140024350d40d9b9fb25aaba Mon Sep 17 00:00:00 2001 From: Leorize Date: Mon, 20 Jan 2020 21:54:04 -0600 Subject: [PATCH 08/10] compiler/ccgexprs: make all complex const static --- compiler/ccgexprs.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index fd4556687844c..d718eab4221d1 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", [ From c38f56e00be24fe088ba00ba7136c583350c5012 Mon Sep 17 00:00:00 2001 From: Leorize Date: Tue, 21 Jan 2020 21:24:07 -0600 Subject: [PATCH 09/10] nimbase.h: fix export for windows --- lib/nimbase.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nimbase.h b/lib/nimbase.h index 39885c70cdebf..9205d5e89d14e 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -182,9 +182,9 @@ __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_IMPORT extern __declspec(dllimport) #else From 114a5189726465d0d1a75c4969002dc8a38e0776 Mon Sep 17 00:00:00 2001 From: Leorize Date: Tue, 21 Jan 2020 21:29:55 -0600 Subject: [PATCH 10/10] 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. --- compiler/ccgthreadvars.nim | 2 +- compiler/cgen.nim | 2 +- lib/nimbase.h | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 6c94548353fa2..3701f337d2ddb 100644 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -33,7 +33,7 @@ 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 ") + 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)) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 302cc37b9cb1e..706e8e3ee2070 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -549,7 +549,7 @@ 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 ") + 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) diff --git a/lib/nimbase.h b/lib/nimbase.h index 9205d5e89d14e..004ba170b1b59 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -186,6 +186,7 @@ __AVR__ # else # 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