Refactoring: Introduce getIrType()

As *the* way to access the IrType associated with a Type via its `ctype`
field. Most importantly, it makes sure all access is redirected to the
*unqualified* type's `ctype`, which allows to get rid of the 'multiple
types' workaround for aggregates in DtoType(). Those were e.g. hit for
`shared struct SpinLock`, where the struct's type includes the `shared`
modifier...
This commit is contained in:
Martin Kinkelin 2020-09-27 22:16:57 +02:00
parent ab2ae5e0a2
commit 3f716ff75e
15 changed files with 117 additions and 115 deletions

View file

@ -761,9 +761,8 @@ DISubroutineType DIBuilder::CreateFunctionType(Type *type) {
// The calling convention has to be recorded to distinguish
// extern(D) functions from extern(C++) ones.
DtoType(t);
assert(t->ctype);
unsigned CC = t->ctype->getIrFuncTy().reverseParams ? DW_CC_D_dmd : 0;
unsigned CC =
getIrType(t, true)->getIrFuncTy().reverseParams ? DW_CC_D_dmd : 0;
return DBuilder.createSubroutineType(paramsArray, DIFlags::FlagZero, CC);
}

View file

@ -1806,9 +1806,9 @@ LLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
// Look up field to index and any offset to apply.
unsigned fieldIndex;
unsigned byteOffset;
assert(ad->type->ctype->isAggr());
static_cast<IrTypeAggr *>(ad->type->ctype)
->getMemberLocation(vd, fieldIndex, byteOffset);
auto irTypeAggr = getIrType(ad->type)->isAggr();
assert(irTypeAggr);
irTypeAggr->getMemberLocation(vd, fieldIndex, byteOffset);
LLValue *val = DtoGEP(src, 0, fieldIndex);
@ -1828,9 +1828,9 @@ LLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
unsigned getFieldGEPIndex(AggregateDeclaration *ad, VarDeclaration *vd) {
unsigned fieldIndex;
unsigned byteOffset;
assert(ad->type->ctype->isAggr());
static_cast<IrTypeAggr *>(ad->type->ctype)
->getMemberLocation(vd, fieldIndex, byteOffset);
auto irTypeAggr = getIrType(ad->type)->isAggr();
assert(irTypeAggr);
irTypeAggr->getMemberLocation(vd, fieldIndex, byteOffset);
assert(byteOffset == 0 && "Cannot address field by a simple GEP.");
return fieldIndex;
}

View file

@ -258,9 +258,8 @@ struct LazyFunctionDeclarer {
// the call to DtoType performs many actions such as rewriting the function
// type and storing it in dty
auto llfunctype = llvm::cast<llvm::FunctionType>(DtoType(dty));
assert(dty->ctype);
auto attrs =
dty->ctype->getIrFuncTy().getParamAttrs(gABI->passThisBeforeSret(dty));
auto attrs = getIrType(dty)->getIrFuncTy().getParamAttrs(
gABI->passThisBeforeSret(dty));
attrs.merge(attributes);
for (auto fname : mangledFunctionNames) {

View file

@ -40,10 +40,7 @@ IrFuncTy &DtoIrTypeFunction(DValue *fnval) {
}
}
Type *type = stripModifiers(fnval->type->toBasetype());
DtoType(type);
assert(type->ctype);
return type->ctype->getIrFuncTy();
return getIrType(fnval->type->toBasetype(), true)->getIrFuncTy();
}
TypeFunction *DtoTypeFunction(DValue *fnval) {

View file

@ -289,7 +289,7 @@ public:
static_cast<TypeClass *>(tb)->sym->isInterfaceDeclaration()) {
assert(it->isBaseOf(cd, NULL));
IrTypeClass *typeclass = cd->type->ctype->isClass();
IrTypeClass *typeclass = getIrType(cd->type)->isClass();
// find interface impl
size_t i_index = typeclass->getInterfaceIndex(it);
@ -565,7 +565,7 @@ public:
IF_LOG Logger::cout() << "Using existing global: " << *result << '\n';
} else {
auto globalVar = new llvm::GlobalVariable(
p->module, origClass->type->ctype->isClass()->getMemoryLLType(),
p->module, getIrType(origClass->type)->isClass()->getMemoryLLType(),
false, llvm::GlobalValue::InternalLinkage, nullptr, ".classref");
p->setStructLiteralConstant(value, globalVar);
@ -615,10 +615,9 @@ public:
if (InterfaceDeclaration *it = targetClass->isInterfaceDeclaration()) {
assert(it->isBaseOf(origClass, NULL));
IrTypeClass *typeclass = origClass->type->ctype->isClass();
// find interface impl
size_t i_index = typeclass->getInterfaceIndex(it);
size_t i_index =
getIrType(origClass->type)->isClass()->getInterfaceIndex(it);
assert(i_index != ~0UL);
// offset pointer

View file

@ -124,32 +124,16 @@ LLType *DtoType(Type *t) {
// aggregates
case Tstruct: {
TypeStruct *ts = static_cast<TypeStruct *>(t);
if (ts->sym->type->ty == Terror)
auto sd = static_cast<TypeStruct *>(t)->sym;
if (sd->type->ty == Terror)
return getOpaqueErrorType();
if (ts->sym->type->ctype) {
// This should not happen, but the frontend seems to be buggy. Not
// sure if this is the best way to handle the situation, but we
// certainly don't want to override ts->sym->type->ctype.
IF_LOG Logger::cout()
<< "Struct with multiple Types detected: " << ts->toChars() << " ("
<< ts->sym->locToChars() << ")" << std::endl;
return ts->sym->type->ctype->getLLType();
}
return IrTypeStruct::get(ts->sym)->getLLType();
return IrTypeStruct::get(sd)->getLLType();
}
case Tclass: {
TypeClass *tc = static_cast<TypeClass *>(t);
if (tc->sym->type->ty == Terror)
auto cd = static_cast<TypeClass *>(t)->sym;
if (cd->type->ty == Terror)
return getOpaqueErrorType();
if (tc->sym->type->ctype) {
// See Tstruct case.
IF_LOG Logger::cout()
<< "Class with multiple Types detected: " << tc->toChars() << " ("
<< tc->sym->locToChars() << ")" << std::endl;
return tc->sym->type->ctype->getLLType();
}
return IrTypeClass::get(tc->sym)->getLLType();
return IrTypeClass::get(cd)->getLLType();
}
// functions
@ -182,9 +166,8 @@ LLType *DtoType(Type *t) {
case Taarray:
return getVoidPtrType();
case Tvector: {
case Tvector:
return IrTypeVector::get(t)->getLLType();
}
default:
llvm_unreachable("Unknown class of D Type!");

View file

@ -179,8 +179,7 @@ void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
b.push(cpp_ti);
auto wrapperType = llvm::cast<llvm::StructType>(
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype)
->getMemoryLLType());
getIrType(cppTypeInfoPtrType)->isClass()->getMemoryLLType());
auto wrapperInit = b.get_constant(wrapperType);
ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit,

View file

@ -35,7 +35,7 @@ llvm::StructType *IrAggr::getLLStructType() {
return llStructType;
LLType *llType = DtoType(type);
if (auto irClassType = type->ctype->isClass())
if (auto irClassType = getIrType(type)->isClass())
llType = irClassType->getMemoryLLType();
llStructType = llvm::dyn_cast<LLStructType>(llType);
@ -223,7 +223,7 @@ IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) {
}
// build constant
const bool isPacked = static_cast<IrTypeAggr *>(type->ctype)->packed;
const bool isPacked = getIrType(type)->isAggr()->packed;
LLStructType *llType =
isCompatible ? llStructType
: LLStructType::get(gIR->context(), types, isPacked);

View file

@ -45,7 +45,7 @@ IrClass::IrClass(ClassDeclaration *cd) : IrAggr(cd) {
addInterfaceVtbls(cd);
assert(interfacesWithVtbls.size() ==
stripModifiers(type)->ctype->isClass()->getNumInterfaceVtbls() &&
getIrType(type)->isClass()->getNumInterfaceVtbls() &&
"inconsistent number of interface vtables in this class");
}
@ -67,7 +67,7 @@ LLGlobalVariable *IrClass::getVtblSymbol(bool define) {
if (!vtbl) {
const auto irMangle = getIRMangledVTableSymbolName(aggrdecl);
LLType *vtblTy = stripModifiers(type)->ctype->isClass()->getVtblType();
LLType *vtblTy = getIrType(type)->isClass()->getVtblType();
vtbl = declareGlobal(aggrdecl->loc, gIR->module, vtblTy, irMangle,
/*isConstant=*/true);
@ -91,9 +91,7 @@ LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) {
// 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();
IrTypeClass *tc = getIrType(getClassInfoType(), true)->isClass();
assert(tc && "invalid ClassInfo type");
// We need to keep the symbol mutable as the type is not declared as
@ -152,7 +150,7 @@ LLGlobalVariable *IrClass::getInterfaceArraySymbol() {
ClassDeclaration *cd = aggrdecl->isClassDeclaration();
size_t n = stripModifiers(type)->ctype->isClass()->getNumInterfaceVtbls();
size_t n = getIrType(type)->isClass()->getNumInterfaceVtbls();
assert(n > 0 && "getting ClassInfo.interfaces storage symbol, but we "
"don't implement any interfaces");
@ -657,7 +655,7 @@ LLConstant *IrClass::getInterfaceVtblInit(BaseClass *b,
void IrClass::defineInterfaceVtbls() {
const size_t n = interfacesWithVtbls.size();
assert(n == stripModifiers(type)->ctype->isClass()->getNumInterfaceVtbls() &&
assert(n == getIrType(type)->isClass()->getNumInterfaceVtbls() &&
"inconsistent number of interface vtables in this class");
for (size_t i = 0; i < n; ++i) {
@ -676,7 +674,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
assert(cd);
size_t n = interfacesWithVtbls.size();
assert(stripModifiers(type)->ctype->isClass()->getNumInterfaceVtbls() == n &&
assert(getIrType(type)->isClass()->getNumInterfaceVtbls() == n &&
"inconsistent number of interface vtables in this class");
Type *interfacesArrayType = getInterfacesArrayType();
@ -710,7 +708,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
IrClass *irinter = getIrAggr(it->sym);
assert(irinter && "interface has null IrStruct");
IrTypeClass *itc = stripModifiers(irinter->type)->ctype->isClass();
IrTypeClass *itc = getIrType(irinter->type)->isClass();
assert(itc && "null interface IrTypeClass");
// classinfo

View file

@ -26,8 +26,7 @@
namespace {
LLStructType* getTypeInfoStructMemType() {
Type *t = getStructTypeInfoType();
DtoType(t);
IrTypeClass *tc = t->ctype->isClass();
IrTypeClass *tc = getIrType(t, true)->isClass();
assert(tc && "invalid TypeInfo_Struct type");
return llvm::cast<LLStructType>(tc->getMemoryLLType());

View file

@ -24,7 +24,7 @@
IrType::IrType(Type *dt, LLType *lt) : dtype(dt), type(lt) {
assert(dt && "null D Type");
assert(lt && "null LLVM Type");
assert(!dt->ctype && "already has IrType");
assert(!getIrType(dt) && "already has IrType");
}
IrFuncTy &IrType::getIrFuncTy() {
@ -37,7 +37,7 @@ IrTypeBasic::IrTypeBasic(Type *dt) : IrType(dt, basic2llvm(dt)) {}
IrTypeBasic *IrTypeBasic::get(Type *dt) {
auto t = new IrTypeBasic(dt);
dt->ctype = t;
getIrType(dt) = t;
return t;
}
@ -136,9 +136,11 @@ llvm::Type *IrTypeBasic::basic2llvm(Type *t) {
IrTypePointer::IrTypePointer(Type *dt, LLType *lt) : IrType(dt, lt) {}
IrTypePointer *IrTypePointer::get(Type *dt) {
assert(!dt->ctype);
assert((dt->ty == Tpointer || dt->ty == Tnull) && "not pointer/null type");
auto &ctype = getIrType(dt);
assert(!ctype);
LLType *elemType;
if (dt->ty == Tnull) {
elemType = llvm::Type::getInt8Ty(getGlobalContext());
@ -147,13 +149,13 @@ IrTypePointer *IrTypePointer::get(Type *dt) {
// DtoType could have already created the same type, e.g. for
// dt == Node* in struct Node { Node* n; }.
if (dt->ctype) {
return dt->ctype->isPointer();
if (ctype) {
return ctype->isPointer();
}
}
auto t = new IrTypePointer(dt, llvm::PointerType::get(elemType, 0));
dt->ctype = t;
ctype = t;
return t;
}
@ -162,20 +164,22 @@ IrTypePointer *IrTypePointer::get(Type *dt) {
IrTypeSArray::IrTypeSArray(Type *dt, LLType *lt) : IrType(dt, lt) {}
IrTypeSArray *IrTypeSArray::get(Type *dt) {
assert(!dt->ctype);
assert(dt->ty == Tsarray && "not static array type");
auto &ctype = getIrType(dt);
assert(!ctype);
LLType *elemType = DtoMemType(dt->nextOf());
// We might have already built the type during DtoMemType e.g. as part of a
// forward reference in a struct.
if (!dt->ctype) {
if (!ctype) {
TypeSArray *tsa = static_cast<TypeSArray *>(dt);
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
dt->ctype = new IrTypeSArray(dt, llvm::ArrayType::get(elemType, dim));
ctype = new IrTypeSArray(dt, llvm::ArrayType::get(elemType, dim));
}
return dt->ctype->isSArray();
return ctype->isSArray();
}
//////////////////////////////////////////////////////////////////////////////
@ -183,20 +187,22 @@ IrTypeSArray *IrTypeSArray::get(Type *dt) {
IrTypeArray::IrTypeArray(Type *dt, LLType *lt) : IrType(dt, lt) {}
IrTypeArray *IrTypeArray::get(Type *dt) {
assert(!dt->ctype);
assert(dt->ty == Tarray && "not dynamic array type");
auto &ctype = getIrType(dt);
assert(!ctype);
LLType *elemType = DtoMemType(dt->nextOf());
// Could have already built the type as part of a struct forward reference,
// just as for pointers.
if (!dt->ctype) {
if (!ctype) {
llvm::Type *types[] = {DtoSize_t(), llvm::PointerType::get(elemType, 0)};
LLType *at = llvm::StructType::get(getGlobalContext(), types, false);
dt->ctype = new IrTypeArray(dt, at);
ctype = new IrTypeArray(dt, at);
}
return dt->ctype->isArray();
return ctype->isArray();
}
//////////////////////////////////////////////////////////////////////////////
@ -204,26 +210,40 @@ IrTypeArray *IrTypeArray::get(Type *dt) {
IrTypeVector::IrTypeVector(Type *dt, llvm::Type *lt) : IrType(dt, lt) {}
IrTypeVector *IrTypeVector::get(Type *dt) {
LLType *lt = vector2llvm(dt);
TypeVector *tv = dt->isTypeVector();
assert(tv && "not vector type");
auto &ctype = getIrType(dt);
assert(!ctype);
TypeSArray *tsa = tv->basetype->isTypeSArray();
assert(tsa);
LLType *elemType = DtoMemType(tsa->next);
// Could have already built the type as part of a struct forward reference,
// just as for pointers and arrays.
if (!dt->ctype) {
dt->ctype = new IrTypeVector(dt, lt);
}
return dt->ctype->isVector();
}
llvm::Type *IrTypeVector::vector2llvm(Type *dt) {
assert(dt->ty == Tvector && "not vector type");
TypeVector *tv = static_cast<TypeVector *>(dt);
assert(tv->basetype->ty == Tsarray);
TypeSArray *tsa = static_cast<TypeSArray *>(tv->basetype);
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
LLType *elemType = DtoMemType(tsa->next);
return llvm::VectorType::get(elemType, dim
if (!ctype) {
LLType *lt = llvm::VectorType::get(elemType, tsa->dim->toUInteger()
#if LDC_LLVM_VER >= 1100
,
/*Scalable=*/false
#endif
);
ctype = new IrTypeVector(dt, lt);
}
return ctype->isVector();
}
//////////////////////////////////////////////////////////////////////////////
IrType *&getIrType(Type *t, bool create) {
t = stripModifiers(t);
if (create) {
DtoType(t);
assert(t->ctype);
}
return t->ctype;
}

View file

@ -182,6 +182,9 @@ public:
protected:
///
explicit IrTypeVector(Type *dt, llvm::Type *lt);
static llvm::Type *vector2llvm(Type *dt);
};
//////////////////////////////////////////////////////////////////////////////
/// Returns a reference to the IrType* associated with the specified D type.
IrType *&getIrType(Type *t, bool create = false);

View file

@ -60,12 +60,13 @@ void IrTypeClass::addClassData(AggrTypeBuilder &builder,
}
IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) {
const auto t = new IrTypeClass(cd);
cd->type->ctype = t;
IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(),
cd->loc.toChars());
LOG_SCOPE;
const auto t = new IrTypeClass(cd);
getIrType(cd->type) = t;
IF_LOG Logger::println("Instance size: %u", cd->structsize);
// This class may contain an align declaration. See GitHub #726.

View file

@ -19,20 +19,22 @@ IrTypeFunction::IrTypeFunction(Type *dt, llvm::Type *lt, IrFuncTy irFty_)
: IrType(dt, lt), irFty(std::move(irFty_)) {}
IrTypeFunction *IrTypeFunction::get(Type *dt) {
assert(!dt->ctype);
assert(dt->ty == Tfunction);
TypeFunction *tf = dt->isTypeFunction();
assert(tf);
TypeFunction *tf = static_cast<TypeFunction *>(dt);
auto &ctype = getIrType(tf);
assert(!ctype);
IrFuncTy irFty(tf);
llvm::Type *lt = DtoFunctionType(tf, irFty, nullptr, nullptr);
// Could have already built the type as part of a struct forward reference,
// just as for pointers and arrays.
if (!dt->ctype) {
dt->ctype = new IrTypeFunction(dt, lt, irFty);
if (!ctype) {
ctype = new IrTypeFunction(dt, lt, irFty);
}
return dt->ctype->isFunction();
return ctype->isFunction();
}
//////////////////////////////////////////////////////////////////////////////
@ -41,11 +43,12 @@ IrTypeDelegate::IrTypeDelegate(Type *dt, llvm::Type *lt, IrFuncTy irFty_)
: IrType(dt, lt), irFty(std::move(irFty_)) {}
IrTypeDelegate *IrTypeDelegate::get(Type *t) {
assert(!t->ctype);
assert(t->ty == Tdelegate);
assert(t->nextOf()->ty == Tfunction);
TypeFunction *tf = t->nextOf()->isTypeFunction();
assert(tf);
TypeFunction *tf = static_cast<TypeFunction *>(t->nextOf());
auto &ctype = getIrType(t);
assert(!ctype);
IrFuncTy irFty(tf);
llvm::Type *ltf =
@ -55,8 +58,9 @@ IrTypeDelegate *IrTypeDelegate::get(Type *t) {
// Could have already built the type as part of a struct forward reference,
// just as for pointers and arrays.
if (!t->ctype) {
t->ctype = new IrTypeDelegate(t, lt, irFty);
if (!ctype) {
ctype = new IrTypeDelegate(t, lt, irFty);
}
return t->ctype->isDelegate();
return ctype->isDelegate();
}

View file

@ -30,14 +30,15 @@ IrTypeStruct::IrTypeStruct(StructDeclaration *sd)
//////////////////////////////////////////////////////////////////////////////
std::vector<IrTypeStruct*> IrTypeStruct::dcomputeTypes;
std::vector<IrTypeStruct *> IrTypeStruct::dcomputeTypes;
/// Resets special DCompute structs so they get re-created
/// with the proper address space when generating device code.
void IrTypeStruct::resetDComputeTypes() {
for(auto&& irTypeStruct : dcomputeTypes) {
delete irTypeStruct->dtype->ctype;
irTypeStruct->dtype->ctype = nullptr;
for (auto irTypeStruct : dcomputeTypes) {
auto &ctype = getIrType(irTypeStruct->dtype);
delete ctype;
ctype = nullptr;
}
dcomputeTypes.clear();
@ -46,13 +47,13 @@ void IrTypeStruct::resetDComputeTypes() {
//////////////////////////////////////////////////////////////////////////////
IrTypeStruct *IrTypeStruct::get(StructDeclaration *sd) {
auto t = new IrTypeStruct(sd);
sd->type->ctype = t;
IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(),
sd->loc.toChars());
LOG_SCOPE;
auto t = new IrTypeStruct(sd);
getIrType(sd->type) = t;
// if it's a forward declaration, all bets are off, stick with the opaque
if (sd->sizeok != SIZEOKdone) {
return t;