Refactored IrType construction to use static get() method.

This also allows us to enable the assert in IrType::IrType.

Unfortunately, this is mostly a "peace of mind" commit, there
doesn't seem to have been a bug actually caused by the transitory
duplicate IrTypePointer/IrTypeStruct instances.

The remaining xyz2llvm static methods are not exactly pretty,
they should probably just be folded into get.
This commit is contained in:
David Nadlinger
2012-12-20 21:30:29 +01:00
parent 464c695814
commit a3a511ca55
9 changed files with 170 additions and 156 deletions

View File

@@ -113,55 +113,65 @@ LLType* DtoType(Type* t)
case Twchar:
case Tdchar:
{
t->irtype = new IrTypeBasic(t);
return t->irtype->buildType();
return IrTypeBasic::get(t)->getLLType();
}
// pointers
case Tnull:
case Tpointer:
{
t->irtype = new IrTypePointer(t);
return t->irtype->buildType();
return IrTypePointer::get(t)->getLLType();
}
// arrays
case Tarray:
{
t->irtype = new IrTypeArray(t);
return t->irtype->buildType();
return IrTypeArray::get(t)->getLLType();
}
case Tsarray:
{
t->irtype = new IrTypeSArray(t);
return t->irtype->buildType();
return IrTypeSArray::get(t)->getLLType();
}
// aggregates
case Tstruct: {
case Tstruct:
{
TypeStruct* ts = static_cast<TypeStruct*>(t);
t->irtype = new IrTypeStruct(ts->sym);
return t->irtype->buildType();
if (ts->sym->type->irtype)
{
// 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->irtype.
IF_LOG Logger::cout() << "Struct with multiple Types detected: " <<
ts->toChars() << " (" << ts->sym->locToChars() << ")" << std::endl;
return ts->sym->type->irtype->getLLType();
}
return IrTypeStruct::get(ts->sym)->getLLType();
}
case Tclass: {
case Tclass:
{
TypeClass* tc = static_cast<TypeClass*>(t);
t->irtype = new IrTypeClass(tc->sym);
return t->irtype->buildType();
if (tc->sym->type->irtype)
{
// See Tstruct case.
IF_LOG Logger::cout() << "Class with multiple Types detected: " <<
tc->toChars() << " (" << tc->sym->locToChars() << ")" << std::endl;
return tc->sym->type->irtype->getLLType();
}
return IrTypeClass::get(tc->sym)->getLLType();
}
// functions
case Tfunction:
{
t->irtype = new IrTypeFunction(t);
return t->irtype->buildType();
return IrTypeFunction::get(t)->getLLType();
}
// delegates
case Tdelegate:
{
t->irtype = new IrTypeDelegate(t);
return t->irtype->buildType();
return IrTypeDelegate::get(t)->getLLType();
}
// typedefs
@@ -183,8 +193,7 @@ LLType* DtoType(Type* t)
#if DMDV2
case Tvector:
{
t->irtype = new IrTypeVector(t);
return t->irtype->buildType();
return IrTypeVector::get(t)->getLLType();
}
#endif

View File

@@ -13,6 +13,7 @@
#include "mtype.h"
#include "gen/irstate.h"
#include "gen/logger.h"
#include "gen/tollvm.h"
#include "ir/irtype.h"
// This code uses llvm::getGlobalContext() as these functions are invoked before gIR is set.
@@ -20,21 +21,13 @@
//////////////////////////////////////////////////////////////////////////////
extern LLType* DtoType(Type* dt);
extern LLIntegerType* DtoSize_t();
//////////////////////////////////////////////////////////////////////////////
IrType::IrType(Type* dt, LLType* lt)
: dtype(dt),
type(lt)
{
assert(dt && "null D Type");
assert(lt && "null LLVM Type");
#if 0
// FIXME: For some reason the assert fails
assert(dt->irtype == NULL && "already has IrType");
#endif
assert(!dt->irtype && "already has IrType");
}
//////////////////////////////////////////////////////////////////////////////
@@ -48,9 +41,11 @@ IrTypeBasic::IrTypeBasic(Type * dt)
//////////////////////////////////////////////////////////////////////////////
llvm::Type * IrTypeBasic::buildType()
IrTypeBasic* IrTypeBasic::get(Type* dt)
{
return type;
IrTypeBasic* t = new IrTypeBasic(dt);
dt->irtype = t;
return t;
}
//////////////////////////////////////////////////////////////////////////////
@@ -145,35 +140,36 @@ llvm::Type * IrTypeBasic::basic2llvm(Type* t)
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
IrTypePointer::IrTypePointer(Type * dt)
: IrType(dt, dt->ty == Tnull ? null2llvm(dt) : pointer2llvm(dt))
IrTypePointer::IrTypePointer(Type* dt, LLType* lt)
: IrType(dt, lt)
{
}
//////////////////////////////////////////////////////////////////////////////
llvm::Type * IrTypePointer::buildType()
IrTypePointer* IrTypePointer::get(Type* dt)
{
return type;
}
assert(!dt->irtype);
assert((dt->ty == Tpointer || dt->ty == Tnull) && "not pointer/null type");
//////////////////////////////////////////////////////////////////////////////
llvm::Type * IrTypePointer::pointer2llvm(Type * dt)
{
assert(dt->ty == Tpointer && "not pointer type");
LLType* elemType = DtoType(dt->nextOf());
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
LLType* elemType;
if (dt->ty == Tnull)
{
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
return llvm::PointerType::get(elemType, 0);
}
}
else
{
elemType = DtoTypeNotVoid(dt->nextOf());
llvm::Type* IrTypePointer::null2llvm(Type* dt)
{
assert(dt->ty == Tnull && "not null type");
LLType* elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
return llvm::PointerType::get(elemType, 0);
// DtoTypeNotVoid could have already created the same type, e.g. for
// dt == Node* in struct Node { Node* n; }.
if (dt->irtype)
return dt->irtype->isPointer();
}
IrTypePointer* t = new IrTypePointer(dt, llvm::PointerType::get(elemType, 0));
dt->irtype = t;
return t;
}
//////////////////////////////////////////////////////////////////////////////
@@ -187,9 +183,11 @@ IrTypeSArray::IrTypeSArray(Type * dt)
//////////////////////////////////////////////////////////////////////////////
llvm::Type * IrTypeSArray::buildType()
IrTypeSArray* IrTypeSArray::get(Type* dt)
{
return type;
IrTypeSArray* t = new IrTypeSArray(dt);
dt->irtype = t;
return t;
}
//////////////////////////////////////////////////////////////////////////////
@@ -198,7 +196,7 @@ llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
{
assert(t->ty == Tsarray && "not static array type");
TypeSArray* tsa = static_cast<TypeSArray*>(t);
dim = static_cast<uint64_t>(tsa->dim->toUInteger());
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
LLType* elemType = DtoType(t->nextOf());
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
@@ -216,9 +214,11 @@ IrTypeArray::IrTypeArray(Type * dt)
//////////////////////////////////////////////////////////////////////////////
llvm::Type * IrTypeArray::buildType()
IrTypeArray* IrTypeArray::get(Type* dt)
{
return type;
IrTypeArray* t = new IrTypeArray(dt);
dt->irtype = t;
return t;
}
//////////////////////////////////////////////////////////////////////////////
@@ -255,9 +255,11 @@ IrTypeVector::IrTypeVector(Type* dt)
//////////////////////////////////////////////////////////////////////////////
llvm::Type* IrTypeVector::buildType()
IrTypeVector* IrTypeVector::get(Type* dt)
{
return type;
IrTypeVector* t = new IrTypeVector(dt);
dt->irtype = t;
return t;
}
//////////////////////////////////////////////////////////////////////////////
@@ -268,7 +270,7 @@ llvm::Type* IrTypeVector::vector2llvm(Type* dt)
TypeVector* tv = static_cast<TypeVector*>(dt);
assert(tv->basetype->ty == Tsarray);
TypeSArray* tsa = static_cast<TypeSArray*>(tv->basetype);
dim = static_cast<uint64_t>(tsa->dim->toUInteger());
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
LLType* elemType = DtoType(tsa->next);
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());

View File

@@ -8,8 +8,7 @@
//===----------------------------------------------------------------------===//
//
// The types derived from IrType are used to attach LLVM type information and
// other codegen metadata (e.g. for vtbl resolution) to frontend Types. There
// is an 1:1 correspondence between Type and IrType instances.
// other codegen metadata (e.g. for vtbl resolution) to frontend Types.
//
//===----------------------------------------------------------------------===//
@@ -40,13 +39,17 @@ class IrTypeVector;
//////////////////////////////////////////////////////////////////////////////
/// Base class for IrTypeS.
/// Code generation state/metadata for D types. The mapping from IrType to
/// Type is injective but not surjective.
///
/// Derived classes should be created using their static get() methods, which
/// makes sure that uniqueness is preserved in the face of forward references.
/// Note that the get() methods expect the IrType of the passed type/symbol to
/// be not yet set. This could be altered to just return the existing IrType
/// in order to bring the API entirely in line with the LLVM type get() methods.
class IrType
{
public:
///
IrType(Type* dt, llvm::Type* lt);
///
virtual IrTypeAggr* isAggr() { return NULL; }
///
@@ -75,10 +78,10 @@ public:
///
virtual llvm::Type* getLLType() { return type; }
///
virtual llvm::Type* buildType() = 0;
protected:
///
IrType(Type* dt, llvm::Type* lt);
///
Type* dtype;
@@ -93,19 +96,18 @@ class IrTypeBasic : public IrType
{
public:
///
IrTypeBasic(Type* dt);
static IrTypeBasic* get(Type* dt);
///
IrTypeBasic* isBasic() { return this; }
///
llvm::Type* buildType();
protected:
///
LLType* getComplexType(llvm::LLVMContext& ctx, LLType* type);
IrTypeBasic(Type* dt);
///
llvm::Type* basic2llvm(Type* t);
static LLType* getComplexType(llvm::LLVMContext& ctx, LLType* type);
///
static llvm::Type* basic2llvm(Type* t);
};
//////////////////////////////////////////////////////////////////////////////
@@ -115,19 +117,14 @@ class IrTypePointer : public IrType
{
public:
///
IrTypePointer(Type* dt);
static IrTypePointer* get(Type* dt);
///
IrTypePointer* isPointer() { return this; }
///
llvm::Type* buildType();
protected:
///
llvm::Type* pointer2llvm(Type* t);
///
llvm::Type* null2llvm(Type* t);
IrTypePointer(Type* dt, LLType *lt);
};
//////////////////////////////////////////////////////////////////////////////
@@ -137,20 +134,17 @@ class IrTypeSArray : public IrType
{
public:
///
IrTypeSArray(Type* dt);
static IrTypeSArray* get(Type* dt);
///
IrTypeSArray* isSArray() { return this; }
///
llvm::Type* buildType();
protected:
///
llvm::Type* sarray2llvm(Type* t);
IrTypeSArray(Type* dt);
/// Dimension.
uint64_t dim;
///
static llvm::Type* sarray2llvm(Type* t);
};
//////////////////////////////////////////////////////////////////////////////
@@ -160,17 +154,16 @@ class IrTypeArray : public IrType
{
public:
///
IrTypeArray(Type* dt);
static IrTypeArray* get(Type* dt);
///
IrTypeArray* isArray() { return this; }
///
llvm::Type* buildType();
protected:
///
llvm::Type* array2llvm(Type* t);
IrTypeArray(Type* dt);
///
static llvm::Type* array2llvm(Type* t);
};
//////////////////////////////////////////////////////////////////////////////
@@ -181,17 +174,16 @@ class IrTypeVector : public IrType
{
public:
///
IrTypeVector(Type* dt);
static IrTypeVector* get(Type* dt);
///
IrTypeVector* isVector() { return this; }
///
llvm::Type* buildType();
protected:
llvm::Type* vector2llvm(Type* dt);
/// Dimension.
uint64_t dim;
///
IrTypeVector(Type* dt);
static llvm::Type* vector2llvm(Type* dt);
};
#endif

View File

@@ -222,8 +222,11 @@ void IrTypeClass::addBaseClassData(
//////////////////////////////////////////////////////////////////////////////
llvm::Type* IrTypeClass::buildType()
IrTypeClass* IrTypeClass::get(ClassDeclaration* cd)
{
IrTypeClass* t = new IrTypeClass(cd);
cd->type->irtype = t;
IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->loc.toChars());
LOG_SCOPE;
IF_LOG Logger::println("Instance size: %u", cd->structsize);
@@ -235,12 +238,12 @@ llvm::Type* IrTypeClass::buildType()
defaultTypes.reserve(32);
// add vtbl
defaultTypes.push_back(llvm::PointerType::get(vtbl_type, 0));
defaultTypes.push_back(llvm::PointerType::get(t->vtbl_type, 0));
// interfaces are just a vtable
if (cd->isInterfaceDeclaration())
{
num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->dim : 0;
t->num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->dim : 0;
}
// classes have monitor and fields
else
@@ -253,7 +256,7 @@ llvm::Type* IrTypeClass::buildType()
size_t field_index = 2;
// add data members recursively
addBaseClassData(defaultTypes, cd, offset, field_index);
t->addBaseClassData(defaultTypes, cd, offset, field_index);
#if 1
// tail padding?
@@ -270,16 +273,16 @@ llvm::Type* IrTypeClass::buildType()
fatal();
// set struct body
isaStruct(type)->setBody(defaultTypes, false);
isaStruct(t->type)->setBody(defaultTypes, false);
// VTBL
// set vtbl type body
vtbl_type->setBody(buildVtblType(ClassDeclaration::classinfo->type, &cd->vtbl));
t->vtbl_type->setBody(t->buildVtblType(ClassDeclaration::classinfo->type, &cd->vtbl));
IF_LOG Logger::cout() << "class type: " << *type << std::endl;
IF_LOG Logger::cout() << "class type: " << *t->type << std::endl;
return getLLType();
return t;
}
//////////////////////////////////////////////////////////////////////////////

View File

@@ -22,14 +22,11 @@ class IrTypeClass : public IrTypeAggr
{
public:
///
IrTypeClass(ClassDeclaration* cd);
static IrTypeClass* get(ClassDeclaration* cd);
///
virtual IrTypeClass* isClass() { return this; }
///
llvm::Type* buildType();
///
llvm::Type* getLLType();
@@ -53,6 +50,9 @@ public:
unsigned getNumInterfaceVtbls() { return num_interface_vtbls; }
protected:
///
IrTypeClass(ClassDeclaration* cd);
///
ClassDeclaration* cd;
///

View File

@@ -16,47 +16,51 @@
#include "ir/irtypefunction.h"
IrTypeFunction::IrTypeFunction(Type* dt)
: IrType(dt, func2llvm(dt))
IrTypeFunction::IrTypeFunction(Type* dt, LLType* lt)
: IrType(dt, lt)
{
irfty = NULL;
}
llvm::Type * IrTypeFunction::buildType()
IrTypeFunction* IrTypeFunction::get(Type* dt)
{
return type;
}
assert(dt->ty == Tfunction);
llvm::Type* IrTypeFunction::func2llvm(Type* dt)
{
llvm::Type* T;
// We can't get cycles here, but we can end up building the type as part of
// a class vtbl, ...
llvm::Type* lt;
TypeFunction* tf = static_cast<TypeFunction*>(dt);
if (tf->funcdecl)
T = DtoFunctionType(tf->funcdecl);
lt = DtoFunctionType(tf->funcdecl);
else
T = DtoFunctionType(tf,NULL,NULL);
return T;
lt = DtoFunctionType(tf,NULL,NULL);
if (!dt->irtype)
dt->irtype = new IrTypeFunction(dt, lt);
return dt->irtype->isFunction();
}
//////////////////////////////////////////////////////////////////////////////
IrTypeDelegate::IrTypeDelegate(Type * dt)
: IrType(dt, delegate2llvm(dt))
IrTypeDelegate::IrTypeDelegate(Type * dt, LLType* lt)
: IrType(dt, lt)
{
}
llvm::Type* IrTypeDelegate::buildType()
{
return type;
}
llvm::Type* IrTypeDelegate::delegate2llvm(Type* dt)
IrTypeDelegate* IrTypeDelegate::get(Type* dt)
{
assert(dt->ty == Tdelegate);
// We can't get cycles here, but we can end up building the type as part of
// a class vtbl, ...
LLType* func = DtoFunctionType(dt->nextOf(), NULL, Type::tvoid->pointerTo());
llvm::SmallVector<LLType*, 2> types;
types.push_back(getVoidPtrType());
types.push_back(getPtrToType(func));
LLStructType* dgtype = LLStructType::get(gIR->context(), types);
return dgtype;
if (!dt->irtype)
{
llvm::SmallVector<LLType*, 2> types;
types.push_back(getVoidPtrType());
types.push_back(getPtrToType(func));
LLStructType* lt = LLStructType::get(gIR->context(), types);
dt->irtype = new IrTypeDelegate(dt, lt);
}
return dt->irtype->isDelegate();
}

View File

@@ -23,18 +23,17 @@ class IrTypeFunction : public IrType
{
public:
///
IrTypeFunction(Type* dt);
static IrTypeFunction* get(Type* dt);
///
IrTypeFunction* isFunction() { return this; }
///
llvm::Type* buildType();
IrFuncTy* fty() { return irfty; }
protected:
llvm::Type* func2llvm(Type* dt);
///
IrTypeFunction(Type* dt, llvm::Type* lt);
///
IrFuncTy* irfty;
};
@@ -44,15 +43,14 @@ class IrTypeDelegate : public IrType
{
public:
///
IrTypeDelegate(Type* dt);
static IrTypeDelegate* get(Type* dt);
///
IrTypeDelegate* isDelegate() { return this; }
///
llvm::Type* buildType();
protected:
llvm::Type* delegate2llvm(Type* dt);
///
IrTypeDelegate(Type* dt, llvm::Type* lt);
};
#endif

View File

@@ -84,20 +84,23 @@ bool var_offset_sort_cb(const VarDeclaration* v1, const VarDeclaration* v2)
// this is pretty much the exact same thing we need to do for fields in each
// base class of a class
llvm::Type* IrTypeStruct::buildType()
IrTypeStruct* IrTypeStruct::get(StructDeclaration* sd)
{
IrTypeStruct* t = new IrTypeStruct(sd);
sd->type->irtype = t;
IF_LOG Logger::println("Building struct type %s @ %s",
sd->toPrettyChars(), sd->loc.toChars());
LOG_SCOPE;
// if it's a forward declaration, all bets are off, stick with the opaque
if (sd->sizeok != 1)
return type;
return t;
// mirror the sd->fields array but only fill in contributors
size_t n = sd->fields.dim;
LLSmallVector<VarDeclaration*, 16> data(n, NULL);
default_fields.reserve(n);
t->default_fields.reserve(n);
// first fill in the fields with explicit initializers
VarDeclarationIter field_it(sd->fields);
@@ -197,7 +200,7 @@ llvm::Type* IrTypeStruct::buildType()
assert(vd->offset >= offset);
// add to default field list
default_fields.push_back(vd);
t->default_fields.push_back(vd);
// get next aligned offset for this type
size_t alignedoffset = offset;
@@ -229,11 +232,11 @@ llvm::Type* IrTypeStruct::buildType()
}
// set struct body
isaStruct(type)->setBody(defaultTypes, packed);
isaStruct(t->type)->setBody(defaultTypes, packed);
IF_LOG Logger::cout() << "final struct type: " << *type << std::endl;
IF_LOG Logger::cout() << "final struct type: " << *t->type << std::endl;
return type;
return t;
}
//////////////////////////////////////////////////////////////////////////////

View File

@@ -28,9 +28,6 @@ struct TypeStruct;
class IrTypeAggr : public IrType
{
public:
///
IrTypeAggr(AggregateDeclaration* ad);
///
IrTypeAggr* isAggr() { return this; }
@@ -44,6 +41,9 @@ public:
iterator def_end() { return default_fields.end(); }
protected:
///
IrTypeAggr(AggregateDeclaration* ad);
/// AggregateDeclaration this type represents.
AggregateDeclaration* aggr;
@@ -61,7 +61,7 @@ class IrTypeStruct : public IrTypeAggr
{
public:
///
IrTypeStruct(StructDeclaration* sd);
static IrTypeStruct* get(StructDeclaration* sd);
///
IrTypeStruct* isStruct() { return this; }
@@ -70,6 +70,9 @@ public:
llvm::Type* buildType();
protected:
///
IrTypeStruct(StructDeclaration* sd);
/// StructDeclaration this type represents.
StructDeclaration* sd;