mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-12 02:43:14 +01:00
Completed interface implementation. Hopefully that's it for now..
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user