Cleaned up TypeInfo_Struct.

Fixed problem with DtoConstSize_t taking a size_t argument, this is not enough for cross compiling from 32bit host to a 64bit target. It now takes uint64_t. There's probably a lot of similar case around to code ...
This commit is contained in:
Tomas Lindquist Olsen 2009-05-17 04:41:10 +02:00
parent f3c7278e88
commit d80de9deb3
5 changed files with 90 additions and 154 deletions

View file

@ -80,6 +80,30 @@ void TypeInfoBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol
push_void_array(dim, G); push_void_array(dim, G);
} }
void TypeInfoBuilder::push_uint(unsigned u)
{
inits.push_back(DtoConstUint(u));
}
void TypeInfoBuilder::push_size(uint64_t s)
{
inits.push_back(DtoConstSize_t(s));
}
void TypeInfoBuilder::push_funcptr(FuncDeclaration* fd)
{
if (fd)
{
fd->codegen(Type::sir);
LLConstant* F = fd->ir.irFunc->func;
inits.push_back(F);
}
else
{
push_null_vp();
}
}
void TypeInfoBuilder::finalize(IrGlobal* tid) void TypeInfoBuilder::finalize(IrGlobal* tid)
{ {
// create the inititalizer // create the inititalizer

View file

@ -22,12 +22,17 @@ struct TypeInfoBuilder
void push(llvm::Constant* C); void push(llvm::Constant* C);
void push_null_vp(); void push_null_vp();
void push_null_void_array();
void push_uint(unsigned u);
void push_size(uint64_t s);
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_string(const char* str); void push_funcptr(FuncDeclaration* fd);
void push_null_void_array();
void push_void_array(size_t dim, llvm::Constant* ptr); void push_void_array(size_t dim, llvm::Constant* ptr);
void push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* sym); void push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol* sym);
/// Creates the initializer constant and assigns it to the global.
void finalize(IrGlobal* tid); void finalize(IrGlobal* tid);
}; };

View file

@ -489,7 +489,7 @@ void DtoMemoryBarrier(bool ll, bool ls, bool sl, bool ss, bool device)
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
llvm::ConstantInt* DtoConstSize_t(size_t i) llvm::ConstantInt* DtoConstSize_t(uint64_t i)
{ {
return llvm::ConstantInt::get(DtoSize_t(), i, false); return llvm::ConstantInt::get(DtoSize_t(), i, false);
} }

View file

@ -50,7 +50,7 @@ LLValue* DtoGEPi1(LLValue* ptr, unsigned i0, const char* var=NULL, llvm::BasicBl
LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var=NULL, llvm::BasicBlock* bb=NULL); LLValue* DtoGEPi(LLValue* ptr, unsigned i0, unsigned i1, const char* var=NULL, llvm::BasicBlock* bb=NULL);
// to constant helpers // to constant helpers
LLConstantInt* DtoConstSize_t(size_t); LLConstantInt* DtoConstSize_t(uint64_t);
LLConstantInt* DtoConstUint(unsigned i); LLConstantInt* DtoConstUint(unsigned i);
LLConstantInt* DtoConstInt(int i); LLConstantInt* DtoConstInt(int i);
LLConstantInt* DtoConstUbyte(unsigned char i); LLConstantInt* DtoConstUbyte(unsigned char i);

View file

@ -547,6 +547,21 @@ void TypeInfoDelegateDeclaration::llvmDefine()
/* ========================================================================= */ /* ========================================================================= */
static FuncDeclaration* find_method_overload(AggregateDeclaration* ad, Identifier* id, TypeFunction* tf, Module* mod)
{
Dsymbol *s = search_function(ad, id);
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
FuncDeclaration *fd = fdx->overloadExactMatch(tf, mod);
if (fd)
{
return fd;
}
}
return NULL;
}
void TypeInfoStructDeclaration::llvmDefine() void TypeInfoStructDeclaration::llvmDefine()
{ {
Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars()); Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars());
@ -565,190 +580,82 @@ void TypeInfoStructDeclaration::llvmDefine()
} }
sd->codegen(Type::sir); sd->codegen(Type::sir);
IrStruct* irstruct = sd->ir.irStruct;
ClassDeclaration* base = Type::typeinfostruct; TypeInfoBuilder b(Type::typeinfostruct);
base->codegen(Type::sir);
const LLStructType* stype = isaStruct(base->type->irtype->getPA());
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
// char[] name // char[] name
char *name = sd->toPrettyChars(); b.push_string(sd->toPrettyChars());
sinits.push_back(DtoConstString(name));
//Logger::println("************** A");
assert(sinits.back()->getType() == stype->getElementType(2));
// void[] init // void[] init
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty); // never emit a null array, even for zero initialized typeinfo
#if 0 // the size() method uses this array!
// the implementation of TypeInfo_Struct uses this to determine size. :/ size_t init_size = getTypeStoreSize(tc->irtype->getPA());
if (sd->zeroInit) // 0 initializer, or the same as the base type b.push_void_array(init_size, irstruct->getInitSymbol());
{
sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
}
else
#endif
{
size_t cisize = getTypeStoreSize(tc->irtype->getPA().get());
LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->getInitSymbol(), initpt);
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
}
// toX functions ground work // toX functions ground work
FuncDeclaration *fd;
FuncDeclaration *fdx;
TypeFunction *tf;
Type *ta;
Dsymbol *s;
static TypeFunction *tftohash; static TypeFunction *tftohash;
static TypeFunction *tftostring; static TypeFunction *tftostring;
if (!tftohash) if (!tftohash)
{ {
Scope sc; Scope sc;
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
tftohash = (TypeFunction *)tftohash->semantic(0, &sc); tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
} }
// this one takes a parameter, so we need to build a new one each time
// to get the right type. can we avoid this?
TypeFunction *tfeqptr; TypeFunction *tfeqptr;
{ {
Scope sc; Scope sc;
Arguments *arguments = new Arguments; Arguments *arguments = new Arguments;
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
arguments->push(arg);
arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
} }
#if 0 // well use this module for all overload lookups
TypeFunction *tfeq; Module *gm = getModule();
{
Scope sc;
Array *arguments = new Array;
Argument *arg = new Argument(In, tc, NULL, NULL);
arguments->push(arg); // toHash
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash, gm);
tfeq = (TypeFunction *)tfeq->semantic(0, &sc); b.push_funcptr(fd);
}
#endif
//Logger::println("************** B"); // opEquals
const LLPointerType* ptty = isaPointer(stype->getElementType(4)); fd = find_method_overload(sd, Id::eq, tfeqptr, gm);
assert(ptty); b.push_funcptr(fd);
s = search_function(sd, Id::tohash); // opCmp
fdx = s ? s->isFuncDeclaration() : NULL; fd = find_method_overload(sd, Id::cmp, tfeqptr, gm);
if (fdx) b.push_funcptr(fd);
{
fd = fdx->overloadExactMatch(tftohash, getModule());
if (fd) {
fd->codegen(Type::sir);
assert(fd->ir.irFunc->func != 0);
LLConstant* c = isaConstant(fd->ir.irFunc->func);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) uint toHash()");
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
s = search_function(sd, Id::eq); // toString
fdx = s ? s->isFuncDeclaration() : NULL; fd = find_method_overload(sd, Id::tostring, tftostring, gm);
for (int i = 0; i < 2; i++) b.push_funcptr(fd);
{
//Logger::println("************** C %d", i);
ptty = isaPointer(stype->getElementType(5+i));
if (fdx)
{
fd = fdx->overloadExactMatch(tfeqptr, getModule());
if (fd) {
fd->codegen(Type::sir);
assert(fd->ir.irFunc->func != 0);
LLConstant* c = isaConstant(fd->ir.irFunc->func);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
s = search_function(sd, Id::cmp);
fdx = s ? s->isFuncDeclaration() : NULL;
}
//Logger::println("************** D");
ptty = isaPointer(stype->getElementType(7));
s = search_function(sd, Id::tostring);
fdx = s ? s->isFuncDeclaration() : NULL;
if (fdx)
{
fd = fdx->overloadExactMatch(tftostring, getModule());
if (fd) {
fd->codegen(Type::sir);
assert(fd->ir.irFunc->func != 0);
LLConstant* c = isaConstant(fd->ir.irFunc->func);
assert(c);
c = llvm::ConstantExpr::getBitCast(c, ptty);
sinits.push_back(c);
}
else {
//fdx->error("must be declared as extern (D) char[] toString()");
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
}
else {
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
}
// uint m_flags; // uint m_flags;
sinits.push_back(DtoConstUint(tc->hasPointers())); unsigned hasptrs = tc->hasPointers() ? 1 : 0;
b.push_uint(hasptrs);
#if DMDV2 #if DMDV2
// just (void*)null for now
// const(MemberInfo[]) function(in char[]) xgetMembers; // const(MemberInfo[]) function(in char[]) xgetMembers;
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); b.push_null_vp();
//void function(void*) xdtor; //void function(void*) xdtor;
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); b.push_null_vp();
//void function(void*) xpostblit; //void function(void*) xpostblit;
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size()))); b.push_null_vp();
#endif #endif
// create the inititalizer // finish
LLConstant* tiInit = llvm::ConstantStruct::get(sinits); b.finalize(ir.irGlobal);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
} }
/* ========================================================================= */ /* ========================================================================= */