Completed interface implementation. Hopefully that's it for now..

This commit is contained in:
Tomas Lindquist Olsen
2009-04-16 13:18:56 +02:00
parent bb98d68f64
commit 5db458d8da
4 changed files with 74 additions and 25 deletions

View File

@@ -91,7 +91,7 @@ LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
// 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 @@ void IrStruct::addBaseClassInits(
// 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 @@ LLConstant * IrStruct::createClassDefaultInitializer()
//////////////////////////////////////////////////////////////////////////////
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 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
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 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
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 @@ llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instan
gIR->module
);
// insert into the vtbl map
interfaceVtblMap.insert(std::make_pair(b->base, GV));
return GV;
@@ -357,7 +375,11 @@ LLConstant * IrStruct::getClassInfoInterfaces()
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 @@ LLConstant * IrStruct::getClassInfoInterfaces()
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 * IrStruct::getClassInfoInterfaces()
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 * IrStruct::getClassInfoInterfaces()
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));
}

View File

@@ -84,6 +84,14 @@ protected:
/// Basically: static object.Interface[num_interfaces]
llvm::GlobalVariable* classInterfacesArray;
/// std::vector of BaseClass*
typedef std::vector<BaseClass*> 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 @@ protected:
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.

View File

@@ -24,6 +24,7 @@ IrTypeClass::IrTypeClass(ClassDeclaration* cd)
vtbl_pa(llvm::OpaqueType::get())
{
vtbl_size = cd->vtbl.dim;
num_interface_vtbls = 0;
}
//////////////////////////////////////////////////////////////////////////////
@@ -91,6 +92,9 @@ void IrTypeClass::addBaseClassData(
ArrayIter<BaseClass> 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 @@ void IrTypeClass::addBaseClassData(
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++;
}
}

View File

@@ -16,12 +16,12 @@ public:
///
const llvm::Type* buildType();
///
const llvm::Type* getVtbl() { return vtbl_pa.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
/// class or ~0 if not found.
@@ -30,28 +30,36 @@ public:
/// 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<ClassDeclaration*, size_t> 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);
///