changeset 112:368547b1cbe6 trunk

[svn r116] Implemented the ClassInfo.destructor field.
author lindquist
date Thu, 22 Nov 2007 22:30:10 +0100
parents a7ae554ce4f4
children 27b9f749d9fe
files gen/classes.cpp llvmdc.kdevelop.filelist test/classinfo1.d test/classinfo4.d
diffstat 4 files changed, 101 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/gen/classes.cpp	Thu Nov 22 21:17:54 2007 +0100
+++ b/gen/classes.cpp	Thu Nov 22 22:30:10 2007 +0100
@@ -457,7 +457,7 @@
         for (size_t i = 0; i < cd2->members->dim; i++)
         {
         Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
-        if (VarDeclaration* vd = sm->isVarDeclaration())
+        if (VarDeclaration* vd = sm->isVarDeclaration()) // is this enough?
         {
             llvm::Constant* c = build_offti_entry(vd);
             assert(c);
@@ -495,6 +495,75 @@
     return DtoConstSlice(size, ptr);
 }
 
+static llvm::Constant* build_class_dtor(ClassDeclaration* cd)
+{
+    // construct the function
+    std::vector<const llvm::Type*> paramTypes;
+    paramTypes.push_back(llvm::PointerType::get(cd->type->llvmType->get()));
+
+    const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false);
+
+    if (cd->dtors.dim == 0) {
+        return llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+    }
+    else if (cd->dtors.dim == 1) {
+        DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0];
+        DtoForceDeclareDsymbol(d);
+        assert(d->llvmValue);
+        return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), llvm::PointerType::get(llvm::Type::Int8Ty));
+    }
+
+    std::string gname("_D");
+    gname.append(cd->mangle());
+    gname.append("12__destructorMFZv");
+
+    llvm::Function* func = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, gname, gIR->module);
+    llvm::Value* thisptr = func->arg_begin();
+    thisptr->setName("this");
+
+    llvm::BasicBlock* bb = new llvm::BasicBlock("entry", func);
+    LLVMBuilder builder(bb);
+
+    for (size_t i = 0; i < cd->dtors.dim; i++)
+    {
+        DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[i];
+        DtoForceDeclareDsymbol(d);
+        assert(d->llvmValue);
+        builder.CreateCall(d->llvmValue, thisptr);
+    }
+    builder.CreateRetVoid();
+
+    return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty));
+}
+
+static uint build_classinfo_flags(ClassDeclaration* cd)
+{
+    uint flags = 0;
+    //flags |= isCOMclass(); // IUnknown
+    bool hasOffTi = false;
+    if (cd->ctor) flags |= 8;
+    for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
+    {
+    if (cd2->members)
+    {
+        for (size_t i = 0; i < cd2->members->dim; i++)
+        {
+        Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
+        if (sm->isVarDeclaration()) // is this enough?
+            hasOffTi = true;
+        //printf("sm = %s %s\n", sm->kind(), sm->toChars());
+        if (sm->hasPointers())
+            goto L2;
+        }
+    }
+    }
+    flags |= 2;         // no pointers
+L2:
+    if (hasOffTi)
+        flags |= 4;
+    return flags;
+}
+
 void DtoDefineClassInfo(ClassDeclaration* cd)
 {
 //     The layout is:
@@ -594,8 +663,7 @@
     }
 
     // destructor
-    // TODO
-    c = cinfo->llvmInitZ->getOperand(6);
+    c = build_class_dtor(cd);
     inits.push_back(c);
 
     // invariant
@@ -604,25 +672,7 @@
     inits.push_back(c);
 
     // uint flags, adapted from original dmd code
-    uint flags = 0;
-    //flags |= 4; // has offTi
-    //flags |= isCOMclass(); // IUnknown
-    if (cd->ctor) flags |= 8;
-    for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
-    {
-    if (cd2->members)
-    {
-        for (size_t i = 0; i < cd2->members->dim; i++)
-        {
-        Dsymbol *sm = (Dsymbol *)cd2->members->data[i];
-        //printf("sm = %s %s\n", sm->kind(), sm->toChars());
-        if (sm->hasPointers())
-            goto L2;
-        }
-    }
-    }
-    flags |= 2;         // no pointers
-L2:
+    uint flags = build_classinfo_flags(cd);
     c = DtoConstUint(flags);
     inits.push_back(c);
 
--- a/llvmdc.kdevelop.filelist	Thu Nov 22 21:17:54 2007 +0100
+++ b/llvmdc.kdevelop.filelist	Thu Nov 22 22:30:10 2007 +0100
@@ -338,6 +338,7 @@
 test/classinfo2.d
 test/classinfo3.d
 test/classinfo4.d
+test/classinfo5.d
 test/comma.d
 test/complex1.d
 test/complex2.d
--- a/test/classinfo1.d	Thu Nov 22 21:17:54 2007 +0100
+++ b/test/classinfo1.d	Thu Nov 22 22:30:10 2007 +0100
@@ -16,13 +16,13 @@
     char[] name = ci.name;
     printf("%.*s\n", name.length, name.ptr);
     assert(ci.name == "classinfo1.NoPtrs");
-    assert(ci.flags == 2);
+    assert(ci.flags & 2);
     }
     {
     ClassInfo ci = HasPtrs.classinfo;
     char[] name = ci.name;
     printf("%.*s\n", name.length, name.ptr);
     assert(ci.name == "classinfo1.HasPtrs");
-    assert(ci.flags == 0);
+    assert(!(ci.flags & 2));
     }
 }
--- a/test/classinfo4.d	Thu Nov 22 21:17:54 2007 +0100
+++ b/test/classinfo4.d	Thu Nov 22 22:30:10 2007 +0100
@@ -4,15 +4,40 @@
 {
 }
 
-class D
+class D : C
 {
     this()
     {
     }
+    ~this()
+    {
+    }
+}
+
+template T()
+{
+    ~this()
+    {
+    }
+}
+
+class E : D
+{
+    this()
+    {
+    }
+    ~this()
+    {
+    }
+    mixin T;
 }
 
 void main()
 {
     assert(C.classinfo.defaultConstructor is null);
+    assert(C.classinfo.destructor is null);
     assert(D.classinfo.defaultConstructor !is null);
+    assert(D.classinfo.destructor !is null);
+    assert(E.classinfo.defaultConstructor !is null);
+    assert(E.classinfo.destructor !is null);
 }