[pkg-d-commits] [ldc] 41/95: Use DMD's typinf.d directly

Matthias Klumpp mak at moszumanska.debian.org
Thu Jul 13 20:53:58 UTC 2017


This is an automated email from the git hooks/post-receive script.

mak pushed a commit to annotated tag v1.3.0-beta1
in repository ldc.

commit fd7c075e3bfd742a1e664f937ad1f07c1623bf4e
Author: Martin <noone at nowhere.com>
Date:   Sun Mar 5 14:28:56 2017 +0100

    Use DMD's typinf.d directly
    
    Instead of letting our old copy silently go more and more out-of-sync.
    In this case, we missed the upstream fix wrt. skipping the declaration of
    ClassInfos for speculative class types.
    
    There are 2 noteworthy functional changes for function
    `getOrCreateTypeInfoDeclaration()`:
    
    1) The old version always overwrote `torig->vtinfo` with `t->vtinfo` when
       declaring a new TypeInfo, whereas upstream's `genTypeInfo()` only sets
       it if it was null before.
    
    2) The old version called `semanticTypeInfo()` during a semantic pass,
       upstream doesn't.
    
    The LDC-specific exception for class types in `builtinTypeInfo()` is still
    required.
    
    Fixes dmd-testsuite's runnable/b16278.d.
---
 ddmd/typinf.d        | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++
 gen/declarations.cpp |  80 ----------------
 gen/typinf.cpp       | 116 +---------------------
 gen/typinf.h         |   3 +
 4 files changed, 273 insertions(+), 192 deletions(-)

diff --git a/ddmd/typinf.d b/ddmd/typinf.d
new file mode 100644
index 0000000..2889bf5
--- /dev/null
+++ b/ddmd/typinf.d
@@ -0,0 +1,266 @@
+/**
+ * Compiler implementation of the
+ * $(LINK2 http://www.dlang.org, D programming language).
+ *
+ * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
+ * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
+ * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
+ * Source:      $(DMDSRC _typeinf.d)
+ */
+
+module ddmd.typinf;
+
+import ddmd.declaration;
+import ddmd.dmodule;
+import ddmd.dscope;
+import ddmd.dclass;
+import ddmd.dstruct;
+import ddmd.errors;
+import ddmd.globals;
+import ddmd.gluelayer;
+import ddmd.mtype;
+import ddmd.visitor;
+
+version (IN_LLVM)
+{
+    import ddmd.dsymbol;
+    extern (C++) void Declaration_codegen(Dsymbol decl);
+}
+
+/****************************************************
+ * Get the exact TypeInfo.
+ */
+extern (C++) void genTypeInfo(Type torig, Scope* sc)
+{
+    //printf("Type::genTypeInfo() %p, %s\n", this, toChars());
+    if (!Type.dtypeinfo)
+    {
+        torig.error(Loc(), "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
+        fatal();
+    }
+
+    Type t = torig.merge2(); // do this since not all Type's are merge'd
+    if (!t.vtinfo)
+    {
+        if (t.isShared()) // does both 'shared' and 'shared const'
+            t.vtinfo = TypeInfoSharedDeclaration.create(t);
+        else if (t.isConst())
+            t.vtinfo = TypeInfoConstDeclaration.create(t);
+        else if (t.isImmutable())
+            t.vtinfo = TypeInfoInvariantDeclaration.create(t);
+        else if (t.isWild())
+            t.vtinfo = TypeInfoWildDeclaration.create(t);
+        else
+            t.vtinfo = getTypeInfoDeclaration(t);
+        assert(t.vtinfo);
+
+        /* If this has a custom implementation in std/typeinfo, then
+         * do not generate a COMDAT for it.
+         */
+        if (!builtinTypeInfo(t))
+        {
+            // Generate COMDAT
+            if (sc) // if in semantic() pass
+            {
+                // Find module that will go all the way to an object file
+                Module m = sc._module.importedFrom;
+                m.members.push(t.vtinfo);
+            }
+            else // if in obj generation pass
+            {
+                version (IN_LLVM)
+                    Declaration_codegen(t.vtinfo);
+                else
+                    toObjFile(t.vtinfo, global.params.multiobj);
+            }
+        }
+    }
+    if (!torig.vtinfo)
+        torig.vtinfo = t.vtinfo; // Types aren't merged, but we can share the vtinfo's
+    assert(torig.vtinfo);
+}
+
+extern (C++) Type getTypeInfoType(Type t, Scope* sc)
+{
+    assert(t.ty != Terror);
+    genTypeInfo(t, sc);
+    return t.vtinfo.type;
+}
+
+extern (C++) TypeInfoDeclaration getTypeInfoDeclaration(Type t)
+{
+    //printf("Type::getTypeInfoDeclaration() %s\n", t.toChars());
+    switch (t.ty)
+    {
+    case Tpointer:
+        return TypeInfoPointerDeclaration.create(t);
+    case Tarray:
+        return TypeInfoArrayDeclaration.create(t);
+    case Tsarray:
+        return TypeInfoStaticArrayDeclaration.create(t);
+    case Taarray:
+        return TypeInfoAssociativeArrayDeclaration.create(t);
+    case Tstruct:
+        return TypeInfoStructDeclaration.create(t);
+    case Tvector:
+        return TypeInfoVectorDeclaration.create(t);
+    case Tenum:
+        return TypeInfoEnumDeclaration.create(t);
+    case Tfunction:
+        return TypeInfoFunctionDeclaration.create(t);
+    case Tdelegate:
+        return TypeInfoDelegateDeclaration.create(t);
+    case Ttuple:
+        return TypeInfoTupleDeclaration.create(t);
+    case Tclass:
+        if ((cast(TypeClass)t).sym.isInterfaceDeclaration())
+            return TypeInfoInterfaceDeclaration.create(t);
+        else
+            return TypeInfoClassDeclaration.create(t);
+
+    default:
+        return TypeInfoDeclaration.create(t);
+    }
+}
+
+extern (C++) bool isSpeculativeType(Type t)
+{
+    extern (C++) final class SpeculativeTypeVisitor : Visitor
+    {
+        alias visit = super.visit;
+    public:
+        bool result;
+
+        extern (D) this()
+        {
+        }
+
+        override void visit(Type t)
+        {
+            Type tb = t.toBasetype();
+            if (tb != t)
+                tb.accept(this);
+        }
+
+        override void visit(TypeNext t)
+        {
+            if (t.next)
+                t.next.accept(this);
+        }
+
+        override void visit(TypeBasic t)
+        {
+        }
+
+        override void visit(TypeVector t)
+        {
+            t.basetype.accept(this);
+        }
+
+        override void visit(TypeAArray t)
+        {
+            t.index.accept(this);
+            visit(cast(TypeNext)t);
+        }
+
+        override void visit(TypeFunction t)
+        {
+            visit(cast(TypeNext)t);
+            // Currently TypeInfo_Function doesn't store parameter types.
+        }
+
+        override void visit(TypeStruct t)
+        {
+            StructDeclaration sd = t.sym;
+            if (auto ti = sd.isInstantiated())
+            {
+                if (!ti.needsCodegen())
+                {
+                    if (ti.minst || sd.requestTypeInfo)
+                        return;
+
+                    /* Bugzilla 14425: TypeInfo_Struct would refer the members of
+                     * struct (e.g. opEquals via xopEquals field), so if it's instantiated
+                     * in speculative context, TypeInfo creation should also be
+                     * stopped to avoid 'unresolved symbol' linker errors.
+                     */
+                    /* When -debug/-unittest is specified, all of non-root instances are
+                     * automatically changed to speculative, and here is always reached
+                     * from those instantiated non-root structs.
+                     * Therefore, if the TypeInfo is not auctually requested,
+                     * we have to elide its codegen.
+                     */
+                    result |= true;
+                    return;
+                }
+            }
+            else
+            {
+                //assert(!sd.inNonRoot() || sd.requestTypeInfo);    // valid?
+            }
+        }
+
+        override void visit(TypeClass t)
+        {
+            ClassDeclaration sd = t.sym;
+            if (auto ti = sd.isInstantiated())
+            {
+                if (!ti.needsCodegen() && !ti.minst)
+                {
+                    result |= true;
+                }
+            }
+        }
+
+
+        override void visit(TypeTuple t)
+        {
+            if (t.arguments)
+            {
+                for (size_t i = 0; i < t.arguments.dim; i++)
+                {
+                    Type tprm = (*t.arguments)[i].type;
+                    if (tprm)
+                        tprm.accept(this);
+                    if (result)
+                        return;
+                }
+            }
+        }
+    }
+
+    scope SpeculativeTypeVisitor v = new SpeculativeTypeVisitor();
+    t.accept(v);
+    return v.result;
+}
+
+/* ========================================================================= */
+
+/* These decide if there's an instance for them already in std.typeinfo,
+ * because then the compiler doesn't need to build one.
+ */
+extern (C++) static bool builtinTypeInfo(Type t)
+{
+  version (IN_LLVM)
+  {
+    // FIXME: if I enable for Tclass, the way LDC does typeinfo will cause
+    // a bunch of linker errors to missing ClassInfo init symbols.
+    if (t.isTypeBasic() || t.ty == Tnull)
+        return !t.mod;
+  }
+  else
+  {
+    if (t.isTypeBasic() || t.ty == Tclass || t.ty == Tnull)
+        return !t.mod;
+  }
+    if (t.ty == Tarray)
+    {
+        Type next = t.nextOf();
+        // strings are so common, make them builtin
+        return !t.mod &&
+               (next.isTypeBasic() !is null && !next.mod ||
+                next.ty == Tchar && next.mod == MODimmutable ||
+                next.ty == Tchar && next.mod == MODconst);
+    }
+    return false;
+}
diff --git a/gen/declarations.cpp b/gen/declarations.cpp
index 816e935..934a8b9 100644
--- a/gen/declarations.cpp
+++ b/gen/declarations.cpp
@@ -30,86 +30,6 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-namespace {
-// from dmd/src/typinf.c
-bool isSpeculativeType(Type *t) {
-  class SpeculativeTypeVisitor : public Visitor {
-  public:
-    bool result;
-
-    SpeculativeTypeVisitor() : result(false) {}
-
-    using Visitor::visit;
-    void visit(Type *t) override {
-      Type *tb = t->toBasetype();
-      if (tb != t) {
-        tb->accept(this);
-      }
-    }
-    void visit(TypeNext *t) override {
-      if (t->next) {
-        t->next->accept(this);
-      }
-    }
-    void visit(TypeBasic *t) override {}
-    void visit(TypeVector *t) override { t->basetype->accept(this); }
-    void visit(TypeAArray *t) override {
-      t->index->accept(this);
-      visit((TypeNext *)t);
-    }
-    void visit(TypeFunction *t) override {
-      visit((TypeNext *)t);
-      // Currently TypeInfo_Function doesn't store parameter types.
-    }
-    void visit(TypeStruct *t) override {
-      StructDeclaration *sd = t->sym;
-      if (TemplateInstance *ti = sd->isInstantiated()) {
-        if (!ti->needsCodegen()) {
-          if (ti->minst || sd->requestTypeInfo) {
-            return;
-          }
-
-          /* Bugzilla 14425: TypeInfo_Struct would refer the members of
-           * struct (e.g. opEquals via xopEquals field), so if it's instantiated
-           * in speculative context, TypeInfo creation should also be
-           * stopped to avoid 'unresolved symbol' linker errors.
-           */
-          /* When -debug/-unittest is specified, all of non-root instances are
-           * automatically changed to speculative, and here is always reached
-           * from those instantiated non-root structs.
-           * Therefore, if the TypeInfo is not auctually requested,
-           * we have to elide its codegen.
-           */
-          result |= true;
-          return;
-        }
-      } else {
-        // assert(!sd->inNonRoot() || sd->requestTypeInfo);  // valid?
-      }
-    }
-    void visit(TypeClass *t) override {}
-    void visit(TypeTuple *t) override {
-      if (t->arguments) {
-        for (size_t i = 0; i < t->arguments->dim; i++) {
-          Type *tprm = (*t->arguments)[i]->type;
-          if (tprm) {
-            tprm->accept(this);
-          }
-          if (result) {
-            return;
-          }
-        }
-      }
-    }
-  };
-  SpeculativeTypeVisitor v;
-  t->accept(&v);
-  return v.result;
-}
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
 class CodegenVisitor : public Visitor {
   IRState *irs;
 
diff --git a/gen/typinf.cpp b/gen/typinf.cpp
index 2c56807..a63cbf0 100644
--- a/gen/typinf.cpp
+++ b/gen/typinf.cpp
@@ -53,129 +53,21 @@
 #include <cstdio>
 #include <ir/irtypeclass.h>
 
-static bool builtinTypeInfo(Type *t);
 FuncDeclaration *search_toString(StructDeclaration *sd);
 
-namespace {
-TypeInfoDeclaration *createUnqualified(Type *t) {
-  switch (t->ty) {
-  case Tpointer:
-    return TypeInfoPointerDeclaration::create(t);
-  case Tarray:
-    return TypeInfoArrayDeclaration::create(t);
-  case Tsarray:
-    return TypeInfoStaticArrayDeclaration::create(t);
-  case Taarray:
-    return TypeInfoAssociativeArrayDeclaration::create(t);
-  case Tstruct:
-    return TypeInfoStructDeclaration::create(t);
-  case Tvector:
-    return TypeInfoVectorDeclaration::create(t);
-  case Tenum:
-    return TypeInfoEnumDeclaration::create(t);
-  case Tfunction:
-    return TypeInfoFunctionDeclaration::create(t);
-  case Tdelegate:
-    return TypeInfoDelegateDeclaration::create(t);
-  case Ttuple:
-    return TypeInfoTupleDeclaration::create(t);
-  case Tclass:
-    if ((static_cast<TypeClass *>(t))->sym->isInterfaceDeclaration()) {
-      return TypeInfoInterfaceDeclaration::create(t);
-    } else {
-      return TypeInfoClassDeclaration::create(t);
-    }
-  default:
-    return TypeInfoDeclaration::create(t);
-  }
-}
-}
+// defined in ddmd/typinf.d:
+void genTypeInfo(Type *torig, Scope *sc);
+bool builtinTypeInfo(Type *t);
 
 TypeInfoDeclaration *getOrCreateTypeInfoDeclaration(Type *torig, Scope *sc) {
   IF_LOG Logger::println("Type::getTypeInfo(): %s", torig->toChars());
   LOG_SCOPE
 
-  if (!Type::dtypeinfo) {
-    torig->error(Loc(), "TypeInfo not found. object.d may be incorrectly "
-                        "installed or corrupt, compile with -v switch");
-    fatal();
-  }
+  genTypeInfo(torig, sc);
 
-  Type *t = torig->merge2(); // do this since not all Type's are merge'd
-  if (!t->vtinfo) {
-    if (t->isShared()) { // does both 'shared' and 'shared const'
-      t->vtinfo = TypeInfoSharedDeclaration::create(t);
-    } else if (t->isConst()) {
-      t->vtinfo = TypeInfoConstDeclaration::create(t);
-    } else if (t->isImmutable()) {
-      t->vtinfo = TypeInfoInvariantDeclaration::create(t);
-    } else if (t->isWild()) {
-      t->vtinfo = TypeInfoWildDeclaration::create(t);
-    } else {
-      t->vtinfo = createUnqualified(t);
-    }
-    assert(t->vtinfo);
-    torig->vtinfo = t->vtinfo;
-
-    /* If this has a custom implementation in std/typeinfo, then
-     * do not generate a COMDAT for it.
-     */
-    if (!builtinTypeInfo(t)) { // Generate COMDAT
-      if (sc)                  // if in semantic() pass
-      {
-        // Find module that will go all the way to an object file
-        Module *m = sc->module->importedFrom;
-        m->members->push(t->vtinfo);
-
-        semanticTypeInfo(sc, t);
-      } else // if in obj generation pass
-      {
-        Declaration_codegen(t->vtinfo);
-      }
-    }
-  }
-  if (!torig->vtinfo) {
-    torig->vtinfo =
-        t->vtinfo; // Types aren't merged, but we can share the vtinfo's
-  }
-  assert(torig->vtinfo);
   return torig->vtinfo;
 }
 
-Type *getTypeInfoType(Type *t, Scope *sc) {
-  assert(t->ty != Terror);
-  getOrCreateTypeInfoDeclaration(t, sc);
-  return t->vtinfo->type;
-}
-
-/* ========================================================================= */
-
-/* These decide if there's an instance for them already in std.typeinfo,
- * because then the compiler doesn't need to build one.
- */
-
-static bool builtinTypeInfo(Type *t) {
-#if 0
-    // FIXME if I enable for Tclass, the way LDC does typeinfo will cause a
-    // bunch of linker errors to missing class typeinfo definitions.
-    if (t->isTypeBasic() || t->ty == Tclass)
-        return !t->mod;
-#else
-  if (t->isTypeBasic()) {
-    return !t->mod;
-  }
-#endif
-
-  if (t->ty == Tarray) {
-    Type *next = t->nextOf();
-    return !t->mod && ((next->isTypeBasic() != nullptr && !next->mod) ||
-                       // strings are so common, make them builtin
-                       (next->ty == Tchar && next->mod == MODimmutable) ||
-                       (next->ty == Tchar && next->mod == MODconst));
-  }
-  return false;
-}
-
 /* ========================================================================= */
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/gen/typinf.h b/gen/typinf.h
index 6a0f0cd..2bf69fd 100644
--- a/gen/typinf.h
+++ b/gen/typinf.h
@@ -24,6 +24,9 @@ void DtoResolveTypeInfo(TypeInfoDeclaration *tid);
 TypeInfoDeclaration *getOrCreateTypeInfoDeclaration(Type *t, Scope *sc);
 void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p);
 void TypeInfoClassDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p);
+
+// defined in ddmd/typinf.d:
 Type *getTypeInfoType(Type *t, Scope *sc);
+bool isSpeculativeType(Type *t);
 
 #endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-d/ldc.git



More information about the pkg-d-commits mailing list