llvm::Constant * IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) { IF_LOG Logger::println("Creating initializer constant for %s", aggrdecl->toChars()); LOG_SCOPE; llvm::SmallVector<llvm::Constant *, 16> constants; unsigned offset = 0; if (type->ty == Tclass) { // add vtbl constants.push_back(getVtblSymbol()); offset += Target::ptrsize; // add monitor (except for C++ classes) if (!aggrdecl->isClassDeclaration()->isCPPclass()) { constants.push_back(getNullValue(getVoidPtrType())); offset += Target::ptrsize; } } // Add the initializers for the member fields. While we are traversing the // class hierarchy, use the opportunity to populate interfacesWithVtbls if // we haven't done so previously (due to e.g. ClassReferenceExp, we can // have multiple initializer constants for a single class). addFieldInitializers(constants, explicitInitializers, aggrdecl, offset, interfacesWithVtbls.empty()); // tail padding? const size_t structsize = aggrdecl->size(Loc()); if (offset < structsize) add_zeros(constants, offset, structsize); assert(!constants.empty()); // get LL field types llvm::SmallVector<llvm::Type *, 16> types; types.reserve(constants.size()); for (auto c : constants) types.push_back(c->getType()); auto llStructType = getLLStructType(); bool isCompatible = (types.size() == llStructType->getNumElements()); if (isCompatible) { for (size_t i = 0; i < types.size(); i++) { if (types[i] != llStructType->getElementType(i)) { isCompatible = false; break; } } } // build constant LLStructType *llType = isCompatible ? llStructType : LLStructType::get(gIR->context(), types, isPacked()); llvm::Constant *c = LLConstantStruct::get(llType, constants); IF_LOG Logger::cout() << "final initializer: " << *c << std::endl; return c; }
std::vector<llvm::Constant*> IrStruct::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::Constant* IrAggr::createInitializerConstant( const VarInitMap& explicitInitializers, llvm::StructType* initializerType) { IF_LOG Logger::println("Creating initializer constant for %s", aggrdecl->toChars()); LOG_SCOPE; llvm::SmallVector<llvm::Constant*, 16> constants; unsigned offset = 0; if (type->ty == Tclass) { // add vtbl constants.push_back(getVtblSymbol()); // add monitor constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo()))); // we start right after the vtbl and monitor offset = Target::ptrsize * 2; } // Add the initializers for the member fields. While we are traversing the // class hierarchy, use the opportunity to populate interfacesWithVtbls if // we haven't done so previously (due to e.g. ClassReferenceExp, we can // have multiple initializer constants for a single class). addFieldInitializers(constants, explicitInitializers, aggrdecl, offset, interfacesWithVtbls.empty()); // tail padding? const size_t structsize = aggrdecl->size(Loc()); if (offset < structsize) { add_zeros(constants, offset, structsize); } // get initializer type if (!initializerType || initializerType->isOpaque()) { llvm::SmallVector<llvm::Constant*, 16>::iterator itr, end = constants.end(); llvm::SmallVector<llvm::Type*, 16> types; types.reserve(constants.size()); for (itr = constants.begin(); itr != end; ++itr) types.push_back((*itr)->getType()); if (!initializerType) initializerType = LLStructType::get(gIR->context(), types, isPacked()); else initializerType->setBody(types, isPacked()); } // build constant assert(!constants.empty()); llvm::Constant* c = LLConstantStruct::get(initializerType, constants); IF_LOG Logger::cout() << "final initializer: " << *c << std::endl; return c; }