mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 01:20:51 +03:00
Refactoring: Improve Ir{Aggr,Class,Struct} encapsulation
This commit is contained in:
parent
a765bf8901
commit
e9021fd6c8
6 changed files with 122 additions and 112 deletions
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
26
ir/iraggr.h
26
ir/iraggr.h
|
@ -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();
|
||||||
|
|
||||||
|
|
110
ir/irclass.cpp
110
ir/irclass.cpp
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue