# HG changeset patch # User lindquist # Date 1195767010 -3600 # Node ID 368547b1cbe6d9e3f14e0e7e2aeb2c6a867c1310 # Parent a7ae554ce4f41796409de7e518c315251ddcb476 [svn r116] Implemented the ClassInfo.destructor field. diff -r a7ae554ce4f4 -r 368547b1cbe6 gen/classes.cpp --- 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 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); diff -r a7ae554ce4f4 -r 368547b1cbe6 llvmdc.kdevelop.filelist --- 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 diff -r a7ae554ce4f4 -r 368547b1cbe6 test/classinfo1.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)); } } diff -r a7ae554ce4f4 -r 368547b1cbe6 test/classinfo4.d --- 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); }