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 // The calling convention has to be recorded to distinguish
// extern(D) functions from extern(C++) ones. // extern(D) functions from extern(C++) ones.
DtoType(t); unsigned CC =
assert(t->ctype); getIrType(t, true)->getIrFuncTy().reverseParams ? DW_CC_D_dmd : 0;
unsigned CC = t->ctype->getIrFuncTy().reverseParams ? DW_CC_D_dmd : 0;
return DBuilder.createSubroutineType(paramsArray, DIFlags::FlagZero, CC); 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. // Look up field to index and any offset to apply.
unsigned fieldIndex; unsigned fieldIndex;
unsigned byteOffset; unsigned byteOffset;
assert(ad->type->ctype->isAggr()); auto irTypeAggr = getIrType(ad->type)->isAggr();
static_cast<IrTypeAggr *>(ad->type->ctype) assert(irTypeAggr);
->getMemberLocation(vd, fieldIndex, byteOffset); irTypeAggr->getMemberLocation(vd, fieldIndex, byteOffset);
LLValue *val = DtoGEP(src, 0, fieldIndex); LLValue *val = DtoGEP(src, 0, fieldIndex);
@ -1828,9 +1828,9 @@ LLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
unsigned getFieldGEPIndex(AggregateDeclaration *ad, VarDeclaration *vd) { unsigned getFieldGEPIndex(AggregateDeclaration *ad, VarDeclaration *vd) {
unsigned fieldIndex; unsigned fieldIndex;
unsigned byteOffset; unsigned byteOffset;
assert(ad->type->ctype->isAggr()); auto irTypeAggr = getIrType(ad->type)->isAggr();
static_cast<IrTypeAggr *>(ad->type->ctype) assert(irTypeAggr);
->getMemberLocation(vd, fieldIndex, byteOffset); irTypeAggr->getMemberLocation(vd, fieldIndex, byteOffset);
assert(byteOffset == 0 && "Cannot address field by a simple GEP."); assert(byteOffset == 0 && "Cannot address field by a simple GEP.");
return fieldIndex; return fieldIndex;
} }

View file

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

View file

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

View file

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

View file

@ -124,32 +124,16 @@ LLType *DtoType(Type *t) {
// aggregates // aggregates
case Tstruct: { case Tstruct: {
TypeStruct *ts = static_cast<TypeStruct *>(t); auto sd = static_cast<TypeStruct *>(t)->sym;
if (ts->sym->type->ty == Terror) if (sd->type->ty == Terror)
return getOpaqueErrorType(); return getOpaqueErrorType();
if (ts->sym->type->ctype) { return IrTypeStruct::get(sd)->getLLType();
// 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();
} }
case Tclass: { case Tclass: {
TypeClass *tc = static_cast<TypeClass *>(t); auto cd = static_cast<TypeClass *>(t)->sym;
if (tc->sym->type->ty == Terror) if (cd->type->ty == Terror)
return getOpaqueErrorType(); return getOpaqueErrorType();
if (tc->sym->type->ctype) { return IrTypeClass::get(cd)->getLLType();
// 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();
} }
// functions // functions
@ -182,9 +166,8 @@ LLType *DtoType(Type *t) {
case Taarray: case Taarray:
return getVoidPtrType(); return getVoidPtrType();
case Tvector: { case Tvector:
return IrTypeVector::get(t)->getLLType(); return IrTypeVector::get(t)->getLLType();
}
default: default:
llvm_unreachable("Unknown class of D Type!"); 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); b.push(cpp_ti);
auto wrapperType = llvm::cast<llvm::StructType>( auto wrapperType = llvm::cast<llvm::StructType>(
static_cast<IrTypeClass *>(cppTypeInfoPtrType->ctype) getIrType(cppTypeInfoPtrType)->isClass()->getMemoryLLType());
->getMemoryLLType());
auto wrapperInit = b.get_constant(wrapperType); auto wrapperInit = b.get_constant(wrapperType);
ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit, ci = defineGlobal(p.cd->loc, irs.module, wrapperMangle, wrapperInit,

View file

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

View file

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

View file

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

View file

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

View file

@ -182,6 +182,9 @@ public:
protected: protected:
/// ///
explicit IrTypeVector(Type *dt, llvm::Type *lt); 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) { 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(), IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(),
cd->loc.toChars()); cd->loc.toChars());
LOG_SCOPE; LOG_SCOPE;
const auto t = new IrTypeClass(cd);
getIrType(cd->type) = t;
IF_LOG Logger::println("Instance size: %u", cd->structsize); IF_LOG Logger::println("Instance size: %u", cd->structsize);
// This class may contain an align declaration. See GitHub #726. // 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_)) {} : IrType(dt, lt), irFty(std::move(irFty_)) {}
IrTypeFunction *IrTypeFunction::get(Type *dt) { IrTypeFunction *IrTypeFunction::get(Type *dt) {
assert(!dt->ctype); TypeFunction *tf = dt->isTypeFunction();
assert(dt->ty == Tfunction); assert(tf);
TypeFunction *tf = static_cast<TypeFunction *>(dt); auto &ctype = getIrType(tf);
assert(!ctype);
IrFuncTy irFty(tf); IrFuncTy irFty(tf);
llvm::Type *lt = DtoFunctionType(tf, irFty, nullptr, nullptr); llvm::Type *lt = DtoFunctionType(tf, irFty, nullptr, nullptr);
// Could have already built the type as part of a struct forward reference, // Could have already built the type as part of a struct forward reference,
// just as for pointers and arrays. // just as for pointers and arrays.
if (!dt->ctype) { if (!ctype) {
dt->ctype = new IrTypeFunction(dt, lt, irFty); 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_)) {} : IrType(dt, lt), irFty(std::move(irFty_)) {}
IrTypeDelegate *IrTypeDelegate::get(Type *t) { IrTypeDelegate *IrTypeDelegate::get(Type *t) {
assert(!t->ctype);
assert(t->ty == Tdelegate); 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); IrFuncTy irFty(tf);
llvm::Type *ltf = 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, // Could have already built the type as part of a struct forward reference,
// just as for pointers and arrays. // just as for pointers and arrays.
if (!t->ctype) { if (!ctype) {
t->ctype = new IrTypeDelegate(t, lt, irFty); 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 /// Resets special DCompute structs so they get re-created
/// with the proper address space when generating device code. /// with the proper address space when generating device code.
void IrTypeStruct::resetDComputeTypes() { void IrTypeStruct::resetDComputeTypes() {
for(auto&& irTypeStruct : dcomputeTypes) { for (auto irTypeStruct : dcomputeTypes) {
delete irTypeStruct->dtype->ctype; auto &ctype = getIrType(irTypeStruct->dtype);
irTypeStruct->dtype->ctype = nullptr; delete ctype;
ctype = nullptr;
} }
dcomputeTypes.clear(); dcomputeTypes.clear();
@ -46,13 +47,13 @@ void IrTypeStruct::resetDComputeTypes() {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
IrTypeStruct *IrTypeStruct::get(StructDeclaration *sd) { 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(), IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(),
sd->loc.toChars()); sd->loc.toChars());
LOG_SCOPE; 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 it's a forward declaration, all bets are off, stick with the opaque
if (sd->sizeok != SIZEOKdone) { if (sd->sizeok != SIZEOKdone) {
return t; return t;