diff dmd2/cppmangle.c @ 1452:638d16625da2

LDC 2 compiles again.
author Robert Clipsham <robert@octarineparrot.com>
date Sat, 30 May 2009 17:23:32 +0100
parents
children e4f7b5d9c68a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/cppmangle.c	Sat May 30 17:23:32 2009 +0100
@@ -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
+