Refactoring: Improve Ir{Aggr,Class,Struct} encapsulation

This commit is contained in:
Martin Kinkelin 2020-07-18 12:20:33 +02:00
parent a765bf8901
commit e9021fd6c8
6 changed files with 122 additions and 112 deletions

View file

@ -107,8 +107,7 @@ public:
// Emit TypeInfo. // Emit TypeInfo.
IrClass *ir = getIrAggr(decl); IrClass *ir = getIrAggr(decl);
if (!ir->suppressTypeInfo()) { if (!ir->suppressTypeInfo()) {
llvm::GlobalVariable *interfaceZ = ir->getClassInfoSymbol(); ir->getClassInfoSymbol(/*define=*/true);
defineGlobal(interfaceZ, ir->getClassInfoInit(), decl);
} }
} }
@ -148,10 +147,7 @@ public:
// Define the __initZ symbol. // Define the __initZ symbol.
if (!decl->zeroInit) { if (!decl->zeroInit) {
auto &initZ = ir->getInitSymbol(); ir->getInitSymbol(/*define=*/true);
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkageAndVisibility(decl, initGlobal);
} }
// Emit special __xopEquals/__xopCmp/__xtoHash member functions required // Emit special __xopEquals/__xopCmp/__xtoHash member functions required
@ -204,20 +200,15 @@ public:
IrClass *ir = getIrAggr(decl); IrClass *ir = getIrAggr(decl);
auto &initZ = ir->getInitSymbol(); ir->getInitSymbol(/*define=*/true);
auto initGlobal = llvm::cast<LLGlobalVariable>(initZ);
initZ = irs->setGlobalVarInitializer(initGlobal, ir->getDefaultInit());
setLinkageAndVisibility(decl, initGlobal);
llvm::GlobalVariable *vtbl = ir->getVtblSymbol(); ir->getVtblSymbol(/*define*/true);
defineGlobal(vtbl, ir->getVtblInit(), decl);
ir->defineInterfaceVtbls(); ir->defineInterfaceVtbls();
// Emit TypeInfo. // Emit TypeInfo.
if (!ir->suppressTypeInfo()) { if (!ir->suppressTypeInfo()) {
llvm::GlobalVariable *classZ = ir->getClassInfoSymbol(); ir->getClassInfoSymbol(/*define=*/true);
defineGlobal(classZ, ir->getClassInfoInit(), decl);
} }
} }

View file

@ -487,12 +487,8 @@ class DeclareOrDefineVisitor : public Visitor {
return; return;
} }
LLConstant *init = irstruct->getTypeInfoInit(); // might define ti! irstruct->getTypeInfoSymbol(/*define=*/true);
ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
if (!ti->hasInitializer()) {
defineGlobal(ti, init, sd);
ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
}
} }
// Only declare class TypeInfos. They are defined once in their owning module // Only declare class TypeInfos. They are defined once in their owning module

View file

@ -51,19 +51,26 @@ bool IrAggr::suppressTypeInfo() const {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
LLConstant *&IrAggr::getInitSymbol() { LLConstant *IrAggr::getInitSymbol(bool define) {
if (init) { if (!init) {
return init; const auto irMangle = getIRMangledInitSymbolName(aggrdecl);
auto initGlobal =
declareGlobal(aggrdecl->loc, gIR->module, getLLStructType(), irMangle,
/*isConstant=*/true);
initGlobal->setAlignment(LLMaybeAlign(DtoAlignment(type)));
init = initGlobal;
} }
// create the initZ symbol if (define) {
const auto irMangle = getIRMangledInitSymbolName(aggrdecl); auto initConstant = getDefaultInit();
auto initGlobal = llvm::dyn_cast<LLGlobalVariable>(init);
auto initGlobal = declareGlobal(aggrdecl->loc, gIR->module, getLLStructType(), if (initGlobal // NOT a bitcast pointer to helper global
irMangle, /*isConstant=*/true); && !initGlobal->hasInitializer()) {
initGlobal->setAlignment(LLMaybeAlign(DtoAlignment(type))); init = gIR->setGlobalVarInitializer(initGlobal, initConstant, aggrdecl);
}
init = initGlobal; }
return init; return init;
} }

View file

@ -58,7 +58,7 @@ public:
virtual ~IrAggr() = default; virtual ~IrAggr() = default;
/// Creates the __initZ symbol lazily. /// Creates the __initZ symbol lazily.
llvm::Constant *&getInitSymbol(); llvm::Constant *getInitSymbol(bool define = false);
/// Builds the __initZ initializer constant lazily. /// Builds the __initZ initializer constant lazily.
llvm::Constant *getDefaultInit(); llvm::Constant *getDefaultInit();
@ -112,7 +112,9 @@ public:
explicit IrStruct(StructDeclaration *sd) : IrAggr(sd) {} explicit IrStruct(StructDeclaration *sd) : IrAggr(sd) {}
/// Creates the TypeInfo_Struct symbol lazily. /// Creates the TypeInfo_Struct symbol lazily.
llvm::GlobalVariable *getTypeInfoSymbol(); llvm::GlobalVariable *getTypeInfoSymbol(bool define = false);
private:
/// Builds the TypeInfo_Struct initializer constant lazily. /// Builds the TypeInfo_Struct initializer constant lazily.
llvm::Constant *getTypeInfoInit(); llvm::Constant *getTypeInfoInit();
}; };
@ -123,21 +125,14 @@ public:
explicit IrClass(ClassDeclaration *cd) : IrAggr(cd) {} explicit IrClass(ClassDeclaration *cd) : IrAggr(cd) {}
/// Creates the __ClassZ/__InterfaceZ symbol lazily. /// Creates the __ClassZ/__InterfaceZ symbol lazily.
llvm::GlobalVariable *getClassInfoSymbol(); llvm::GlobalVariable *getClassInfoSymbol(bool define = false);
/// Builds the __ClassZ/__InterfaceZ initializer constant lazily.
llvm::Constant *getClassInfoInit();
/// Creates the __vtblZ symbol lazily. /// Creates the __vtblZ symbol lazily.
llvm::GlobalVariable *getVtblSymbol(); llvm::GlobalVariable *getVtblSymbol(bool define = false);
/// Builds the __vtblZ initializer constant lazily.
llvm::Constant *getVtblInit();
/// Defines all interface vtbls. /// Defines all interface vtbls.
void defineInterfaceVtbls(); void defineInterfaceVtbls();
/// Creates the __interfaceInfos symbol lazily.
llvm::GlobalVariable *getInterfaceArraySymbol();
/// Initialize interface. /// Initialize interface.
void initializeInterface(); void initializeInterface();
@ -162,6 +157,12 @@ private:
/// Corresponds to the Interface instances needed to be output. /// Corresponds to the Interface instances needed to be output.
std::vector<BaseClass *> interfacesWithVtbls; std::vector<BaseClass *> interfacesWithVtbls;
/// Builds the __ClassZ/__InterfaceZ initializer constant lazily.
llvm::Constant *getClassInfoInit();
/// Builds the __vtblZ initializer constant lazily.
llvm::Constant *getVtblInit();
/// Returns the vtbl for an interface implementation. /// Returns the vtbl for an interface implementation.
llvm::GlobalVariable *getInterfaceVtblSymbol(BaseClass *b, llvm::GlobalVariable *getInterfaceVtblSymbol(BaseClass *b,
size_t interfaces_index); size_t interfaces_index);
@ -169,6 +170,9 @@ private:
void defineInterfaceVtbl(BaseClass *b, bool new_inst, void defineInterfaceVtbl(BaseClass *b, bool new_inst,
size_t interfaces_index); size_t interfaces_index);
/// Creates the __interfaceInfos symbol lazily.
llvm::GlobalVariable *getInterfaceArraySymbol();
/// Create the Interface[] interfaces ClassInfo field initializer. /// Create the Interface[] interfaces ClassInfo field initializer.
llvm::Constant *getClassInfoInterfaces(); llvm::Constant *getClassInfoInterfaces();

View file

@ -41,67 +41,75 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
LLGlobalVariable *IrClass::getVtblSymbol() { LLGlobalVariable *IrClass::getVtblSymbol(bool define) {
if (vtbl) { if (!vtbl) {
return vtbl; const auto irMangle = getIRMangledVTableSymbolName(aggrdecl);
LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType();
vtbl = declareGlobal(aggrdecl->loc, gIR->module, vtblTy, irMangle,
/*isConstant=*/true);
} }
// create the vtblZ symbol if (define) {
const auto irMangle = getIRMangledVTableSymbolName(aggrdecl); auto init = getVtblInit(); // might define vtbl
if (!vtbl->hasInitializer())
LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType(); defineGlobal(vtbl, init, aggrdecl);
}
vtbl = declareGlobal(aggrdecl->loc, gIR->module, vtblTy, irMangle,
/*isConstant=*/true);
return vtbl; return vtbl;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
LLGlobalVariable *IrClass::getClassInfoSymbol() { LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) {
if (typeInfo) { if (!typeInfo) {
return typeInfo; const auto irMangle = getIRMangledClassInfoSymbolName(aggrdecl);
// The type is also ClassInfo for interfaces the actual TypeInfo for them
// is a TypeInfo_Interface instance that references __ClassZ in its "base"
// member.
Type *cinfoType = getClassInfoType();
DtoType(cinfoType);
IrTypeClass *tc = stripModifiers(cinfoType)->ctype->isClass();
assert(tc && "invalid ClassInfo type");
// classinfos cannot be constants since they're used as locks for
// synchronized
typeInfo = declareGlobal(aggrdecl->loc, gIR->module, tc->getMemoryLLType(),
irMangle, false);
// Generate some metadata on this ClassInfo if it's for a class.
if (!aggrdecl->isInterfaceDeclaration()) {
// regular TypeInfo metadata
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
// Gather information
LLType *type = DtoType(aggrdecl->type);
LLType *bodyType = llvm::cast<LLPointerType>(type)->getElementType();
bool hasDestructor = (aggrdecl->dtor != nullptr);
bool hasCustomDelete = false;
// Construct the fields
llvm::Metadata *mdVals[CD_NumFields];
mdVals[CD_BodyType] =
llvm::ConstantAsMetadata::get(llvm::UndefValue::get(bodyType));
mdVals[CD_Finalize] = llvm::ConstantAsMetadata::get(
LLConstantInt::get(LLType::getInt1Ty(gIR->context()), hasDestructor));
mdVals[CD_CustomDelete] =
llvm::ConstantAsMetadata::get(LLConstantInt::get(
LLType::getInt1Ty(gIR->context()), hasCustomDelete));
// Construct the metadata and insert it into the module.
const auto metaname = getMetadataName(CD_PREFIX, typeInfo);
llvm::NamedMDNode *node = gIR->module.getOrInsertNamedMetadata(metaname);
node->addOperand(llvm::MDNode::get(
gIR->context(), llvm::makeArrayRef(mdVals, CD_NumFields)));
}
} }
// create the ClassZ / InterfaceZ symbol if (define) {
const auto irMangle = getIRMangledClassInfoSymbolName(aggrdecl); auto init = getClassInfoInit();
if (!typeInfo->hasInitializer())
// The type is also ClassInfo for interfaces the actual TypeInfo for them defineGlobal(typeInfo, init, aggrdecl);
// is a TypeInfo_Interface instance that references __ClassZ in its "base"
// member.
Type *cinfoType = getClassInfoType();
DtoType(cinfoType);
IrTypeClass *tc = stripModifiers(cinfoType)->ctype->isClass();
assert(tc && "invalid ClassInfo type");
// classinfos cannot be constants since they're used as locks for synchronized
typeInfo = declareGlobal(aggrdecl->loc, gIR->module, tc->getMemoryLLType(),
irMangle, false);
// Generate some metadata on this ClassInfo if it's for a class.
if (!aggrdecl->isInterfaceDeclaration()) {
// regular TypeInfo metadata
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
// Gather information
LLType *type = DtoType(aggrdecl->type);
LLType *bodyType = llvm::cast<LLPointerType>(type)->getElementType();
bool hasDestructor = (aggrdecl->dtor != nullptr);
bool hasCustomDelete = false;
// Construct the fields
llvm::Metadata *mdVals[CD_NumFields];
mdVals[CD_BodyType] =
llvm::ConstantAsMetadata::get(llvm::UndefValue::get(bodyType));
mdVals[CD_Finalize] = llvm::ConstantAsMetadata::get(
LLConstantInt::get(LLType::getInt1Ty(gIR->context()), hasDestructor));
mdVals[CD_CustomDelete] = llvm::ConstantAsMetadata::get(
LLConstantInt::get(LLType::getInt1Ty(gIR->context()), hasCustomDelete));
// Construct the metadata and insert it into the module.
const auto metaname = getMetadataName(CD_PREFIX, typeInfo);
llvm::NamedMDNode *node = gIR->module.getOrInsertNamedMetadata(metaname);
node->addOperand(llvm::MDNode::get(
gIR->context(), llvm::makeArrayRef(mdVals, CD_NumFields)));
} }
return typeInfo; return typeInfo;

View file

@ -34,27 +34,31 @@ LLStructType* getTypeInfoStructMemType() {
} }
} }
LLGlobalVariable* IrStruct::getTypeInfoSymbol() { LLGlobalVariable* IrStruct::getTypeInfoSymbol(bool define) {
if (typeInfo) { if (!typeInfo) {
return typeInfo; OutBuffer mangledName;
mangledName.writestring("TypeInfo_S");
mangleToBuffer(aggrdecl, &mangledName);
const auto length = mangledName.length();
mangledName.prependstring(("_D" + std::to_string(length)).c_str());
mangledName.writestring("6__initZ");
const auto irMangle = getIRMangledVarName(mangledName.peekChars(), LINKd);
// We need to keep the symbol mutable as the type is not declared as
// immutable on the D side, and e.g. synchronized() can be used on the
// implicit monitor.
typeInfo = declareGlobal(aggrdecl->loc, gIR->module,
getTypeInfoStructMemType(), irMangle, false);
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
} }
OutBuffer mangledName; if (define) {
mangledName.writestring("TypeInfo_S"); auto init = getTypeInfoInit();
mangleToBuffer(aggrdecl, &mangledName); if (!typeInfo->hasInitializer())
const auto length = mangledName.length(); defineGlobal(typeInfo, init, aggrdecl);
mangledName.prependstring(("_D" + std::to_string(length)).c_str()); }
mangledName.writestring("6__initZ");
const auto irMangle = getIRMangledVarName(mangledName.peekChars(), LINKd);
// We need to keep the symbol mutable as the type is not declared as
// immutable on the D side, and e.g. synchronized() can be used on the
// implicit monitor.
typeInfo = declareGlobal(aggrdecl->loc, gIR->module,
getTypeInfoStructMemType(), irMangle, false);
emitTypeInfoMetadata(typeInfo, aggrdecl->type);
return typeInfo; return typeInfo;
} }