diff gen/classes.cpp @ 113:27b9f749d9fe trunk

[svn r117] Initial working implementation of interfaces. Groundwork for all the different types of class/interface casts laid out.
author lindquist
date Sat, 24 Nov 2007 06:33:00 +0100
parents 368547b1cbe6
children 5880c12dba83
line wrap: on
line diff
--- a/gen/classes.cpp	Thu Nov 22 22:30:10 2007 +0100
+++ b/gen/classes.cpp	Sat Nov 24 06:33:00 2007 +0100
@@ -1,3 +1,4 @@
+#include <sstream>
 #include "gen/llvm.h"
 
 #include "mtype.h"
@@ -11,6 +12,8 @@
 #include "gen/logger.h"
 #include "gen/classes.h"
 #include "gen/functions.h"
+#include "gen/runtime.h"
+#include "gen/dvalue.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
@@ -21,10 +24,14 @@
     {
         BaseClass* bc = (BaseClass*)(bcs->data[j]);
         assert(bc);
+        if (bc->base->isInterfaceDeclaration())
+            continue; // interfaces only has methods
+
+        LLVM_AddBaseClassData(&bc->base->baseclasses);
+
         Logger::println("Adding base class members of %s", bc->base->toChars());
         LOG_SCOPE;
 
-        LLVM_AddBaseClassData(&bc->base->baseclasses);
         for (int k=0; k < bc->base->members->dim; k++) {
             Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]);
             if (dsym->isVarDeclaration())
@@ -46,10 +53,17 @@
     if (cd->baseClass) {
         DtoResolveClass(cd->baseClass);
     }
-    // resolve typeinfo
-    //DtoResolveClass(ClassDeclaration::typeinfo);
-    // resolve classinfo
-    //DtoResolveClass(ClassDeclaration::classinfo);
+
+    // resolve interfaces
+    if (cd->vtblInterfaces) {
+        for (int i=0; i < cd->vtblInterfaces->dim; i++) {
+            BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
+            ClassDeclaration *id = b->base;
+            DtoResolveClass(id);
+            // Fill in vtbl[]
+            b->fillVtbl(cd, &b->vtbl, 1);
+        }
+    }
 
     Logger::println("DtoResolveClass(%s)", cd->toPrettyChars());
     LOG_SCOPE;
@@ -71,6 +85,22 @@
     std::vector<const llvm::Type*> fieldtypes;
     fieldtypes.push_back(vtabty);
 
+    // add interface vtables
+    if (cd->vtblInterfaces)
+    for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
+    {
+        BaseClass *b = (BaseClass *)cd->vtblInterfaces->data[i];
+        ClassDeclaration *id = b->base;
+        assert(id->type->ty == Tclass);
+        TypeClass* itc = (TypeClass*)id->type;
+        const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get());
+        fieldtypes.push_back(ivtblTy);
+
+        // add this interface to the map
+        IRInterface* iri = new IRInterface(b, isaStruct(itc->llvmVtblType->get()));
+        irstruct->interfaces.insert(std::make_pair(id, iri));
+    }
+
     // base classes first
     LLVM_AddBaseClassData(&cd->baseclasses);
 
@@ -98,16 +128,31 @@
     else
         *ts->llvmType = structtype;
 
-    bool needs_definition = false;
     if (cd->parent->isModule()) {
         gIR->module->addTypeName(cd->mangle(), ts->llvmType->get());
-        needs_definition = (cd->getModule() == gIR->dmodule);
     }
     else {
         assert(0 && "class parent is not a module");
     }
 
-    // generate vtable
+    // build interface info type
+    std::vector<const llvm::Type*> infoTypes;
+    // ClassInfo classinfo
+    ClassDeclaration* cinfod = ClassDeclaration::classinfo;
+    DtoResolveClass(cinfod);
+    infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get()));
+    // void*[] vtbl
+    std::vector<const llvm::Type*> infoVtbltypes;
+    infoVtbltypes.push_back(DtoSize_t());
+    const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+    infoVtbltypes.push_back(byteptrptrty);
+    infoTypes.push_back(llvm::StructType::get(infoVtbltypes));
+    // int offset
+    infoTypes.push_back(llvm::Type::Int32Ty);
+    // create type
+    const llvm::StructType* infoTy = llvm::StructType::get(infoTypes);
+
+    // create vtable type
     llvm::GlobalVariable* svtblVar = 0;
     std::vector<const llvm::Type*> sinits_ty;
 
@@ -124,18 +169,21 @@
             const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get());
             sinits_ty.push_back(fpty);
         }
-        else if (ClassDeclaration* cd = dsym->isClassDeclaration()) {
-            //Logger::println("*** ClassDeclaration in vtable: %s", cd->toChars());
+        else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) {
+            Logger::println("*** ClassDeclaration in vtable: %s", cd2->toChars());
             const llvm::Type* cinfoty;
-            if (cd != ClassDeclaration::classinfo) {
-                cd = ClassDeclaration::classinfo;
-                DtoResolveClass(cd);
-                cinfoty = cd->type->llvmType->get();
+            if (cd->isInterfaceDeclaration()) {
+                cinfoty = infoTy;
+            }
+            else if (cd != cinfod) {
+                DtoResolveClass(cinfod);
+                cinfoty = cinfod->type->llvmType->get();
             }
             else {
+                // this is the ClassInfo class, the type is this type
                 cinfoty = ts->llvmType->get();
             }
-            const llvm::Type* cty = llvm::PointerType::get(cd->type->llvmType->get());
+            const llvm::Type* cty = llvm::PointerType::get(cinfoty);
             sinits_ty.push_back(cty);
         }
         else
@@ -182,26 +230,78 @@
         needs_definition = (cd->getModule() == gIR->dmodule);
     }
 
-    // vtable
-    std::string varname("_D");
-    varname.append(cd->mangle());
-    varname.append("6__vtblZ");
+    // interface vtables are emitted by the class implementing them
+    // also interfaces have no static initializer
+    if (!cd->isInterfaceDeclaration()) {
+        // vtable
+        std::string varname("_D");
+        varname.append(cd->mangle());
+        varname.append("6__vtblZ");
+
+        llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+
+        const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
+        cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
 
-    std::string styname(cd->mangle());
-    styname.append("__vtblTy");
-
-    llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
+        // build interface info type
+        std::vector<const llvm::Type*> types;
+        // ClassInfo classinfo
+        ClassDeclaration* cd2 = ClassDeclaration::classinfo;
+        DtoResolveClass(cd2);
+        types.push_back(llvm::PointerType::get(cd2->type->llvmType->get()));
+        // void*[] vtbl
+        std::vector<const llvm::Type*> vtbltypes;
+        vtbltypes.push_back(DtoSize_t());
+        const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        vtbltypes.push_back(byteptrptrty);
+        types.push_back(llvm::StructType::get(vtbltypes));
+        // int offset
+        types.push_back(llvm::Type::Int32Ty);
+        // create type
+        const llvm::StructType* infoTy = llvm::StructType::get(types);
 
-    const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
-    cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
+        // interface info array
+        if (needs_definition && cd->vtblInterfaces->dim > 0) {
+            // symbol name
+            std::string nam = "_D";
+            nam.append(cd->mangle());
+            nam.append("16__interfaceInfosZ");
+            // resolve array type
+            const llvm::ArrayType* arrTy = llvm::ArrayType::get(infoTy, cd->vtblInterfaces->dim);
+            // declare global
+            irstruct->interfaceInfosTy = arrTy;
+            irstruct->interfaceInfos = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, 0, nam, gIR->module);
+        }
+
+        // interface vtables
+        unsigned idx = 0;
+        for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
+        {
+            ClassDeclaration* id = i->first;
+            IRInterface* iri = i->second;
 
-    // init
-    std::string initname("_D");
-    initname.append(cd->mangle());
-    initname.append("6__initZ");
+            std::string nam("_D");
+            nam.append(cd->mangle());
+            nam.append("11__interface");
+            nam.append(id->mangle());
+            nam.append("6__vtblZ");
 
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
-    ts->llvmInit = initvar;
+            assert(iri->vtblTy);
+            iri->vtbl = new llvm::GlobalVariable(iri->vtblTy, true, _linkage, 0, nam, gIR->module);
+            iri->infoTy = infoTy;
+            llvm::Constant* idxs[2] = {DtoConstUint(0), DtoConstUint(idx)};
+            iri->info = llvm::ConstantExpr::getGetElementPtr(irstruct->interfaceInfos, idxs, 2);
+            idx++;
+        }
+
+        // init
+        std::string initname("_D");
+        initname.append(cd->mangle());
+        initname.append("6__initZ");
+
+        llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module);
+        ts->llvmInit = initvar;
+    }
 
     gIR->classes.pop_back();
     gIR->structs.pop_back();
@@ -225,6 +325,9 @@
     if (cd->llvmInitialized) return;
     cd->llvmInitialized = true;
 
+    if (cd->isInterfaceDeclaration())
+        return; // nothing to do
+
     Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars());
     LOG_SCOPE;
 
@@ -248,6 +351,14 @@
     assert(cd->llvmVtbl != 0);
     fieldinits.push_back(cd->llvmVtbl);
 
+    // next comes interface vtables
+    for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
+    {
+        IRInterface* iri = i->second;
+        assert(iri->vtbl);
+        fieldinits.push_back(iri->vtbl);
+    }
+
     // rest
     for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
         Logger::println("adding fieldinit for: %s", i->second.var->toChars());
@@ -260,7 +371,8 @@
     const llvm::StructType* structtype = isaStruct(ts->llvmType->get());
 
     // generate initializer
-    /*Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
+#if 0
+    Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n';
 
     for(size_t i=0; i<structtype->getNumElements(); ++i) {
         Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n';
@@ -268,7 +380,8 @@
 
     for(size_t i=0; i<fieldinits.size(); ++i) {
         Logger::cout() << "i#" << i << " = " << *fieldinits[i]->getType() << '\n';
-    }*/
+    }
+#endif
 
     llvm::Constant* _init = llvm::ConstantStruct::get(structtype, fieldinits);
     assert(_init);
@@ -300,16 +413,83 @@
 
     const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get());
 
-    /*for (size_t i=0; i< sinits.size(); ++i)
+#if 0
+    for (size_t i=0; i< sinits.size(); ++i)
     {
         Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n';
         Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n';
         assert(svtbl_ty->getElementType(i) == sinits[i]->getType());
-    }*/
+    }
+#endif
 
     llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits);
     cd->llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(cvtblInit);
 
+    // create interface vtable const initalizers
+    int idx = 1;
+    int idxScale = (global.params.is64bit) ? 8 : 4;
+    for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
+    {
+        ClassDeclaration* id = i->first;
+        assert(id->type->ty == Tclass);
+        TypeClass* its = (TypeClass*)id->type;
+
+        IRInterface* iri = i->second;
+        BaseClass* b = iri->base;
+
+        const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get());
+
+        // generate interface info initializer
+        std::vector<llvm::Constant*> infoInits;
+        // classinfo
+        assert(id->llvmClass);
+        llvm::Constant* c = id->llvmClass;
+        infoInits.push_back(c);
+        // vtbl
+        const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));
+        c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty);
+        c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c);
+        infoInits.push_back(c);
+        // offset
+        infoInits.push_back(DtoConstInt(idx*idxScale));
+        // create interface info initializer constant
+        iri->infoInit = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(iri->infoTy, infoInits));
+
+        // generate vtable initializer
+        std::vector<llvm::Constant*> iinits;
+
+        // add interface info
+        iinits.push_back(iri->info);
+
+        for (int k=1; k < b->vtbl.dim; k++)
+        {
+            Logger::println("interface vtbl const init nr. %d", k);
+            Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k];
+            FuncDeclaration* fd = dsym->isFuncDeclaration();
+            assert(fd);
+            DtoForceDeclareDsymbol(fd);
+            assert(fd->llvmValue);
+            llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
+            // we have to bitcast, as the type created in ResolveClass expects a different this type
+            c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k));
+            iinits.push_back(c);
+        }
+
+#if 1
+        for (size_t x=0; x< iinits.size(); ++x)
+        {
+            Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n";
+            Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n";
+            assert(ivtbl_ty->getElementType(x) == iinits[x]->getType());
+        }
+#endif
+
+        llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits);
+        iri->vtblInit = llvm::cast<llvm::ConstantStruct>(civtblInit);
+
+        idx++;
+    }
+
     gIR->classes.pop_back();
     gIR->structs.pop_back();
 }
@@ -330,8 +510,26 @@
 
     bool def = false;
     if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) {
-        ts->llvmInit->setInitializer(cd->llvmInitZ);
-        cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
+        // interfaces don't have initializers
+        if (!cd->isInterfaceDeclaration()) {
+            ts->llvmInit->setInitializer(cd->llvmInitZ);
+            cd->llvmVtbl->setInitializer(cd->llvmConstVtbl);
+
+            // initialize interface vtables
+            IRStruct* irstruct = cd->llvmIRStruct;
+            std::vector<llvm::Constant*> infoInits;
+            for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i)
+            {
+                IRInterface* iri = i->second;
+                iri->vtbl->setInitializer(iri->vtblInit);
+                infoInits.push_back(iri->infoInit);
+            }
+            // initialize interface info array
+            if (!infoInits.empty()) {
+                llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits);
+                irstruct->interfaceInfos->setInitializer(arrInit);
+            }
+        }
         def = true;
     }
 
@@ -394,6 +592,54 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+DValue* DtoCastObjectToInterface(DValue* val, Type* _to)
+{
+    // call:
+    // Object _d_dynamic_cast(Object o, ClassInfo c)
+
+    llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
+    const llvm::FunctionType* funcTy = func->getFunctionType();
+
+    std::vector<llvm::Value*> args;
+
+    // Object o
+    llvm::Value* tmp = val->getRVal();
+    tmp = DtoBitCast(tmp, funcTy->getParamType(0));
+    args.push_back(tmp);
+
+    // ClassInfo c
+    TypeClass* to = (TypeClass*)DtoDType(_to);
+    DtoForceDeclareDsymbol(to->sym);
+    assert(to->sym->llvmClass);
+    args.push_back(to->sym->llvmClass);
+
+    // call it
+    llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp");
+    ret = DtoBitCast(ret, DtoType(_to));
+    return new DImValue(_to, ret);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DValue* DtoCastInterfaceToObject(DValue* val)
+{
+    // call:
+    // Object _d_toObject(void* p)
+
+    llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_toObject");
+    const llvm::FunctionType* funcTy = func->getFunctionType();
+
+    // void* p
+    llvm::Value* tmp = val->getRVal();
+    tmp = DtoBitCast(tmp, funcTy->getParamType(0));
+
+    // call it
+    llvm::Value* ret = gIR->ir->CreateCall(func, tmp, "tmp");
+    return new DImValue(ClassDeclaration::object->type, ret);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 void DtoDeclareClassInfo(ClassDeclaration* cd)
 {
     if (cd->llvmClassDeclared) return;
@@ -407,7 +653,10 @@
 
     std::string gname("_D");
     gname.append(cd->mangle());
-    gname.append("7__ClassZ");
+    if (!cd->isInterfaceDeclaration())
+        gname.append("7__ClassZ");
+    else
+        gname.append("11__InterfaceZ");
 
     const llvm::Type* st = cinfo->type->llvmType->get();
 
@@ -538,6 +787,7 @@
 
 static uint build_classinfo_flags(ClassDeclaration* cd)
 {
+    // adapted from original dmd code
     uint flags = 0;
     //flags |= isCOMclass(); // IUnknown
     bool hasOffTi = false;
@@ -591,12 +841,14 @@
 
     assert(cd->type->ty == Tclass);
     assert(cd->llvmClass);
-    assert(cd->llvmInitZ);
-    assert(cd->llvmVtbl);
-    assert(cd->llvmConstVtbl);
 
     TypeClass* cdty = (TypeClass*)cd->type;
-    assert(cdty->llvmInit);
+    if (!cd->isInterfaceDeclaration()) {
+        assert(cd->llvmInitZ);
+        assert(cd->llvmVtbl);
+        assert(cd->llvmConstVtbl);
+        assert(cdty->llvmInit);
+    }
 
     // holds the list of initializers for llvm
     std::vector<llvm::Constant*> inits;
@@ -617,10 +869,15 @@
 
     // byte[] init
     const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
-    assert(!cd->llvmInitZ->getType()->isAbstract());
-    size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
-    c = DtoConstSlice(DtoConstSize_t(initsz), c);
+    if (cd->isInterfaceDeclaration()) {
+        c = cinfo->llvmInitZ->getOperand(1);
+    }
+    else {
+        c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty);
+        assert(!cd->llvmInitZ->getType()->isAbstract());
+        size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType());
+        c = DtoConstSlice(DtoConstSize_t(initsz), c);
+    }
     inits.push_back(c);
 
     // class name
@@ -636,21 +893,34 @@
     inits.push_back(c);
 
     // vtbl array
-    const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
-    assert(!cd->llvmVtbl->getType()->isAbstract());
-    c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
-    assert(!cd->llvmConstVtbl->getType()->isAbstract());
-    size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType());
-    c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
+    if (cd->isInterfaceDeclaration()) {
+        c = cinfo->llvmInitZ->getOperand(3);
+    }
+    else {
+        const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty);
+        assert(!cd->llvmVtbl->getType()->isAbstract());
+        c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty);
+        assert(!cd->llvmConstVtbl->getType()->isAbstract());
+        size_t vtblsz = cd->llvmConstVtbl->getType()->getNumElements();
+        c = DtoConstSlice(DtoConstSize_t(vtblsz), c);
+    }
     inits.push_back(c);
 
     // interfaces array
-    // TODO
-    c = cinfo->llvmInitZ->getOperand(4);
+    IRStruct* irstruct = cd->llvmIRStruct;
+    if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) {
+        c = cinfo->llvmInitZ->getOperand(4);
+    }
+    else {
+        const llvm::Type* t = cinfo->llvmInitZ->getOperand(4)->getType()->getContainedType(1);
+        c = llvm::ConstantExpr::getBitCast(irstruct->interfaceInfos, t);
+        size_t iisz = irstruct->interfaceInfosTy->getNumElements();
+        c = DtoConstSlice(DtoConstSize_t(iisz), c);
+    }
     inits.push_back(c);
 
     // base classinfo
-    if (cd->baseClass) {
+    if (cd->baseClass && !cd->isInterfaceDeclaration()) {
         DtoDeclareClassInfo(cd->baseClass);
         c = cd->baseClass->llvmClass;
         assert(c);
@@ -663,7 +933,12 @@
     }
 
     // destructor
-    c = build_class_dtor(cd);
+    if (cd->isInterfaceDeclaration()) {
+        c = cinfo->llvmInitZ->getOperand(6);
+    }
+    else {
+        c = build_class_dtor(cd);
+    }
     inits.push_back(c);
 
     // invariant
@@ -671,9 +946,14 @@
     c = cinfo->llvmInitZ->getOperand(7);
     inits.push_back(c);
 
-    // uint flags, adapted from original dmd code
-    uint flags = build_classinfo_flags(cd);
-    c = DtoConstUint(flags);
+    // uint flags
+    if (cd->isInterfaceDeclaration()) {
+        c = cinfo->llvmInitZ->getOperand(8);
+    }
+    else {
+        uint flags = build_classinfo_flags(cd);
+        c = DtoConstUint(flags);
+    }
     inits.push_back(c);
 
     // allocator
@@ -682,11 +962,16 @@
     inits.push_back(c);
 
     // offset typeinfo
-    c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10));
+    if (cd->isInterfaceDeclaration()) {
+        c = cinfo->llvmInitZ->getOperand(10);
+    }
+    else {
+        c = build_offti_array(cd, cinfo->llvmInitZ->getOperand(10));
+    }
     inits.push_back(c);
 
     // default constructor
-    if (cd->defaultCtor) {
+    if (cd->defaultCtor && !cd->isInterfaceDeclaration()) {
         DtoForceDeclareDsymbol(cd->defaultCtor);
         c = isaConstant(cd->defaultCtor->llvmValue);
         //const llvm::Type* toTy = cinfo->llvmInitZ->getOperand(11)->getType();