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:
David Nadlinger
2013-06-12 15:36:15 +02:00
parent 2cebe6408c
commit 9a016a1002
7 changed files with 280 additions and 417 deletions

View File

@@ -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);