Skip to content

Commit

Permalink
fix Issue 8207 - extern(D) symbols should include another underscore
Browse files Browse the repository at this point in the history
    1. Removed ABI name fiddling from the front-end.
    2. Removed `Target.prefixName` and C++ tests for matching `__Z`.
    3. Prepend prefixes for C++ and D symbols in the backend only
       for the targets that require it (Win32, OSX).
    4. Removed `RTLSYM__DINVARIANT` runtime library symbol, name is now
       the same on all targets.
    5. Correctly set C++ mangling on `LINK.cpp` symbols, before they
       were all being set as D mangled symbols.
    6. Use System mangling as synonym for do not modify symbol.
    7. Added workaround for `extern(D) ___tls_get_addr`.
  • Loading branch information
ibuclaw committed Feb 10, 2018
1 parent 2232b6e commit db29765
Show file tree
Hide file tree
Showing 16 changed files with 60 additions and 75 deletions.
8 changes: 8 additions & 0 deletions changelog/fix8207.dd
@@ -0,0 +1,8 @@
D ABI change on Win32 and OSX targets

The compiler has been updated to prefix all `extern(D)` symbols with an extra
underscore where the platform expects one on all external symbols. This allows
compiled code to work better with binutil programs, such as the ability to list
symbols demangled inside a debugger.

This is an ABI breaking change and requires recompiling libraries.
7 changes: 6 additions & 1 deletion src/dmd/backend/cgobj.c
Expand Up @@ -49,6 +49,11 @@ struct Loc
void error(Loc loc, const char *format, ...);
#endif

#if MARS
// C++ name mangling is handled by front end
#define cpp_mangle(s) ((s)->Sident)
#endif

#if TARGET_WINDOS

static char __file__[] = __FILE__; // for tassert.h
Expand Down Expand Up @@ -2403,14 +2408,14 @@ size_t Obj::mangle(Symbol *s,char *dest)
break;
}
case mTYman_c:
case mTYman_d:
if (config.flags4 & CFG4underscore)
{
dest[1] = '_'; // leading _ in name
memcpy(&dest[2],name,len); // copy in name
len++;
break;
}
case mTYman_d:
case mTYman_sys:
memcpy(dest + 1, name, len); // no mangling
dest[1 + len] = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/dmd/backend/machobj.c
Expand Up @@ -2111,8 +2111,6 @@ char *obj_mangle2(Symbol *s,char *dest)
memcpy(dest + 1 + len, pstr, pstrlen + 1);
break;
}
case mTYman_cpp:
case mTYman_d:
case mTYman_sys:
case 0:
if (len >= DEST_LEN)
Expand All @@ -2121,6 +2119,8 @@ char *obj_mangle2(Symbol *s,char *dest)
break;

case mTYman_c:
case mTYman_cpp:
case mTYman_d:
if (len >= DEST_LEN - 1)
dest = (char *)mem_malloc(1 + len + 1);
dest[0] = '_';
Expand Down
7 changes: 6 additions & 1 deletion src/dmd/backend/mscoffobj.c
Expand Up @@ -45,6 +45,11 @@ static char __file__[] = __FILE__; // for tassert.h
#define DEST_LEN (IDMAX + IDOHD + 1)
char *obj_mangle2(Symbol *s,char *dest);

#if MARS
// C++ name mangling is handled by front end
#define cpp_mangle(s) ((s)->Sident)
#endif

/******************************************
*/

Expand Down Expand Up @@ -1734,7 +1739,6 @@ char *obj_mangle2(Symbol *s,char *dest)
}
// fall through
case mTYman_cpp:
case mTYman_d:
case mTYman_sys:
case_mTYman_c64:
case 0:
Expand All @@ -1744,6 +1748,7 @@ char *obj_mangle2(Symbol *s,char *dest)
break;

case mTYman_c:
case mTYman_d:
if(I64)
goto case_mTYman_c64;
// Prepend _ to identifier
Expand Down
1 change: 0 additions & 1 deletion src/dmd/backend/rtlsym.d
Expand Up @@ -34,7 +34,6 @@ enum
RTLSYM_DARRAY,
RTLSYM_DARRAYP,
RTLSYM_DINVARIANT,
RTLSYM__DINVARIANT,
RTLSYM_MEMCPY,
RTLSYM_MEMSET8,
RTLSYM_MEMSET16,
Expand Down
3 changes: 1 addition & 2 deletions src/dmd/backend/rtlsym.h
Expand Up @@ -56,8 +56,7 @@ SYMBOL_MARS(DUNITTESTP, FLfunc,FREGSAVED,"_d_unittestp", 0, t) \
SYMBOL_MARS(DUNITTEST_MSG, FLfunc,FREGSAVED,"_d_unittest_msg", 0, t) \
SYMBOL_MARS(DARRAY, FLfunc,FREGSAVED,"_d_arraybounds", SFLexit, t) \
SYMBOL_MARS(DARRAYP, FLfunc,FREGSAVED,"_d_arrayboundsp", SFLexit, t) \
SYMBOL_MARS(DINVARIANT, FLfunc,FREGSAVED,"D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \
SYMBOL_MARS(_DINVARIANT, FLfunc,FREGSAVED,"_D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \
SYMBOL_MARS(DINVARIANT, FLfunc,FREGSAVED,"_D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \
SYMBOL_MARS(MEMCPY, FLfunc,FREGSAVED,"memcpy", 0, t) \
SYMBOL_MARS(MEMSET8, FLfunc,FREGSAVED,"memset", 0, t) \
SYMBOL_MARS(MEMSET16, FLfunc,FREGSAVED,"_memset16", 0, t) \
Expand Down
1 change: 0 additions & 1 deletion src/dmd/cppmangle.d
Expand Up @@ -49,7 +49,6 @@ const(char)* toCppMangleItanium(Dsymbol s)
{
//printf("toCppMangleItanium(%s)\n", s.toChars());
OutBuffer buf;
Target.prefixName(&buf, LINK.cpp);
scope CppMangleVisitor v = new CppMangleVisitor(&buf, s.loc);
v.mangleOf(s);
return buf.extractString();
Expand Down
4 changes: 2 additions & 2 deletions src/dmd/dmsc.d
Expand Up @@ -193,8 +193,8 @@ extern (C) Symbol *symboldata(targ_size_t offset,tym_t ty)
Symbol *s = symbol_generate(SClocstat, type_fake(ty));
s.Sfl = FLdata;
s.Soffset = offset;
s.Stype.Tmangle = mTYman_d; // writes symbol unmodified in Obj::mangle
symbol_keep(s); // keep around
s.Stype.Tmangle = mTYman_sys; // writes symbol unmodified in Obj::mangle
symbol_keep(s); // keep around
return s;
}

Expand Down
8 changes: 1 addition & 7 deletions src/dmd/e2ir.d
Expand Up @@ -1982,13 +1982,7 @@ elem *toElem(Expression e, IRState *irs)
!(cast(TypeClass)t1).sym.isCPPclass())
{
ts = symbol_genauto(Type_toCtype(t1));
int rtl;
if (global.params.isLinux || global.params.isFreeBSD || global.params.isDragonFlyBSD || global.params.isSolaris ||
global.params.is64bit && global.params.isWindows)
rtl = RTLSYM__DINVARIANT;
else
rtl = RTLSYM_DINVARIANT;
einv = el_bin(OPcall, TYvoid, el_var(getRtlsym(rtl)), el_var(ts));
einv = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_DINVARIANT)), el_var(ts));
}
else if (global.params.useInvariants &&
t1.ty == Tpointer &&
Expand Down
5 changes: 5 additions & 0 deletions src/dmd/glue.d
Expand Up @@ -968,6 +968,11 @@ void FuncDeclaration_toObjFile(FuncDeclaration fd, bool multiobj)
objmod.includelib(libname);
s.Sclass = SCglobal;
}
else if (fd.ident == Id.tls_get_addr && fd.linkage == LINK.d)
{
// TODO: Change linkage in druntime to extern(C).
f.Fredirect = cast(char*)Id.tls_get_addr.toChars();
}
}

symtab_t *symtabsave = cstate.CSpsymtab;
Expand Down
8 changes: 1 addition & 7 deletions src/dmd/mtype.d
Expand Up @@ -2807,13 +2807,7 @@ extern (C++) abstract class Type : RootObject
//printf("%p %s, deco = %s, name = %s\n", this, toChars(), deco, name);
assert(0 < length && length < namelen); // don't overflow the buffer

int off = 0;
static if (!IN_GCC)
{
if (global.params.isOSX || global.params.isWindows && !global.params.is64bit)
++off; // C mangling will add '_' back in
}
auto id = Identifier.idPool(name + off, length - off);
auto id = Identifier.idPool(name, length);

if (name != namebuf.ptr)
free(name);
Expand Down
39 changes: 9 additions & 30 deletions src/dmd/target.d
Expand Up @@ -41,18 +41,23 @@ struct Target
{
extern (C++) __gshared
{
// D ABI
int ptrsize; /// size of a pointer in bytes
int realsize; /// size a real consumes in memory
int realpad; /// padding added to the CPU real size to bring it up to realsize
int realalignsize; /// alignment for reals
int classinfosize; /// size of `ClassInfo`
ulong maxStaticDataSize; /// maximum size of static data

// C ABI
int c_longsize; /// size of a C `long` or `unsigned long` type
int c_long_doublesize; /// size of a C `long double`

// C++ ABI
bool reverseCppOverloads; /// set if overloaded functions are grouped and in reverse order (such as in dmc and cl)
bool cppExceptions; /// set if catching C++ exceptions is supported
char int64Mangle; /// mangling character for C++ int64_t
char uint64Mangle; /// mangling character for C++ uint64_t
int c_longsize; /// size of a C `long` or `unsigned long` type
int c_long_doublesize; /// size of a C `long double`
int classinfosize; /// size of `ClassInfo`
ulong maxStaticDataSize; /// maximum size of static data
}

/**
Expand Down Expand Up @@ -474,32 +479,6 @@ struct Target
{
}

/**
* For the given symbol written to the OutBuffer, apply any
* target-specific prefixes based on the given linkage.
* Params:
* buf = buffer to write into
* linkage = extern linkage of decl
*/
extern (C++) static void prefixName(OutBuffer* buf, LINK linkage)
{
final switch (linkage)
{
case LINK.cpp:
if (global.params.isOSX)
buf.prependbyte('_');
break;
case LINK.default_:
case LINK.d:
case LINK.c:
case LINK.windows:
case LINK.pascal:
case LINK.objc:
case LINK.system:
break;
}
}

/**
* Mangle the given symbol for C++ ABI.
* Params:
Expand Down
26 changes: 15 additions & 11 deletions src/dmd/target.h
Expand Up @@ -28,19 +28,24 @@ struct OutBuffer;

struct Target
{
// D ABI
static int ptrsize;
static int realsize; // size a real consumes in memory
static int realpad; // 'padding' added to the CPU real size to bring it up to realsize
static int realalignsize; // alignment for reals
static bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order
static bool cppExceptions; // set if catching C++ exceptions is supported
static char int64Mangle; // mangling character for C++ int64_t
static char uint64Mangle; // mangling character for C++ uint64_t
static int c_longsize; // size of a C 'long' or 'unsigned long' type
static int c_long_doublesize; // size of a C 'long double'
static int classinfosize; // size of 'ClassInfo'
static int realsize; // size a real consumes in memory
static int realpad; // 'padding' added to the CPU real size to bring it up to realsize
static int realalignsize; // alignment for reals
static int classinfosize; // size of 'ClassInfo'
static unsigned long long maxStaticDataSize; // maximum size of static data

// C ABI
static int c_longsize; // size of a C 'long' or 'unsigned long' type
static int c_long_doublesize; // size of a C 'long double'

// C++ ABI
static bool reverseCppOverloads; // with dmc and cl, overloaded functions are grouped and in reverse order
static bool cppExceptions; // set if catching C++ exceptions is supported
static char int64Mangle; // mangling character for C++ int64_t
static char uint64Mangle; // mangling character for C++ uint64_t

template <typename T>
struct FPTypeProperties
{
Expand Down Expand Up @@ -75,7 +80,6 @@ struct Target
static Expression *paintAsType(Expression *e, Type *type);
// ABI and backend.
static void loadModule(Module *m);
static void prefixName(OutBuffer *buf, LINK linkage);
static const char *toCppMangle(Dsymbol *s);
static const char *cppTypeInfoMangle(ClassDeclaration *cd);
static const char *cppTypeMangle(Type *t);
Expand Down
4 changes: 2 additions & 2 deletions src/dmd/tocsym.d
Expand Up @@ -263,7 +263,7 @@ Symbol *toSymbol(Dsymbol s)
break;
case LINK.cpp:
s.Sflags |= SFLpublic;
m = mTYman_d;
m = mTYman_cpp;
break;
case LINK.default_:
case LINK.system:
Expand Down Expand Up @@ -374,7 +374,7 @@ Symbol *toSymbol(Dsymbol s)
t.Tty = TYmfunc;
}
}
t.Tmangle = mTYman_d;
t.Tmangle = mTYman_cpp;
break;
case LINK.default_:
case LINK.system:
Expand Down
2 changes: 1 addition & 1 deletion src/dmd/toobj.d
Expand Up @@ -1357,7 +1357,7 @@ void toObjFile(Dsymbol ds, bool multiobj)
return mTYman_d;

case LINK.cpp:
return mTYman_d;
return mTYman_cpp;

case LINK.default_:
case LINK.system:
Expand Down
8 changes: 1 addition & 7 deletions test/compilable/cppmangle.d
Expand Up @@ -364,13 +364,7 @@ extern(C++)
}
}

version (OSX)
{
static assert(T.foo.mangleof == "__ZNK1T3fooEi");
static assert(T.bar.mangleof == "__ZN1T3barEi");
static assert(T.boo.mangleof == "__ZN1T3booE");
}
else version (Posix)
version (Posix)
{
static assert(T.foo.mangleof == "_ZNK1T3fooEi");
static assert(T.bar.mangleof == "_ZN1T3barEi");
Expand Down

0 comments on commit db29765

Please sign in to comment.