Update !ClassInfo generation to use !RTTIBuilder, slight update of !RTTIBuilder .

This commit is contained in:
Tomas Lindquist Olsen 2009-05-17 16:27:01 +02:00
parent b6daf3d545
commit dc4b7e8118
3 changed files with 99 additions and 107 deletions

View file

@ -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,7 +786,8 @@ 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;
@ -839,7 +795,6 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
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;
} }

View file

@ -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);
}

View file

@ -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