[pkg-d-commits] [ldc] 154/211: Use opaque [N x i8*] for vtables

Matthias Klumpp mak at moszumanska.debian.org
Sun Apr 23 22:36:19 UTC 2017


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

mak pushed a commit to annotated tag v1.1.0
in repository ldc.

commit 16d15e01cb94d86c357e4b0350f6117794ad9672
Author: Martin <noone at nowhere.com>
Date:   Sat Nov 5 19:14:46 2016 +0100

    Use opaque [N x i8*] for vtables
    
    This fixes the forward-referencing issue #1741.
---
 gen/classes.cpp                        |  5 +-
 gen/toir.cpp                           |  6 ++-
 ir/irclass.cpp                         | 45 +++++++-----------
 ir/irtypeclass.cpp                     | 87 ++--------------------------------
 ir/irtypeclass.h                       | 17 +------
 tests/codegen/in_place_construct_asm.d |  1 +
 tests/compilable/gh1741.d              | 13 +++++
 tests/compilable/inputs/gh1741b.d      |  3 ++
 8 files changed, 46 insertions(+), 131 deletions(-)

diff --git a/gen/classes.cpp b/gen/classes.cpp
index 6fef7a6..2fc6b32 100644
--- a/gen/classes.cpp
+++ b/gen/classes.cpp
@@ -390,7 +390,6 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl,
 
   LLValue *funcval = vthis;
   // get the vtbl for objects
-  stripModifiers(inst->type->toBasetype())->ctype->isClass()->getVtblType(true);
   funcval = DtoGEPi(funcval, 0, 0);
   // load vtbl ptr
   funcval = DtoLoad(funcval);
@@ -398,12 +397,12 @@ LLValue *DtoVirtualFunctionPointer(DValue *inst, FuncDeclaration *fdecl,
   std::string vtblname = name;
   vtblname.append("@vtbl");
   funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, vtblname.c_str());
-  // load funcptr
+  // load opaque pointer
   funcval = DtoAlignedLoad(funcval);
 
   IF_LOG Logger::cout() << "funcval: " << *funcval << '\n';
 
-  // cast to final funcptr type
+  // cast to funcptr type
   funcval = DtoBitCast(funcval, getPtrToType(DtoFunctionType(fdecl)));
 
   // postpone naming until after casting to get the name in call instructions
diff --git a/gen/toir.cpp b/gen/toir.cpp
index 22402bf..c6ecd29 100644
--- a/gen/toir.cpp
+++ b/gen/toir.cpp
@@ -2664,13 +2664,12 @@ public:
       LLValue *val = DtoRVal(ex);
 
       // Get and load vtbl pointer.
-      stripModifiers(t)->ctype->isClass()->getVtblType(true);
       llvm::Value *vtbl = DtoLoad(DtoGEPi(val, 0, 0));
 
       // TypeInfo ptr is first vtbl entry.
       llvm::Value *typinf = DtoGEPi(vtbl, 0, 0);
 
-      Type *resultType = Type::typeinfoclass->type;
+      Type *resultType;
       if (static_cast<TypeClass *>(t)->sym->isInterfaceDeclaration()) {
         // For interfaces, the first entry in the vtbl is actually a pointer
         // to an Interface instance, which has the type info as its first
@@ -2678,6 +2677,9 @@ public:
         resultType = Type::typeinfointerface->type;
         typinf = DtoLoad(
             DtoBitCast(typinf, DtoType(resultType->pointerTo()->pointerTo())));
+      } else {
+        resultType = Type::typeinfoclass->type;
+        typinf = DtoBitCast(typinf, DtoType(resultType->pointerTo()));
       }
 
       result = new DLValue(resultType, typinf);
diff --git a/ir/irclass.cpp b/ir/irclass.cpp
index aaab098..42fb198 100644
--- a/ir/irclass.cpp
+++ b/ir/irclass.cpp
@@ -49,7 +49,7 @@ LLGlobalVariable *IrAggr::getVtblSymbol() {
   // create the vtblZ symbol
   auto initname = getMangledVTableSymbolName(aggrdecl);
 
-  LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType(false);
+  LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType();
 
   vtbl =
       getOrCreateGlobal(aggrdecl->loc, gIR->module, vtblTy, true,
@@ -165,11 +165,13 @@ LLConstant *IrAggr::getVtblInit() {
   std::vector<llvm::Constant *> constants;
   constants.reserve(cd->vtbl.dim);
 
+  const auto voidPtrType = getVoidPtrType();
+
   // start with the classinfo
   llvm::Constant *c;
   if (!cd->isCPPclass()) {
     c = getClassInfoSymbol();
-    c = DtoBitCast(c, DtoType(Type::typeinfoclass->type));
+    c = DtoBitCast(c, voidPtrType);
     constants.push_back(c);
   }
 
@@ -220,26 +222,12 @@ LLConstant *IrAggr::getVtblInit() {
         }
       }
     }
-    constants.push_back(c);
+    constants.push_back(DtoBitCast(c, voidPtrType));
   }
 
-  // build the constant struct
-  LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType(true);
-#ifndef NDEBUG
-  size_t nc = constants.size();
-
-  for (size_t i = 0; i < nc; ++i) {
-    if (constants[i]->getType() != vtblTy->getContainedType(i)) {
-      llvm::errs() << "type mismatch for entry # " << i
-                   << " in vtbl initializer\n";
-
-      constants[i]->getType()->dump();
-      vtblTy->getContainedType(i)->dump();
-    }
-  }
-
-#endif
-  constVtbl = LLConstantStruct::get(isaStruct(vtblTy), constants);
+  // build the constant array
+  LLArrayType *vtblTy = LLArrayType::get(voidPtrType, constants.size());
+  constVtbl = LLConstantArray::get(vtblTy, constants);
 
   return constVtbl;
 }
@@ -277,6 +265,8 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
   std::vector<llvm::Constant *> constants;
   constants.reserve(vtbl_array.dim);
 
+  const auto voidPtrTy = getVoidPtrType();
+
   if (!b->sym->isCPPinterface()) { // skip interface info for CPP interfaces
     // index into the interfaces array
     llvm::Constant *idxs[2] = {DtoConstSize_t(0),
@@ -289,7 +279,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
 #endif
         interfaceInfosZ, idxs, true);
 
-    constants.push_back(c);
+    constants.push_back(DtoBitCast(c, voidPtrTy));
   }
 
   // Thunk prefix
@@ -306,7 +296,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
       // FIXME
       // why is this null?
       // happens for mini/s.d
-      constants.push_back(getNullValue(getVoidPtrType()));
+      constants.push_back(getNullValue(voidPtrTy));
       continue;
     }
 
@@ -327,7 +317,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
     if (fd->interfaceVirtual)
       thunkOffset -= fd->interfaceVirtual->offset;
     if (thunkOffset == 0) {
-      constants.push_back(irFunc->func);
+      constants.push_back(DtoBitCast(irFunc->func, voidPtrTy));
       continue;
     }
 
@@ -434,12 +424,12 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
       gIR->funcGenStates.pop_back();
     }
 
-    constants.push_back(thunk);
+    constants.push_back(DtoBitCast(thunk, voidPtrTy));
   }
 
   // build the vtbl constant
-  llvm::Constant *vtbl_constant =
-      LLConstantStruct::getAnon(gIR->context(), constants, false);
+  llvm::Constant *vtbl_constant = LLConstantArray::get(
+      LLArrayType::get(voidPtrTy, constants.size()), constants);
 
   std::string mangledName("_D");
   mangledName.append(mangle(cd));
@@ -526,7 +516,8 @@ LLConstant *IrAggr::getClassInfoInterfaces() {
       assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
       vtb = itv->second;
       vtb = DtoBitCast(vtb, voidptrptr_type);
-      vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
+      auto vtblSize = itc->getVtblType()->getNumContainedTypes();
+      vtb = DtoConstSlice(DtoConstSize_t(vtblSize), vtb);
     }
 
     // offset
diff --git a/ir/irtypeclass.cpp b/ir/irtypeclass.cpp
index 0e37d61..ef6b5a2 100644
--- a/ir/irtypeclass.cpp
+++ b/ir/irtypeclass.cpp
@@ -25,10 +25,7 @@
 
 IrTypeClass::IrTypeClass(ClassDeclaration *cd)
     : IrTypeAggr(cd), cd(cd), tc(static_cast<TypeClass *>(cd->type)) {
-  std::string vtbl_name(cd->toPrettyChars());
-  vtbl_name.append(".__vtbl");
-  vtbl_type = LLStructType::create(gIR->context(), vtbl_name);
-  vtbl_size = cd->vtbl.dim;
+  vtbl_type = LLArrayType::get(getVoidPtrType(), cd->vtbl.dim);
 }
 
 void IrTypeClass::addClassData(AggrTypeBuilder &builder,
@@ -52,15 +49,10 @@ void IrTypeClass::addClassData(AggrTypeBuilder &builder,
       IF_LOG Logger::println("Adding interface vtbl for %s",
                              b->sym->toPrettyChars());
 
-      FuncDeclarations arr;
-      b->fillVtbl(cd, &arr, currCd == cd);
-
       // add to the interface map
       addInterfaceToMap(b->sym, builder.currentFieldIndex());
-      Type* first = b->sym->isCPPinterface() ? nullptr : interfacePtrType;
-      const auto ivtblType =
-          llvm::StructType::get(gIR->context(), buildVtblType(first, &arr));
-      builder.addType(llvm::PointerType::get(ivtblType, 0), Target::ptrsize);
+      auto vtblTy = LLArrayType::get(getVoidPtrType(), b->sym->vtbl.dim);
+      builder.addType(llvm::PointerType::get(vtblTy, 0), Target::ptrsize);
 
       ++num_interface_vtbls;
     }
@@ -122,83 +114,10 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
   return t;
 }
 
-std::vector<llvm::Type *>
-IrTypeClass::buildVtblType(Type *first, FuncDeclarations *vtbl_array) {
-  IF_LOG Logger::println("Building vtbl type for class %s",
-                         cd->toPrettyChars());
-  LOG_SCOPE;
-
-  std::vector<llvm::Type *> types;
-  types.reserve(vtbl_array->dim);
-
-  auto I = vtbl_array->begin();
-  // first comes the classinfo for D interfaces
-  if (first) {
-    types.push_back(DtoType(first));
-    ++I;
-  }
-
-  // then come the functions
-  for (auto E = vtbl_array->end(); I != E; ++I) {
-    FuncDeclaration *fd = *I;
-    if (fd == nullptr) {
-      // FIXME: This stems from the ancient D1 days – can it still happen?
-      types.push_back(getVoidPtrType());
-      continue;
-    }
-
-    IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());
-
-    // If inferring return type and semantic3 has not been run, do it now.
-    // This pops up in some other places in the frontend as well, however
-    // it is probably a bug that it still occurs that late.
-    if (!fd->type->nextOf() && fd->inferRetType) {
-      Logger::println("Running late functionSemantic to infer return type.");
-      TemplateInstance *spec = fd->isSpeculative();
-      unsigned int olderrs = global.errors;
-      fd->functionSemantic();
-      if (spec && global.errors != olderrs) {
-        spec->errors = global.errors - olderrs;
-      }
-    }
-
-    if (!fd->type->nextOf()) {
-      // Return type of the function has not been inferred. This seems to
-      // happen with virtual functions and is probably a frontend bug.
-      IF_LOG Logger::println("Broken function type, semanticRun: %d",
-                             fd->semanticRun);
-      types.push_back(getVoidPtrType());
-      continue;
-    }
-
-    types.push_back(getPtrToType(DtoFunctionType(fd)));
-  }
-
-  return types;
-}
-
 llvm::Type *IrTypeClass::getLLType() { return llvm::PointerType::get(type, 0); }
 
 llvm::Type *IrTypeClass::getMemoryLLType() { return type; }
 
-llvm::StructType *IrTypeClass::getVtblType(bool notOpaque) {
-  if (notOpaque && vtbl_type->isOpaque()) {
-    FuncDeclarations vtbl;
-    vtbl.reserve(cd->vtbl.dim);
-    if (!cd->isCPPclass())
-      vtbl.push(nullptr);
-    for (size_t i = cd->vtblOffset(); i < cd->vtbl.dim; ++i) {
-      FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration();
-      assert(fd);
-      vtbl.push(fd);
-    }
-    Type* first = cd->isCPPclass() ? nullptr : Type::typeinfoclass->type;
-    vtbl_type->setBody(buildVtblType(first, &vtbl));
-  }
-
-  return vtbl_type;
-}
-
 size_t IrTypeClass::getInterfaceIndex(ClassDeclaration *inter) {
   auto it = interfaceMap.find(inter);
   if (it == interfaceMap.end()) {
diff --git a/ir/irtypeclass.h b/ir/irtypeclass.h
index 829ad83..91633c3 100644
--- a/ir/irtypeclass.h
+++ b/ir/irtypeclass.h
@@ -37,16 +37,13 @@ public:
   llvm::Type *getMemoryLLType();
 
   /// Returns the vtable type for this class.
-  llvm::StructType *getVtblType(bool notOpaque);
+  llvm::ArrayType *getVtblType() { return vtbl_type; }
 
   /// Get index to interface implementation.
   /// Returns the index of a specific interface implementation in this
   /// class or ~0 if not found.
   size_t getInterfaceIndex(ClassDeclaration *inter);
 
-  /// Returns the total number of pointers in the vtable.
-  unsigned getVtblSize() { return vtbl_size; }
-
   /// Returns the number of interface implementations (vtables) in this
   /// class.
   unsigned getNumInterfaceVtbls() { return num_interface_vtbls; }
@@ -61,10 +58,7 @@ protected:
   TypeClass *tc = nullptr;
 
   /// Vtable type.
-  llvm::StructType *vtbl_type = nullptr;
-
-  /// Number of pointers in vtable.
-  unsigned vtbl_size = 0;
+  llvm::ArrayType *vtbl_type = nullptr;
 
   /// Number of interface implementations (vtables) in this class.
   unsigned num_interface_vtbls = 0;
@@ -78,13 +72,6 @@ protected:
 
   //////////////////////////////////////////////////////////////////////////
 
-  /// Builds a vtable type given the type of the first entry and an array
-  /// of all entries.
-  /// If first is nullptr for C++ interfaces, the vtbl_array will be added
-  /// as is without replacing the first entry.
-  std::vector<llvm::Type *> buildVtblType(Type *first,
-                                          FuncDeclarations *vtbl_array);
-
   /// Adds the data members for the given class to the type builder, including
   /// those inherited from base classes/interfaces.
   void addClassData(AggrTypeBuilder &builder, ClassDeclaration *currCd);
diff --git a/tests/codegen/in_place_construct_asm.d b/tests/codegen/in_place_construct_asm.d
index bd9c970..dab0bb8 100644
--- a/tests/codegen/in_place_construct_asm.d
+++ b/tests/codegen/in_place_construct_asm.d
@@ -1,6 +1,7 @@
 // Tests in-place construction of structs returned by inline assembly (issue #1823).
 
 // Target Win64 for simplicity (e.g., 4x32-bit struct not returned in memory for non-Windows x64).
+// REQUIRES: target_X86
 // RUN: %ldc -mtriple=x86_64-pc-windows-msvc -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
 
 import ldc.llvmasm;
diff --git a/tests/compilable/gh1741.d b/tests/compilable/gh1741.d
new file mode 100644
index 0000000..af01e18
--- /dev/null
+++ b/tests/compilable/gh1741.d
@@ -0,0 +1,13 @@
+// Explicitly target Linux x86_64.
+// REQUIRES: target_X86
+// RUN: %ldc -mtriple=x86_64-pc-linux-gnu -c %s %S/inputs/gh1741b.d
+
+struct S
+{
+    C c;
+}
+
+class C
+{
+    @property s() { return S(); }
+}
diff --git a/tests/compilable/inputs/gh1741b.d b/tests/compilable/inputs/gh1741b.d
new file mode 100644
index 0000000..4606cdd
--- /dev/null
+++ b/tests/compilable/inputs/gh1741b.d
@@ -0,0 +1,3 @@
+import gh1741;
+
+S s;

-- 
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