Set flag hasDtor for ClassInfos, if appropriate.

This commit is contained in:
Martin 2015-04-22 22:23:51 +02:00
parent 904ec2097c
commit c7e77f9bde
2 changed files with 63 additions and 89 deletions

View file

@ -522,56 +522,47 @@ static LLConstant* build_class_dtor(ClassDeclaration* cd)
return llvm::ConstantExpr::getBitCast(getIrFunc(dtor)->func, getPtrToType(LLType::getInt8Ty(gIR->context()))); return llvm::ConstantExpr::getBitCast(getIrFunc(dtor)->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
} }
//! needs to match object_.d static ClassFlags::Type build_classinfo_flags(ClassDeclaration* cd)
struct ClassInfoFlags
{ {
enum // adapted from original dmd code:
{ // toobj.c: ToObjFile::visit(ClassDeclaration*) and ToObjFile::visit(InterfaceDeclaration*)
isCOMclass = 0x1,
noPointers = 0x2,
hasOffTi = 0x4,
hasCtor = 0x8,
hasGetMembers = 0x10,
hasTypeInfo = 0x20,
isAbstract = 0x40,
isCPPclass = 0x80
};
};
static unsigned build_classinfo_flags(ClassDeclaration* cd) ClassFlags::Type flags = ClassFlags::hasOffTi | ClassFlags::hasTypeInfo;
if (cd->isInterfaceDeclaration())
{ {
// adapted from original dmd code if (cd->isCOMinterface()) flags |= ClassFlags::isCOMclass;
unsigned flags = 0; return flags;
flags |= (unsigned) cd->isCOMclass(); // IUnknown }
bool hasOffTi = false;
if (cd->isCOMclass()) flags |= ClassFlags::isCOMclass;
if (cd->isCPPclass()) flags |= ClassFlags::isCPPclass;
flags |= ClassFlags::hasGetMembers;
if (cd->ctor) if (cd->ctor)
flags |= ClassInfoFlags::hasCtor; flags |= ClassFlags::hasCtor;
for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
{
if (pc->dtor)
{
flags |= ClassFlags::hasDtor;
break;
}
}
if (cd->isabstract) if (cd->isabstract)
flags |= ClassInfoFlags::isAbstract; flags |= ClassFlags::isAbstract;
if (cd->isCPPclass()) for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
flags |= ClassInfoFlags::isCPPclass;
for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass)
{ {
if (!cd2->members) if (pc->members)
continue;
for (size_t i = 0; i < cd2->members->dim; i++)
{ {
Dsymbol *sm = static_cast<Dsymbol *>(cd2->members->data[i]); for (size_t i = 0; i < pc->members->dim; i++)
if (sm->isVarDeclaration() && !sm->isVarDeclaration()->isDataseg()) // is this enough? {
hasOffTi = true; Dsymbol *sm = (*pc->members)[i];
//printf("sm = %s %s\n", sm->kind(), sm->toChars()); //printf("sm = %s %s\n", sm->kind(), sm->toChars());
if (sm->hasPointers()) if (sm->hasPointers())
goto L2; return flags;
} }
} }
flags |= ClassInfoFlags::noPointers; }
L2: flags |= ClassFlags::noPointers;
if (hasOffTi)
flags |= ClassInfoFlags::hasOffTi;
// always define the typeinfo field.
// why would ever not do this?
flags |= ClassInfoFlags::hasTypeInfo;
return flags; return flags;
} }
@ -582,18 +573,19 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
// { // {
// void **vptr; // void **vptr;
// monitor_t monitor; // monitor_t monitor;
// byte[] initializer; // static initialization data // byte[] init;
// char[] name; // class name // string name;
// void*[] vtbl; // void*[] vtbl;
// Interface[] interfaces; // Interface[] interfaces;
// ClassInfo *base; // base class // TypeInfo_Class base;
// void *destructor; // void *destructor;
// void *invariant; // class invariant // void function(Object) classInvariant;
// uint flags; // ClassFlags m_flags;
// void* deallocator; // void* deallocator;
// OffsetTypeInfo[] offTi; // OffsetTypeInfo[] m_offTi;
// void *defaultConstructor; // void function(Object) defaultConstructor;
// immutable(void)* m_RTInfo; // immutable(void)* m_RTInfo;
// }
IF_LOG Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); IF_LOG Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
LOG_SCOPE; LOG_SCOPE;
@ -617,7 +609,8 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
LLType* voidPtr = getVoidPtrType(); LLType* voidPtr = getVoidPtrType();
LLType* voidPtrPtr = getPtrToType(voidPtr); LLType* voidPtrPtr = getPtrToType(voidPtr);
// byte[] init // adapted from original dmd code
// init[]
if (cd->isInterfaceDeclaration()) if (cd->isInterfaceDeclaration())
{ {
b.push_null_void_array(); b.push_null_void_array();
@ -628,8 +621,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
b.push_void_array(initsz, ir->getInitSymbol()); b.push_void_array(initsz, ir->getInitSymbol());
} }
// class name // name[]
// code from dmd
const char *name = cd->ident->toChars(); const char *name = cd->ident->toChars();
size_t namelen = strlen(name); size_t namelen = strlen(name);
if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0)) if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
@ -639,7 +631,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
} }
b.push_string(name); b.push_string(name);
// vtbl array // vtbl[]
if (cd->isInterfaceDeclaration()) if (cd->isInterfaceDeclaration())
{ {
b.push_array(0, getNullValue(voidPtrPtr)); b.push_array(0, getNullValue(voidPtrPtr));
@ -650,10 +642,10 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
b.push_array(cd->vtbl.dim, c); b.push_array(cd->vtbl.dim, c);
} }
// interfaces array // interfaces[]
b.push(ir->getClassInfoInterfaces()); b.push(ir->getClassInfoInterfaces());
// base classinfo // base
// interfaces never get a base, just the interfaces[] // interfaces never get a base, just the interfaces[]
if (cd->baseClass && !cd->isInterfaceDeclaration()) if (cd->baseClass && !cd->isInterfaceDeclaration())
b.push_classinfo(cd->baseClass); b.push_classinfo(cd->baseClass);
@ -667,46 +659,37 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
b.push(build_class_dtor(cd)); b.push(build_class_dtor(cd));
// invariant // invariant
VarDeclaration* invVar = static_cast<VarDeclaration*>(cinfo->fields.data[6]); VarDeclaration* invVar = cinfo->fields[6];
b.push_funcptr(cd->inv, invVar->type); b.push_funcptr(cd->inv, invVar->type);
// uint flags // flags
unsigned flags; ClassFlags::Type flags = build_classinfo_flags(cd);
if (cd->isInterfaceDeclaration())
flags = ClassInfoFlags::hasOffTi | (unsigned) cd->isCOMinterface() | ClassInfoFlags::hasTypeInfo;
else
flags = build_classinfo_flags(cd);
b.push_uint(flags); b.push_uint(flags);
// deallocator // deallocator
b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo()); b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());
// offset typeinfo // offset typeinfo
VarDeclaration* offTiVar = static_cast<VarDeclaration*>(cinfo->fields.data[9]); VarDeclaration* offTiVar = cinfo->fields[9];
#if GENERATE_OFFTI #if GENERATE_OFFTI
if (cd->isInterfaceDeclaration()) if (cd->isInterfaceDeclaration())
b.push_null(offTiVar->type); b.push_null(offTiVar->type);
else else
b.push(build_offti_array(cd, DtoType(offTiVar->type))); b.push(build_offti_array(cd, DtoType(offTiVar->type)));
#else
#else // GENERATE_OFFTI
b.push_null(offTiVar->type); b.push_null(offTiVar->type);
#endif
#endif // GENERATE_OFFTI // defaultConstructor
VarDeclaration* defConstructorVar = cinfo->fields.data[10];
// default constructor
VarDeclaration* defConstructorVar = static_cast<VarDeclaration*>(cinfo->fields.data[10]);
b.push_funcptr(cd->defaultCtor, defConstructorVar->type); b.push_funcptr(cd->defaultCtor, defConstructorVar->type);
// immutable(void)* m_RTInfo; // m_RTInfo
// The cases where getRTInfo is null are not quite here, but the code is // The cases where getRTInfo is null are not quite here, but the code is
// modelled after what DMD does. // modelled after what DMD does.
if (cd->getRTInfo) if (cd->getRTInfo)
b.push(toConstElem(cd->getRTInfo, gIR)); b.push(toConstElem(cd->getRTInfo, gIR));
else if (flags & ClassInfoFlags::noPointers) else if (flags & ClassFlags::noPointers)
b.push_size_as_vp(0); // no pointers b.push_size_as_vp(0); // no pointers
else else
b.push_size_as_vp(1); // has pointers b.push_size_as_vp(1); // has pointers

View file

@ -26,15 +26,6 @@ class TypeClass;
/// Resolves the llvm type for a class declaration /// Resolves the llvm type for a class declaration
void DtoResolveClass(ClassDeclaration* cd); void DtoResolveClass(ClassDeclaration* cd);
/// Provides the llvm declaration for a class declaration
void DtoDeclareClass(ClassDeclaration* cd);
/// Constructs the constant initializer for a class declaration
void DtoConstInitClass(ClassDeclaration* cd);
/// Provides the llvm definition for a class declaration
void DtoDefineClass(ClassDeclaration* cd);
/// Builds the initializer of cd's ClassInfo. /// Builds the initializer of cd's ClassInfo.
/// FIXME: this should be put into IrStruct and eventually IrClass. /// FIXME: this should be put into IrStruct and eventually IrClass.
llvm::Constant* DtoDefineClassInfo(ClassDeclaration* cd); llvm::Constant* DtoDefineClassInfo(ClassDeclaration* cd);