prevent name mangling for C++ DLLs

This commit is contained in:
Araq 2015-03-05 01:34:09 +01:00
commit d61f326f38
2 changed files with 42 additions and 34 deletions

View file

@ -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])

View file

@ -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