mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +03:00
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:
parent
f3c7278e88
commit
d80de9deb3
5 changed files with 90 additions and 154 deletions
|
@ -80,6 +80,30 @@ void TypeInfoBuilder::push_void_array(llvm::Constant* CI, Type* valtype, Dsymbol
|
|||
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)
|
||||
{
|
||||
// create the inititalizer
|
||||
|
|
|
@ -22,12 +22,17 @@ struct TypeInfoBuilder
|
|||
|
||||
void push(llvm::Constant* C);
|
||||
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_classinfo(ClassDeclaration* cd);
|
||||
void push_string(const char* str);
|
||||
void push_null_void_array();
|
||||
void push_funcptr(FuncDeclaration* fd);
|
||||
void push_void_array(size_t dim, llvm::Constant* ptr);
|
||||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
// to constant helpers
|
||||
LLConstantInt* DtoConstSize_t(size_t);
|
||||
LLConstantInt* DtoConstSize_t(uint64_t);
|
||||
LLConstantInt* DtoConstUint(unsigned i);
|
||||
LLConstantInt* DtoConstInt(int i);
|
||||
LLConstantInt* DtoConstUbyte(unsigned char i);
|
||||
|
|
207
gen/typinf.cpp
207
gen/typinf.cpp
|
@ -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()
|
||||
{
|
||||
Logger::println("TypeInfoStructDeclaration::llvmDefine() %s", toChars());
|
||||
|
@ -565,190 +580,82 @@ void TypeInfoStructDeclaration::llvmDefine()
|
|||
}
|
||||
|
||||
sd->codegen(Type::sir);
|
||||
IrStruct* irstruct = sd->ir.irStruct;
|
||||
|
||||
ClassDeclaration* base = 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)));
|
||||
TypeInfoBuilder b(Type::typeinfostruct);
|
||||
|
||||
// char[] name
|
||||
char *name = sd->toPrettyChars();
|
||||
sinits.push_back(DtoConstString(name));
|
||||
//Logger::println("************** A");
|
||||
assert(sinits.back()->getType() == stype->getElementType(2));
|
||||
b.push_string(sd->toPrettyChars());
|
||||
|
||||
// void[] init
|
||||
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
|
||||
#if 0
|
||||
// the implementation of TypeInfo_Struct uses this to determine size. :/
|
||||
if (sd->zeroInit) // 0 initializer, or the same as the base type
|
||||
{
|
||||
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));
|
||||
}
|
||||
// never emit a null array, even for zero initialized typeinfo
|
||||
// the size() method uses this array!
|
||||
size_t init_size = getTypeStoreSize(tc->irtype->getPA());
|
||||
b.push_void_array(init_size, irstruct->getInitSymbol());
|
||||
|
||||
// toX functions ground work
|
||||
FuncDeclaration *fd;
|
||||
FuncDeclaration *fdx;
|
||||
TypeFunction *tf;
|
||||
Type *ta;
|
||||
Dsymbol *s;
|
||||
|
||||
static TypeFunction *tftohash;
|
||||
static TypeFunction *tftostring;
|
||||
|
||||
if (!tftohash)
|
||||
{
|
||||
Scope sc;
|
||||
|
||||
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
|
||||
tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
|
||||
|
||||
tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
|
||||
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
|
||||
Scope sc;
|
||||
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
|
||||
tftohash = (TypeFunction *)tftohash->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;
|
||||
{
|
||||
Scope sc;
|
||||
Arguments *arguments = new Arguments;
|
||||
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
|
||||
|
||||
arguments->push(arg);
|
||||
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
|
||||
Scope sc;
|
||||
Arguments *arguments = new Arguments;
|
||||
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
|
||||
arguments->push(arg);
|
||||
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
|
||||
}
|
||||
|
||||
#if 0
|
||||
TypeFunction *tfeq;
|
||||
{
|
||||
Scope sc;
|
||||
Array *arguments = new Array;
|
||||
Argument *arg = new Argument(In, tc, NULL, NULL);
|
||||
// well use this module for all overload lookups
|
||||
Module *gm = getModule();
|
||||
|
||||
arguments->push(arg);
|
||||
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
||||
tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
|
||||
}
|
||||
#endif
|
||||
// toHash
|
||||
FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash, gm);
|
||||
b.push_funcptr(fd);
|
||||
|
||||
//Logger::println("************** B");
|
||||
const LLPointerType* ptty = isaPointer(stype->getElementType(4));
|
||||
assert(ptty);
|
||||
// opEquals
|
||||
fd = find_method_overload(sd, Id::eq, tfeqptr, gm);
|
||||
b.push_funcptr(fd);
|
||||
|
||||
s = search_function(sd, Id::tohash);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{
|
||||
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));
|
||||
}
|
||||
// opCmp
|
||||
fd = find_method_overload(sd, Id::cmp, tfeqptr, gm);
|
||||
b.push_funcptr(fd);
|
||||
|
||||
s = search_function(sd, Id::eq);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
//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));
|
||||
}
|
||||
// toString
|
||||
fd = find_method_overload(sd, Id::tostring, tftostring, gm);
|
||||
b.push_funcptr(fd);
|
||||
|
||||
// uint m_flags;
|
||||
sinits.push_back(DtoConstUint(tc->hasPointers()));
|
||||
unsigned hasptrs = tc->hasPointers() ? 1 : 0;
|
||||
b.push_uint(hasptrs);
|
||||
|
||||
#if DMDV2
|
||||
// just (void*)null for now
|
||||
|
||||
// const(MemberInfo[]) function(in char[]) xgetMembers;
|
||||
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size())));
|
||||
b.push_null_vp();
|
||||
|
||||
//void function(void*) xdtor;
|
||||
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size())));
|
||||
b.push_null_vp();
|
||||
|
||||
//void function(void*) xpostblit;
|
||||
sinits.push_back(LLConstant::getNullValue(stype->getElementType(sinits.size())));
|
||||
|
||||
b.push_null_vp();
|
||||
#endif
|
||||
|
||||
// create the inititalizer
|
||||
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
|
||||
|
||||
// refine global type
|
||||
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
|
||||
|
||||
// set the initializer
|
||||
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
|
||||
// finish
|
||||
b.finalize(ir.irGlobal);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue