Expand Up
@@ -39,442 +39,434 @@
* so nothing would be compatible anyway.
*/
struct CppMangleState
class CppMangleVisitor : public Visitor
{
static Objects components ;
int substitute (OutBuffer * buf , RootObject * p );
int exist (RootObject * p );
void store (RootObject * p );
};
Objects CppMangleState ::components ;
Objects components ;
OutBuffer buf ;
void writeBase36 (OutBuffer * buf , size_t i )
{
if (i >= 36 )
void writeBase36 (size_t i )
{
writeBase36 (buf , i / 36 );
i %= 36 ;
if (i >= 36 )
{
writeBase36 (i / 36 );
i %= 36 ;
}
if (i < 10 )
buf .writeByte ((char )(i + '0' ));
else if (i < 36 )
buf .writeByte ((char )(i - 10 + 'A' ));
else
assert (0 );
}
if (i < 10 )
buf -> writeByte ((char )(i + '0' ));
else if (i < 36 )
buf -> writeByte ((char )(i - 10 + 'A' ));
else
assert (0 );
}
int CppMangleState ::substitute (OutBuffer * buf , RootObject * p )
{
for (size_t i = 0 ; i < components .dim ; i ++ )
int substitute (RootObject * p )
{
if ( p == components [ i ] )
for ( size_t i = 0 ; i < components . dim ; i ++ )
{
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
*/
buf -> writeByte ('S' );
if (i )
writeBase36 (buf , i - 1 );
buf -> writeByte ('_' );
return 1 ;
if (p == components [i ])
{
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
*/
buf .writeByte ('S' );
if (i )
writeBase36 (i - 1 );
buf .writeByte ('_' );
return 1 ;
}
}
components .push (p );
return 0 ;
}
components .push (p );
return 0 ;
}
int CppMangleState ::exist (RootObject * p )
{
for (size_t i = 0 ; i < components .dim ; i ++ )
int exist (RootObject * p )
{
if ( p == components [ i ] )
for ( size_t i = 0 ; i < components . dim ; i ++ )
{
return 1 ;
if (p == components [i ])
{
return 1 ;
}
}
return 0 ;
}
return 0 ;
}
void CppMangleState :: store (RootObject * p )
{
components .push (p );
}
void store (RootObject * p )
{
components .push (p );
}
void source_name (OutBuffer * buf , Dsymbol * s )
{
char * name = s -> ident -> toChars ();
buf -> printf ("%d%s" , strlen (name ), name );
}
void source_name (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 ))
void prefix_name (Dsymbol * s )
{
Dsymbol * p = s -> toParent ();
if (p && !p -> isModule ())
if (!substitute (s ))
{
prefix_name (buf , cms , p );
Dsymbol * p = s -> toParent ();
if (p && !p -> isModule ())
{
prefix_name (p );
}
source_name (s );
}
source_name (buf , s );
}
}
void cpp_mangle_name (OutBuffer * buf , CppMangleState * cms , Dsymbol * s )
{
Dsymbol * p = s -> toParent ();
if (p && !p -> isModule ())
public:
CppMangleVisitor (const char * prefix )
: buf (), components ()
{
buf -> writeByte ('N' );
buf .writestring (prefix );
}
char * finish ()
{
buf .writeByte (0 );
return (char * )buf .extractData ();
}
FuncDeclaration * fd = s -> isFuncDeclaration ();
VarDeclaration * vd = s -> isVarDeclaration ();
if (fd && fd -> type -> isConst ())
void cpp_mangle_name (Dsymbol * s )
{
Dsymbol * p = s -> toParent ();
if (p && !p -> isModule ())
{
buf -> writeByte ('K' );
buf .writeByte ('N' );
FuncDeclaration * fd = s -> isFuncDeclaration ();
VarDeclaration * vd = s -> isVarDeclaration ();
if (fd && fd -> type -> isConst ())
{
buf .writeByte ('K' );
}
if (vd && !(vd -> storage_class & (STCextern | STCgshared )))
{
s -> error ("C++ static non- __gshared non-extern variables not supported" );
}
if (vd || fd )
{
prefix_name (p );
source_name (s );
}
else
{
assert (0 );
}
buf .writeByte ('E' );
}
if (vd && !(vd -> storage_class & (STCextern | STCgshared )))
{
s -> error ("C++ static non- __gshared non-extern variables not supported" );
else
source_name (s );
}
void visit (Type * t )
{
/* Make this the 'vendor extended type' when there is no
* C++ analog.
* u <source-name>
*/
if (!substitute (t ))
{ assert (t -> deco );
buf .printf ("u%d%s" , strlen (t -> deco ), t -> deco );
}
if (vd || fd )
}
void visit (TypeBasic * t )
{
/* 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
*/
char c ;
char p = 0 ;
switch (t -> ty )
{
prefix_name (buf , cms , p );
source_name (buf , s );
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 );
}
else
if ( p || t -> isConst ())
{
assert (0 );
if (substitute (t ))
return ;
}
buf -> writeByte ('E' );
}
else
source_name (buf , s );
}
if (t -> isConst ())
buf .writeByte ('K' );
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 ;
buf .writestring (global .params .isOSX ? "__Z" : "_Z" );
cpp_mangle_name (& buf , & cms , s );
if (p )
buf .writeByte (p );
FuncDeclaration * fd = s -> isFuncDeclaration ();
if (fd )
{ // add <bare-function-type>
TypeFunction * tf = (TypeFunction * )fd -> type ;
assert (tf -> ty == Tfunction );
Parameter::argsCppMangle (& buf , & cms , tf -> parameters , tf -> varargs );
buf .writeByte (c );
}
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 visit (TypeVector * t )
{
if (!substitute (t ))
{
buf .writestring ("U8__vector" );
t -> basetype -> accept (this );
}
}
}
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 )
void visit ( TypeSArray * t )
{
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 (!substitute (t ))
{
buf .printf ("A%llu_" , t -> dim ? t -> dim -> toInteger () : 0 );
t -> next -> accept (this );
}
}
if (p || isConst ())
void visit (TypeDArray * t )
{
if (cms -> substitute (buf , this ))
return ;
visit ((Type * )t );
}
if (isConst ())
buf -> writeByte ('K' );
if (p )
buf -> writeByte (p );
buf -> writeByte (c );
}
void TypeVector ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> substitute (buf , this ))
{ buf -> writestring ("U8__vector" );
basetype -> toCppMangle (buf , cms );
void visit (TypeAArray * t )
{
visit ((Type * )t );
}
}
void TypeSArray ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> substitute (buf , this ))
{ buf -> printf ("A%llu_" , dim ? dim -> toInteger () : 0 );
next -> toCppMangle (buf , cms );
void visit (TypePointer * t )
{
if (!exist (t ))
{
buf .writeByte ('P' );
t -> next -> accept (this );
store (t );
}
else
substitute (t );
}
}
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 -> exist (this ))
{ buf -> writeByte ('P' );
next -> toCppMangle (buf , cms );
cms -> store (this );
void visit (TypeReference * t )
{
if (!exist (t ))
{
buf .writeByte ('R' );
t -> next -> accept (this );
store (t );
}
else
substitute (t );
}
else
cms -> substitute (buf , this );
}
void TypeReference ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> exist (this ))
{ buf -> writeByte ('R' );
next -> toCppMangle (buf , cms );
cms -> store (this );
void visit (TypeFunction * t )
{
/*
* <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 (!exist (t ))
{
buf .writeByte ('F' );
if (t -> linkage == LINKc )
buf .writeByte ('Y' );
t -> next -> accept (this );
argsCppMangle (t -> parameters , t -> varargs );
buf .writeByte ('E' );
store (t );
}
else
substitute (t );
}
else
cms -> substitute (buf , this );
}
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 -> exist (this ))
void visit (TypeDelegate * t )
{
buf -> writeByte ('F' );
if (linkage == LINKc )
buf -> writeByte ('Y' );
next -> toCppMangle (buf , cms );
Parameter::argsCppMangle (buf , cms , parameters , varargs );
buf -> writeByte ('E' );
cms -> store (this );
visit ((Type * )t );
}
else
cms -> substitute (buf , this );
}
void visit (TypeStruct * t )
{
if (!exist (t ))
{
if (t -> isConst ())
buf .writeByte ('K' );
void TypeDelegate ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
Type::toCppMangle (buf , cms );
}
if (!substitute (t -> sym ))
cpp_mangle_name (t -> sym );
if (t -> isConst ())
store (t );
}
else
substitute (t );
}
void TypeStruct ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> exist (this ))
void visit (TypeEnum * t )
{
if (isConst ())
buf -> writeByte ('K' );
if (!exist (t ))
{
if (t -> isConst ())
buf .writeByte ('K' );
if (!cms -> substitute (buf , sym ))
cpp_mangle_name ( buf , cms , sym );
if (!substitute (t -> sym ))
cpp_mangle_name ( t -> sym );
if (isConst ())
cms -> store (this );
if (t -> isConst ())
store (t );
}
else
substitute (t );
}
else
cms -> substitute (buf , this );
}
void visit (TypeTypedef * t )
{
visit ((Type * )t );
}
void TypeEnum ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> exist (this ))
void visit (TypeClass * t )
{
if (isConst ())
buf -> writeByte ('K' );
if (!exist (t ))
{
buf .writeByte ('P' );
if (!cms -> substitute (buf , sym ))
cpp_mangle_name ( buf , cms , sym );
if (!substitute (t -> sym ))
cpp_mangle_name ( t -> sym );
if (isConst ())
cms -> store (this );
store (t );
}
else
substitute (t );
}
else
cms -> substitute (buf , this );
}
struct ArgsCppMangleCtx
{
CppMangleVisitor * v ;
size_t cnt ;
};
void TypeTypedef ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
Type::toCppMangle (buf , cms );
}
void argsCppMangle (Parameters * arguments , int varargs )
{
size_t n = 0 ;
if (arguments )
{
ArgsCppMangleCtx ctx = { this , 0 };
Parameter::foreach (arguments , & argsCppMangleDg , & ctx );
n = ctx .cnt ;
}
if (varargs )
buf .writestring ("z" );
else if (!n )
buf .writeByte ('v' ); // encode ( ) arguments
}
void TypeClass ::toCppMangle (OutBuffer * buf , CppMangleState * cms )
{
if (!cms -> exist (this ))
static int argsCppMangleDg (void * ctx , size_t n , Parameter * arg )
{
buf -> writeByte ('P' );
ArgsCppMangleCtx * p = (ArgsCppMangleCtx * )ctx ;
Type * t = arg -> type -> merge2 ();
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 ();
}
if (!cms -> substitute (buf , sym ))
cpp_mangle_name (buf , cms , sym );
/* If it is a basic, enum or struct type,
* then don't mark it const
*/
if ((t -> ty == Tenum || t -> ty == Tstruct || t -> isTypeBasic ()) && t -> isConst ())
t -> mutableOf ()-> accept (p -> v );
else
t -> accept (p -> v );
cms -> store (this );
p -> cnt ++ ;
return 0 ;
}
else
cms -> substitute (buf , this );
}
struct ArgsCppMangleCtx
{
OutBuffer * buf ;
CppMangleState * cms ;
size_t cnt ;
};
static int argsCppMangleDg ( void * ctx , size_t n , Parameter * arg )
char * toCppMangle ( Dsymbol * s )
{
ArgsCppMangleCtx * p = (ArgsCppMangleCtx * )ctx ;
Type * t = arg -> type -> merge2 ();
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 ();
}
/* If it is a basic, enum or struct type,
* then don't mark it const
/*
* <mangled-name> ::= _Z <encoding>
* <encoding> ::= <function name> <bare-function-type>
* ::= <data name>
* ::= <special-name>
*/
if ((t -> ty == Tenum || t -> ty == Tstruct || t -> isTypeBasic ()) && t -> isConst ())
t -> mutableOf ()-> toCppMangle (p -> buf , p -> cms );
else
t -> toCppMangle (p -> buf , p -> cms );
p -> cnt ++ ;
return 0 ;
}
CppMangleVisitor v (global .params .isOSX ? "__Z " : "_Z ");
void Parameter :: argsCppMangle ( OutBuffer * buf , CppMangleState * cms , Parameters * arguments , int varargs )
{
size_t n = 0 ;
if (arguments )
{
ArgsCppMangleCtx ctx = { buf , cms , 0 } ;
foreach ( arguments , & argsCppMangleDg , & ctx ) ;
n = ctx . cnt ;
v . cpp_mangle_name ( s );
FuncDeclaration * fd = s -> isFuncDeclaration () ;
if (fd )
{ // add <bare-function-type>
assert ( fd -> type -> ty == Tfunction ) ;
TypeFunction * tf = ( TypeFunction * ) fd -> type ;
v . argsCppMangle ( tf -> parameters , tf -> varargs ) ;
}
if (varargs )
buf -> writestring ("z" );
else if (!n )
buf -> writeByte ('v' ); // encode ( ) arguments
return v .finish ();
}
#endif