public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/darwin)] Backport backref patches, missing patches for tests
@ 2020-12-22 13:41 Iain Buclaw
  0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2020-12-22 13:41 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9b6f44b4d65e422dbd504bca115fafd4176ec022

commit 9b6f44b4d65e422dbd504bca115fafd4176ec022
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Tue Dec 22 14:34:11 2020 +0100

    Backport backref patches, missing patches for tests

Diff:
---
 gcc/d/dmd/dmangle.c   | 319 ++++++++++++++++++++++++++++++++++++++++++--------
 gcc/d/dmd/dtemplate.c | 116 +-----------------
 2 files changed, 270 insertions(+), 165 deletions(-)

diff --git a/gcc/d/dmd/dmangle.c b/gcc/d/dmd/dmangle.c
index 8f869266871..f6eee52afbf 100644
--- a/gcc/d/dmd/dmangle.c
+++ b/gcc/d/dmd/dmangle.c
@@ -10,6 +10,7 @@
 
 #include "root/dsystem.h"
 #include "root/root.h"
+#include "root/aav.h"
 
 #include "mangle.h"
 #include "init.h"
@@ -133,13 +134,114 @@ void MODtoDecoBuffer(OutBuffer *buf, MOD mod)
 class Mangler : public Visitor
 {
 public:
+    AA *types;
+    AA *idents;
     OutBuffer *buf;
 
     Mangler(OutBuffer *buf)
     {
+        this->types = NULL;
+        this->idents = NULL;
         this->buf = buf;
     }
 
+    /**
+    * writes a back reference with the relative position encoded with base 26
+    *  using upper case letters for all digits but the last digit which uses
+    *  a lower case letter.
+    * The decoder has to look up the referenced position to determine
+    *  whether the back reference is an identifer (starts with a digit)
+    *  or a type (starts with a letter).
+    *
+    * Params:
+    *  pos           = relative position to encode
+    */
+    void writeBackRef(size_t pos)
+    {
+        buf->writeByte('Q');
+        const size_t base = 26;
+        size_t mul = 1;
+        while (pos >= mul * base)
+            mul *= base;
+        while (mul >= base)
+        {
+            unsigned char dig = (unsigned char)(pos / mul);
+            buf->writeByte('A' + dig);
+            pos -= dig * mul;
+            mul /= base;
+        }
+        buf->writeByte('a' + (unsigned char)pos);
+    }
+
+    /**
+    * Back references a non-basic type
+    *
+    * The encoded mangling is
+    *       'Q' <relative position of first occurrence of type>
+    *
+    * Params:
+    *  t = the type to encode via back referencing
+    *
+    * Returns:
+    *  true if the type was found. A back reference has been encoded.
+    *  false if the type was not found. The current position is saved for later back references.
+    */
+    bool backrefType(Type *t)
+    {
+        if (!t->isTypeBasic())
+        {
+            size_t *p = (size_t *)dmd_aaGet(&types, (void *)t);
+            if (*p)
+            {
+                writeBackRef(buf->length() - *p);
+                return true;
+            }
+            *p = buf->length();
+        }
+        return false;
+    }
+
+    /**
+    * Back references a single identifier
+    *
+    * The encoded mangling is
+    *       'Q' <relative position of first occurrence of type>
+    *
+    * Params:
+    *  id = the identifier to encode via back referencing
+    *
+    * Returns:
+    *  true if the identifier was found. A back reference has been encoded.
+    *  false if the identifier was not found. The current position is saved for later back references.
+    */
+    bool backrefIdentifier(Identifier *id)
+    {
+        size_t *p = (size_t *)dmd_aaGet(&idents, (void *)id);
+        if (*p)
+        {
+            writeBackRef(buf->length() - *p);
+            return true;
+        }
+        *p = buf->length();
+        return false;
+    }
+
+    void mangleSymbol(Dsymbol *s)
+    {
+        s->accept(this);
+    }
+
+    void mangleType(Type *t)
+    {
+        if (!backrefType(t))
+            t->accept(this);
+    }
+
+    void mangleIdentifier(Identifier *id, Dsymbol *s)
+    {
+        if (!backrefIdentifier(id))
+            toBuffer(id->toChars(), s);
+    }
 
     ////////////////////////////////////////////////////////////////////////////
 
@@ -153,7 +255,7 @@ public:
         {
             MODtoDecoBuffer(buf, t->mod);
         }
-        t->accept(this);
+        mangleType(t);
     }
 
     void visit(Type *t)
@@ -207,8 +309,9 @@ public:
     void mangleFuncType(TypeFunction *t, TypeFunction *ta, unsigned char modMask, Type *tret)
     {
         //printf("mangleFuncType() %s\n", t->toChars());
-        if (t->inuse)
+        if (t->inuse && tret)
         {
+            // printf("TypeFunction.mangleFuncType() t = %s inuse\n", t->toChars());
             t->inuse = 2;       // flag error to caller
             return;
         }
@@ -280,35 +383,29 @@ public:
     void visit(TypeEnum *t)
     {
         visit((Type *)t);
-        t->sym->accept(this);
+        mangleSymbol(t->sym);
     }
 
     void visit(TypeStruct *t)
     {
         //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", t->toChars(), name);
         visit((Type *)t);
-        t->sym->accept(this);
+        mangleSymbol(t->sym);
     }
 
     void visit(TypeClass *t)
     {
         //printf("TypeClass::toDecoBuffer('%s' mod=%x) = '%s'\n", t->toChars(), mod, name);
         visit((Type *)t);
-        t->sym->accept(this);
+        mangleSymbol(t->sym);
     }
 
     void visit(TypeTuple *t)
     {
         //printf("TypeTuple::toDecoBuffer() t = %p, %s\n", t, t->toChars());
         visit((Type *)t);
-
-        OutBuffer buf2;
-        buf2.reserve(32);
-        Mangler v(&buf2);
-        v.paramsToDecoBuffer(t->arguments);
-        const char *s = buf2.peekChars();
-        int len = (int)buf2.length();
-        buf->printf("%d%.*s", len, len, s);
+        paramsToDecoBuffer(t->arguments);
+        buf->writeByte('Z');
     }
 
     void visit(TypeNull *t)
@@ -323,16 +420,14 @@ public:
         mangleParent(sthis);
 
         assert(sthis->ident);
-        const char *id = sthis->ident->toChars();
-        toBuffer(id, sthis);
-
+        mangleIdentifier(sthis->ident, sthis);
         if (FuncDeclaration *fd = sthis->isFuncDeclaration())
         {
             mangleFunc(fd, false);
         }
-        else if (sthis->type->deco)
+        else if (sthis->type)
         {
-            buf->writestring(sthis->type->deco);
+            visitWithMask(sthis->type, 0);
         }
         else
             assert(0);
@@ -349,12 +444,14 @@ public:
         if (p)
         {
             mangleParent(p);
-
-            if (p->getIdent())
+            TemplateInstance *ti = p->isTemplateInstance();
+            if (ti && !ti->isTemplateMixin())
             {
-                const char *id = p->ident->toChars();
-                toBuffer(id, s);
-
+                mangleTemplateInstance(ti);
+            }
+            else if (p->getIdent())
+            {
+                mangleIdentifier(p->ident, s);
                 if (FuncDeclaration *f = p->isFuncDeclaration())
                     mangleFunc(f, true);
             }
@@ -375,13 +472,13 @@ public:
             TypeFunction *tfo = (TypeFunction *)fd->originalType;
             mangleFuncType(tf, tfo, 0, NULL);
         }
-        else if (fd->type->deco)
+        else if (fd->type)
         {
-            buf->writestring(fd->type->deco);
+            visitWithMask(fd->type, 0);
         }
         else
         {
-            printf("[%s] %s %s\n", fd->loc.toChars(), fd->toChars(), fd->type->toChars());
+            printf("[%s] %s no type\n", fd->loc.toChars(), fd->toChars());
             assert(0);  // don't mangle function until semantic3 done.
         }
     }
@@ -392,8 +489,8 @@ public:
     void toBuffer(const char *id, Dsymbol *s)
     {
         size_t len = strlen(id);
-        if (len >= 8 * 1024 * 1024)         // 8 megs ought be enough for anyone
-            s->error("excessive length %llu for symbol, possible recursive expansion?", len);
+        if (buf->length() + len >= 8 * 1024 * 1024) // 8 megs ought be enough for anyone
+            s->error("excessive length %llu for symbol, possible recursive expansion?", buf->length() + len);
         else
         {
             buf->printf("%llu", (ulonglong)len);
@@ -401,39 +498,40 @@ public:
         }
     }
 
-    void visit(Declaration *d)
+    static const char *externallyMangledIdentifier(Declaration *d)
     {
-        //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
-        //        d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
         if (!d->parent || d->parent->isModule() || d->linkage == LINKcpp) // if at global scope
         {
             switch (d->linkage)
             {
                 case LINKd:
                     break;
-
                 case LINKc:
                 case LINKwindows:
                 case LINKobjc:
-                    buf->writestring(d->ident->toChars());
-                    return;
-
+                    return d->ident->toChars();
                 case LINKcpp:
-                    buf->writestring(target.cpp.toMangle(d));
-                    return;
-
+                    return target.cpp.toMangle(d);
                 case LINKdefault:
                     d->error("forward declaration");
-                    buf->writestring(d->ident->toChars());
-                    return;
-
+                    return d->ident->toChars();
                 default:
                     fprintf(stderr, "'%s', linkage = %d\n", d->toChars(), d->linkage);
                     assert(0);
-                    return;
             }
         }
+        return NULL;
+    }
 
+    void visit(Declaration *d)
+    {
+        //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d)\n",
+        //        d, d->toChars(), d->parent ? d->parent->toChars() : "null", d->linkage);
+        if (const char *id = externallyMangledIdentifier(d))
+        {
+            buf->writestring(id);
+            return;
+        }
         buf->writestring("_D");
         mangleDecl(d);
     }
@@ -481,7 +579,7 @@ public:
         }
         if (fa)
         {
-            fa->accept(this);
+            mangleSymbol(fa);
             return;
         }
         visit((Dsymbol *)fd);
@@ -507,7 +605,7 @@ public:
         {
             if (!od->hasOverloads || td->overnext == NULL)
             {
-                td->accept(this);
+                mangleSymbol(td);
                 return;
             }
         }
@@ -586,20 +684,131 @@ public:
         else
             mangleParent(ti);
 
-        ti->getIdent();
-        const char *id = ti->ident ? ti->ident->toChars() : ti->toChars();
-        toBuffer(id, ti);
+        if (ti->isTemplateMixin() && ti->ident)
+            mangleIdentifier(ti->ident, ti);
+        else
+            mangleTemplateInstance(ti);
+    }
+
+    void mangleTemplateInstance(TemplateInstance *ti)
+    {
+        TemplateDeclaration *tempdecl = ti->tempdecl->isTemplateDeclaration();
+        assert(tempdecl);
+
+        // Use "__U" for the symbols declared inside template constraint.
+        const char T = ti->members ? 'T' : 'U';
+        buf->printf("__%c", T);
+        mangleIdentifier(tempdecl->ident, tempdecl);
 
-        //printf("TemplateInstance::mangle() %s = %s\n", ti->toChars(), ti->id);
+        Objects *args = ti->tiargs;
+        size_t nparams = tempdecl->parameters->length - (tempdecl->isVariadic() ? 1 : 0);
+        for (size_t i = 0; i < args->length; i++)
+        {
+            RootObject *o = (*args)[i];
+            Type *ta = isType(o);
+            Expression *ea = isExpression(o);
+            Dsymbol *sa = isDsymbol(o);
+            Tuple *va = isTuple(o);
+            //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
+            if (i < nparams && (*tempdecl->parameters)[i]->specialization())
+                buf->writeByte('H'); // https://issues.dlang.org/show_bug.cgi?id=6574
+            if (ta)
+            {
+                buf->writeByte('T');
+                visitWithMask(ta, 0);
+            }
+            else if (ea)
+            {
+                // Don't interpret it yet, it might actually be an alias template parameter.
+                // Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
+                const bool keepLvalue = true;
+                ea = ea->optimize(WANTvalue, keepLvalue);
+                if (ea->op == TOKvar)
+                {
+                    sa = ((VarExp *)ea)->var;
+                    ea = NULL;
+                    goto Lsa;
+                }
+                if (ea->op == TOKthis)
+                {
+                    sa = ((ThisExp *)ea)->var;
+                    ea = NULL;
+                    goto Lsa;
+                }
+                if (ea->op == TOKfunction)
+                {
+                    if (((FuncExp *)ea)->td)
+                        sa = ((FuncExp *)ea)->td;
+                    else
+                        sa = ((FuncExp *)ea)->fd;
+                    ea = NULL;
+                    goto Lsa;
+                }
+                buf->writeByte('V');
+                if (ea->op == TOKtuple)
+                {
+                    ea->error("tuple is not a valid template value argument");
+                    continue;
+                }
+                // Now that we know it is not an alias, we MUST obtain a value
+                unsigned olderr = global.errors;
+                ea = ea->ctfeInterpret();
+                if (ea->op == TOKerror || olderr != global.errors)
+                    continue;
+
+                /* Use type mangling that matches what it would be for a function parameter
+                */
+                visitWithMask(ea->type, 0);
+                ea->accept(this);
+            }
+            else if (sa)
+            {
+            Lsa:
+                sa = sa->toAlias();
+                if (Declaration *d = sa->isDeclaration())
+                {
+                    if (FuncAliasDeclaration *fad = d->isFuncAliasDeclaration())
+                        d = fad->toAliasFunc();
+                    if (d->mangleOverride.length)
+                    {
+                        buf->writeByte('X');
+                        toBuffer(d->mangleOverride.ptr, d);
+                        continue;
+                    }
+                    if (const char *id = externallyMangledIdentifier(d))
+                    {
+                        buf->writeByte('X');
+                        toBuffer(id, d);
+                        continue;
+                    }
+                    if (!d->type || !d->type->deco)
+                    {
+                        ti->error("forward reference of %s %s", d->kind(), d->toChars());
+                        continue;
+                    }
+                }
+                buf->writeByte('S');
+                mangleSymbol(sa);
+            }
+            else if (va)
+            {
+                assert(i + 1 == args->length); // must be last one
+                args = &va->objects;
+                i = -(size_t)1;
+            }
+            else
+                assert(0);
+        }
+        buf->writeByte('Z');
     }
 
     void visit(Dsymbol *s)
     {
         mangleParent(s);
-
-        const char *id = s->ident ? s->ident->toChars() : s->toChars();
-        toBuffer(id, s);
-
+        if (s->ident)
+            mangleIdentifier(s->ident, s);
+        else
+            toBuffer(s->toChars(), s);
         //printf("Dsymbol::mangle() %s = %s\n", s->toChars(), id);
     }
 
@@ -859,3 +1068,9 @@ void mangleToBuffer(Dsymbol *s, OutBuffer *buf)
     Mangler v(buf);
     s->accept(&v);
 }
+
+void mangleToBuffer(TemplateInstance *ti, OutBuffer *buf)
+{
+    Mangler v(buf);
+    v.mangleTemplateInstance(ti);
+}
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index caa8a5ba9f4..fe65bd23e3c 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -7546,122 +7546,12 @@ Dsymbols *TemplateInstance::appendToModuleMember()
 
 Identifier *TemplateInstance::genIdent(Objects *args)
 {
-    TemplateDeclaration *tempdecl = this->tempdecl->isTemplateDeclaration();
-    assert(tempdecl);
-
     //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
+    assert(args == tiargs);
     OutBuffer buf;
-    const char *id = tempdecl->ident->toChars();
-    if (!members)
-    {
-        // Use "__U" for the symbols declared inside template constraint.
-        buf.printf("__U%llu%s", (ulonglong)strlen(id), id);
-    }
-    else
-        buf.printf("__T%llu%s", (ulonglong)strlen(id), id);
-    size_t nparams = tempdecl->parameters->length - (tempdecl->isVariadic() ? 1 : 0);
-    for (size_t i = 0; i < args->length; i++)
-    {
-        RootObject *o = (*args)[i];
-        Type *ta = isType(o);
-        Expression *ea = isExpression(o);
-        Dsymbol *sa = isDsymbol(o);
-        Tuple *va = isTuple(o);
-        //printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
-        if (i < nparams && (*tempdecl->parameters)[i]->specialization())
-            buf.writeByte('H');     // Bugzilla 6574
-        if (ta)
-        {
-            buf.writeByte('T');
-            if (ta->deco)
-                buf.writestring(ta->deco);
-            else
-            {
-                assert(global.errors);
-            }
-        }
-        else if (ea)
-        {
-            // Don't interpret it yet, it might actually be an alias template parameter.
-            // Only constfold manifest constants, not const/immutable lvalues, see https://issues.dlang.org/show_bug.cgi?id=17339.
-            const bool keepLvalue = true;
-            ea = ea->optimize(WANTvalue, keepLvalue);
-            if (ea->op == TOKvar)
-            {
-                sa = ((VarExp *)ea)->var;
-                ea = NULL;
-                goto Lsa;
-            }
-            if (ea->op == TOKthis)
-            {
-                sa = ((ThisExp *)ea)->var;
-                ea = NULL;
-                goto Lsa;
-            }
-            if (ea->op == TOKfunction)
-            {
-                if (((FuncExp *)ea)->td)
-                    sa = ((FuncExp *)ea)->td;
-                else
-                    sa = ((FuncExp *)ea)->fd;
-                ea = NULL;
-                goto Lsa;
-            }
-            buf.writeByte('V');
-            if (ea->op == TOKtuple)
-            {
-                ea->error("tuple is not a valid template value argument");
-                continue;
-            }
-            // Now that we know it is not an alias, we MUST obtain a value
-            unsigned olderr = global.errors;
-            ea = ea->ctfeInterpret();
-            if (ea->op == TOKerror || olderr != global.errors)
-                continue;
-
-            /* Use deco that matches what it would be for a function parameter
-             */
-            buf.writestring(ea->type->deco);
-            mangleToBuffer(ea, &buf);
-        }
-        else if (sa)
-        {
-          Lsa:
-            buf.writeByte('S');
-            sa = sa->toAlias();
-            Declaration *d = sa->isDeclaration();
-            if (d && (!d->type || !d->type->deco))
-            {
-                error("forward reference of %s %s", d->kind(), d->toChars());
-                continue;
-            }
-
-            OutBuffer bufsa;
-            mangleToBuffer(sa, &bufsa);
-            const char *s = bufsa.extractChars();
-
-            /* Bugzilla 3043: if the first character of s is a digit this
-             * causes ambiguity issues because the digits of the two numbers are adjacent.
-             * Current demanglers resolve this by trying various places to separate the
-             * numbers until one gets a successful demangle.
-             * Unfortunately, fixing this ambiguity will break existing binary
-             * compatibility and the demanglers, so we'll leave it as is.
-             */
-            buf.printf("%u%s", (unsigned)strlen(s), s);
-        }
-        else if (va)
-        {
-            assert(i + 1 == args->length);         // must be last one
-            args = &va->objects;
-            i = -(size_t)1;
-        }
-        else
-            assert(0);
-    }
-    buf.writeByte('Z');
-    id = buf.peekChars();
+    mangleToBuffer(this, &buf);
     //printf("\tgenIdent = %s\n", id);
-    return Identifier::idPool(id);
+    return Identifier::idPool(buf.peekChars());
 }
 
 /*************************************


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-12-22 13:41 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-22 13:41 [gcc(refs/users/ibuclaw/heads/darwin)] Backport backref patches, missing patches for tests Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).