mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 19:36:06 +03:00
LDC 2 compiles again.
This commit is contained in:
parent
6619190ba5
commit
c5be82c5ae
97 changed files with 67333 additions and 56949 deletions
381
dmd2/cppmangle.c
Normal file
381
dmd2/cppmangle.c
Normal file
|
@ -0,0 +1,381 @@
|
|||
|
||||
// Compiler implementation of the D programming language
|
||||
// Copyright (c) 1999-2007 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// http://www.digitalmars.com
|
||||
// License for redistribution is by either the Artistic License
|
||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||
// See the included readme.txt for details.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mars.h"
|
||||
#include "dsymbol.h"
|
||||
#include "mtype.h"
|
||||
#include "scope.h"
|
||||
#include "init.h"
|
||||
#include "expression.h"
|
||||
#include "attrib.h"
|
||||
#include "declaration.h"
|
||||
#include "template.h"
|
||||
#include "id.h"
|
||||
#include "enum.h"
|
||||
#include "import.h"
|
||||
#include "aggregate.h"
|
||||
|
||||
#if DMDV2
|
||||
|
||||
/* Do mangling for C++ linkage.
|
||||
* Follows Itanium C++ ABI 1.86
|
||||
* No attempt is made to support mangling of templates, operator
|
||||
* overloading, or special functions.
|
||||
*
|
||||
* So why don't we use the C++ ABI for D name mangling?
|
||||
* Because D supports a lot of things (like modules) that the C++
|
||||
* ABI has no concept of. These affect every D mangled name,
|
||||
* so nothing would be compatible anyway.
|
||||
*/
|
||||
|
||||
struct CppMangleState
|
||||
{
|
||||
static Array components;
|
||||
|
||||
int substitute(OutBuffer *buf, void *p);
|
||||
};
|
||||
|
||||
Array CppMangleState::components;
|
||||
|
||||
|
||||
void writeBase36(OutBuffer *buf, unsigned i)
|
||||
{
|
||||
if (i >= 36)
|
||||
{
|
||||
writeBase36(buf, i / 36);
|
||||
i %= 36;
|
||||
}
|
||||
if (i < 10)
|
||||
buf->writeByte(i + '0');
|
||||
else if (i < 36)
|
||||
buf->writeByte(i - 10 + 'A');
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int CppMangleState::substitute(OutBuffer *buf, void *p)
|
||||
{
|
||||
for (size_t i = 0; i < components.dim; i++)
|
||||
{
|
||||
if (p == components.data[i])
|
||||
{
|
||||
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
|
||||
*/
|
||||
buf->writeByte('S');
|
||||
if (i)
|
||||
writeBase36(buf, i - 1);
|
||||
buf->writeByte('_');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
components.push(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void source_name(OutBuffer *buf, Dsymbol *s)
|
||||
{
|
||||
char *name = s->ident->toChars();
|
||||
buf->printf("%d%s", strlen(name), name);
|
||||
}
|
||||
|
||||
void prefix_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
|
||||
{
|
||||
if (!cms->substitute(buf, s))
|
||||
{
|
||||
Dsymbol *p = s->toParent();
|
||||
if (p && !p->isModule())
|
||||
{
|
||||
prefix_name(buf, cms, p);
|
||||
}
|
||||
source_name(buf, s);
|
||||
}
|
||||
}
|
||||
|
||||
void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
|
||||
{
|
||||
Dsymbol *p = s->toParent();
|
||||
if (p && !p->isModule())
|
||||
{
|
||||
buf->writeByte('N');
|
||||
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd->isConst())
|
||||
buf->writeByte('K');
|
||||
|
||||
prefix_name(buf, cms, p);
|
||||
source_name(buf, s);
|
||||
|
||||
buf->writeByte('E');
|
||||
}
|
||||
else
|
||||
source_name(buf, s);
|
||||
}
|
||||
|
||||
|
||||
char *cpp_mangle(Dsymbol *s)
|
||||
{
|
||||
/*
|
||||
* <mangled-name> ::= _Z <encoding>
|
||||
* <encoding> ::= <function name> <bare-function-type>
|
||||
* ::= <data name>
|
||||
* ::= <special-name>
|
||||
*/
|
||||
|
||||
CppMangleState cms;
|
||||
memset(&cms, 0, sizeof(cms));
|
||||
cms.components.setDim(0);
|
||||
|
||||
OutBuffer buf;
|
||||
#if MACHOBJ
|
||||
buf.writestring("__Z");
|
||||
#else
|
||||
buf.writestring("_Z");
|
||||
#endif
|
||||
|
||||
cpp_mangle_name(&buf, &cms, s);
|
||||
|
||||
FuncDeclaration *fd = s->isFuncDeclaration();
|
||||
if (fd)
|
||||
{ // add <bare-function-type>
|
||||
TypeFunction *tf = (TypeFunction *)fd->type;
|
||||
assert(tf->ty == Tfunction);
|
||||
Argument::argsCppMangle(&buf, &cms, tf->parameters, tf->varargs);
|
||||
}
|
||||
buf.writeByte(0);
|
||||
return (char *)buf.extractData();
|
||||
}
|
||||
|
||||
/* ============= Type Encodings ============================================= */
|
||||
|
||||
void Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
/* Make this the 'vendor extended type' when there is no
|
||||
* C++ analog.
|
||||
* u <source-name>
|
||||
*/
|
||||
if (!cms->substitute(buf, this))
|
||||
{ assert(deco);
|
||||
buf->printf("u%d%s", strlen(deco), deco);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{ char c;
|
||||
char p = 0;
|
||||
|
||||
/* ABI spec says:
|
||||
* v void
|
||||
* w wchar_t
|
||||
* b bool
|
||||
* c char
|
||||
* a signed char
|
||||
* h unsigned char
|
||||
* s short
|
||||
* t unsigned short
|
||||
* i int
|
||||
* j unsigned int
|
||||
* l long
|
||||
* m unsigned long
|
||||
* x long long, __int64
|
||||
* y unsigned long long, __int64
|
||||
* n __int128
|
||||
* o unsigned __int128
|
||||
* f float
|
||||
* d double
|
||||
* e long double, __float80
|
||||
* g __float128
|
||||
* z ellipsis
|
||||
* u <source-name> # vendor extended type
|
||||
*/
|
||||
|
||||
switch (ty)
|
||||
{
|
||||
case Tvoid: c = 'v'; break;
|
||||
case Tint8: c = 'a'; break;
|
||||
case Tuns8: c = 'h'; break;
|
||||
case Tint16: c = 's'; break;
|
||||
case Tuns16: c = 't'; break;
|
||||
case Tint32: c = 'i'; break;
|
||||
case Tuns32: c = 'j'; break;
|
||||
case Tfloat32: c = 'f'; break;
|
||||
case Tint64: c = 'x'; break;
|
||||
case Tuns64: c = 'y'; break;
|
||||
case Tfloat64: c = 'd'; break;
|
||||
case Tfloat80: c = 'e'; break;
|
||||
case Tbool: c = 'b'; break;
|
||||
case Tchar: c = 'c'; break;
|
||||
case Twchar: c = 't'; break;
|
||||
case Tdchar: c = 'w'; break;
|
||||
|
||||
case Timaginary32: p = 'G'; c = 'f'; break;
|
||||
case Timaginary64: p = 'G'; c = 'd'; break;
|
||||
case Timaginary80: p = 'G'; c = 'e'; break;
|
||||
case Tcomplex32: p = 'C'; c = 'f'; break;
|
||||
case Tcomplex64: p = 'C'; c = 'd'; break;
|
||||
case Tcomplex80: p = 'C'; c = 'e'; break;
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
if (cms->substitute(buf, this))
|
||||
return;
|
||||
buf->writeByte(p);
|
||||
}
|
||||
buf->writeByte(c);
|
||||
}
|
||||
|
||||
|
||||
void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->printf("A%ju_", dim ? dim->toInteger() : 0);
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('P');
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('R');
|
||||
next->toCppMangle(buf, cms);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{ /*
|
||||
* <function-type> ::= F [Y] <bare-function-type> E
|
||||
* <bare-function-type> ::= <signature type>+
|
||||
* # types are possible return type, then parameter types
|
||||
*/
|
||||
|
||||
/* ABI says:
|
||||
"The type of a non-static member function is considered to be different,
|
||||
for the purposes of substitution, from the type of a namespace-scope or
|
||||
static member function whose type appears similar. The types of two
|
||||
non-static member functions are considered to be different, for the
|
||||
purposes of substitution, if the functions are members of different
|
||||
classes. In other words, for the purposes of substitution, the class of
|
||||
which the function is a member is considered part of the type of
|
||||
function."
|
||||
|
||||
BUG: Right now, types of functions are never merged, so our simplistic
|
||||
component matcher always finds them to be different.
|
||||
We should use Type::equals on these, and use different
|
||||
TypeFunctions for non-static member functions, and non-static
|
||||
member functions of different classes.
|
||||
*/
|
||||
if (!cms->substitute(buf, this))
|
||||
{
|
||||
buf->writeByte('F');
|
||||
if (linkage == LINKc)
|
||||
buf->writeByte('Y');
|
||||
next->toCppMangle(buf, cms);
|
||||
Argument::argsCppMangle(buf, cms, parameters, varargs);
|
||||
buf->writeByte('E');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
|
||||
|
||||
void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
|
||||
|
||||
void TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
Type::toCppMangle(buf, cms);
|
||||
}
|
||||
|
||||
|
||||
void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
|
||||
{
|
||||
if (!cms->substitute(buf, this))
|
||||
{ buf->writeByte('P');
|
||||
if (!cms->substitute(buf, sym))
|
||||
cpp_mangle_name(buf, cms, sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Argument::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Arguments *arguments, int varargs)
|
||||
{ int n = 0;
|
||||
if (arguments)
|
||||
{
|
||||
for (size_t i = 0; i < arguments->dim; i++)
|
||||
{ Argument *arg = (Argument *)arguments->data[i];
|
||||
Type *t = arg->type;
|
||||
if (arg->storageClass & (STCout | STCref))
|
||||
t = t->referenceTo();
|
||||
else if (arg->storageClass & STClazy)
|
||||
{ // Mangle as delegate
|
||||
Type *td = new TypeFunction(NULL, t, 0, LINKd);
|
||||
td = new TypeDelegate(td);
|
||||
t = t->merge();
|
||||
}
|
||||
if (t->ty == Tsarray)
|
||||
{ // Mangle static arrays as pointers
|
||||
t = t->pointerTo();
|
||||
}
|
||||
t->toCppMangle(buf, cms);
|
||||
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (varargs)
|
||||
buf->writestring("z");
|
||||
else if (!n)
|
||||
buf->writeByte('v'); // encode ( ) arguments
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue