changeset 1375:63f4afd01036

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 ...
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Sun, 17 May 2009 04:41:10 +0200
parents e630ff79e10d
children a5d0e04298a8
files gen/rttibuilder.cpp gen/rttibuilder.h gen/tollvm.cpp gen/tollvm.h gen/typinf.cpp
diffstat 5 files changed, 93 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/gen/rttibuilder.cpp	Sun May 17 03:10:55 2009 +0200
+++ b/gen/rttibuilder.cpp	Sun May 17 04:41:10 2009 +0200
@@ -80,6 +80,30 @@
     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
--- a/gen/rttibuilder.h	Sun May 17 03:10:55 2009 +0200
+++ b/gen/rttibuilder.h	Sun May 17 04:41:10 2009 +0200
@@ -22,12 +22,17 @@
 
     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);
 };
 
--- a/gen/tollvm.cpp	Sun May 17 03:10:55 2009 +0200
+++ b/gen/tollvm.cpp	Sun May 17 04:41:10 2009 +0200
@@ -489,7 +489,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::ConstantInt* DtoConstSize_t(size_t i)
+llvm::ConstantInt* DtoConstSize_t(uint64_t i)
 {
     return llvm::ConstantInt::get(DtoSize_t(), i, false);
 }
--- a/gen/tollvm.h	Sun May 17 03:10:55 2009 +0200
+++ b/gen/tollvm.h	Sun May 17 04:41:10 2009 +0200
@@ -50,7 +50,7 @@
 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);
--- a/gen/typinf.cpp	Sun May 17 03:10:55 2009 +0200
+++ b/gen/typinf.cpp	Sun May 17 04:41:10 2009 +0200
@@ -547,6 +547,21 @@
 
 /* ========================================================================= */
 
+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 @@
     }
 
     sd->codegen(Type::sir);
-
-    ClassDeclaration* base = Type::typeinfostruct;
-    base->codegen(Type::sir);
-
-    const LLStructType* stype = isaStruct(base->type->irtype->getPA());
+    IrStruct* irstruct = sd->ir.irStruct;
 
-    // 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);
-    }
-
-    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;
+        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);
     }
 
-#if 0
-    TypeFunction *tfeq;
+    // 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;
-    Array *arguments = new Array;
-    Argument *arg = new Argument(In, tc, NULL, NULL);
-
-    arguments->push(arg);
-    tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
-    tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
-    }
-#endif
-
-    //Logger::println("************** B");
-    const LLPointerType* ptty = isaPointer(stype->getElementType(4));
-    assert(ptty);
-
-    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));
+        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);
     }
 
-    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));
-        }
+    // well use this module for all overload lookups
+    Module *gm = getModule();
+
+    // toHash
+    FuncDeclaration* fd = find_method_overload(sd, Id::tohash, tftohash, gm);
+    b.push_funcptr(fd);
 
-        s = search_function(sd, Id::cmp);
-        fdx = s ? s->isFuncDeclaration() : NULL;
-    }
+    // opEquals
+    fd = find_method_overload(sd, Id::eq, tfeqptr, gm);
+    b.push_funcptr(fd);
 
-    //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));
-    }
+    // opCmp
+    fd = find_method_overload(sd, Id::cmp, tfeqptr, gm);
+    b.push_funcptr(fd);
+
+    // 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);
 }
 
 /* ========================================================================= */