Mercurial > projects > ldc
diff ir/irclass.cpp @ 1230:e67c85d6e680
Completed interface implementation. Hopefully that's it for now..
author | Tomas Lindquist Olsen <tomas.l.olsen gmail.com> |
---|---|
date | Thu, 16 Apr 2009 13:18:56 +0200 |
parents | fafe7c8d6734 |
children | 212ec2d9d176 |
line wrap: on
line diff
--- a/ir/irclass.cpp Thu Apr 16 11:01:49 2009 +0200 +++ b/ir/irclass.cpp Thu Apr 16 13:18:56 2009 +0200 @@ -91,7 +91,7 @@ // create Interface[N] const llvm::ArrayType* array_type = llvm::ArrayType::get( InterfaceTy, - cd->vtblInterfaces->dim); + type->irtype->isClass()->getNumInterfaceVtbls()); // put it in a global std::string name("_D"); @@ -222,12 +222,18 @@ // false when it's not okay to use functions from super classes bool newinsts = (base == aggrdecl->isClassDeclaration()); + size_t inter_idx = interfacesWithVtbls.size(); + ArrayIter<BaseClass> it2(*base->vtblInterfaces); for (; !it2.done(); it2.next()) { BaseClass* b = it2.get(); - constants.push_back(getInterfaceVtbl(b, newinsts)); + constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx)); offset += PTRSIZE; + + // add to the interface list + interfacesWithVtbls.push_back(b); + inter_idx++; } } @@ -279,12 +285,9 @@ ////////////////////////////////////////////////////////////////////////////// -llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance) +llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index) { - ClassDeclaration* cd = aggrdecl->isClassDeclaration(); - assert(cd && "not a class aggregate"); - - ClassGlobalMap::iterator it = interfaceVtblMap.find(cd); + ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base); if (it != interfaceVtblMap.end()) return it->second; @@ -292,6 +295,9 @@ b->base->toPrettyChars(), aggrdecl->toPrettyChars()); LOG_SCOPE; + ClassDeclaration* cd = aggrdecl->isClassDeclaration(); + assert(cd && "not a class aggregate"); + Array vtbl_array; b->fillVtbl(cd, &vtbl_array, new_instance); @@ -299,7 +305,18 @@ constants.reserve(vtbl_array.dim); // start with the interface info - llvm::Constant* c = getNullValue(DtoType(Type::tvoid->pointerTo())); + VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); + Type* first = interfaces_idx->type->next->pointerTo(); + + // index into the interfaces array + llvm::Constant* idxs[2] = { + DtoConstSize_t(0), + DtoConstSize_t(interfaces_index) + }; + + llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr( + getInterfaceArraySymbol(), idxs, 2); + constants.push_back(c); // add virtual function pointers @@ -342,6 +359,7 @@ gIR->module ); + // insert into the vtbl map interfaceVtblMap.insert(std::make_pair(b->base, GV)); return GV; @@ -357,7 +375,11 @@ ClassDeclaration* cd = aggrdecl->isClassDeclaration(); assert(cd); - if (!cd->vtblInterfaces || cd->vtblInterfaces->dim == 0) + size_t n = interfacesWithVtbls.size(); + assert(type->irtype->isClass()->getNumInterfaceVtbls() == n && + "inconsistent number of interface vtables in this class"); + + if (n == 0) { VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3); return getNullValue(DtoType(idx->type)); @@ -381,9 +403,10 @@ const LLType* our_type = type->irtype->isClass()->getPA().get(); - ArrayIter<BaseClass> it(*cd->vtblInterfaces); - while (it.more()) + for (size_t i = 0; i < n; ++i) { + BaseClass* it = interfacesWithVtbls[i]; + IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars()); IrStruct* irinter = it->base->ir.irStruct; @@ -409,15 +432,12 @@ LLConstant* inits[3] = { ci, vtb, off }; LLConstant* entry = llvm::ConstantStruct::get(inits, 3); constants.push_back(entry); - - // next - it.next(); } // create Interface[N] const llvm::ArrayType* array_type = llvm::ArrayType::get( constants[0]->getType(), - cd->vtblInterfaces->dim); + n); LLConstant* arr = llvm::ConstantArray::get( array_type, @@ -429,12 +449,14 @@ LLConstant* idxs[2] = { DtoConstSize_t(0), - DtoConstSize_t(0) + // only the interface explicitly implemented by this class + // (not super classes) should show in ClassInfo + DtoConstSize_t(n - cd->vtblInterfaces->dim) }; // return as a slice return DtoConstSlice( - DtoConstSize_t(cd->vtblInterfaces->dim), + DtoConstSize_t(n), llvm::ConstantExpr::getGetElementPtr(classInterfacesArray, idxs, 2)); }