# HG changeset patch # User Tomas Lindquist Olsen # Date 1239880736 -7200 # Node ID e67c85d6e680800e7c3177ef96ca5b64ad61db98 # Parent fafe7c8d67349e89d4c385673e3db0d3fdc7005d Completed interface implementation. Hopefully that's it for now.. diff -r fafe7c8d6734 -r e67c85d6e680 ir/irclass.cpp --- 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 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 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)); } diff -r fafe7c8d6734 -r e67c85d6e680 ir/irstruct.h --- a/ir/irstruct.h Thu Apr 16 11:01:49 2009 +0200 +++ b/ir/irstruct.h Thu Apr 16 13:18:56 2009 +0200 @@ -84,6 +84,14 @@ /// Basically: static object.Interface[num_interfaces] llvm::GlobalVariable* classInterfacesArray; + /// std::vector of BaseClass* + typedef std::vector BaseClassVector; + + /// Array of all interface vtbl implementations - in order - implemented + /// by this class. + /// Corresponds to the Interface instances needed to be output. + BaseClassVector interfacesWithVtbls; + ////////////////////////////////////////////////////////////////////////// /// Create static default initializer for struct. @@ -93,7 +101,10 @@ LLConstant* createClassDefaultInitializer(); /// Returns vtbl for interface implementation, creates it if not already built. - llvm::GlobalVariable* getInterfaceVtbl(BaseClass* b, bool new_inst); + llvm::GlobalVariable* getInterfaceVtbl( + BaseClass* b, + bool new_inst, + size_t interfaces_index); /// Add base class data to initializer list. /// Also creates the IrField instance for each data field. diff -r fafe7c8d6734 -r e67c85d6e680 ir/irtypeclass.cpp --- a/ir/irtypeclass.cpp Thu Apr 16 11:01:49 2009 +0200 +++ b/ir/irtypeclass.cpp Thu Apr 16 13:18:56 2009 +0200 @@ -24,6 +24,7 @@ vtbl_pa(llvm::OpaqueType::get()) { vtbl_size = cd->vtbl.dim; + num_interface_vtbls = 0; } ////////////////////////////////////////////////////////////////////////////// @@ -91,6 +92,9 @@ ArrayIter it2(*base->vtblInterfaces); + VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3); + Type* first = interfaces_idx->type->next->pointerTo(); + for (; !it2.done(); it2.next()) { BaseClass* b = it2.get(); @@ -99,15 +103,19 @@ Array arr; b->fillVtbl(cd, &arr, new_instances); - const llvm::Type* ivtbl_type = buildVtblType(Type::tvoid->pointerTo(), &arr); + const llvm::Type* ivtbl_type = buildVtblType(first, &arr); defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0)); offset += PTRSIZE; // add to the interface map + // FIXME: and all it's baseinterfaces if (interfaceMap.find(b->base) == interfaceMap.end()) interfaceMap.insert(std::make_pair(b->base, field_index)); field_index++; + + // inc count + num_interface_vtbls++; } } diff -r fafe7c8d6734 -r e67c85d6e680 ir/irtypeclass.h --- a/ir/irtypeclass.h Thu Apr 16 11:01:49 2009 +0200 +++ b/ir/irtypeclass.h Thu Apr 16 13:18:56 2009 +0200 @@ -17,10 +17,10 @@ const llvm::Type* buildType(); /// - const llvm::Type* getVtbl() { return vtbl_pa.get(); } + const llvm::Type* get(); - /// - const llvm::Type* get(); + /// Returns the vtable type for this class. + const llvm::Type* getVtbl() { return vtbl_pa.get(); } /// Get index to interface implementation. /// Returns the index of a specific interface implementation in this @@ -30,28 +30,36 @@ /// Returns the total number of pointers in the vtable. unsigned getVtblSize() { return vtbl_size; } + /// Returns the number of interface implementations (vtables) in this + /// class. + unsigned getNumInterfaceVtbls() { return num_interface_vtbls; } + protected: /// ClassDeclaration* cd; /// TypeClass* tc; - /// + /// Type holder for the vtable type. llvm::PATypeHolder vtbl_pa; /// Number of pointers in vtable. unsigned vtbl_size; + /// Number of interface implementations (vtables) in this class. + unsigned num_interface_vtbls; + /// std::map type mapping ClassDeclaration* to size_t. typedef std::map ClassIndexMap; /// Map for mapping the index of a specific interface implementation - /// in this class to it's ClassDeclaration*. + /// in this class to its ClassDeclaration. ClassIndexMap interfaceMap; ////////////////////////////////////////////////////////////////////////// - /// + /// Builds a vtable type given the type of the first entry and an array + /// of all entries. const llvm::Type* buildVtblType(Type* first, Array* vtbl_array); ///