mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 11:26:02 +03:00
Set flag hasDtor
for ClassInfos, if appropriate.
This commit is contained in:
parent
904ec2097c
commit
c7e77f9bde
2 changed files with 63 additions and 89 deletions
125
gen/classes.cpp
125
gen/classes.cpp
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue