Merge current development state of 2.067

First merge of current development stream. Asm blocks are known to be broken.

DMD:      0c9f437bc24015707130ba42dc434d9cd58282fb
druntime: 86d49cfb3670904603df0cfdfe44c6fff565c0fc
Phobos:   a8ca4f7964becac680af0eadbde05aa7d10fc338
This commit is contained in:
kai 2014-11-15 18:46:05 +01:00
parent 2bcf8880d1
commit a2748cd2fd
95 changed files with 8240 additions and 7214 deletions

View file

@ -49,6 +49,7 @@ class CppMangleVisitor : public Visitor
Objects components;
OutBuffer buf;
bool is_top_level;
bool components_on;
void writeBase36(size_t i)
{
@ -67,50 +68,55 @@ class CppMangleVisitor : public Visitor
int substitute(RootObject *p)
{
for (size_t i = 0; i < components.dim; i++)
{
if (p == components[i])
//printf("substitute %s\n", p ? p->toChars() : NULL);
if (components_on)
for (size_t i = 0; i < components.dim; i++)
{
/* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
*/
buf.writeByte('S');
if (i)
writeBase36(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;
}
}
}
return 0;
}
int exist(RootObject *p)
{
for (size_t i = 0; i < components.dim; i++)
{
if (p == components[i])
//printf("exist %s\n", p ? p->toChars() : NULL);
if (components_on)
for (size_t i = 0; i < components.dim; i++)
{
return 1;
if (p == components[i])
{
return 1;
}
}
}
return 0;
}
void store(RootObject *p)
{
//printf("push %s\n", p ? p->toChars() : NULL);
components.push(p);
//printf("store %s\n", p ? p->toChars() : NULL);
if (components_on)
components.push(p);
}
void source_name(Dsymbol *s)
void source_name(Dsymbol *s, bool skipname = false)
{
char *name = s->ident->toChars();
//printf("source_name(%s)\n", s->toChars());
TemplateInstance *ti = s->isTemplateInstance();
if (ti)
{
if (!substitute(ti->tempdecl))
if (!skipname && !substitute(ti->tempdecl))
{
store(ti->tempdecl);
name = ti->name->toChars();
const char *name = ti->toAlias()->ident->toChars();
buf.printf("%d%s", strlen(name), name);
}
buf.writeByte('I');
@ -208,8 +214,7 @@ class CppMangleVisitor : public Visitor
{
if (!substitute(d))
{
cpp_mangle_name(d);
store(d);
cpp_mangle_name(d, false);
}
}
else
@ -234,12 +239,14 @@ class CppMangleVisitor : public Visitor
}
else
{
const char *name = s->ident->toChars();
buf.printf("%d%s", strlen(name), name);
}
}
void prefix_name(Dsymbol *s)
{
//printf("prefix_name(%s)\n", s->toChars());
if (!substitute(s))
{
store(s);
@ -265,13 +272,32 @@ class CppMangleVisitor : public Visitor
}
}
void cpp_mangle_name(Dsymbol *s)
/* Is s the initial qualifier?
*/
bool is_initial_qualifier(Dsymbol *s)
{
Dsymbol *p = s->toParent();
if (p && p->isTemplateInstance())
{
if (exist(p->isTemplateInstance()->tempdecl))
{
return true;
}
p = p->toParent();
}
return !p || p->isModule();
}
void cpp_mangle_name(Dsymbol *s, bool qualified)
{
//printf("cpp_mangle_name(%s, %d)\n", s->toChars(), qualified);
Dsymbol *p = s->toParent();
Dsymbol *se = s;
bool dont_write_prefix = false;
if (p && p->isTemplateInstance())
{
s = p;
se = p;
if (exist(p->isTemplateInstance()->tempdecl))
dont_write_prefix = true;
p = p->toParent();
@ -279,14 +305,93 @@ class CppMangleVisitor : public Visitor
if (p && !p->isModule())
{
buf.writeByte('N');
if (!dont_write_prefix)
prefix_name(p);
source_name(s);
buf.writeByte('E');
/* The N..E is not required if:
* 1. the parent is 'std'
* 2. 'std' is the initial qualifier
* 3. there is no CV-qualifier or a ref-qualifier for a member function
* ABI 5.1.8
*/
if (p->ident == Id::std &&
is_initial_qualifier(p) &&
!qualified)
{
if (s->ident == Id::allocator)
{
buf.writestring("Sa"); // "Sa" is short for ::std::allocator
source_name(se, true);
}
else if (s->ident == Id::basic_string)
{
components_on = false; // turn off substitutions
buf.writestring("Sb"); // "Sb" is short for ::std::basic_string
size_t off = buf.offset;
source_name(se, true);
components_on = true;
// Replace ::std::basic_string < char, ::std::char_traits<char>, ::std::allocator<char> >
// with Ss
//printf("xx: '%.*s'\n", (int)(buf.offset - off), buf.data + off);
if (buf.offset - off >= 26 &&
memcmp(buf.data + off, "IcSt11char_traitsIcESaIcEE", 26) == 0)
{
buf.remove(off - 2, 28);
buf.insert(off - 2, "Ss", 2);
return;
}
buf.setsize(off);
source_name(se, true);
}
else if (s->ident == Id::basic_istream ||
s->ident == Id::basic_ostream ||
s->ident == Id::basic_iostream)
{
/* Replace
* ::std::basic_istream<char, std::char_traits<char> > with Si
* ::std::basic_ostream<char, std::char_traits<char> > with So
* ::std::basic_iostream<char, std::char_traits<char> > with Sd
*/
size_t off = buf.offset;
components_on = false; // turn off substitutions
source_name(se, true);
components_on = true;
//printf("xx: '%.*s'\n", (int)(buf.offset - off), buf.data + off);
if (buf.offset - off >= 21 &&
memcmp(buf.data + off, "IcSt11char_traitsIcEE", 21) == 0)
{
buf.remove(off, 21);
char mbuf[2];
mbuf[0] = 'S';
mbuf[1] = 'i';
if (s->ident == Id::basic_ostream)
mbuf[1] = 'o';
else if(s->ident == Id::basic_iostream)
mbuf[1] = 'd';
buf.insert(off, mbuf, 2);
return;
}
buf.setsize(off);
buf.writestring("St");
source_name(se);
}
else
{
buf.writestring("St");
source_name(se);
}
}
else
{
buf.writeByte('N');
if (!dont_write_prefix)
prefix_name(p);
source_name(se);
buf.writeByte('E');
}
}
else
source_name(s);
source_name(se);
store(s);
}
void mangle_variable(VarDeclaration *d, bool is_temp_arg_ref)
@ -324,6 +429,7 @@ class CppMangleVisitor : public Visitor
void mangle_function(FuncDeclaration *d)
{
//printf("mangle_function(%s)\n", d->toChars());
/*
* <mangled-name> ::= _Z <encoding>
* <encoding> ::= <function name> <bare-function-type>
@ -340,6 +446,30 @@ class CppMangleVisitor : public Visitor
if (d->type->isConst())
buf.writeByte('K');
prefix_name(p);
// See ABI 5.1.8 Compression
// Replace ::std::allocator with Sa
if (buf.offset >= 17 && memcmp(buf.data, "_ZN3std9allocator", 17) == 0)
{
buf.remove(3, 14);
buf.insert(3, "Sa", 2);
}
// Replace ::std::basic_string with Sb
if (buf.offset >= 21 && memcmp(buf.data, "_ZN3std12basic_string", 21) == 0)
{
buf.remove(3, 18);
buf.insert(3, "Sb", 2);
}
// Replace ::std with St
if (buf.offset >= 7 && memcmp(buf.data, "_ZN3std", 7) == 0)
{
buf.remove(3, 4);
buf.insert(3, "St", 2);
}
if (d->isDtorDeclaration())
{
buf.writestring("D1");
@ -408,7 +538,7 @@ class CppMangleVisitor : public Visitor
public:
CppMangleVisitor()
: buf(), components(), is_top_level(false)
: buf(), components(), is_top_level(false), components_on(true)
{
}
@ -483,14 +613,14 @@ public:
case Tint32: c = 'i'; break;
case Tuns32: c = 'j'; break;
case Tfloat32: c = 'f'; break;
case Tint64: c = (Target::longsize == 8 ? 'l' : 'x'); break;
case Tuns64: c = (Target::longsize == 8 ? 'm' : 'y'); break;
case Tint64: c = (Target::c_longsize == 8 ? 'l' : 'x'); break;
case Tuns64: c = (Target::c_longsize == 8 ? 'm' : 'y'); break;
case Tfloat64: c = 'd'; break;
case Tfloat80: c = (Target::realsize - Target::realpad == 16) ? 'g' : 'e'; break;
case Tbool: c = 'b'; break;
case Tchar: c = 'c'; break;
case Twchar: c = 't'; break;
case Tdchar: c = 'w'; break;
case Twchar: c = 't'; break; // unsigned short
case Tdchar: c = 'w'; break; // wchar_t (UTF-32)
case Timaginary32: p = 'G'; c = 'f'; break;
case Timaginary64: p = 'G'; c = 'd'; break;
@ -639,7 +769,42 @@ public:
void visit(TypeStruct *t)
{
Identifier *id = t->sym->ident;
//printf("struct id = '%s'\n", id->toChars());
char c;
if (id == Id::__c_long)
c = 'l';
else if (id == Id::__c_ulong)
c = 'm';
else
c = 0;
if (c)
{
if (t->isImmutable() || t->isShared())
{
visit((Type *)t);
}
if (t->isConst())
{
if (substitute(t))
{
return;
}
else
{
store(t);
}
}
if (t->isConst())
buf.writeByte('K');
buf.writeByte(c);
return;
}
is_top_level = false;
if (substitute(t)) return;
if (t->isImmutable() || t->isShared())
{
@ -650,8 +815,7 @@ public:
if (!substitute(t->sym))
{
cpp_mangle_name(t->sym);
store(t->sym);
cpp_mangle_name(t->sym, t->isConst());
}
if (t->isImmutable() || t->isShared())
@ -667,13 +831,13 @@ public:
{
is_top_level = false;
if (substitute(t)) return;
if (t->isConst())
buf.writeByte('K');
if (!substitute(t->sym))
{
cpp_mangle_name(t->sym);
store(t->sym);
cpp_mangle_name(t->sym, t->isConst());
}
if (t->isImmutable() || t->isShared())
@ -685,11 +849,6 @@ public:
store(t);
}
void visit(TypeTypedef *t)
{
visit((Type *)t);
}
void visit(TypeClass *t)
{
if (substitute(t)) return;
@ -701,12 +860,13 @@ public:
buf.writeByte('K');
is_top_level = false;
buf.writeByte('P');
if (t->isConst())
buf.writeByte('K');
if (!substitute(t->sym))
{
cpp_mangle_name(t->sym);
store(t->sym);
cpp_mangle_name(t->sym, t->isConst());
}
if (t->isConst())
store(NULL);
@ -716,6 +876,7 @@ public:
char *toCppMangle(Dsymbol *s)
{
//printf("toCppMangle(%s)\n", s->toChars());
CppMangleVisitor v;
return v.mangleOf(s);
}
@ -818,7 +979,7 @@ public:
case Tfloat64: buf.writeByte('N'); break;
case Tbool: buf.writestring("_N"); break;
case Tchar: buf.writeByte('D'); break;
case Twchar: buf.writeByte('G'); break; // unsigned short
case Tdchar: buf.writeByte('I'); break; // unsigned int
case Tfloat80:
if (flags & IS_DMC)
@ -827,7 +988,7 @@ public:
buf.writestring("_T"); // Intel long double
break;
case Tdchar:
case Twchar:
if (flags & IS_DMC)
buf.writestring("_Y"); // DigitalMars wchar_t
else
@ -981,14 +1142,44 @@ public:
void visit(TypeStruct *type)
{
if (checkTypeSaved(type)) return;
//printf("visit(TypeStruct); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE));
mangleModifier(type);
if (type->sym->isUnionDeclaration())
buf.writeByte('T');
Identifier *id = type->sym->ident;
char c;
if (id == Id::__c_long_double)
c = 'O'; // VC++ long double
else if (id == Id::__c_long)
c = 'J'; // VC++ long
else if (id == Id::__c_ulong)
c = 'K'; // VC++ unsigned long
else
buf.writeByte('U');
mangleIdent(type->sym);
c = 0;
if (c)
{
if (type->isImmutable() || type->isShared())
{
visit((Type*)type);
return;
}
if (type->isConst() && ((flags & IS_NOT_TOP_TYPE) || (flags & IS_DMC)))
{
if (checkTypeSaved(type)) return;
}
mangleModifier(type);
buf.writeByte(c);
}
else
{
if (checkTypeSaved(type)) return;
//printf("visit(TypeStruct); is_not_top_type = %d\n", (int)(flags & IS_NOT_TOP_TYPE));
mangleModifier(type);
if (type->sym->isUnionDeclaration())
buf.writeByte('T');
else
buf.writeByte('U');
mangleIdent(type->sym);
}
flags &= ~IS_NOT_TOP_TYPE;
flags &= ~IGNORE_CONST;
}
@ -1096,7 +1287,7 @@ private:
// Pivate methods always non-virtual in D and it should be mangled as non-virtual in C++
if (d->isVirtual() && d->vtblIndex != -1)
{
switch (d->protection)
switch (d->protection.kind)
{
case PROTprivate:
buf.writeByte('E');
@ -1111,7 +1302,7 @@ private:
}
else
{
switch (d->protection)
switch (d->protection.kind)
{
case PROTprivate:
buf.writeByte('A');
@ -1137,7 +1328,7 @@ private:
}
else if (d->isMember2()) // static function
{ // <flags> ::= <virtual/protection flag> <calling convention flag>
switch (d->protection)
switch (d->protection.kind)
{
case PROTprivate:
buf.writeByte('C');
@ -1179,7 +1370,7 @@ private:
}
else
{
switch (d->protection)
switch (d->protection.kind)
{
case PROTprivate:
buf.writeByte('0');
@ -1608,8 +1799,14 @@ private:
flags &= ~IGNORE_CONST;
if (rettype->ty == Tstruct || rettype->ty == Tenum)
{
tmp.buf.writeByte('?');
tmp.buf.writeByte('A');
Identifier *id = rettype->toDsymbol(NULL)->ident;
if (id != Id::__c_long_double &&
id != Id::__c_long &&
id != Id::__c_ulong)
{
tmp.buf.writeByte('?');
tmp.buf.writeByte('A');
}
}
tmp.flags |= MANGLE_RETURN_TYPE;
rettype->accept(&tmp);
@ -1673,7 +1870,7 @@ private:
char *toCppMangle(Dsymbol *s)
{
VisualCPPMangler v(!global.params.is64bit);
VisualCPPMangler v(!global.params.mscoff);
return v.mangleOf(s);
}