mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-14 07:09:50 +03:00
Update !ClassInfo generation to use !RTTIBuilder, slight update of !RTTIBuilder .
This commit is contained in:
parent
b6daf3d545
commit
dc4b7e8118
3 changed files with 99 additions and 107 deletions
149
gen/classes.cpp
149
gen/classes.cpp
|
@ -5,17 +5,19 @@
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "declaration.h"
|
#include "declaration.h"
|
||||||
|
|
||||||
#include "gen/irstate.h"
|
|
||||||
#include "gen/tollvm.h"
|
|
||||||
#include "gen/llvmhelpers.h"
|
|
||||||
#include "gen/arrays.h"
|
|
||||||
#include "gen/logger.h"
|
|
||||||
#include "gen/classes.h"
|
|
||||||
#include "gen/structs.h"
|
|
||||||
#include "gen/functions.h"
|
|
||||||
#include "gen/runtime.h"
|
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
|
||||||
|
#include "gen/arrays.h"
|
||||||
|
#include "gen/classes.h"
|
||||||
|
#include "gen/functions.h"
|
||||||
|
#include "gen/llvmhelpers.h"
|
||||||
|
#include "gen/logger.h"
|
||||||
#include "gen/nested.h"
|
#include "gen/nested.h"
|
||||||
|
#include "gen/rttibuilder.h"
|
||||||
|
#include "gen/runtime.h"
|
||||||
|
#include "gen/structs.h"
|
||||||
|
#include "gen/tollvm.h"
|
||||||
#include "gen/utils.h"
|
#include "gen/utils.h"
|
||||||
|
|
||||||
#include "ir/irstruct.h"
|
#include "ir/irstruct.h"
|
||||||
|
@ -666,45 +668,36 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
|
Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
IrStruct* ir = cd->ir.irStruct;
|
|
||||||
|
|
||||||
assert(cd->type->ty == Tclass);
|
assert(cd->type->ty == Tclass);
|
||||||
|
|
||||||
TypeClass* cdty = (TypeClass*)cd->type;
|
TypeClass* cdty = (TypeClass*)cd->type;
|
||||||
|
|
||||||
// holds the list of initializers for llvm
|
IrStruct* ir = cd->ir.irStruct;
|
||||||
std::vector<LLConstant*> inits;
|
assert(ir);
|
||||||
|
|
||||||
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||||
cinfo->codegen(Type::sir);
|
|
||||||
|
// use the rtti builder
|
||||||
|
RTTIBuilder b(ClassDeclaration::classinfo);
|
||||||
|
|
||||||
LLConstant* c;
|
LLConstant* c;
|
||||||
|
|
||||||
const LLType* voidPtr = getVoidPtrType();
|
const LLType* voidPtr = getVoidPtrType();
|
||||||
const LLType* voidPtrPtr = getPtrToType(voidPtr);
|
const LLType* voidPtrPtr = getPtrToType(voidPtr);
|
||||||
|
|
||||||
// own vtable
|
|
||||||
c = cinfo->ir.irStruct->getVtblSymbol();
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// monitor
|
|
||||||
c = LLConstant::getNullValue(voidPtr);
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// byte[] init
|
// byte[] init
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(voidPtr));
|
{
|
||||||
|
b.push_null_void_array();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c = DtoBitCast(ir->getInitSymbol(), voidPtr);
|
const LLType* cd_type = cdty->irtype->getPA();
|
||||||
//Logger::cout() << *ir->constInit->getType() << std::endl;
|
size_t initsz = getTypePaddedSize(cd_type);
|
||||||
size_t initsz = getTypePaddedSize(ir->getInitSymbol()->getType()->getContainedType(0));
|
b.push_void_array(initsz, ir->getInitSymbol());
|
||||||
c = DtoConstSlice(DtoConstSize_t(initsz), c);
|
|
||||||
}
|
}
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// class name
|
// class name
|
||||||
// from dmd
|
// code from dmd
|
||||||
char *name = cd->ident->toChars();
|
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))
|
||||||
|
@ -712,116 +705,78 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
name = cd->toPrettyChars();
|
name = cd->toPrettyChars();
|
||||||
namelen = strlen(name);
|
namelen = strlen(name);
|
||||||
}
|
}
|
||||||
c = DtoConstString(name);
|
b.push_string(name);
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// vtbl array
|
// vtbl array
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
c = DtoConstSlice(DtoConstSize_t(0), LLConstant::getNullValue(getPtrToType(voidPtr)));
|
{
|
||||||
else {
|
b.push_array(0, getNullValue(voidPtrPtr));
|
||||||
c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
|
}
|
||||||
c = DtoConstSlice(DtoConstSize_t(cd->vtbl.dim), c);
|
else
|
||||||
|
{
|
||||||
|
c = DtoBitCast(ir->getVtblSymbol(), voidPtrPtr);
|
||||||
|
b.push_array(cd->vtbl.dim, c);
|
||||||
}
|
}
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// interfaces array
|
// interfaces array
|
||||||
c = ir->getClassInfoInterfaces();
|
b.push(ir->getClassInfoInterfaces());
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// base classinfo
|
// base classinfo
|
||||||
// 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())
|
||||||
c = cd->baseClass->ir.irStruct->getClassInfoSymbol();
|
b.push_classinfo(cd->baseClass);
|
||||||
assert(c);
|
else
|
||||||
inits.push_back(c);
|
b.push_null(cinfo->type);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// null
|
|
||||||
c = LLConstant::getNullValue(DtoType(cinfo->type));
|
|
||||||
inits.push_back(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
c = LLConstant::getNullValue(voidPtr);
|
b.push_null_vp();
|
||||||
else
|
else
|
||||||
c = build_class_dtor(cd);
|
b.push(build_class_dtor(cd));
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// invariant
|
// invariant
|
||||||
VarDeclaration* invVar = (VarDeclaration*)cinfo->fields.data[6];
|
VarDeclaration* invVar = (VarDeclaration*)cinfo->fields.data[6];
|
||||||
const LLType* invTy = DtoType(invVar->type);
|
b.push_funcptr(cd->inv, invVar->type);
|
||||||
if (cd->inv)
|
|
||||||
{
|
|
||||||
cd->inv->codegen(Type::sir);
|
|
||||||
c = cd->inv->ir.irFunc->func;
|
|
||||||
c = DtoBitCast(c, invTy);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c = LLConstant::getNullValue(invTy);
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// uint flags
|
// uint flags
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
c = DtoConstUint(0);
|
b.push_uint(0);
|
||||||
else {
|
else
|
||||||
unsigned flags = build_classinfo_flags(cd);
|
b.push_uint(build_classinfo_flags(cd));
|
||||||
c = DtoConstUint(flags);
|
|
||||||
}
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// deallocator
|
// deallocator
|
||||||
if (cd->aggDelete)
|
b.push_funcptr(cd->aggDelete, Type::tvoid->pointerTo());
|
||||||
{
|
|
||||||
cd->aggDelete->codegen(Type::sir);
|
|
||||||
c = cd->aggDelete->ir.irFunc->func;
|
|
||||||
c = DtoBitCast(c, voidPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c = LLConstant::getNullValue(voidPtr);
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// offset typeinfo
|
// offset typeinfo
|
||||||
VarDeclaration* offTiVar = (VarDeclaration*)cinfo->fields.data[9];
|
VarDeclaration* offTiVar = (VarDeclaration*)cinfo->fields.data[9];
|
||||||
const LLType* offTiTy = DtoType(offTiVar->type);
|
|
||||||
|
|
||||||
#if GENERATE_OFFTI
|
#if GENERATE_OFFTI
|
||||||
|
|
||||||
if (cd->isInterfaceDeclaration())
|
if (cd->isInterfaceDeclaration())
|
||||||
c = LLConstant::getNullValue(offTiTy);
|
b.push_null(offTiVar->type);
|
||||||
else
|
else
|
||||||
c = build_offti_array(cd, offTiTy);
|
b.push(build_offti_array(cd, DtoType(offTiVar->type)));
|
||||||
|
|
||||||
#else // GENERATE_OFFTI
|
#else // GENERATE_OFFTI
|
||||||
|
|
||||||
c = LLConstant::getNullValue(offTiTy);
|
b.push_null(offTiVar->type);
|
||||||
|
|
||||||
#endif // GENERATE_OFFTI
|
#endif // GENERATE_OFFTI
|
||||||
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// default constructor
|
// default constructor
|
||||||
if (cd->defaultCtor)
|
b.push_funcptr(cd->defaultCtor, Type::tvoid->pointerTo());
|
||||||
{
|
|
||||||
cd->defaultCtor->codegen(Type::sir);
|
|
||||||
c = isaConstant(cd->defaultCtor->ir.irFunc->func);
|
|
||||||
c = DtoBitCast(c, voidPtr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c = LLConstant::getNullValue(voidPtr);
|
|
||||||
inits.push_back(c);
|
|
||||||
|
|
||||||
// typeinfo - since 1.045
|
// typeinfo - since 1.045
|
||||||
inits.push_back(DtoTypeInfoOf(cd->type, true));
|
b.push_typeinfo(cd->type);
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
|
|
||||||
// xgetMembers
|
// xgetMembers
|
||||||
VarDeclaration* xgetVar = (VarDeclaration*)cinfo->fields.data[11];
|
VarDeclaration* xgetVar = (VarDeclaration*)cinfo->fields.data[11];
|
||||||
const LLType* xgetTy = DtoType(xgetVar->type);
|
|
||||||
|
|
||||||
// FIXME: fill it out!
|
// FIXME: fill it out!
|
||||||
inits.push_back( LLConstant::getNullValue(xgetTy) );
|
b.push_null(xgetVar->type);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*size_t n = inits.size();
|
/*size_t n = inits.size();
|
||||||
|
@ -831,14 +786,14 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// build the initializer
|
// build the initializer
|
||||||
LLConstant* finalinit = llvm::ConstantStruct::get(inits);
|
LLConstant* finalinit = b.get_constant();
|
||||||
|
|
||||||
//Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
|
//Logger::cout() << "built the classinfo initializer:\n" << *finalinit <<'\n';
|
||||||
ir->constClassInfo = finalinit;
|
ir->constClassInfo = finalinit;
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
assert(finalinit->getType() == ir->classInfo->getType()->getContainedType(0) &&
|
assert(finalinit->getType() == ir->classInfo->getType()->getContainedType(0) &&
|
||||||
"__ClassZ initializer does not match the ClassInfo type");
|
"__ClassZ initializer does not match the ClassInfo type");
|
||||||
|
|
||||||
|
|
||||||
// return initializer
|
// return initializer
|
||||||
return finalinit;
|
return finalinit;
|
||||||
|
|
|
@ -34,6 +34,11 @@ void RTTIBuilder::push(llvm::Constant* C)
|
||||||
inits.push_back(C);
|
inits.push_back(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTTIBuilder::push_null(Type* T)
|
||||||
|
{
|
||||||
|
inits.push_back(getNullValue(DtoType(T)));
|
||||||
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_null_vp()
|
void RTTIBuilder::push_null_vp()
|
||||||
{
|
{
|
||||||
inits.push_back(getNullValue(getVoidPtrType()));
|
inits.push_back(getNullValue(getVoidPtrType()));
|
||||||
|
@ -77,10 +82,7 @@ void RTTIBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* ma
|
||||||
CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname, gIR->module);
|
CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname, gIR->module);
|
||||||
G->setAlignment(valtype->alignsize());
|
G->setAlignment(valtype->alignsize());
|
||||||
|
|
||||||
size_t dim = getTypePaddedSize(CI->getType());
|
push_void_array(getTypePaddedSize(CI->getType()), G);
|
||||||
LLConstant* ptr = DtoBitCast(CI, DtoType(valtype->pointerTo()));
|
|
||||||
|
|
||||||
push_void_array(dim, G);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, Dsymbol * mangle_sym)
|
void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, Dsymbol * mangle_sym)
|
||||||
|
@ -94,10 +96,12 @@ void RTTIBuilder::push_array(llvm::Constant * CI, uint64_t dim, Type* valtype, D
|
||||||
CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname, gIR->module);
|
CI->getType(), true, TYPEINFO_LINKAGE_TYPE, CI, initname, gIR->module);
|
||||||
G->setAlignment(valtype->alignsize());
|
G->setAlignment(valtype->alignsize());
|
||||||
|
|
||||||
inits.push_back(DtoConstSlice(
|
push_array(dim, DtoBitCast(G, DtoType(valtype->pointerTo())));
|
||||||
DtoConstSize_t(dim),
|
}
|
||||||
DtoBitCast(CI, DtoType(valtype->pointerTo()))
|
|
||||||
));
|
void RTTIBuilder::push_array(uint64_t dim, llvm::Constant * ptr)
|
||||||
|
{
|
||||||
|
inits.push_back(DtoConstSlice(DtoConstSize_t(dim), ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_uint(unsigned u)
|
void RTTIBuilder::push_uint(unsigned u)
|
||||||
|
@ -110,14 +114,20 @@ void RTTIBuilder::push_size(uint64_t s)
|
||||||
inits.push_back(DtoConstSize_t(s));
|
inits.push_back(DtoConstSize_t(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTTIBuilder::push_funcptr(FuncDeclaration* fd)
|
void RTTIBuilder::push_funcptr(FuncDeclaration* fd, Type* castto)
|
||||||
{
|
{
|
||||||
if (fd)
|
if (fd)
|
||||||
{
|
{
|
||||||
fd->codegen(Type::sir);
|
fd->codegen(Type::sir);
|
||||||
LLConstant* F = fd->ir.irFunc->func;
|
LLConstant* F = fd->ir.irFunc->func;
|
||||||
|
if (castto)
|
||||||
|
F = DtoBitCast(F, DtoType(castto));
|
||||||
inits.push_back(F);
|
inits.push_back(F);
|
||||||
}
|
}
|
||||||
|
else if (castto)
|
||||||
|
{
|
||||||
|
push_null(castto);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
push_null_vp();
|
push_null_vp();
|
||||||
|
@ -135,3 +145,9 @@ void RTTIBuilder::finalize(IrGlobal* tid)
|
||||||
// set the initializer
|
// set the initializer
|
||||||
isaGlobalVar(tid->value)->setInitializer(tiInit);
|
isaGlobalVar(tid->value)->setInitializer(tiInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLConstant* RTTIBuilder::get_constant()
|
||||||
|
{
|
||||||
|
// just return the inititalizer
|
||||||
|
return llvm::ConstantStruct::get(&inits[0], inits.size(), false);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct RTTIBuilder
|
||||||
RTTIBuilder(ClassDeclaration* base_class);
|
RTTIBuilder(ClassDeclaration* base_class);
|
||||||
|
|
||||||
void push(llvm::Constant* C);
|
void push(llvm::Constant* C);
|
||||||
|
void push_null(Type* T);
|
||||||
void push_null_vp();
|
void push_null_vp();
|
||||||
void push_null_void_array();
|
void push_null_void_array();
|
||||||
void push_uint(unsigned u);
|
void push_uint(unsigned u);
|
||||||
|
@ -29,13 +30,33 @@ struct RTTIBuilder
|
||||||
void push_string(const char* str);
|
void push_string(const char* str);
|
||||||
void push_typeinfo(Type* t);
|
void push_typeinfo(Type* t);
|
||||||
void push_classinfo(ClassDeclaration* cd);
|
void push_classinfo(ClassDeclaration* cd);
|
||||||
void push_funcptr(FuncDeclaration* fd);
|
|
||||||
|
/// pushes the function pointer or a null void* if it cannot.
|
||||||
|
void push_funcptr(FuncDeclaration* fd, Type* castto = NULL);
|
||||||
|
|
||||||
|
/// pushes the array slice given.
|
||||||
|
void push_array(uint64_t dim, llvm::Constant * ptr);
|
||||||
|
|
||||||
|
/// pushes void[] slice, dim is used directly, ptr is cast to void* .
|
||||||
void push_void_array(uint64_t dim, llvm::Constant* ptr);
|
void push_void_array(uint64_t dim, llvm::Constant* ptr);
|
||||||
|
|
||||||
|
/// pushes void[] slice with data.
|
||||||
|
/// CI is the constant initializer the array should point to, the length
|
||||||
|
/// and ptr are resolved automatically
|
||||||
void push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* mangle_sym);
|
void push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* mangle_sym);
|
||||||
|
|
||||||
|
/// pushes valtype[] slice with data.
|
||||||
|
/// CI is the constant initializer that .ptr should point to
|
||||||
|
/// dim is .length member directly
|
||||||
|
/// valtype provides the D element type, .ptr is cast to valtype->pointerTo()
|
||||||
|
/// mangle_sym provides the mangle prefix for the symbol generated.
|
||||||
void push_array(llvm::Constant* CI, uint64_t dim, Type* valtype, Dsymbol* mangle_sym);
|
void push_array(llvm::Constant* CI, uint64_t dim, Type* valtype, Dsymbol* mangle_sym);
|
||||||
|
|
||||||
/// Creates the initializer constant and assigns it to the global.
|
/// Creates the initializer constant and assigns it to the global.
|
||||||
void finalize(IrGlobal* tid);
|
void finalize(IrGlobal* tid);
|
||||||
|
|
||||||
|
/// Creates the initializer constant and assigns it to the global.
|
||||||
|
llvm::Constant* get_constant();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue