changeset 9:dafae18f9c08 trunk

[svn r13] * Updated for LLVM 2.1 * Class v-tables are now typesafe * Code cleanups
author lindquist
date Mon, 01 Oct 2007 21:19:53 +0200
parents 5e69b77a5c51
children c0f2c47e5034
files dmd/declaration.h dmd/mars.c dmd/mtype.c dmd/mtype.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c lib/llvmdcore.bc lphobos/build.sh test/classes6.d test/funcs2.d
diffstat 12 files changed, 223 insertions(+), 250 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/declaration.h	Thu Sep 27 06:03:06 2007 +0200
+++ b/dmd/declaration.h	Mon Oct 01 21:19:53 2007 +0200
@@ -126,9 +126,6 @@
     Declaration *isDeclaration() { return this; }
 
     virtual void toObjFile();           // compile to .obj file
-
-    // llvm stuff
-    llvm::Value* llvmValue;
 };
 
 /**************************************************************/
--- a/dmd/mars.c	Thu Sep 27 06:03:06 2007 +0200
+++ b/dmd/mars.c	Mon Oct 01 21:19:53 2007 +0200
@@ -158,7 +158,8 @@
     printf("LLVM D Compiler %s (based on DMD %s)\n%s\n%s\n",
     global.llvmdc_version, global.version, global.copyright, global.written);
     printf("\
-Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
+D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\
+LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\
 Usage:\n\
   dmd files.d ... { -switch }\n\
 \n\
--- a/dmd/mtype.c	Thu Sep 27 06:03:06 2007 +0200
+++ b/dmd/mtype.c	Mon Oct 01 21:19:53 2007 +0200
@@ -2541,6 +2541,7 @@
     this->linkage = linkage;
     this->inuse = 0;
     this->llvmRetInPtr = false;
+    this->llvmUsesThis = false;
     this->llvmRetArg = 0;
     this->llvmAllocaPoint = 0;
 }
--- a/dmd/mtype.h	Thu Sep 27 06:03:06 2007 +0200
+++ b/dmd/mtype.h	Mon Oct 01 21:19:53 2007 +0200
@@ -433,6 +433,7 @@
     unsigned totym();
 
     bool llvmRetInPtr;
+    bool llvmUsesThis;
     llvm::Value* llvmRetArg;
     llvm::Instruction* llvmAllocaPoint;
 };
--- a/gen/toir.c	Thu Sep 27 06:03:06 2007 +0200
+++ b/gen/toir.c	Mon Oct 01 21:19:53 2007 +0200
@@ -1246,16 +1246,14 @@
             assert(fdecl->vtblIndex > 0);
             assert(e1->type->ty == Tclass);
 
-            const llvm::Type* vtbltype = llvm::PointerType::get(llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty),0));
-
             llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
             llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false);
             funcval = LLVM_DtoGEP(e->arg, zero, zero, "tmp", p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-            funcval = new llvm::BitCastInst(funcval, vtbltype, "tmp", p->scopebb());
             funcval = LLVM_DtoGEP(funcval, zero, vtblidx, "tmp", p->scopebb());
             funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
-            funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb());
+            assert(funcval->getType() == fdecl->llvmValue->getType());
+            //funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb());
         }
         e->val = funcval;
         e->type = elem::VAL;
--- a/gen/tollvm.c	Thu Sep 27 06:03:06 2007 +0200
+++ b/gen/tollvm.c	Mon Oct 01 21:19:53 2007 +0200
@@ -208,7 +208,7 @@
     TypeFunction* f = (TypeFunction*)fdecl->type;
     assert(f != 0);
 
-    // has already been pulled in by a reference to (
+    // type has already been resolved
     if (f->llvmType != 0) {
         return llvm::cast<llvm::FunctionType>(f->llvmType);
     }
@@ -247,10 +247,17 @@
         paramvec.push_back(rettype);
     }
 
-    if (fdecl->needThis() && fdecl->vthis) {
-        Logger::print("this is: %s\n", fdecl->vthis->type->toChars());
-        paramvec.push_back(LLVM_DtoType(fdecl->vthis->type));
-        usesthis = true;
+    if (fdecl->needThis()) {
+        if (AggregateDeclaration* ad = fdecl->isMember()) {
+            Logger::print("isMember = this is: %s\n", ad->type->toChars());
+            const llvm::Type* thisty = LLVM_DtoType(ad->type);
+            if (llvm::isa<llvm::StructType>(thisty))
+                thisty = llvm::PointerType::get(thisty);
+            paramvec.push_back(thisty);
+            usesthis = true;
+        }
+        else
+        assert(0);
     }
 
     size_t n = Argument::dim(f->parameters);
@@ -295,6 +302,8 @@
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
 
     f->llvmType = functype;
+    f->llvmRetInPtr = retinptr;
+    f->llvmUsesThis = usesthis;
     return functype;
 }
 
@@ -837,3 +846,74 @@
     Logger::cout() << '\n';
     return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
 }
+
+llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl)
+{
+    if (fdecl->llvmValue != 0) {
+        return llvm::cast<llvm::Function>(fdecl->llvmValue);
+    }
+
+    static int fdi = 0;
+    Logger::print("FuncDeclaration::toObjFile(%d,%s): %s\n", fdi++, fdecl->needThis()?"this":"static",fdecl->toChars());
+    LOG_SCOPE;
+
+    if (fdecl->llvmInternal == LLVMintrinsic && fdecl->fbody) {
+        error("intrinsics cannot have function bodies");
+        fatal();
+    }
+
+    // construct function
+    TypeFunction* f = (TypeFunction*)fdecl->type;
+    assert(f != 0);
+    llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
+
+    // mangled name
+    char* mangled_name = (fdecl->llvmInternal == LLVMintrinsic) ? fdecl->llvmInternal1 : fdecl->mangle();
+
+    // make the function
+    llvm::Function* func = gIR->module->getFunction(mangled_name);
+    if (func == 0) {
+        func = new llvm::Function(functype,LLVM_DtoLinkage(fdecl->protection, fdecl->storage_class),mangled_name,gIR->module);
+    }
+
+    if (fdecl->llvmInternal != LLVMintrinsic)
+        func->setCallingConv(LLVM_DtoCallingConv(f->linkage));
+
+    fdecl->llvmValue = func;
+    f->llvmType = functype;
+
+    if (fdecl->isMain()) {
+        gIR->mainFunc = func;
+    }
+
+    // name parameters
+    llvm::Function::arg_iterator iarg = func->arg_begin();
+    int k = 0;
+    if (f->llvmRetInPtr) {
+        iarg->setName("retval");
+        f->llvmRetArg = iarg;
+        ++iarg;
+    }
+    if (f->llvmUsesThis) {
+        iarg->setName("this");
+        ++iarg;
+    }
+    for (; iarg != func->arg_end(); ++iarg)
+    {
+        Argument* arg = Argument::getNth(f->parameters, k++);
+        assert(arg != 0);
+        //arg->llvmValue = iarg;
+        //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
+        if (arg->ident != 0) {
+            if (arg->vardecl) {
+                arg->vardecl->llvmValue = iarg;
+            }
+            iarg->setName(arg->ident->toChars());
+        }
+        else {
+            iarg->setName("unnamed");
+        }
+    }
+
+    return func;
+}
--- a/gen/tollvm.h	Thu Sep 27 06:03:06 2007 +0200
+++ b/gen/tollvm.h	Mon Oct 01 21:19:53 2007 +0200
@@ -11,6 +11,7 @@
 
 llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
 llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
+llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl);
 
 llvm::StructType* LLVM_DtoDelegateType(Type* t);
 llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v);
--- a/gen/toobj.c	Thu Sep 27 06:03:06 2007 +0200
+++ b/gen/toobj.c	Mon Oct 01 21:19:53 2007 +0200
@@ -336,7 +336,8 @@
     gIR->queueClassMethods.push_back(true);
 
     // add vtable
-    const llvm::Type* vtabty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    llvm::PATypeHolder pa = llvm::OpaqueType::get();
+    const llvm::Type* vtabty = llvm::PointerType::get(pa);
     gIR->topstruct().fields.push_back(vtabty);
     gIR->topstruct().inits.push_back(0);
 
@@ -361,18 +362,99 @@
     ts->llvmType = structtype;
     llvmType = structtype;
 
-    bool emit_vtable = false;
     bool define_vtable = false;
     if (parent->isModule()) {
         gIR->module->addTypeName(mangle(),ts->llvmType);
-        emit_vtable = true;
         define_vtable = (getModule() == gIR->dmodule);
     }
     else {
         assert(0 && "class parent is not a module");
     }
 
-    // generate member functions
+    // generate vtable
+    llvm::GlobalVariable* svtblVar = 0;
+    std::vector<llvm::Constant*> sinits;
+    std::vector<const llvm::Type*> sinits_ty;
+    sinits.reserve(vtbl.dim);
+    sinits_ty.reserve(vtbl.dim);
+
+    for (int k=0; k < vtbl.dim; k++)
+    {
+        Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
+        assert(dsym);
+        //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
+
+        if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
+            fd->toObjFile();
+            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+            sinits.push_back(c);
+            sinits_ty.push_back(c->getType());
+        }
+        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
+            const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty);
+            llvm::Constant* c = llvm::Constant::getNullValue(cty);
+            sinits.push_back(c);
+            sinits_ty.push_back(cty);
+        }
+        else
+        assert(0);
+    }
+
+    const llvm::StructType* svtbl_ty = 0;
+    if (!sinits.empty())
+    {
+        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+
+        std::string varname(mangle());
+        varname.append("__vtblZ");
+        std::string styname(mangle());
+        styname.append("__vtblTy");
+
+        svtbl_ty = llvm::StructType::get(sinits_ty);
+        gIR->module->addTypeName(styname, svtbl_ty);
+        svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
+
+        if (define_vtable) {
+            svtblVar->setInitializer(llvm::ConstantStruct::get(svtbl_ty, sinits));
+        }
+        llvmVtbl = svtblVar;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////////
+
+    // refine for final vtable type
+    llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(svtbl_ty);
+    svtbl_ty = llvm::cast<llvm::StructType>(pa.get());
+    structtype = llvm::cast<llvm::StructType>(gIR->topstruct().recty.get());
+    ts->llvmType = structtype;
+    llvmType = structtype;
+
+    // generate initializer
+    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+    llvm::Constant* _init = 0;
+
+    // first field is always the vtable
+    assert(svtblVar != 0);
+    gIR->topstruct().inits[0] = svtblVar;
+
+    //assert(tk == gIR->topstruct().size());
+    #ifndef LLVMD_NO_LOGGER
+    Logger::cout() << *structtype << '\n';
+    //for (size_t k=0; k<gIR->topstruct().inits.size(); ++k)
+    //    Logger::cout() << *gIR->topstruct().inits[k] << '\n';
+    #endif
+    _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
+    assert(_init);
+    std::string initname(mangle());
+    initname.append("__initZ");
+    Logger::cout() << *_init << '\n';
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
+    ts->llvmInit = initvar;
+    if (define_vtable) {
+        initvar->setInitializer(_init);
+    }
+
+    // generate member function definitions
     gIR->queueClassMethods.back() = false;
     IRState::FuncDeclVec& mfs = gIR->classmethods.back();
     size_t n = mfs.size();
@@ -380,76 +462,6 @@
         mfs[i]->toObjFile();
     }
 
-    // create vtable initializer
-    if (emit_vtable)
-    {
-        llvm::GlobalVariable* vtblVar = 0;
-        std::vector<llvm::Constant*> inits;
-        inits.reserve(vtbl.dim);
-        for (int k=0; k < vtbl.dim; k++)
-        {
-            Dsymbol* dsym = (Dsymbol*)vtbl.data[k];
-            assert(dsym);
-            //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n';
-
-            if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
-                fd->toObjFile();
-                Logger::cout() << "casting to constant" << *fd->llvmValue << '\n';
-                llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
-                c = llvm::ConstantExpr::getBitCast(c, llvm::PointerType::get(llvm::Type::Int8Ty));
-                inits.push_back(c);
-            }
-            else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-                llvm::Constant* c = llvm::Constant::getNullValue(llvm::PointerType::get(llvm::Type::Int8Ty));
-                inits.push_back(c);
-            }
-            else
-            assert(0);
-        }
-        if (!inits.empty())
-        {
-            llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-            std::string varname(mangle());
-            varname.append("__vtblZ");
-            const llvm::ArrayType* vtbl_ty = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), inits.size());
-            vtblVar = new llvm::GlobalVariable(vtbl_ty, true, _linkage, 0, varname, gIR->module);
-            if (define_vtable) {
-                //Logger::cout() << "vtbl:::" << '\n' << *vtbl_st << '\n';// << " == | == " << _init << '\n';
-                llvm::Constant* _init = llvm::ConstantArray::get(vtbl_ty, inits);
-                vtblVar->setInitializer(_init);
-            }
-            llvmVtbl = vtblVar;
-        }
-
-        ////////////////////////////////////////////////////////////////////////////////
-
-        // generate initializer
-        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
-        llvm::Constant* _init = 0;
-
-        // first field is always the vtable
-        assert(vtblVar != 0);
-        llvm::Constant* vtbl_init_var = llvm::ConstantExpr::getBitCast(vtblVar, llvm::PointerType::get(llvm::Type::Int8Ty));
-        gIR->topstruct().inits[0] = vtbl_init_var;
-
-        //assert(tk == gIR->topstruct().size());
-        #ifndef LLVMD_NO_LOGGER
-        Logger::cout() << *structtype << '\n';
-        for (size_t k=0; k<gIR->topstruct().inits.size(); ++k)
-            Logger::cout() << *gIR->topstruct().inits[k] << '\n';
-        #endif
-        _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
-        assert(_init);
-        std::string initname(mangle());
-        initname.append("__initZ");
-        Logger::cout() << *_init << '\n';
-        llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
-        ts->llvmInit = initvar;
-        if (define_vtable) {
-            initvar->setInitializer(_init);
-        }
-    }
-
     gIR->queueClassMethods.pop_back();
     gIR->classmethods.pop_back();
     gIR->classes.pop_back();
@@ -560,6 +572,8 @@
             else if (llvm::isa<llvm::StructType>(_type)) {
                 const llvm::StructType* structty = llvm::cast<llvm::StructType>(_type);
                 TypeStruct* ts = (TypeStruct*)type;
+                assert(ts);
+                assert(ts->sym);
                 assert(ts->sym->llvmInitZ);
                 _init = ts->sym->llvmInitZ;
             }
@@ -594,11 +608,13 @@
 
 void FuncDeclaration::toObjFile()
 {
-    if (llvmValue != 0 && llvmDModule == gIR->dmodule) {
+    if (llvmDModule == gIR->dmodule) {
+        assert(llvmValue != 0);
         return;
     }
 
-    // has already been pulled in by a reference to (
+    llvm::Function* func = LLVM_DtoDeclareFunction(this);
+
     if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) {
         Logger::println("queueing %s", toChars());
         assert(!gIR->classmethods.empty());
@@ -606,160 +622,11 @@
         return; // will be generated later when the this parameter has a type
     }
 
-    static int fdi = 0;
-    Logger::print("FuncDeclaration::toObjFile(%d,%s): %s\n", fdi++, needThis()?"this":"static",toChars());
-    LOG_SCOPE;
-
-    if (llvmInternal == LLVMintrinsic && fbody) {
-        error("intrinsics cannot have function bodies");
-        fatal();
-    }
+    if (llvmNeedsDefinition)
+    {
 
     TypeFunction* f = (TypeFunction*)type;
-    assert(f != 0);
-
-    // return value type
-    const llvm::Type* rettype;
-    const llvm::Type* actualRettype;
-    Type* rt = f->next;
-    bool retinptr = false;
-    bool usesthis = false;
-
-    if (isMain()) {
-        rettype = llvm::Type::Int32Ty;
-        actualRettype = rettype;
-        gIR->emitMain = true;
-    }
-    else if (rt) {
-        if (rt->ty == Tstruct || rt->ty == Tdelegate || rt->ty == Tarray) {
-            rettype = llvm::PointerType::get(LLVM_DtoType(rt));
-            actualRettype = llvm::Type::VoidTy;
-            f->llvmRetInPtr = retinptr = true;
-        }
-        else {
-            rettype = LLVM_DtoType(rt);
-            actualRettype = rettype;
-        }
-    }
-    else {
-        assert(0);
-    }
-
-    // parameter types
-    std::vector<const llvm::Type*> paramvec;
-
-    if (retinptr) {
-        Logger::print("returning through pointer parameter\n");
-        paramvec.push_back(rettype);
-    }
-
-    if (needThis()) {
-        if (AggregateDeclaration* ad = isMember()) {
-            Logger::print("isMember = this is: %s\n", ad->type->toChars());
-            const llvm::Type* thisty = LLVM_DtoType(ad->type);
-            if (llvm::isa<llvm::StructType>(thisty))
-                thisty = llvm::PointerType::get(thisty);
-            paramvec.push_back(thisty);
-            usesthis = true;
-        }
-        else
-        assert(0);
-    }
-
-    size_t n = Argument::dim(f->parameters);
-    for (int i=0; i < n; ++i) {
-        Argument* arg = Argument::getNth(f->parameters, i);
-        // ensure scalar
-        Type* argT = arg->type;
-        assert(argT);
-
-        if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) {
-            //assert(arg->vardecl);
-            //arg->vardecl->refparam = true;
-        }
-        else
-            arg->llvmCopy = true;
-
-        const llvm::Type* at = LLVM_DtoType(argT);
-        if (llvm::isa<llvm::StructType>(at)) {
-            Logger::println("struct param");
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else if (llvm::isa<llvm::ArrayType>(at)) {
-            Logger::println("sarray param");
-            assert(argT->ty == Tsarray);
-            //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0)));
-            paramvec.push_back(llvm::PointerType::get(at));
-        }
-        else {
-            if (!arg->llvmCopy) {
-                Logger::println("ref param");
-                at = llvm::PointerType::get(at);
-            }
-            else {
-                Logger::println("in param");
-            }
-            paramvec.push_back(at);
-        }
-    }
-    
-    // construct function
-    bool isvararg = f->varargs;
-    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
-    
-    // mangled name
-    char* mangled_name = (llvmInternal == LLVMintrinsic) ? llvmInternal1 : mangle();
-    llvm::Function* func = gIR->module->getFunction(mangled_name);
-    
-    // make the function
-    /*if (func != 0) {
-        llvmValue = func;
-        f->llvmType = functype;
-        return; // already pulled in from a forward declaration
-    }
-    else */
-    if (func == 0) {
-        func = new llvm::Function(functype,LLVM_DtoLinkage(protection, storage_class),mangled_name,gIR->module);
-    }
-
-    if (llvmInternal != LLVMintrinsic)
-        func->setCallingConv(LLVM_DtoCallingConv(f->linkage));
-
-    llvmValue = func;
-    f->llvmType = functype;
-
-    if (isMain()) {
-        gIR->mainFunc = func;
-    }
-
-    // name parameters
-    llvm::Function::arg_iterator iarg = func->arg_begin();
-    int k = 0;
-    int nunnamed = 0;
-    if (retinptr) {
-        iarg->setName("retval");
-        f->llvmRetArg = iarg;
-        ++iarg;
-    }
-    if (usesthis) {
-        iarg->setName("this");
-        ++iarg;
-    }
-    for (; iarg != func->arg_end(); ++iarg)
-    {
-        Argument* arg = Argument::getNth(f->parameters, k++);
-        //arg->llvmValue = iarg;
-        //printf("identifier: '%s' %p\n", arg->ident->toChars(), arg->ident);
-        if (arg->ident != 0) {
-            if (arg->vardecl) {
-                arg->vardecl->llvmValue = iarg;
-            }
-            iarg->setName(arg->ident->toChars());
-        }
-        else {
-            ++nunnamed;
-        }
-    }
+    llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(f->llvmType);
 
     // only members of the current module maybe be defined
     if (getModule() == gIR->dmodule)
@@ -796,7 +663,9 @@
         // function definition
         if (allow_fbody && fbody != 0)
         {
-            assert(nunnamed == 0);
+            if (isMain())
+                gIR->emitMain = true;
+
             gIR->funcs.push(func);
             gIR->functypes.push(f);
 
@@ -832,18 +701,19 @@
             gIR->funcs.pop();
 
             // get rid of the endentry block, it's never used
+            assert(!func->getBasicBlockList().empty());
             func->getBasicBlockList().pop_back();
 
             // if the last block is empty now, it must be unreachable or it's a bug somewhere else
+            // would be nice to figure out how to assert that this is correct
             llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
             if (lastbb->empty()) {
+                // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ...
                 new llvm::UnreachableInst(lastbb);
             }
         }
     }
-    else
-    {
-        Logger::println("only declaration");
+
     }
 
     llvmDModule = gIR->dmodule;
Binary file lib/llvmdcore.bc has changed
--- a/lphobos/build.sh	Thu Sep 27 06:03:06 2007 +0200
+++ b/lphobos/build.sh	Mon Oct 01 21:19:53 2007 +0200
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 if [ "$1" = "gdb" ]; then
-dc_cmd="gdb --args llvmdmd"
+dc_cmd="gdb --args llvmdc"
 else
 dc_cmd="llvmdc"
 fi
@@ -11,11 +11,11 @@
         internal/moduleinit.d \
         -c -noruntime -odobj || exit 1
 
-$dc_cmd internal/objectimpl.d -c -odobj || exit 1
+llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
+llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1
 
-llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
-
-llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || return 1
+$dc_cmd internal/objectimpl.d -c -odobj || exit 1
+llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1
 
 opt -f -std-compile-opts -o=../lib/llvmdcore.bc obj/all.bc || exit 1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/classes6.d	Mon Oct 01 21:19:53 2007 +0200
@@ -0,0 +1,15 @@
+module classes6;
+
+class C
+{
+    void f()
+    {
+        printf("hello world\n");
+    }
+}
+
+void main()
+{
+    scope c = new C;
+    c.f();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/funcs2.d	Mon Oct 01 21:19:53 2007 +0200
@@ -0,0 +1,9 @@
+module funcs2;
+
+void func()
+{
+}
+
+void main()
+{
+}