changeset 54:28e99b04a132 trunk

[svn r58] Fixed cond expression resulting in a non-basic type. Fixed identity expression for dynamic arrays. Revamped the system to keep track of lvalues and rvalues and their relations. Typedef declaration now generate the custom typeinfo. Other bugfixes.
author lindquist
date Wed, 24 Oct 2007 01:37:34 +0200
parents 06ccc817acd4
children 0ccfae271c45
files dmd/aggregate.h dmd/struct.c gen/arrays.c gen/arrays.h gen/irstate.c gen/irstate.h gen/statements.c gen/toir.c gen/tollvm.c gen/tollvm.h gen/toobj.c gen/typinf.c lphobos/internal/objectimpl.d test/bug32.d test/bug33.d test/condexp1.d test/typeinfo3.d
diffstat 17 files changed, 371 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Tue Oct 23 07:16:02 2007 +0200
+++ b/dmd/aggregate.h	Wed Oct 24 01:37:34 2007 +0200
@@ -40,6 +40,7 @@
     class Type;
     class Value;
     class Constant;
+    class ConstantStruct;
 }
 
 struct AggregateDeclaration : ScopeDsymbol
@@ -98,6 +99,7 @@
     bool llvmInProgress;
     llvm::Type* llvmType;
     llvm::Value* 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/struct.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/dmd/struct.c	Wed Oct 24 01:37:34 2007 +0200
@@ -47,6 +47,7 @@
 
     llvmType = NULL;
     llvmVtbl = NULL;
+    llvmConstVtbl = NULL;
     llvmInitZ = NULL;
     llvmInProgress = false;
 }
--- a/gen/arrays.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/arrays.c	Wed Oct 24 01:37:34 2007 +0200
@@ -100,6 +100,7 @@
     }
     else
     {
+        Logger::cout() << "array assignment type dont match: " << *dst->getType() << '\n' << *src->getType() << '\n';
         if (!llvm::isa<llvm::ArrayType>(src->getType()->getContainedType(0)))
         {
             Logger::cout() << "invalid: " << *src << '\n';
@@ -109,7 +110,7 @@
         llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
 
         llvm::Value* dstlen = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-        llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
+        llvm::Value* srclen = LLVM_DtoConstSize_t(arrty->getNumElements());
         new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
 
         llvm::Value* dstptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
@@ -551,3 +552,25 @@
     args.push_back(llvm::ConstantInt::get(LLVM_DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
     return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r)
+{
+    assert(l->getType() == r->getType());
+
+    llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
+
+    llvm::Value* ll = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,0, "tmp"),"tmp");
+    llvm::Value* rl = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,0, "tmp"),"tmp");
+    llvm::Value* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
+
+    llvm::Value* lp = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,1, "tmp"),"tmp");
+    llvm::Value* rp = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,1, "tmp"),"tmp");
+    llvm::Value* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
+
+    llvm::Value* b = gIR->ir->CreateAnd(b1,b2,"tmp");
+    if (op == TOKnotidentity)
+        return gIR->ir->CreateNot(b,"tmp");
+    else
+        return b;
+}
--- a/gen/arrays.h	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/arrays.h	Wed Oct 24 01:37:34 2007 +0200
@@ -22,7 +22,9 @@
 void LLVM_DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
 
 llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
+
 llvm::Value* LLVM_DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
+llvm::Value* LLVM_DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r);
 
 llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty);
 
--- a/gen/irstate.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/irstate.c	Wed Oct 24 01:37:34 2007 +0200
@@ -35,7 +35,6 @@
 {
     dmodule = 0;
     module = 0;
-    inLvalue = false;
     emitMain = false;
     mainFunc = 0;
     ir.state = this;
@@ -71,10 +70,9 @@
     return structs.back();
 }
 
-llvm::Value* IRState::toplval()
+IRExp* IRState::topexp()
 {
-    assert(!lvals.empty() && "Lval vector is empty!");
-    return lvals.back();
+    return exps.empty() ? NULL : &exps.back();
 }
 
 IRScope& IRState::scope()
@@ -153,3 +151,18 @@
     func = NULL;
     allocapoint = NULL;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+IRExp::IRExp()
+{
+    e1 = e2 = NULL;
+    v = NULL;
+}
+
+IRExp::IRExp(Expression* l, Expression* r, llvm::Value* val)
+{
+    e1 = l;
+    e2 = r;
+    v = val;
+}
--- a/gen/irstate.h	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/irstate.h	Wed Oct 24 01:37:34 2007 +0200
@@ -88,6 +88,15 @@
     LLVMBuilder* operator->();
 };
 
+struct IRExp
+{
+    Expression* e1;
+    Expression* e2;
+    llvm::Value* v;
+    IRExp();
+    IRExp(Expression* l, Expression* r, llvm::Value* val);
+};
+
 // represents the module
 struct IRState
 {
@@ -119,11 +128,10 @@
     bool emitMain;
     llvm::Function* mainFunc;
 
-    // L-values
-    bool inLvalue;
-    typedef std::vector<llvm::Value*> LvalVec;
-    LvalVec lvals;
-    llvm::Value* toplval();
+    // expression l/r value handling
+    typedef std::vector<IRExp> ExpVec;
+    ExpVec exps;
+    IRExp* topexp();
 
     // basic block scopes
     std::vector<IRScope> scopes;
@@ -141,7 +149,7 @@
     // might be a better way but it works. problem is I only get a
     // VarDeclaration for __dollar, but I can't see how to get the
     // array pointer from this :(
-    LvalVec arrays;
+    std::vector<llvm::Value*> arrays;
 
     // builder helper
     IRBuilderHelper ir;
--- a/gen/statements.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/statements.c	Wed Oct 24 01:37:34 2007 +0200
@@ -51,10 +51,10 @@
     Logger::println("ReturnStatement::toIR(%d): %s", rsi++, toChars());
     LOG_SCOPE;
 
-    IRFunction::FinallyVec& fin = p->func().finallys;
-
     if (exp)
     {
+        Logger::println("return type is: %s", exp->type->toChars());
+
         Type* exptype = LLVM_DtoDType(exp->type);
         TY expty = exptype->ty;
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
@@ -63,28 +63,36 @@
             TypeFunction* f = p->topfunctype();
             assert(f->llvmRetInPtr && f->llvmRetArg);
 
-            p->lvals.push_back(f->llvmRetArg);
+            p->exps.push_back(IRExp(NULL,exp,f->llvmRetArg));
             elem* e = exp->toElem(p);
-            p->lvals.pop_back();
+            p->exps.pop_back();
 
             if (expty == Tstruct) {
-                if (!e->inplace) {
-                    assert(e->mem);
-                    LLVM_DtoStructCopy(f->llvmRetArg,e->mem);
-                }
+                if (!e->inplace)
+                    LLVM_DtoStructCopy(f->llvmRetArg,e->getValue());
             }
             else if (expty == Tdelegate) {
-                LLVM_DtoDelegateCopy(f->llvmRetArg,e->mem);
+                if (!e->inplace)
+                    LLVM_DtoDelegateCopy(f->llvmRetArg,e->getValue());
             }
             else if (expty == Tarray) {
                 if (e->type == elem::SLICE) {
+                    assert(e->mem);
                     LLVM_DtoSetArray(f->llvmRetArg,e->arg,e->mem);
                 }
-                // else the return value is a variable and should already have been assigned by now
+                else if (!e->inplace) {
+                    if (e->type == elem::NUL) {
+                        LLVM_DtoNullArray(f->llvmRetArg);
+                    }
+                    else {
+                        LLVM_DtoArrayAssign(f->llvmRetArg, e->getValue());
+                    }
+                }
             }
             else
             assert(0);
 
+            IRFunction::FinallyVec& fin = p->func().finallys;
             if (fin.empty())
                 new llvm::ReturnInst(p->scopebb());
             else {
@@ -98,6 +106,8 @@
             llvm::Value* v = e->getValue();
             delete e;
             Logger::cout() << "return value is '" <<*v << "'\n";
+
+            IRFunction::FinallyVec& fin = p->func().finallys;
             if (fin.empty()) {
                 new llvm::ReturnInst(v, p->scopebb());
             }
@@ -113,6 +123,7 @@
     else
     {
         if (p->topfunc()->getReturnType() == llvm::Type::VoidTy) {
+            IRFunction::FinallyVec& fin = p->func().finallys;
             if (fin.empty()) {
                 new llvm::ReturnInst(p->scopebb());
             }
--- a/gen/toir.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/toir.c	Wed Oct 24 01:37:34 2007 +0200
@@ -377,19 +377,16 @@
 
     if (dtype->ty == Tarray) {
         llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
-        if (p->lvals.empty() || !p->toplval()) {
+        if (!p->topexp() || p->topexp()->e2 != this) {
             llvm::Value* tmpmem = new llvm::AllocaInst(LLVM_DtoType(dtype),"tmp",p->topallocapoint());
             LLVM_DtoSetArray(tmpmem, clen, arrptr);
             e->mem = tmpmem;
         }
-        else if (llvm::Value* arr = p->toplval()) {
-            if (llvm::isa<llvm::GlobalVariable>(arr)) {
-                e->val = LLVM_DtoConstantSlice(clen, arrptr);
-            }
-            else {
-                LLVM_DtoSetArray(arr, clen, arrptr);
-                e->inplace = true;
-            }
+        else if (p->topexp()->e2 == this) {
+            llvm::Value* arr = p->topexp()->v;
+            assert(arr);
+            LLVM_DtoSetArray(arr, clen, arrptr);
+            e->inplace = true;
         }
         else
         assert(0);
@@ -453,14 +450,13 @@
     Logger::print("AssignExp::toElem: %s | %s = %s\n", toChars(), e1->type->toChars(), e2->type->toChars());
     LOG_SCOPE;
 
-    assert(e1 && e2);
-    p->inLvalue = true;
-        elem* l = e1->toElem(p);
-    p->inLvalue = false;
-
-    p->lvals.push_back(l->mem);
-        elem* r = e2->toElem(p);
-    p->lvals.pop_back();
+    p->exps.push_back(IRExp(e1,e2,NULL));
+
+    elem* l = e1->toElem(p);
+    p->topexp()->v = l->mem;
+    elem* r = e2->toElem(p);
+
+    p->exps.pop_back();
 
     if (l->type == elem::ARRAYLEN)
     {
@@ -1066,11 +1062,14 @@
 
     Logger::println("hidden struct return");
 
+    IRExp* topexp = p->topexp();
+
     // hidden struct return arguments
     if (retinptr) {
-        if (!p->lvals.empty() && p->toplval()) {
-            assert(llvm::isa<llvm::StructType>(p->toplval()->getType()->getContainedType(0)));
-            llargs[j] = p->toplval();
+        if (topexp && topexp->e2 == this) {
+            assert(topexp->v);
+            assert(llvm::isa<llvm::StructType>(topexp->v->getType()->getContainedType(0)));
+            llargs[j] = topexp->v;
             if (LLVM_DtoIsPassedByRef(tf->next)) {
                 e->inplace = true;
             }
@@ -1534,17 +1533,19 @@
     llvm::Value* sptr = 0;
 
     // if there is no lval, this is probably a temporary struct literal. correct?
-    if (p->lvals.empty() || !p->toplval())
+    if (!p->topexp() || p->topexp()->e2 != this)
     {
         sptr = new llvm::AllocaInst(LLVM_DtoType(type),"tmpstructliteral",p->topallocapoint());
         e->mem = sptr;
         e->type = elem::VAR;
     }
     // already has memory
-    else
+    else if (p->topexp()->e2 == this)
     {
-        sptr = p->toplval();
+        sptr = p->topexp()->v;
     }
+    else
+    assert(0);
 
     assert(sptr);
 
@@ -1558,9 +1559,9 @@
 
         Expression* vx = (Expression*)elements->data[i];
         if (vx != 0) {
-            p->lvals.push_back(arrptr);
+            p->exps.push_back(IRExp(NULL,vx,arrptr));
             elem* ve = vx->toElem(p);
-            p->lvals.pop_back();
+            p->exps.pop_back();
 
             if (!ve->inplace) {
                 llvm::Value* val = ve->getValue();
@@ -2042,7 +2043,8 @@
             if (arguments->dim == 1) {
                 elem* sz = ((Expression*)arguments->data[0])->toElem(p);
                 llvm::Value* dimval = sz->getValue();
-                LLVM_DtoNewDynArray(p->toplval(), dimval, ntype->next);
+                assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
+                LLVM_DtoNewDynArray(p->topexp()->v, dimval, ntype->next);
                 delete sz;
             }
             else {
@@ -2161,7 +2163,7 @@
     elem* e = new elem;
     elem* u = e1->toElem(p);
 
-    if (p->inLvalue)
+    if (p->topexp() && p->topexp()->e1 == this)
     {
         e->mem = u->mem;
         e->type = elem::ARRAYLEN;
@@ -2372,26 +2374,27 @@
 
     elem* e = new elem;
     elem* u = e1->toElem(p);
-    
+
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
-    
+
     const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty);
 
-    llvm::Value* lval = p->toplval();
+    assert(p->topexp() && p->topexp()->e2 == this && p->topexp()->v);
+    llvm::Value* lval = p->topexp()->v;
 
     llvm::Value* context = LLVM_DtoGEP(lval,zero,zero,"tmp",p->scopebb());
     llvm::Value* castcontext = new llvm::BitCastInst(u->getValue(),int8ptrty,"tmp",p->scopebb());
     new llvm::StoreInst(castcontext, context, p->scopebb());
-    
+
     llvm::Value* fptr = LLVM_DtoGEP(lval,zero,one,"tmp",p->scopebb());
-    
+
     assert(func->llvmValue);
     llvm::Value* castfptr = new llvm::BitCastInst(func->llvmValue,fptr->getType()->getContainedType(0),"tmp",p->scopebb());
     new llvm::StoreInst(castfptr, fptr, p->scopebb());
-    
+
     e->inplace = true;
-    
+
     delete u;
     return e;
 }
@@ -2415,8 +2418,16 @@
     else
     r = v->getValue();
 
-    llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
-    e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
+    Type* t1 = LLVM_DtoDType(e1->type);
+
+    if (t1->ty == Tarray) {
+        assert(l->getType() == r->getType());
+        e->val = LLVM_DtoDynArrayIs(op,l,r);
+    }
+    else {
+        llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
+        e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
+    }
     e->type = elem::VAL;
 
     delete u;
@@ -2445,7 +2456,8 @@
     Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    const llvm::Type* resty = LLVM_DtoType(type);
+    Type* dtype = LLVM_DtoDType(type);
+    const llvm::Type* resty = LLVM_DtoType(dtype);
 
     // allocate a temporary for the final result. failed to come up with a better way :/
     llvm::BasicBlock* entryblock = &p->topfunc()->front();
@@ -2463,21 +2475,21 @@
 
     p->scope() = IRScope(condtrue, condfalse);
     elem* u = e1->toElem(p);
-    new llvm::StoreInst(u->getValue(),resval,p->scopebb());
+    LLVM_DtoAssign(dtype, resval, u->getValue());
     new llvm::BranchInst(condend,p->scopebb());
     delete u;
 
     p->scope() = IRScope(condfalse, condend);
     elem* v = e2->toElem(p);
-    new llvm::StoreInst(v->getValue(),resval,p->scopebb());
+    LLVM_DtoAssign(dtype, resval, v->getValue());
     new llvm::BranchInst(condend,p->scopebb());
     delete v;
 
     p->scope() = IRScope(condend, oldend);
 
     elem* e = new elem;
-    e->val = new llvm::LoadInst(resval,"tmp",p->scopebb());
-    e->type = elem::VAL;
+    e->mem = resval;
+    e->type = elem::VAR;
     return e;
 }
 
@@ -2589,12 +2601,13 @@
     Logger::cout() << "array literal has llvm type: " << *t << '\n';
 
     llvm::Value* mem = 0;
-    if (p->lvals.empty() || !p->toplval()) {
+    if (!p->topexp() || p->topexp()->e2 != this) {
         assert(LLVM_DtoDType(type)->ty == Tsarray);
         mem = new llvm::AllocaInst(t,"tmparrayliteral",p->topallocapoint());
     }
-    else {
-        mem = p->toplval();
+    else if (p->topexp()->e2 == this) {
+        mem = p->topexp()->v;
+        assert(mem);
         if (!llvm::isa<llvm::PointerType>(mem->getType()) ||
             !llvm::isa<llvm::ArrayType>(mem->getType()->getContainedType(0)))
         {
@@ -2602,6 +2615,8 @@
             fatal();
         }
     }
+    else
+    assert(0);
 
     for (unsigned i=0; i<elements->dim; ++i)
     {
@@ -2657,14 +2672,17 @@
     fd->toObjFile();
 
     llvm::Value* lval = NULL;
-    if (p->lvals.empty() || p->toplval() == NULL) {
+    if (!p->topexp() || p->topexp()->e2 != this) {
         const llvm::Type* dgty = LLVM_DtoType(type);
         Logger::cout() << "delegate without explicit storage:" << '\n' << *dgty << '\n';
         lval = new llvm::AllocaInst(dgty,"dgstorage",p->topallocapoint());
     }
-    else {
-        lval = p->toplval();
+    else if (p->topexp()->e2 == this) {
+        lval = p->topexp()->v;
+        assert(lval);
     }
+    else
+    assert(0);
 
     elem* e = new elem;
 
--- a/gen/tollvm.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/tollvm.c	Wed Oct 24 01:37:34 2007 +0200
@@ -1100,14 +1100,14 @@
 {
     llvm::Value* retval = 0;
 
-    bool haslvals = !gIR->lvals.empty();
+    bool haslvals = !gIR->exps.empty();
     if (haslvals)
-        gIR->lvals.push_back(NULL);
+        gIR->exps.push_back(IRExp(NULL,NULL,NULL));
 
     elem* arg = argexp->toElem(gIR);
 
     if (haslvals)
-        gIR->lvals.pop_back();
+        gIR->exps.pop_back();
 
     if (arg->inplace) {
         assert(arg->mem != 0);
@@ -1254,3 +1254,29 @@
         gIR->ir->CreateStore(rhs, lhs);
     }
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::ConstantInt* LLVM_DtoConstSize_t(size_t i)
+{
+    return llvm::ConstantInt::get(LLVM_DtoSize_t(), i, false);
+}
+llvm::ConstantInt* LLVM_DtoConstUint(unsigned i)
+{
+    return llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* LLVM_DtoConstString(const char* str)
+{
+    std::string s(str);
+    llvm::Constant* init = llvm::ConstantArray::get(s, true);
+    llvm::GlobalVariable* gvar = new llvm::GlobalVariable(
+        init->getType(), true,llvm::GlobalValue::InternalLinkage, init, "stringliteral", gIR->module);
+    llvm::Constant* idxs[2] = { LLVM_DtoConstUint(0), LLVM_DtoConstUint(0) };
+    return LLVM_DtoConstantSlice(
+        LLVM_DtoConstSize_t(s.length()),
+        llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2)
+    );
+}
--- a/gen/tollvm.h	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/tollvm.h	Wed Oct 24 01:37:34 2007 +0200
@@ -59,4 +59,8 @@
 
 void LLVM_DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs);
 
+llvm::ConstantInt* LLVM_DtoConstSize_t(size_t);
+llvm::ConstantInt* LLVM_DtoConstUint(unsigned i);
+llvm::Constant* LLVM_DtoConstString(const char*);
+
 #include "enums.h"
--- a/gen/toobj.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/toobj.c	Wed Oct 24 01:37:34 2007 +0200
@@ -363,10 +363,10 @@
     ts->llvmType = structtype;
     llvmType = structtype;
 
-    bool define_vtable = false;
+    bool needs_definition = false;
     if (parent->isModule()) {
         gIR->module->addTypeName(mangle(),ts->llvmType);
-        define_vtable = (getModule() == gIR->dmodule);
+        needs_definition = (getModule() == gIR->dmodule);
     }
     else {
         assert(0 && "class parent is not a module");
@@ -418,9 +418,9 @@
         gIR->module->addTypeName(styname, svtbl_ty);
         svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module);
 
-        if (define_vtable) {
-            svtblVar->setInitializer(llvm::ConstantStruct::get(svtbl_ty, sinits));
-        }
+        llvmConstVtbl = llvm::cast<llvm::ConstantStruct>(llvm::ConstantStruct::get(svtbl_ty, sinits));
+        if (needs_definition)
+            svtblVar->setInitializer(llvmConstVtbl);
         llvmVtbl = svtblVar;
     }
 
@@ -441,25 +441,25 @@
     assert(svtblVar != 0);
     gIR->topstruct().inits[0] = svtblVar;
 
-    _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
+    llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
     assert(_init);
 
     std::string initname("_D");
     initname.append(mangle());
     initname.append("6__initZ");
     //Logger::cout() << *_init << '\n';
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
+    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, NULL, initname, gIR->module);
     ts->llvmInit = initvar;
-    if (define_vtable) {
-        initvar->setInitializer(_init);
-    }
 
-    // generate member function definitions
-    gIR->topstruct().queueFuncs = false;
-    IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
-    size_t n = mfs.size();
-    for (size_t i=0; i<n; ++i) {
-        mfs[i]->toObjFile();
+    if (needs_definition) {
+        initvar->setInitializer(_init);
+        // generate member functions
+        gIR->topstruct().queueFuncs = false;
+        IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs;
+        size_t n = mfs.size();
+        for (size_t i=0; i<n; ++i) {
+            mfs[i]->toObjFile();
+        }
     }
 
     gIR->classes.pop_back();
@@ -525,9 +525,7 @@
         // if extern don't emit initializer
         if (!(storage_class & STCextern))
         {
-            gIR->lvals.push_back(gvar);
             _init = LLVM_DtoConstInitializer(t, init);
-            gIR->lvals.pop_back();
 
             //Logger::cout() << "initializer: " << *_init << '\n';
             if (_type != _init->getType()) {
@@ -628,7 +626,8 @@
     LOG_SCOPE;
 
     // generate typeinfo
-    type->getTypeInfo(NULL);
+    if (!type->builtinTypeInfo())
+        type->getTypeInfo(NULL);
 }
 
 /* ================================================================== */
--- a/gen/typinf.c	Tue Oct 23 07:16:02 2007 +0200
+++ b/gen/typinf.c	Wed Oct 24 01:37:34 2007 +0200
@@ -30,6 +30,8 @@
 #include "gen/irstate.h"
 #include "gen/logger.h"
 #include "gen/runtime.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
 
 /*******************************************
  * Get a canonicalized form of the TypeInfo for use with the internal
@@ -242,10 +244,20 @@
     if (llvmTouched) return;
     else llvmTouched = true;
 
-    Logger::println("Getting typeinfo var: %s", mangle());
-    llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
-    assert(llvmValue);
-    Logger::cout() << "Got:" << '\n' << *llvmValue << '\n';
+    Logger::println("typeinfo mangle: %s", mangle());
+
+    if (tinfo->builtinTypeInfo()) {
+        // this is a declaration of a builtin __initZ var
+        llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
+        assert(llvmValue);
+        Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
+    }
+    else {
+        toDt(NULL);
+        // this is a specialized typeinfo
+        //std::vector<const llvm::Type*> stypes;
+        //stypes.push_back(
+    }
 }
 
 /* ========================================================================= */
@@ -257,7 +269,89 @@
 
 void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
 {
-    assert(0 && "TypeInfoTypedefDeclaration");
+    Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
+    LOG_SCOPE;
+
+    ClassDeclaration* base = Type::typeinfotypedef;
+    base->toObjFile();
+
+    llvm::Constant* initZ = base->llvmInitZ;
+    assert(initZ);
+    const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
+
+    std::vector<llvm::Constant*> sinits;
+    sinits.push_back(initZ->getOperand(0));
+
+    assert(tinfo->ty == Ttypedef);
+    TypeTypedef *tc = (TypeTypedef *)tinfo;
+    TypedefDeclaration *sd = tc->sym;
+
+    // TypeInfo base
+    //const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
+    //sinits.push_back(llvm::ConstantPointerNull::get(basept));
+    Logger::println("generating base typeinfo");
+    //sd->basetype = sd->basetype->merge();
+    sd->basetype->getTypeInfo(NULL);        // generate vtinfo
+    assert(sd->basetype->vtinfo);
+    if (!sd->basetype->vtinfo->llvmValue)
+        sd->basetype->vtinfo->toObjFile();
+    assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
+    llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
+    castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
+    sinits.push_back(castbase);
+
+    // char[] name
+    char *name = sd->toPrettyChars();
+    sinits.push_back(LLVM_DtoConstString(name));
+    assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
+
+    // void[] init
+    //const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
+    //sinits.push_back(LLVM_DtoConstantSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
+    sinits.push_back(initZ->getOperand(3));
+
+    // 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;
+
+    /*
+    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
+    */
 }
 
 void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
--- a/lphobos/internal/objectimpl.d	Tue Oct 23 07:16:02 2007 +0200
+++ b/lphobos/internal/objectimpl.d	Wed Oct 24 01:37:34 2007 +0200
@@ -433,8 +433,6 @@
     OffsetTypeInfo[] offTi() { return null; }
 }
 
-/+
-
 class TypeInfo_Typedef : TypeInfo
 {
     char[] toString() { return name; }
@@ -455,7 +453,7 @@
     size_t tsize() { return base.tsize(); }
     void swap(void *p1, void *p2) { return base.swap(p1, p2); }
 
-    TypeInfo next() { return base.next(); }
+    TypeInfo next() { return base; }
     uint flags() { return base.flags(); }
     void[] init() { return m_init.length ? m_init : base.init(); }
 
@@ -468,6 +466,8 @@
 {
 }
 
+/+
+
 class TypeInfo_Pointer : TypeInfo
 {
     char[] toString() { return m_next.toString() ~ "*"; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug32.d	Wed Oct 24 01:37:34 2007 +0200
@@ -0,0 +1,14 @@
+module bug32;
+
+struct S
+{
+    char[] getName() { return name; }
+    char[] name;
+}
+
+void main()
+{
+    S s = S("Kyle");
+    char[] name = s.name;
+    printf("%.*s\n", name.length, name.ptr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug33.d	Wed Oct 24 01:37:34 2007 +0200
@@ -0,0 +1,33 @@
+module bug33;
+
+extern(C) int memcmp(void*,void*,size_t);
+
+private int string_cmp(char[] s1, char[] s2)
+{
+    auto len = s1.length;
+    if (s2.length < len)
+        len = s2.length;
+    int result = memcmp(s1.ptr, s2.ptr, len);
+    if (result == 0)
+        result = cast(int)(cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length);
+    return result;
+}
+
+struct S
+{
+    char[] toString()
+    {
+        return "S";
+    }
+}
+
+int func()
+{
+    S a,b;
+    return string_cmp(a.toString(),b.toString());
+}
+
+void main()
+{
+    assert(func() == 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/condexp1.d	Wed Oct 24 01:37:34 2007 +0200
@@ -0,0 +1,12 @@
+module condexp1;
+
+void main()
+{
+    char[] a = "hello";
+    char[] b = "world";
+    int i = 42;
+    {
+    char[] c = i > 50 ? b : a;
+    assert(c is a);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/typeinfo3.d	Wed Oct 24 01:37:34 2007 +0200
@@ -0,0 +1,13 @@
+module typeinfo3;
+
+typedef int int_t;
+
+void main()
+{
+    int_t i;
+    auto ti = typeid(typeof(i));
+    printf("%s\n",ti.toString.ptr);
+    assert(ti.toString() == "typeinfo3.int_t");
+    assert(ti.next !is null);
+    assert(ti.next.toString() == "int");
+}