changeset 72:d7e764e62462 trunk

[svn r76] Fixed: TypeInfo for structs. Fixed: PostExp was unable to allocate storage for parameters. Fixed: Many types of functions and delegates were broken. Misc cleanups.
author lindquist
date Mon, 29 Oct 2007 03:28:12 +0100
parents 53d3086b5ad3
children b706170e24a9
files dmd/aggregate.h dmd/mtype.h gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c gen/typinf.c lphobos/internal/objectimpl.d test/bug38.d test/bug39.d test/bug40.d test/typeinfo10.d
diffstat 12 files changed, 367 insertions(+), 204 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Sun Oct 28 19:48:57 2007 +0100
+++ b/dmd/aggregate.h	Mon Oct 29 03:28:12 2007 +0100
@@ -98,7 +98,7 @@
 
     bool llvmInProgress;
     llvm::Type* llvmType;
-    llvm::Value* llvmVtbl;
+    llvm::Constant* llvmVtbl;
     llvm::ConstantStruct* llvmConstVtbl;
     llvm::Constant* llvmInitZ;
     virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
--- a/dmd/mtype.h	Sun Oct 28 19:48:57 2007 +0100
+++ b/dmd/mtype.h	Mon Oct 29 03:28:12 2007 +0100
@@ -540,7 +540,7 @@
 
     type *toCtype();
 
-    llvm::Value* llvmInit;
+    llvm::Constant* llvmInit;
 };
 
 struct TypeEnum : Type
@@ -638,7 +638,7 @@
 
     Symbol *toSymbol();
 
-    llvm::Value* llvmInit;
+    llvm::Constant* llvmInit;
 };
 
 struct TypeTuple : Type
--- a/gen/toir.c	Sun Oct 28 19:48:57 2007 +0100
+++ b/gen/toir.c	Mon Oct 29 03:28:12 2007 +0100
@@ -116,6 +116,7 @@
         // _arguments
         if (vd->ident == Id::_arguments)
         {
+            Logger::println("Id::_arguments");
             vd->llvmValue = p->func().decl->llvmArguments;
             assert(vd->llvmValue);
             e->mem = vd->llvmValue;
@@ -124,6 +125,7 @@
         // _argptr
         else if (vd->ident == Id::_argptr)
         {
+            Logger::println("Id::_argptr");
             vd->llvmValue = p->func().decl->llvmArgPtr;
             assert(vd->llvmValue);
             e->mem = vd->llvmValue;
@@ -132,6 +134,7 @@
         // _dollar
         else if (vd->ident == Id::dollar)
         {
+            Logger::println("Id::dollar");
             assert(!p->arrays.empty());
             llvm::Value* tmp = LLVM_DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb());
             e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
@@ -152,6 +155,7 @@
         }
         // nested variable
         else if (vd->nestedref) {
+            Logger::println("nested variable");
             e->mem = LLVM_DtoNestedVariable(vd);
             e->type = elem::VAR;
             e->vardecl = vd;
@@ -159,7 +163,11 @@
         // function parameter
         else if (vd->isParameter()) {
             Logger::println("function param");
-            assert(vd->llvmValue);
+            if (!vd->llvmValue) {
+                // TODO: determine this properly
+                // this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
+                vd->llvmValue = &p->func().func->getArgumentList().back();
+            }
             if (vd->isRef() || vd->isOut()) {
                 e->mem = vd->llvmValue;
                 e->type = elem::VAR;
@@ -1432,18 +1440,27 @@
 
         assert(vd->llvmValue);
         Type* t = LLVM_DtoDType(type);
+        Type* tnext = LLVM_DtoDType(t->next);
         Type* vdtype = LLVM_DtoDType(vd->type); 
 
         llvm::Value* llvalue = vd->nestedref ? LLVM_DtoNestedVariable(vd) : vd->llvmValue;
 
         if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
             TypeStruct* vdt = (TypeStruct*)vdtype;
+            assert(vdt->sym);
             e = new elem;
-            std::vector<unsigned> dst(1,0);
-            vdt->sym->offsetToIndex(t->next, offset, dst);
-            llvm::Value* ptr = llvalue;
-            assert(ptr);
-            e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
+            bool donormally = true;
+            if (offset == 0) {
+                const llvm::Type* llt = LLVM_DtoType(t);
+                e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
+            }
+            else {
+                std::vector<unsigned> dst(1,0);
+                vdt->sym->offsetToIndex(tnext, offset, dst);
+                llvm::Value* ptr = llvalue;
+                assert(ptr);
+                e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
+            }
             e->type = elem::VAL;
             e->field = true;
         }
@@ -2118,7 +2135,8 @@
     else
     assert(post);
 
-    //llvm::Value* tostore = l->storeVal ? l->storeVal : l->val;
+    if (l->mem == 0)
+        LLVM_DtoGiveArgumentStorage(l);
     new llvm::StoreInst(post,l->mem,p->scopebb());
 
     delete l;
--- a/gen/tollvm.c	Sun Oct 28 19:48:57 2007 +0100
+++ b/gen/tollvm.c	Mon Oct 29 03:28:12 2007 +0100
@@ -151,7 +151,7 @@
     case Tfunction:
     {
         if (t->llvmType == 0) {
-            return LLVM_DtoFunctionType(t);
+            return LLVM_DtoFunctionType(t,NULL);
         }
         else {
             return t->llvmType;
@@ -188,94 +188,13 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
+const llvm::FunctionType* LLVM_DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
 {
-    TypeFunction* f = (TypeFunction*)t;
-
-    // parameter types
-    const llvm::Type* rettype;
-    std::vector<const llvm::Type*> paramvec;
-
-    if (LLVM_DtoIsPassedByRef(f->next)) {
-        rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
-        paramvec.push_back(rettype);
-        rettype = llvm::Type::VoidTy;
-    }
-    else {
-        Type* rt = f->next;
-        if (rt)
-        rettype = LLVM_DtoType(rt);
-        else
-        assert(0);
-    }
-
-    if (thisparam) {
-        paramvec.push_back(thisparam);
-    }
-
-    size_t n = Argument::dim(f->parameters);
-    for (int i=0; i < n; ++i) {
-        Argument* arg = Argument::getNth(f->parameters, i);
-        // ensure scalar
-        Type* argT = arg->type;
-        assert(argT);
-        paramvec.push_back(LLVM_DtoType(argT));
-    }
-
-    Logger::cout() << "Return type: " << *rettype << '\n';
-
-    llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, f->varargs);
-    return functype;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
-{
-    TypeFunction* f = (TypeFunction*)fdecl->type;
+    TypeFunction* f = (TypeFunction*)type;
     assert(f != 0);
 
-    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
-    std::vector<const llvm::Type*> args;
-
-    if (fdecl->llvmInternal == LLVMva_start) {
-        args.push_back(i8pty);
-    }
-    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        size_t n = Argument::dim(f->parameters);
-        for (size_t i=0; i<n; ++i) {
-            args.push_back(i8pty);
-        }
-    }
-    else
-    assert(0);
-
-    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
-    f->llvmType = fty;
-    return fty;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
-{
-    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
-        return LLVM_DtoVaFunctionType(fdecl);
-    }
-
-    TypeFunction* f = (TypeFunction*)fdecl->type;
-    assert(f != 0);
-
-    // type has already been resolved
-    if (f->llvmType != 0) {
-        return llvm::cast<llvm::FunctionType>(f->llvmType);
-    }
-
     bool typesafeVararg = false;
     if (f->linkage == LINKd && f->varargs == 1) {
-        assert(fdecl->v_arguments);
-        Logger::println("v_arguments = %s", fdecl->v_arguments->toChars());
-        assert(fdecl->v_arguments->isParameter());
         typesafeVararg = true;
     }
 
@@ -286,11 +205,12 @@
     bool retinptr = false;
     bool usesthis = false;
 
-    if (fdecl->isMain()) {
+    if (ismain) {
         rettype = llvm::Type::Int32Ty;
         actualRettype = rettype;
     }
-    else if (rt) {
+    else {
+        assert(rt);
         if (LLVM_DtoIsPassedByRef(rt)) {
             rettype = llvm::PointerType::get(LLVM_DtoType(rt));
             actualRettype = llvm::Type::VoidTy;
@@ -301,9 +221,6 @@
             actualRettype = rettype;
         }
     }
-    else {
-        assert(0);
-    }
 
     // parameter types
     std::vector<const llvm::Type*> paramvec;
@@ -313,21 +230,8 @@
         paramvec.push_back(rettype);
     }
 
-    if (fdecl->needThis()) {
-        if (AggregateDeclaration* ad = fdecl->isMember()) {
-            Logger::print("isMember = this is: %s\n", ad->type->toChars());
-            const llvm::Type* thisty = LLVM_DtoType(ad->type);
-            Logger::cout() << "this llvm type: " << *thisty << '\n';
-            if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
-                thisty = llvm::PointerType::get(thisty);
-            paramvec.push_back(thisty);
-            usesthis = true;
-        }
-        else
-        assert(0);
-    }
-    else if (fdecl->isNested()) {
-        paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
+    if (thistype) {
+        paramvec.push_back(thistype);
         usesthis = true;
     }
 
@@ -396,7 +300,6 @@
     bool isvararg = !typesafeVararg && f->varargs;
     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
 
-    f->llvmType = functype;
     f->llvmRetInPtr = retinptr;
     f->llvmUsesThis = usesthis;
     return functype;
@@ -404,6 +307,67 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
+{
+    TypeFunction* f = (TypeFunction*)fdecl->type;
+    assert(f != 0);
+
+    const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    std::vector<const llvm::Type*> args;
+
+    if (fdecl->llvmInternal == LLVMva_start) {
+        args.push_back(i8pty);
+    }
+    else if (fdecl->llvmInternal == LLVMva_intrinsic) {
+        size_t n = Argument::dim(f->parameters);
+        for (size_t i=0; i<n; ++i) {
+            args.push_back(i8pty);
+        }
+    }
+    else
+    assert(0);
+
+    const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
+    f->llvmType = fty;
+    return fty;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
+{
+    if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
+        return LLVM_DtoVaFunctionType(fdecl);
+    }
+
+    // type has already been resolved
+    if (fdecl->type->llvmType != 0) {
+        return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
+    }
+
+    const llvm::Type* thisty = NULL;
+    if (fdecl->needThis()) {
+        if (AggregateDeclaration* ad = fdecl->isMember()) {
+            Logger::print("isMember = this is: %s\n", ad->type->toChars());
+            thisty = LLVM_DtoType(ad->type);
+            Logger::cout() << "this llvm type: " << *thisty << '\n';
+            if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
+                thisty = llvm::PointerType::get(thisty);
+        }
+        else
+        assert(0);
+    }
+    else if (fdecl->isNested()) {
+        thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
+    }
+
+    const llvm::FunctionType* functype = LLVM_DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
+    fdecl->type->llvmType = functype;
+    return functype;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 const llvm::StructType* LLVM_DtoDelegateType(Type* t)
 {
     const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
--- a/gen/tollvm.h	Sun Oct 28 19:48:57 2007 +0100
+++ b/gen/tollvm.h	Mon Oct 29 03:28:12 2007 +0100
@@ -11,7 +11,7 @@
 llvm::Value* LLVM_DtoStructCopy(llvm::Value* dst, llvm::Value* src);
 llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si);
 
-const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
+const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
 const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
 llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl);
 
--- a/gen/toobj.c	Sun Oct 28 19:48:57 2007 +0100
+++ b/gen/toobj.c	Mon Oct 29 03:28:12 2007 +0100
@@ -296,7 +296,8 @@
     gIR->structs.pop_back();
 
     // generate typeinfo
-    //type->getTypeInfo(NULL);
+    if (getModule() == gIR->dmodule)
+        type->getTypeInfo(NULL);
 }
 
 /* ================================================================== */
@@ -624,8 +625,7 @@
     LOG_SCOPE;
 
     // generate typeinfo
-    if (!type->builtinTypeInfo())
-        type->getTypeInfo(NULL);
+    type->getTypeInfo(NULL);
 }
 
 /* ================================================================== */
--- a/gen/typinf.c	Sun Oct 28 19:48:57 2007 +0100
+++ b/gen/typinf.c	Mon Oct 29 03:28:12 2007 +0100
@@ -263,12 +263,6 @@
 void TypeInfoDeclaration::toDt(dt_t **pdt)
 {
     assert(0 && "TypeInfoDeclaration");
-
-    /*
-    //printf("TypeInfoDeclaration::toDt() %s\n", toChars());
-    dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo
-    dtdword(pdt, 0);                // monitor
-    */
 }
 
 /* ========================================================================= */
@@ -316,7 +310,6 @@
     if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
     {
         sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
-        //sinits.push_back(initZ->getOperand(3));
     }
     else
     {
@@ -334,43 +327,6 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
 
     llvmValue = gvar;
-
-    /*
-    dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Ttypedef);
-
-    TypeTypedef *tc = (TypeTypedef *)tinfo;
-    TypedefDeclaration *sd = tc->sym;
-    //printf("basetype = %s\n", sd->basetype->toChars());
-
-    // Put out:
-    //  TypeInfo base;
-    //  char[] name;
-    //  void[] m_init;
-
-    sd->basetype = sd->basetype->merge();
-    sd->basetype->getTypeInfo(NULL);        // generate vtinfo
-    assert(sd->basetype->vtinfo);
-    dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr);   // TypeInfo for basetype
-
-    char *name = sd->toPrettyChars();
-    size_t namelen = strlen(name);
-    dtdword(pdt, namelen);
-    dtabytes(pdt, TYnptr, 0, namelen + 1, name);
-
-    // void[] init;
-    if (tinfo->isZeroInit() || !sd->init)
-    {   // 0 initializer, or the same as the base type
-    dtdword(pdt, 0);    // init.length
-    dtdword(pdt, 0);    // init.ptr
-    }
-    else
-    {
-    dtdword(pdt, sd->type->size()); // init.length
-    dtxoff(pdt, sd->toInitializer(), 0, TYnptr);    // init.ptr
-    */
 }
 
 /* ========================================================================= */
@@ -418,7 +374,6 @@
     if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
     {
         sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
-        //sinits.push_back(initZ->getOperand(3));
     }
     else
     {
@@ -437,44 +392,6 @@
     llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
 
     llvmValue = gvar;
-
-    /*
-
-    //printf("TypeInfoEnumDeclaration::toDt()\n");
-    dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum
-    dtdword(pdt, 0);                // monitor
-
-    assert(tinfo->ty == Tenum);
-
-    TypeEnum *tc = (TypeEnum *)tinfo;
-    EnumDeclaration *sd = tc->sym;
-
-    // Put out:
-    //  TypeInfo base;
-    //  char[] name;
-    //  void[] m_init;
-
-    sd->memtype->getTypeInfo(NULL);
-    dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr);    // TypeInfo for enum members
-
-    char *name = sd->toPrettyChars();
-    size_t namelen = strlen(name);
-    dtdword(pdt, namelen);
-    dtabytes(pdt, TYnptr, 0, namelen + 1, name);
-
-    // void[] init;
-    if (tinfo->isZeroInit() || !sd->defaultval)
-    {   // 0 initializer, or the same as the base type
-    dtdword(pdt, 0);    // init.length
-    dtdword(pdt, 0);    // init.ptr
-    }
-    else
-    {
-    dtdword(pdt, sd->type->size()); // init.length
-    dtxoff(pdt, sd->toInitializer(), 0, TYnptr);    // init.ptr
-    }
-
-    */
 }
 
 /* ========================================================================= */
@@ -610,7 +527,166 @@
 
 void TypeInfoStructDeclaration::toDt(dt_t **pdt)
 {
-    assert(0 && "TypeInfoStructDeclaration");
+    Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    assert(tinfo->ty == Tstruct);
+    TypeStruct *tc = (TypeStruct *)tinfo;
+    StructDeclaration *sd = tc->sym;
+
+    ClassDeclaration* base = Type::typeinfostruct;
+    base->toObjFile();
+
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(base->llvmVtbl);
+
+    // char[] name
+    char *name = sd->toPrettyChars();
+    sinits.push_back(LLVM_DtoConstString(name));
+    assert(sinits.back()->getType() == stype->getElementType(1));
+
+    // void[] init
+    const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    if (sd->zeroInit) // 0 initializer, or the same as the base type
+    {
+        sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
+    }
+    else
+    {
+        assert(sd->llvmInitZ);
+        size_t cisize = gTargetData->getTypeSize(tc->llvmType);
+        llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
+        sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(cisize), cicast));
+    }
+
+    // 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);
+    }
+
+#if 0
+    TypeFunction *tfeq;
+    {
+    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
+
+    const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
+
+    s = search_function(sd, Id::tohash);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    if (fdx)
+    {
+        fd = fdx->overloadExactMatch(tftohash);
+        if (fd) {
+            assert(fd->llvmValue != 0);
+            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+            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);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    for (int i = 0; i < 2; i++)
+    {
+        ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
+        if (fdx)
+        {
+            fd = fdx->overloadExactMatch(tfeqptr);
+            if (fd) {
+                assert(fd->llvmValue != 0);
+                llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+                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;
+    }
+
+    ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
+    s = search_function(sd, Id::tostring);
+    fdx = s ? s->isFuncDeclaration() : NULL;
+    if (fdx)
+    {
+        fd = fdx->overloadExactMatch(tftostring);
+        if (fd) {
+            assert(fd->llvmValue != 0);
+            llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
+            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;
+    sinits.push_back(LLVM_DtoConstUint(tc->hasPointers()));
+
+    // create the symbol
+    llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
+
+    llvmValue = gvar;
 
     /*
     //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
--- a/lphobos/internal/objectimpl.d	Sun Oct 28 19:48:57 2007 +0100
+++ b/lphobos/internal/objectimpl.d	Mon Oct 29 03:28:12 2007 +0100
@@ -937,6 +937,8 @@
     ClassInfo info;
 }
 
++/
+
 class TypeInfo_Struct : TypeInfo
 {
     char[] toString() { return name; }
@@ -987,7 +989,7 @@
     return c;
     }
 
-    int compare(void *p2, void *p1)
+    int compare(void *p1, void *p2)
     {
     int c = 0;
 
@@ -1029,6 +1031,8 @@
     uint m_flags;
 }
 
+/+
+
 class TypeInfo_Tuple : TypeInfo
 {
     TypeInfo[] elements;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug38.d	Mon Oct 29 03:28:12 2007 +0100
@@ -0,0 +1,12 @@
+module bug38;
+
+void func(int* p)
+{
+    p++;
+}
+
+void main()
+{
+    int i;
+    func(&i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug39.d	Mon Oct 29 03:28:12 2007 +0100
@@ -0,0 +1,13 @@
+module bug39;
+
+struct S
+{
+    long l;
+}
+
+void main()
+{
+    S s;
+    s.l = 23;
+    void* p = &s;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug40.d	Mon Oct 29 03:28:12 2007 +0100
@@ -0,0 +1,12 @@
+module bug40;
+
+char[] func(void* p)
+{
+    return null;
+}
+
+void main()
+{
+    char[] function(void*) fp = &func;
+    assert(fp(null) is null);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/typeinfo10.d	Mon Oct 29 03:28:12 2007 +0100
@@ -0,0 +1,64 @@
+module typeinfo10;
+
+struct S
+{
+    long l;
+    float f;
+    void* vp;
+
+    hash_t toHash()
+    {
+        return l + cast(size_t)f;
+    }
+
+    int opEquals(S s)
+    {
+        return (s.l == l) && (s.f == f);
+    }
+
+    int opCmp(S a)
+    {
+        if (l == a.l) {
+            return (f < a.f) ? -1 : (f > a.f) ? 1 : 0;
+        }
+        return (l < a.l) ? -1 : 1;
+    }
+
+    char[] toString()
+    {
+        return "S instance";
+    }
+}
+
+void main()
+{
+    S s=S(-1, 0);
+    S t=S(-1, 1);
+    S u=S(11,-1);
+    S v=S(12,13);
+
+    {
+        assert(s == s);
+        assert(s != t);
+        assert(s != v);
+        assert(s < t);
+        assert(u > s);
+        assert(v > u);
+    }
+
+    {
+        auto ti = typeid(S);
+        assert(ti.getHash(&s) == s.toHash());
+        assert(ti.equals(&s,&s));
+        assert(!ti.equals(&s,&t));
+        assert(!ti.equals(&s,&v));
+        assert(ti.compare(&s,&s) == 0);
+        assert(ti.compare(&s,&t) < 0);
+        assert(ti.compare(&u,&s) > 0);
+        assert(ti.compare(&v,&u) > 0);
+        {
+            auto tis = cast(TypeInfo_Struct)ti;
+            assert(tis.xtoString(&s) == s.toString());
+        }
+    }
+}