prevent name mangling for C++ DLLs
This commit is contained in:
parent
83cab19c62
commit
d61f326f38
2 changed files with 42 additions and 34 deletions
|
|
@ -9,31 +9,31 @@
|
||||||
|
|
||||||
# This module declares some helpers for the C code generator.
|
# This module declares some helpers for the C code generator.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
|
ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
|
||||||
platform, trees
|
platform, trees
|
||||||
|
|
||||||
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
|
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkStmtList:
|
of nkStmtList:
|
||||||
for i in 0 .. < n.len:
|
for i in 0 .. < n.len:
|
||||||
result = getPragmaStmt(n[i], w)
|
result = getPragmaStmt(n[i], w)
|
||||||
if result != nil: break
|
if result != nil: break
|
||||||
of nkPragma:
|
of nkPragma:
|
||||||
for i in 0 .. < n.len:
|
for i in 0 .. < n.len:
|
||||||
if whichPragma(n[i]) == w: return n[i]
|
if whichPragma(n[i]) == w: return n[i]
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
|
proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
|
||||||
result = getPragmaStmt(n, w) != nil
|
result = getPragmaStmt(n, w) != nil
|
||||||
|
|
||||||
proc hashString*(s: string): BiggestInt =
|
proc hashString*(s: string): BiggestInt =
|
||||||
# has to be the same algorithm as system.hashString!
|
# has to be the same algorithm as system.hashString!
|
||||||
if CPU[targetCPU].bit == 64:
|
if CPU[targetCPU].bit == 64:
|
||||||
# we have to use the same bitwidth
|
# we have to use the same bitwidth
|
||||||
# as the target CPU
|
# as the target CPU
|
||||||
var b = 0'i64
|
var b = 0'i64
|
||||||
for i in countup(0, len(s) - 1):
|
for i in countup(0, len(s) - 1):
|
||||||
b = b +% ord(s[i])
|
b = b +% ord(s[i])
|
||||||
b = b +% `shl`(b, 10)
|
b = b +% `shl`(b, 10)
|
||||||
b = b xor `shr`(b, 6)
|
b = b xor `shr`(b, 6)
|
||||||
|
|
@ -41,9 +41,9 @@ proc hashString*(s: string): BiggestInt =
|
||||||
b = b xor `shr`(b, 11)
|
b = b xor `shr`(b, 11)
|
||||||
b = b +% `shl`(b, 15)
|
b = b +% `shl`(b, 15)
|
||||||
result = b
|
result = b
|
||||||
else:
|
else:
|
||||||
var a = 0'i32
|
var a = 0'i32
|
||||||
for i in countup(0, len(s) - 1):
|
for i in countup(0, len(s) - 1):
|
||||||
a = a +% ord(s[i]).int32
|
a = a +% ord(s[i]).int32
|
||||||
a = a +% `shl`(a, 10'i32)
|
a = a +% `shl`(a, 10'i32)
|
||||||
a = a xor `shr`(a, 6'i32)
|
a = a xor `shr`(a, 6'i32)
|
||||||
|
|
@ -52,11 +52,11 @@ proc hashString*(s: string): BiggestInt =
|
||||||
a = a +% `shl`(a, 15'i32)
|
a = a +% `shl`(a, 15'i32)
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
var
|
var
|
||||||
gTypeTable: array[TTypeKind, TIdTable]
|
gTypeTable: array[TTypeKind, TIdTable]
|
||||||
gCanonicalTypes: array[TTypeKind, PType]
|
gCanonicalTypes: array[TTypeKind, PType]
|
||||||
|
|
||||||
proc initTypeTables() =
|
proc initTypeTables() =
|
||||||
for i in countup(low(TTypeKind), high(TTypeKind)): initIdTable(gTypeTable[i])
|
for i in countup(low(TTypeKind), high(TTypeKind)): initIdTable(gTypeTable[i])
|
||||||
|
|
||||||
proc resetCaches* =
|
proc resetCaches* =
|
||||||
|
|
@ -67,7 +67,7 @@ proc resetCaches* =
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc echoStats*() =
|
proc echoStats*() =
|
||||||
for i in countup(low(TTypeKind), high(TTypeKind)):
|
for i in countup(low(TTypeKind), high(TTypeKind)):
|
||||||
echo i, " ", gTypeTable[i].counter
|
echo i, " ", gTypeTable[i].counter
|
||||||
|
|
||||||
proc slowSearch(key: PType; k: TTypeKind): PType =
|
proc slowSearch(key: PType; k: TTypeKind): PType =
|
||||||
|
|
@ -78,21 +78,21 @@ proc slowSearch(key: PType; k: TTypeKind): PType =
|
||||||
if idTableHasObjectAsKey(gTypeTable[k], key): return key
|
if idTableHasObjectAsKey(gTypeTable[k], key): return key
|
||||||
for h in countup(0, high(gTypeTable[k].data)):
|
for h in countup(0, high(gTypeTable[k].data)):
|
||||||
var t = PType(gTypeTable[k].data[h].key)
|
var t = PType(gTypeTable[k].data[h].key)
|
||||||
if t != nil and sameBackendType(t, key):
|
if t != nil and sameBackendType(t, key):
|
||||||
return t
|
return t
|
||||||
idTablePut(gTypeTable[k], key, key)
|
idTablePut(gTypeTable[k], key, key)
|
||||||
result = key
|
result = key
|
||||||
|
|
||||||
proc getUniqueType*(key: PType): PType =
|
proc getUniqueType*(key: PType): PType =
|
||||||
# this is a hotspot in the compiler!
|
# this is a hotspot in the compiler!
|
||||||
if key == nil: return
|
if key == nil: return
|
||||||
var k = key.kind
|
var k = key.kind
|
||||||
case k
|
case k
|
||||||
of tyBool, tyChar, tyInt..tyUInt64:
|
of tyBool, tyChar, tyInt..tyUInt64:
|
||||||
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
# no canonicalization for integral types, so that e.g. ``pid_t`` is
|
||||||
# produced instead of ``NI``.
|
# produced instead of ``NI``.
|
||||||
result = key
|
result = key
|
||||||
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
|
of tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
|
||||||
tyCString, tyNone, tyBigNum:
|
tyCString, tyNone, tyBigNum:
|
||||||
result = gCanonicalTypes[k]
|
result = gCanonicalTypes[k]
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
|
@ -127,7 +127,7 @@ proc getUniqueType*(key: PType): PType =
|
||||||
if tfFromGeneric notin key.flags:
|
if tfFromGeneric notin key.flags:
|
||||||
# fast case; lookup per id suffices:
|
# fast case; lookup per id suffices:
|
||||||
result = PType(idTableGet(gTypeTable[k], key))
|
result = PType(idTableGet(gTypeTable[k], key))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
idTablePut(gTypeTable[k], key, key)
|
idTablePut(gTypeTable[k], key, key)
|
||||||
result = key
|
result = key
|
||||||
else:
|
else:
|
||||||
|
|
@ -138,10 +138,10 @@ proc getUniqueType*(key: PType): PType =
|
||||||
if t != nil and sameBackendType(t, key):
|
if t != nil and sameBackendType(t, key):
|
||||||
return t
|
return t
|
||||||
idTablePut(gTypeTable[k], key, key)
|
idTablePut(gTypeTable[k], key, key)
|
||||||
result = key
|
result = key
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
result = PType(idTableGet(gTypeTable[k], key))
|
result = PType(idTableGet(gTypeTable[k], key))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
idTablePut(gTypeTable[k], key, key)
|
idTablePut(gTypeTable[k], key, key)
|
||||||
result = key
|
result = key
|
||||||
of tyProc:
|
of tyProc:
|
||||||
|
|
@ -151,16 +151,16 @@ proc getUniqueType*(key: PType): PType =
|
||||||
# ugh, we need the canon here:
|
# ugh, we need the canon here:
|
||||||
result = slowSearch(key, k)
|
result = slowSearch(key, k)
|
||||||
|
|
||||||
proc tableGetType*(tab: TIdTable, key: PType): RootRef =
|
proc tableGetType*(tab: TIdTable, key: PType): RootRef =
|
||||||
# returns nil if we need to declare this type
|
# returns nil if we need to declare this type
|
||||||
result = idTableGet(tab, key)
|
result = idTableGet(tab, key)
|
||||||
if (result == nil) and (tab.counter > 0):
|
if (result == nil) and (tab.counter > 0):
|
||||||
# we have to do a slow linear search because types may need
|
# we have to do a slow linear search because types may need
|
||||||
# to be compared by their structure:
|
# to be compared by their structure:
|
||||||
for h in countup(0, high(tab.data)):
|
for h in countup(0, high(tab.data)):
|
||||||
var t = PType(tab.data[h].key)
|
var t = PType(tab.data[h].key)
|
||||||
if t != nil:
|
if t != nil:
|
||||||
if sameType(t, key):
|
if sameType(t, key):
|
||||||
return tab.data[h].val
|
return tab.data[h].val
|
||||||
|
|
||||||
proc makeSingleLineCString*(s: string): string =
|
proc makeSingleLineCString*(s: string): string =
|
||||||
|
|
@ -193,16 +193,16 @@ proc mangle*(name: string): string =
|
||||||
else:
|
else:
|
||||||
add(result, "HEX" & toHex(ord(c), 2))
|
add(result, "HEX" & toHex(ord(c), 2))
|
||||||
|
|
||||||
proc makeLLVMString*(s: string): PRope =
|
proc makeLLVMString*(s: string): PRope =
|
||||||
const MaxLineLength = 64
|
const MaxLineLength = 64
|
||||||
result = nil
|
result = nil
|
||||||
var res = "c\""
|
var res = "c\""
|
||||||
for i in countup(0, len(s) - 1):
|
for i in countup(0, len(s) - 1):
|
||||||
if (i + 1) mod MaxLineLength == 0:
|
if (i + 1) mod MaxLineLength == 0:
|
||||||
app(result, toRope(res))
|
app(result, toRope(res))
|
||||||
setLen(res, 0)
|
setLen(res, 0)
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\':
|
of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\':
|
||||||
add(res, '\\')
|
add(res, '\\')
|
||||||
add(res, toHex(ord(s[i]), 2))
|
add(res, toHex(ord(s[i]), 2))
|
||||||
else: add(res, s[i])
|
else: add(res, s[i])
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ __clang__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
# define NIM_THREADVAR __declspec(thread)
|
# define NIM_THREADVAR __declspec(thread)
|
||||||
#else
|
#else
|
||||||
# define NIM_THREADVAR __thread
|
# define NIM_THREADVAR __thread
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -103,7 +103,11 @@ __clang__
|
||||||
# define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
|
# define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
|
||||||
# define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
|
# define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
|
||||||
|
|
||||||
# define N_LIB_EXPORT extern __declspec(dllexport)
|
# ifdef __cplusplus
|
||||||
|
# define N_LIB_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define N_LIB_EXPORT extern __declspec(dllexport)
|
||||||
|
# endif
|
||||||
# define N_LIB_IMPORT extern __declspec(dllimport)
|
# define N_LIB_IMPORT extern __declspec(dllimport)
|
||||||
#else
|
#else
|
||||||
# define N_CDECL(rettype, name) rettype name
|
# define N_CDECL(rettype, name) rettype name
|
||||||
|
|
@ -118,7 +122,11 @@ __clang__
|
||||||
# define N_FASTCALL_PTR(rettype, name) rettype (*name)
|
# define N_FASTCALL_PTR(rettype, name) rettype (*name)
|
||||||
# define N_SAFECALL_PTR(rettype, name) rettype (*name)
|
# define N_SAFECALL_PTR(rettype, name) rettype (*name)
|
||||||
|
|
||||||
# define N_LIB_EXPORT extern
|
# ifdef __cplusplus
|
||||||
|
# define N_LIB_EXPORT extern "C"
|
||||||
|
# else
|
||||||
|
# define N_LIB_EXPORT extern
|
||||||
|
# endif
|
||||||
# define N_LIB_IMPORT extern
|
# define N_LIB_IMPORT extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -345,7 +353,7 @@ struct TFrame {
|
||||||
#define nimln(n, file) \
|
#define nimln(n, file) \
|
||||||
F.line = n; F.filename = file;
|
F.line = n; F.filename = file;
|
||||||
|
|
||||||
#define NIM_POSIX_INIT __attribute__((constructor))
|
#define NIM_POSIX_INIT __attribute__((constructor))
|
||||||
|
|
||||||
#if defined(_MSCVER) && defined(__i386__)
|
#if defined(_MSCVER) && defined(__i386__)
|
||||||
__declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
__declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
||||||
|
|
@ -380,7 +388,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Test to see if Nim and the C compiler agree on the size of a pointer.
|
/* Test to see if Nim and the C compiler agree on the size of a pointer.
|
||||||
On disagreement, your C compiler will say something like:
|
On disagreement, your C compiler will say something like:
|
||||||
"error: 'assert_numbits' declared as an array with a negative size" */
|
"error: 'assert_numbits' declared as an array with a negative size" */
|
||||||
typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
|
typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue