mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-03-01 10:03:30 +01:00
Refactor struct initializers codegen.
This not only reduces code duplication, but the unification also enables code a la StructLiteralExp to handle classes (for CTFE class constant support in 2.063).
This commit is contained in:
103
ir/irclass.cpp
103
ir/irclass.cpp
@@ -263,109 +263,6 @@ LLConstant * IrAggr::getClassInfoInit()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void IrAggr::addBaseClassInits(
|
||||
std::vector<llvm::Constant*>& constants,
|
||||
ClassDeclaration* base,
|
||||
size_t& offset,
|
||||
size_t& field_index)
|
||||
{
|
||||
if (base->baseClass)
|
||||
{
|
||||
addBaseClassInits(constants, base->baseClass, offset, field_index);
|
||||
}
|
||||
|
||||
IrTypeClass* tc = stripModifiers(base->type)->irtype->isClass();
|
||||
assert(tc);
|
||||
|
||||
// go through fields
|
||||
IrTypeAggr::iterator it;
|
||||
for (it = tc->def_begin(); it != tc->def_end(); ++it)
|
||||
{
|
||||
VarDeclaration* vd = *it;
|
||||
|
||||
IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(vd->offset >= offset && "default fields not sorted by offset");
|
||||
|
||||
// get next aligned offset for this type
|
||||
size_t alignedoffset = realignOffset(offset, vd->type);
|
||||
|
||||
// insert explicit padding?
|
||||
if (alignedoffset < vd->offset)
|
||||
{
|
||||
add_zeros(constants, vd->offset - alignedoffset);
|
||||
}
|
||||
|
||||
// add default type
|
||||
constants.push_back(get_default_initializer(vd, vd->init));
|
||||
|
||||
// advance offset to right past this field
|
||||
offset = vd->offset + vd->type->size();
|
||||
}
|
||||
|
||||
// has interface vtbls?
|
||||
if (base->vtblInterfaces && base->vtblInterfaces->dim > 0)
|
||||
{
|
||||
// false when it's not okay to use functions from super classes
|
||||
bool newinsts = (base == aggrdecl->isClassDeclaration());
|
||||
|
||||
size_t inter_idx = interfacesWithVtbls.size();
|
||||
|
||||
offset = (offset + PTRSIZE - 1) & ~(PTRSIZE - 1);
|
||||
|
||||
ArrayIter<BaseClass> it2(*base->vtblInterfaces);
|
||||
for (; !it2.done(); it2.next())
|
||||
{
|
||||
BaseClass* b = it2.get();
|
||||
constants.push_back(getInterfaceVtbl(b, newinsts, inter_idx));
|
||||
offset += PTRSIZE;
|
||||
|
||||
// add to the interface list
|
||||
interfacesWithVtbls.push_back(b);
|
||||
inter_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<llvm::Constant*> IrAggr::createClassDefaultInitializer()
|
||||
{
|
||||
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||
assert(cd && "invalid class aggregate");
|
||||
|
||||
IF_LOG Logger::println("Building class default initializer %s @ %s", cd->toPrettyChars(), cd->loc.toChars());
|
||||
LOG_SCOPE;
|
||||
IF_LOG Logger::println("Instance size: %u", cd->structsize);
|
||||
|
||||
// find the fields that contribute to the default initializer.
|
||||
// these will define the default type.
|
||||
|
||||
std::vector<llvm::Constant*> constants;
|
||||
constants.reserve(32);
|
||||
|
||||
// add vtbl
|
||||
constants.push_back(getVtblSymbol());
|
||||
// add monitor
|
||||
constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));
|
||||
|
||||
// we start right after the vtbl and monitor
|
||||
size_t offset = PTRSIZE * 2;
|
||||
size_t field_index = 2;
|
||||
|
||||
// add data members recursively
|
||||
addBaseClassInits(constants, cd, offset, field_index);
|
||||
|
||||
// tail padding?
|
||||
if (offset < cd->structsize)
|
||||
add_zeros(constants, cd->structsize - offset);
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index)
|
||||
{
|
||||
ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base);
|
||||
|
||||
Reference in New Issue
Block a user