changeset 203:e881c9b1c738 trunk

[svn r219] Fixed: the tango/lib/gc/basic garbage collector now compiles and links into an executable (change in tango/lib/llvmdc-posix.mak), closes #5 . Changed: removed the crappy realloc based dynamic memory runtime and started moving over to DMD style runtime support, part of moving to real GC. Fixed: dynamic arrays now use GC runtime for allocating memory. Fixed: new expression now use GC for allocating memory. Changed: revamped the dynamic array support routines related to dynamic memory. Fixed: assertions no longer create exsessive allocas. Changed: misc. minor cleanups.
author lindquist
date Tue, 13 May 2008 14:42:09 +0200
parents 56e0c5b1d428
children 11fe364b9a3e
files gen/arrays.cpp gen/arrays.h gen/runtime.cpp gen/toir.cpp gen/tollvm.cpp gen/tollvm.h ir/irfunction.cpp ir/irfunction.h tango/lib/compiler/llvmdc/lifetime.d tango/lib/compiler/llvmdc/llvmdc.mak tango/lib/compiler/llvmdc/mem.d tango/lib/gc/basic/gcx.d tango/lib/llvmdc-posix.mak tangotests/mem1.d test/arrays.d
diffstat 15 files changed, 473 insertions(+), 210 deletions(-) [+]
line wrap: on
line diff
--- a/gen/arrays.cpp	Mon May 12 23:49:07 2008 +0200
+++ b/gen/arrays.cpp	Tue May 13 14:42:09 2008 +0200
@@ -62,6 +62,9 @@
 
 void DtoSetArrayToNull(llvm::Value* v)
 {
+    Logger::println("DtoSetArrayToNull");
+    LOG_SCOPE;
+
     llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb());
     llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false);
     new llvm::StoreInst(zerolen, len, gIR->scopebb());
@@ -76,6 +79,9 @@
 
 void DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
 {
+    Logger::println("DtoArrayAssign");
+    LOG_SCOPE;
+
     assert(gIR);
     if (dst->getType() == src->getType())
     {
@@ -114,6 +120,9 @@
 
 void DtoArrayInit(llvm::Value* l, llvm::Value* r)
 {
+    Logger::println("DtoArrayInit");
+    LOG_SCOPE;
+
     const llvm::PointerType* ptrty = isaPointer(l->getType());
     const llvm::Type* t = ptrty->getContainedType(0);
     const llvm::ArrayType* arrty = isaArray(t);
@@ -151,6 +160,9 @@
 
 void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
 {
+    Logger::println("DtoArrayInit");
+    LOG_SCOPE;
+
     Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
     const llvm::Type* pt = ptr->getType()->getContainedType(0);
     const llvm::Type* t = val->getType();
@@ -244,16 +256,24 @@
 
 void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr)
 {
-    Logger::cout() << "DtoSetArray(" << *arr << ", " << *dim << ", " << *ptr << ")\n";
+    Logger::println("DtoSetArray");
+    LOG_SCOPE;
+
+    Logger::cout() << "arr = " << *arr << '\n';
+    Logger::cout() << "dim = " << *dim << '\n';
+    Logger::cout() << "ptr = " << *ptr << '\n';
+
     const llvm::StructType* st = isaStruct(arr->getType()->getContainedType(0));
 
     llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
     llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
 
     llvm::Value* arrdim = DtoGEP(arr,zero,zero,"tmp",gIR->scopebb());
+    Logger::cout() << "arrdim = " << *arrdim << '\n';
     new llvm::StoreInst(dim, arrdim, gIR->scopebb());
 
     llvm::Value* arrptr = DtoGEP(arr,zero,one,"tmp",gIR->scopebb());
+    Logger::cout() << "arrptr = " << *arrptr << '\n';
     new llvm::StoreInst(ptr, arrptr, gIR->scopebb());
 }
 
@@ -484,60 +504,81 @@
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit)
+DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit)
 {
-    const llvm::Type* ty = DtoType(dty);
-    assert(ty != llvm::Type::VoidTy);
-    size_t sz = getABITypeSize(ty);
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
-    llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
+    Logger::println("DtoNewDynArray : %s", arrayType->toChars());
+    LOG_SCOPE;
+
+    bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
 
-    llvm::Value* nullptr = llvm::ConstantPointerNull::get(getPtrToType(ty));
+    llvm::SmallVector<llvm::Value*,2> args;
+    args.push_back(DtoTypeInfoOf(arrayType));
+    assert(DtoType(dim->getType()) == DtoSize_t());
+    args.push_back(dim->getRVal());
 
-    llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
+    llvm::Value* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
+    const llvm::Type* dstType = DtoType(arrayType)->getContainedType(1);
+    if (newptr->getType() != dstType)
+        newptr = DtoBitCast(newptr, dstType, ".gc_mem");
 
-    if (doinit) {
+    Logger::cout() << "final ptr = " << *newptr << '\n';
+
+#if 0
+    if (defaultInit) {
         DValue* e = dty->defaultInit()->toElem(gIR);
         DtoArrayInit(newptr,dim,e->getRVal());
     }
+#endif
 
-    llvm::Value* lenptr = DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
-    new llvm::StoreInst(dim,lenptr,gIR->scopebb());
-    llvm::Value* ptrptr = DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
-    new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
-
-    return newptr;
+    return new DSliceValue(arrayType, args[1], newptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
+DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
 {
-    llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
-    llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
+    Logger::println("DtoResizeDynArray : %s", arrayType->toChars());
+    LOG_SCOPE;
+
+    assert(array);
+    assert(newdim);
+    assert(arrayType);
+    assert(arrayType->toBasetype()->ty == Tarray);
+
+    bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_arraysetlengthT" : "_d_arraysetlengthiT" );
 
-    size_t isz = getABITypeSize(ptrld->getType()->getContainedType(0));
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false);
-    llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb());
+    llvm::SmallVector<llvm::Value*,4> args;
+    args.push_back(DtoTypeInfoOf(arrayType));
+    args.push_back(newdim->getRVal());
+    args.push_back(DtoArrayLen(array));
+    llvm::Value* arrPtr = DtoArrayPtr(array);
+    Logger::cout() << "arrPtr = " << *arrPtr << '\n';
+    args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp"));
 
-    llvm::Value* newptr = DtoRealloc(ptrld, bytesz);
-    new llvm::StoreInst(newptr,ptr,gIR->scopebb());
+    llvm::Value* newptr = gIR->ir->CreateCall(fn, args.begin(), args.end(), ".gc_mem");
+    if (newptr->getType() != arrPtr->getType())
+        newptr = DtoBitCast(newptr, arrPtr->getType(), ".gc_mem");
 
-    llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
-    new llvm::StoreInst(sz,len,gIR->scopebb());
-
-    return newptr;
+    return new DSliceValue(arrayType, newdim->getRVal(), newptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatAssignElement(llvm::Value* arr, Expression* exp)
+DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp)
 {
-    llvm::Value* ptr = DtoGEPi(arr, 0, 0, "tmp");
-    llvm::Value* idx = DtoLoad(ptr);
-    llvm::Value* one = llvm::ConstantInt::get(idx->getType(),1,false);
-    llvm::Value* len = llvm::BinaryOperator::createAdd(idx, one, "tmp", gIR->scopebb());
-    DtoResizeDynArray(arr,len);
+    Logger::println("DtoCatAssignElement");
+    LOG_SCOPE;
+
+    assert(array);
 
-    ptr = DtoLoad(DtoGEPi(arr, 0, 1, "tmp"));
+    llvm::Value* idx = DtoArrayLen(array);
+    llvm::Value* one = DtoConstSize_t(1);
+    llvm::Value* len = gIR->ir->CreateAdd(idx,one,"tmp");
+
+    DValue* newdim = new DImValue(Type::tsize_t, len);
+    DSliceValue* slice = DtoResizeDynArray(array->getType(), array, newdim);
+
+    llvm::Value* ptr = slice->ptr;
     ptr = new llvm::GetElementPtrInst(ptr, idx, "tmp", gIR->scopebb());
 
     DValue* dptr = new DVarValue(exp->type, ptr, true);
@@ -548,33 +589,47 @@
 
     if (!e->inPlace())
         DtoAssign(dptr, e);
+
+    return slice;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatAssignArray(llvm::Value* arr, Expression* exp)
+DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
 {
+    Logger::println("DtoCatAssignArray");
+    LOG_SCOPE;
+
     DValue* e = exp->toElem(gIR);
 
     llvm::Value *len1, *len2, *src1, *src2, *res;
 
-    DValue* darr = new DVarValue(exp->type, arr, true);
-
-    len1 = DtoArrayLen(darr);
+    len1 = DtoArrayLen(arr);
     len2 = DtoArrayLen(e);
     res = gIR->ir->CreateAdd(len1,len2,"tmp");
 
-    llvm::Value* mem = DtoResizeDynArray(arr,res);
+    DValue* newdim = new DImValue(Type::tsize_t, res);
+    DSliceValue* slice = DtoResizeDynArray(arr->getType(), arr, newdim);
 
-    src1 = DtoArrayPtr(darr);
+    src1 = slice->ptr;
     src2 = DtoArrayPtr(e);
 
-    mem = gIR->ir->CreateGEP(mem,len1,"tmp");
-    DtoMemCpy(mem,src2,len2);
+    // advance ptr
+    src1 = gIR->ir->CreateGEP(src1,len1,"tmp");
+
+    // memcpy
+    llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src2->getType()->getContainedType(0)));
+    llvm::Value* bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
+    DtoMemCpy(src1,src2,bytelen);
+
+    return slice;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2)
+DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2)
 {
+    Logger::println("DtoCatArrays");
+    LOG_SCOPE;
+
     Type* t1 = DtoDType(exp1->type);
     Type* t2 = DtoDType(exp2->type);
 
@@ -590,50 +645,86 @@
     len2 = DtoArrayLen(e2);
     res = gIR->ir->CreateAdd(len1,len2,"tmp");
 
-    llvm::Value* mem = DtoNewDynArray(arr, res, DtoDType(t1->next), false);
+    DValue* lenval = new DImValue(Type::tsize_t, res);
+    DSliceValue* slice = DtoNewDynArray(type, lenval, false);
+    llvm::Value* mem = slice->ptr;
 
     src1 = DtoArrayPtr(e1);
     src2 = DtoArrayPtr(e2);
 
-    DtoMemCpy(mem,src1,len1);
+    // first memcpy
+    llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
+    llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
+    DtoMemCpy(mem,src1,bytelen);
+
+    // second memcpy
     mem = gIR->ir->CreateGEP(mem,len1,"tmp");
-    DtoMemCpy(mem,src2,len2);
+    bytelen = gIR->ir->CreateMul(len2, elemSize, "tmp");
+    DtoMemCpy(mem,src2,bytelen);
+
+    return slice;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
-void DtoCatArrayElement(llvm::Value* arr, Expression* exp1, Expression* exp2)
+DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
 {
+    Logger::println("DtoCatArrayElement");
+    LOG_SCOPE;
+
     Type* t1 = DtoDType(exp1->type);
     Type* t2 = DtoDType(exp2->type);
 
-    // handle reverse case
-    if (t2->next && t1 == DtoDType(t2->next))
-    {
-        Type* tmp = t1;
-        t1 = t2;
-        t2 = tmp;
-        Expression* e = exp1;
-        exp1 = exp2;
-        exp2 = e;
-    }
-
     DValue* e1 = exp1->toElem(gIR);
     DValue* e2 = exp2->toElem(gIR);
 
     llvm::Value *len1, *src1, *res;
 
-    len1 = DtoArrayLen(e1);
-    res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
+    // handle prefix case, eg. int~int[]
+    if (t2->next && t1 == DtoDType(t2->next))
+    {
+        len1 = DtoArrayLen(e2);
+        res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
+
+        DValue* lenval = new DImValue(Type::tsize_t, res);
+        DSliceValue* slice = DtoNewDynArray(type, lenval, false);
+        llvm::Value* mem = slice->ptr;
 
-    llvm::Value* mem = DtoNewDynArray(arr, res, DtoDType(t1->next), false);
+        DVarValue* memval = new DVarValue(e1->getType(), mem, true);
+        DtoAssign(memval, e1);
+
+        src1 = DtoArrayPtr(e2);
+
+        mem = gIR->ir->CreateGEP(mem,DtoConstSize_t(1),"tmp");
+
+        llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
+        llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
+        DtoMemCpy(mem,src1,bytelen);
+
 
-    src1 = DtoArrayPtr(e1);
+        return slice;
+    }
+    // handle suffix case, eg. int[]~int
+    else
+    {
+        len1 = DtoArrayLen(e1);
+        res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
 
-    DtoMemCpy(mem,src1,len1);
+        DValue* lenval = new DImValue(Type::tsize_t, res);
+        DSliceValue* slice = DtoNewDynArray(type, lenval, false);
+        llvm::Value* mem = slice->ptr;
 
-    mem = gIR->ir->CreateGEP(mem,len1,"tmp");
-    DVarValue* memval = new DVarValue(e2->getType(), mem, true);
-    DtoAssign(memval, e2);
+        src1 = DtoArrayPtr(e1);
+
+        llvm::Value* elemSize = DtoConstSize_t(getABITypeSize(src1->getType()->getContainedType(0)));
+        llvm::Value* bytelen = gIR->ir->CreateMul(len1, elemSize, "tmp");
+        DtoMemCpy(mem,src1,bytelen);
+
+        mem = gIR->ir->CreateGEP(mem,len1,"tmp");
+        DVarValue* memval = new DVarValue(e2->getType(), mem, true);
+        DtoAssign(memval, e2);
+
+        return slice;
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -866,6 +957,7 @@
 {
     Logger::println("DtoArrayLen");
     LOG_SCOPE;
+
     Type* t = DtoDType(v->getType());
     if (t->ty == Tarray) {
         if (DSliceValue* s = v->isSlice()) {
@@ -894,6 +986,9 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 llvm::Value* DtoArrayPtr(DValue* v)
 {
+    Logger::println("DtoArrayPtr");
+    LOG_SCOPE;
+
     Type* t = DtoDType(v->getType());
     if (t->ty == Tarray) {
         if (DSliceValue* s = v->isSlice()) {
--- a/gen/arrays.h	Mon May 12 23:49:07 2008 +0200
+++ b/gen/arrays.h	Tue May 13 14:42:09 2008 +0200
@@ -19,13 +19,13 @@
 void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
 void DtoSetArrayToNull(llvm::Value* v);
 
-llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true);
-llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
+DSliceValue* DtoNewDynArray(Type* arrayType, DValue* dim, bool defaultInit=true);
+DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim);
 
-void DtoCatAssignElement(llvm::Value* arr, Expression* exp);
-void DtoCatAssignArray(llvm::Value* arr, Expression* exp);
-void DtoCatArrays(llvm::Value* arr, Expression* e1, Expression* e2);
-void DtoCatArrayElement(llvm::Value* arr, Expression* exp1, Expression* exp2);
+DSliceValue* DtoCatAssignElement(DValue* arr, Expression* exp);
+DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp);
+DSliceValue* DtoCatArrays(Type* type, Expression* e1, Expression* e2);
+DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2);
 
 void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
 
--- a/gen/runtime.cpp	Mon May 12 23:49:07 2008 +0200
+++ b/gen/runtime.cpp	Tue May 13 14:42:09 2008 +0200
@@ -237,25 +237,41 @@
     /////////////////////////////////////////////////////////////////////////////////////
     /////////////////////////////////////////////////////////////////////////////////////
 
-    // realloc
-    // void* _d_realloc(void* ptr, size_t n)
+    // void* _d_allocmemoryT(TypeInfo ti)
     {
-        std::string fname("_d_realloc");
+        std::string fname("_d_allocmemoryT");
         std::vector<const llvm::Type*> types;
-        types.push_back(voidPtrTy);
-        types.push_back(sizeTy);
+        types.push_back(typeInfoTy);
         const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
         new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
     }
 
-    // free
-    // void _d_free(void* ptr)
+    // void* _d_newarrayT(TypeInfo ti, size_t length)
+    // void* _d_newarrayiT(TypeInfo ti, size_t length)
     {
-        std::string fname("_d_free");
+        std::string fname("_d_newarrayT");
+        std::string fname2("_d_newarrayiT");
         std::vector<const llvm::Type*> types;
+        types.push_back(typeInfoTy);
+        types.push_back(sizeTy);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
+    }
+
+    // void* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, void* pdata)
+    // void* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, void* pdata)
+    {
+        std::string fname("_d_arraysetlengthT");
+        std::string fname2("_d_arraysetlengthiT");
+        std::vector<const llvm::Type*> types;
+        types.push_back(typeInfoTy);
+        types.push_back(sizeTy);
+        types.push_back(sizeTy);
         types.push_back(voidPtrTy);
-        const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
+        const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
         new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
+        new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
     }
 
     // Object _d_newclass(ClassInfo ci)
--- a/gen/toir.cpp	Mon May 12 23:49:07 2008 +0200
+++ b/gen/toir.cpp	Tue May 13 14:42:09 2008 +0200
@@ -572,10 +572,15 @@
     DImValue* im = r->isIm();
     if (!im || !im->inPlace()) {
         Logger::println("assignment not inplace");
-        if (l->isArrayLen())
-            DtoResizeDynArray(l->getLVal(), r->getRVal());
+        if (DArrayLenValue* al = l->isArrayLen())
+        {
+            DSliceValue* slice = DtoResizeDynArray(l->getType(), l, r);
+            DtoAssign(l, slice);
+        }
         else
+        {
             DtoAssign(l, r);
+        }
     }
 
     if (l->isSlice() || l->isComplex())
@@ -1932,10 +1937,54 @@
 
     Type* ntype = DtoDType(newtype);
 
+    // new class
     if (ntype->ty == Tclass) {
         Logger::println("new class");
         return DtoNewClass((TypeClass*)ntype, this);
     }
+    // new dynamic array
+    else if (ntype->ty == Tarray)
+    {
+        Logger::println("new dynamic array: %s", newtype->toChars());
+        // get dim
+        assert(arguments);
+        assert(arguments->dim == 1);
+        DValue* sz = ((Expression*)arguments->data[0])->toElem(p);
+        // allocate & init
+        return DtoNewDynArray(newtype, sz, true);
+    }
+    // new static array
+    else if (ntype->ty == Tsarray)
+    {
+        assert(0);
+    }
+    // new struct
+    else if (ntype->ty == Tstruct)
+    {
+        // allocate
+        llvm::Value* mem = DtoNew(newtype);
+        // init
+        TypeStruct* ts = (TypeStruct*)ntype;
+        if (ts->isZeroInit()) {
+            DtoStructZeroInit(mem);
+        }
+        else {
+            assert(ts->sym);
+            DtoStructCopy(mem,ts->sym->ir.irStruct->init);
+        }
+        return new DImValue(type, mem, false);
+    }
+    // new basic type
+    else
+    {
+        // allocate
+        llvm::Value* mem = DtoNew(newtype);
+        // BUG: default initialize
+        // return
+        return new DImValue(type, mem, false);
+    }
+
+    /*
 
     const llvm::Type* t = DtoType(ntype);
 
@@ -1969,8 +2018,17 @@
             assert(0 && "num args to 'new' != 1");
         }
     }
+    // simple new of a single non-class, non-array value
     else {
-        emem = new llvm::MallocInst(t,"tmp",p->scopebb());
+        // get runtime function
+        llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocmemoryT");
+        // get type info
+        llvm::Constant* ti = DtoTypeInfoOf(newtype);
+        assert(isaPointer(ti));
+        // call runtime
+        llvm::SmallVector<llvm::Value*,1> arg;
+        arg.push_back(ti);
+        emem = p->ir->CreateCall(fn, arg.begin(), arg.end(), ".gc_mem");
     }
 
     if (ntype->ty == Tstruct) {
@@ -1985,6 +2043,8 @@
     }
 
     return new DImValue(type, emem, inplace);
+    */
+    assert(0);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2053,10 +2113,11 @@
     LOG_SCOPE;
 
     DValue* u = e1->toElem(p);
+    Logger::println("e1 = %s", e1->type->toChars());
 
     if (p->topexp() && p->topexp()->e1 == this)
     {
-        return new DArrayLenValue(type, u->getLVal());
+        return new DArrayLenValue(e1->type, u->getLVal());
     }
     else
     {
@@ -2488,6 +2549,19 @@
 
     bool arrNarr = DtoDType(e1->type) == DtoDType(e2->type);
 
+    // array ~ array
+    if (arrNarr)
+    {
+        return DtoCatArrays(type, e1, e2);
+    }
+    // array ~ element
+    // element ~ array
+    else
+    {
+        return DtoCatArrayElement(type, e1, e2);
+    }
+
+    /*
     IRExp* ex = p->topexp();
     if (ex && ex->e2 == this) {
         assert(ex->v);
@@ -2502,11 +2576,13 @@
         const llvm::Type* arrty = DtoType(t);
         llvm::Value* dst = new llvm::AllocaInst(arrty, "tmpmem", p->topallocapoint());
         if (arrNarr)
+            DtoCatAr
             DtoCatArrays(dst,e1,e2);
         else
             DtoCatArrayElement(dst,e1,e2);
         return new DVarValue(type, dst, true);
     }
+    */
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2523,15 +2599,17 @@
     Type* e2type = DtoDType(e2->type);
 
     if (e2type == elemtype) {
-        DtoCatAssignElement(l->getLVal(),e2);
+        DSliceValue* slice = DtoCatAssignElement(l,e2);
+        DtoAssign(l, slice);
     }
     else if (e1type == e2type) {
-        DtoCatAssignArray(l->getLVal(),e2);
+        DSliceValue* slice = DtoCatAssignArray(l,e2);
+        DtoAssign(l, slice);
     }
     else
         assert(0 && "only one element at a time right now");
 
-    return 0;
+    return l;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/tollvm.cpp	Mon May 12 23:49:07 2008 +0200
+++ b/gen/tollvm.cpp	Tue May 13 14:42:09 2008 +0200
@@ -655,41 +655,20 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
-{
-    /*size_t sz = gTargetData->getTypeSize(ty);
-    llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false);
-    if (ptr == 0) {
-        llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
-        ptr = llvm::ConstantPointerNull::get(i8pty);
-    }
-    return DtoRealloc(ptr, n);*/
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* n)
+llvm::Value* DtoNew(Type* newtype)
 {
-    assert(ptr);
-    assert(n);
-
-    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_realloc");
-    assert(fn);
-
-    llvm::Value* newptr = ptr;
-
-    const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty);
-    if (ptr->getType() != i8pty) {
-        newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb());
-    }
-
-    std::vector<llvm::Value*> args;
-    args.push_back(newptr);
-    args.push_back(n);
-    llvm::Value* ret = new llvm::CallInst(fn, args.begin(), args.end(), "tmprealloc", gIR->scopebb());
-
-    return ret->getType() == ptr->getType() ? ret : new llvm::BitCastInst(ret,ptr->getType(),"tmp",gIR->scopebb());
+    // get runtime function
+    llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocmemoryT");
+    // get type info
+    llvm::Constant* ti = DtoTypeInfoOf(newtype);
+    assert(isaPointer(ti));
+    // call runtime
+    llvm::SmallVector<llvm::Value*,1> arg;
+    arg.push_back(ti);
+    // allocate
+    llvm::Value* mem = gIR->ir->CreateCall(fn, arg.begin(), arg.end(), ".gc_mem");
+    // cast
+    return DtoBitCast(mem, getPtrToType(DtoType(newtype)), ".gc_mem");
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -707,7 +686,12 @@
 
     // file param
     c = DtoConstString(loc->filename);
-    llvm::AllocaInst* alloc = new llvm::AllocaInst(c->getType(), "srcfile", gIR->topallocapoint());
+    llvm::AllocaInst* alloc = gIR->func()->srcfileArg;
+    if (!alloc)
+    {
+        alloc = new llvm::AllocaInst(c->getType(), "srcfile", gIR->topallocapoint());
+        gIR->func()->srcfileArg = alloc;
+    }
     llvm::Value* ptr = DtoGEPi(alloc, 0,0, "tmp");
     DtoStore(c->getOperand(0), ptr);
     ptr = DtoGEPi(alloc, 0,1, "tmp");
@@ -938,6 +922,7 @@
         }
         // rhs is slice
         else if (DSliceValue* s = rhs->isSlice()) {
+            assert(s->getType()->toBasetype() == lhs->getType()->toBasetype());
             DtoSetArray(lhs->getLVal(),s->len,s->ptr);
         }
         // null
@@ -1282,15 +1267,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Constant* DtoConstNullPtr(const llvm::Type* t)
-{
-    return llvm::ConstantPointerNull::get(
-        getPtrToType(t)
-    );
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes)
 {
     const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
@@ -1319,20 +1295,19 @@
 
 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
 {
-    assert(dst->getType() == src->getType());
+    const llvm::Type* arrty = getVoidPtrType();
 
-    const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty);
-    llvm::Value *dstarr, *srcarr;
+    llvm::Value* dstarr;
     if (dst->getType() == arrty)
-    {
         dstarr = dst;
-        srcarr = src;
-    }
     else
-    {
-        dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-        srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
-    }
+        dstarr = DtoBitCast(dst, arrty, "tmp");
+
+    llvm::Value* srcarr;
+    if (src->getType() == arrty)
+        srcarr = src;
+    else
+        srcarr = DtoBitCast(src, arrty, "tmp");
 
     llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
     std::vector<llvm::Value*> llargs;
@@ -1807,6 +1782,8 @@
     gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////
+
 const llvm::StructType* DtoInterfaceInfoType()
 {
     if (gIR->interfaceInfoType)
@@ -1831,3 +1808,28 @@
 
     return gIR->interfaceInfoType;
 }
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Constant* DtoTypeInfoOf(Type* type)
+{
+    const llvm::Type* typeinfotype = DtoType(Type::typeinfo->type);
+    TypeInfoDeclaration* tidecl = type->getTypeInfoDeclaration();
+    DtoForceDeclareDsymbol(tidecl);
+    assert(tidecl->ir.irGlobal != NULL);
+    llvm::Constant* c = isaConstant(tidecl->ir.irGlobal->value);
+    assert(c != NULL);
+    return llvm::ConstantExpr::getBitCast(c, typeinfotype);
+}
+
+
+
+
+
+
+
+
+
+
+
+
--- a/gen/tollvm.h	Mon May 12 23:49:07 2008 +0200
+++ b/gen/tollvm.h	Tue May 13 14:42:09 2008 +0200
@@ -39,6 +39,9 @@
 const llvm::Type* DtoSize_t();
 const llvm::StructType* DtoInterfaceInfoType();
 
+// getting typeinfo of type
+llvm::Constant* DtoTypeInfoOf(Type* ty);
+
 // initializer helpers
 llvm::Constant* DtoConstInitializer(Type* type, Initializer* init);
 llvm::Constant* DtoConstFieldInitializer(Type* type, Initializer* init);
@@ -57,8 +60,7 @@
 llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb=NULL);
 
 // dynamic memory helpers
-llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty);
-llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len);
+llvm::Value* DtoNew(Type* newtype);
 
 // assertion generator
 void DtoAssert(Loc* loc, DValue* msg);
@@ -79,7 +81,6 @@
 llvm::Constant* DtoConstString(const char*);
 llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
 llvm::Constant* DtoConstBool(bool);
-llvm::Constant* DtoConstNullPtr(const llvm::Type* t);
 
 // is template instance check
 bool DtoIsTemplateInstance(Dsymbol* s);
--- a/ir/irfunction.cpp	Mon May 12 23:49:07 2008 +0200
+++ b/ir/irfunction.cpp	Tue May 13 14:42:09 2008 +0200
@@ -24,6 +24,8 @@
     _arguments = NULL;
     _argptr = NULL;
     dwarfSubProg = NULL;
+
+    srcfileArg = NULL;
 }
 
 IrFunction::~IrFunction()
--- a/ir/irfunction.h	Mon May 12 23:49:07 2008 +0200
+++ b/ir/irfunction.h	Tue May 13 14:42:09 2008 +0200
@@ -22,6 +22,8 @@
     llvm::Value* _argptr;
     llvm::Constant* dwarfSubProg;
 
+    llvm::AllocaInst* srcfileArg;
+
     IrFunction(FuncDeclaration* fd);
     virtual ~IrFunction();
 };
--- a/tango/lib/compiler/llvmdc/lifetime.d	Mon May 12 23:49:07 2008 +0200
+++ b/tango/lib/compiler/llvmdc/lifetime.d	Tue May 13 14:42:09 2008 +0200
@@ -189,31 +189,30 @@
     }
 }
 
-
 /**
  *
  */
 struct Array
 {
     size_t length;
-    byte*  data;
+    void*  data;
 }
 
++/
 
 /**
  * Allocate a new array of length elements.
  * ti is the type of the resulting array, or pointer to element.
  * (For when the array is initialized to 0)
  */
-extern (C) Array _d_newarrayT(TypeInfo ti, size_t length)
+extern (C) void* _d_newarrayT(TypeInfo ti, size_t length)
 {
     void* p;
-    Array result;
     auto size = ti.next.tsize();                // array element size
 
     debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size);
     if (length == 0 || size == 0)
-        return Array();
+        return null;
 
     version (D_InlineAsm_X86)
     {
@@ -230,24 +229,25 @@
     p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
     debug(PRINTF) printf(" p = %p\n", p);
     memset(p, 0, size);
-    return Array(length, p);
+    return p;
 
 Loverflow:
     onOutOfMemoryError();
+    return null;
 }
 
 /**
  * For when the array has a non-zero initializer.
  */
-extern (C) Array _d_newarrayiT(TypeInfo ti, size_t length)
+extern (C) void* _d_newarrayiT(TypeInfo ti, size_t length)
 {
-    Array result;
+    void* result;
     auto size = ti.next.tsize();                // array element size
 
     debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size);
 
     if (length == 0 || size == 0)
-        result = Array();
+        result = null;
     else
     {
         auto initializer = ti.next.init();
@@ -285,15 +285,17 @@
                 memcpy(p + u, q, isize);
             }
         }
-        va_end(q);
-        result = Array(length, p);
+        result = p;
     }
     return result;
 
 Loverflow:
     onOutOfMemoryError();
+    return null;
 }
 
+/+
+
 /**
  *
  */
@@ -400,8 +402,6 @@
     return result;
 }
 
-+/
-
 /**
  *
  */
@@ -410,6 +410,16 @@
     return gc_malloc(nbytes);
 }
 
++/
+
+/**
+ * for allocating a single POD value
+ */
+extern (C) void* _d_allocmemoryT(TypeInfo ti)
+{
+    return gc_malloc(ti.tsize(), (ti.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+}
+
 /+
 
 /**
@@ -496,16 +506,14 @@
     }
 }
 
-/+
-
 /**
  * Resize dynamic arrays with 0 initializers.
  */
-extern (C) byte[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p)
+extern (C) byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
 in
 {
     assert(ti);
-    assert(!p.length || p.data);
+    assert(!plength || pdata);
 }
 body
 {
@@ -516,7 +524,7 @@
     {
         printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength);
         if (p)
-            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+            printf("\tp.data = %p, p.length = %d\n", pdata, plength);
     }
 
     if (newlength)
@@ -543,26 +551,26 @@
 
         debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
 
-        if (p.data)
+        if (pdata)
         {
-            newdata = p.data;
-            if (newlength > p.length)
+            newdata = pdata;
+            if (newlength > plength)
             {
-                size_t size = p.length * sizeelem;
-                auto   info = gc_query(p.data);
+                size_t size = plength * sizeelem;
+                auto   info = gc_query(pdata);
 
-                if (info.size <= newsize || info.base != p.data)
+                if (info.size <= newsize || info.base != pdata)
                 {
-                    if (info.size >= PAGESIZE && info.base == p.data)
+                    if (info.size >= PAGESIZE && info.base == pdata)
                     {   // Try to extend in-place
-                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size);
                         if (u)
                         {
                             goto L1;
                         }
                     }
                     newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
-                    newdata[0 .. size] = p.data[0 .. size];
+                    newdata[0 .. size] = pdata[0 .. size];
                 }
              L1:
                 newdata[size .. newsize] = 0;
@@ -575,15 +583,14 @@
     }
     else
     {
-        newdata = p.data;
+        newdata = pdata;
     }
 
-    p.data = newdata;
-    p.length = newlength;
-    return newdata[0 .. newlength];
+    return newdata;
 
 Loverflow:
     onOutOfMemoryError();
+    return null;
 }
 
 
@@ -595,10 +602,10 @@
  *      initsize        size of initializer
  *      ...             initializer
  */
-extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p)
+extern (C) byte* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
 in
 {
-    assert(!p.length || p.data);
+    assert(!plength || pdata);
 }
 body
 {
@@ -616,7 +623,7 @@
     {
         printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize);
         if (p)
-            printf("\tp.data = %p, p.length = %d\n", p.data, p.length);
+            printf("\tp.data = %p, p.length = %d\n", pdata, plength);
     }
 
     if (newlength)
@@ -642,27 +649,27 @@
         }
         debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
 
-        size_t size = p.length * sizeelem;
+        size_t size = plength * sizeelem;
 
-        if (p.data)
+        if (pdata)
         {
-            newdata = p.data;
-            if (newlength > p.length)
+            newdata = pdata;
+            if (newlength > plength)
             {
-                auto info = gc_query(p.data);
+                auto info = gc_query(pdata);
 
-                if (info.size <= newsize || info.base != p.data)
+                if (info.size <= newsize || info.base != pdata)
                 {
-                    if (info.size >= PAGESIZE && info.base == p.data)
+                    if (info.size >= PAGESIZE && info.base == pdata)
                     {   // Try to extend in-place
-                        auto u = gc_extend(p.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size);
                         if (u)
                         {
                             goto L1;
                         }
                     }
                     newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
-                    newdata[0 .. size] = p.data[0 .. size];
+                    newdata[0 .. size] = pdata[0 .. size];
                 L1: ;
                 }
             }
@@ -692,17 +699,17 @@
     }
     else
     {
-        newdata = p.data;
+        newdata = pdata;
     }
 
-    p.data = newdata;
-    p.length = newlength;
-    return newdata[0 .. newlength];
+    return newdata;
 
 Loverflow:
     onOutOfMemoryError();
+    return null;
 }
 
+/+
 
 /**
  * Append y[] to array x[].
--- a/tango/lib/compiler/llvmdc/llvmdc.mak	Mon May 12 23:49:07 2008 +0200
+++ b/tango/lib/compiler/llvmdc/llvmdc.mak	Tue May 13 14:42:09 2008 +0200
@@ -83,7 +83,6 @@
     eh.bc \
     genobj.bc \
     lifetime.bc \
-    mem.bc \
     memory.bc \
     qsort2.bc \
     switch.bc \
--- a/tango/lib/compiler/llvmdc/mem.d	Mon May 12 23:49:07 2008 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-extern(C):
-
-void* realloc(void*,size_t);
-void free(void*);
-
-void* _d_realloc(void* ptr, size_t n)
-{
-    return realloc(ptr, n);
-}
-
-void _d_free(void* ptr)
-{
-    free(ptr);
-}
--- a/tango/lib/gc/basic/gcx.d	Mon May 12 23:49:07 2008 +0200
+++ b/tango/lib/gc/basic/gcx.d	Tue May 13 14:42:09 2008 +0200
@@ -2056,7 +2056,12 @@
         // get put on the stack so they'll be scanned
         void *sp;
         size_t result;
-        version (GNU)
+        version(LLVMDC)
+        {
+            // TODO & BUG:
+            // should make sure registers are on the stack, maybe some external asm ?
+        }
+        else version (GNU)
         {
             __builtin_unwind_init();
             sp = & sp;
@@ -2070,7 +2075,11 @@
         }
         }
         result = fullcollect(sp);
-        version (GNU)
+        version(LLVMDC)
+        {
+            // nothing to do
+        }
+        else version (GNU)
         {
             // nothing to do
         }
--- a/tango/lib/llvmdc-posix.mak	Mon May 12 23:49:07 2008 +0200
+++ b/tango/lib/llvmdc-posix.mak	Tue May 13 14:42:09 2008 +0200
@@ -17,6 +17,7 @@
 
 DIR_CC=./common/tango
 DIR_RT=./compiler/llvmdc
+#DIR_GC=./gc/basic
 DIR_GC=./gc/stub
 
 CP=cp -f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tangotests/mem1.d	Tue May 13 14:42:09 2008 +0200
@@ -0,0 +1,63 @@
+module tangotests.mem1;
+
+import tango.stdc.stdio;
+
+void main()
+{
+    printf("new int;\n");
+    int* i = new int;
+    assert(*i == 0);
+
+    printf("new int[3];\n");
+    int[] ar = new int[3];
+    ar[0] = 1;
+    ar[1] = 56;
+    assert(ar.length == 3);
+    assert(ar[0] == 1);
+    assert(ar[1] == 56);
+    assert(ar[2] == 0);
+
+    printf("array ~= elem;\n");
+    int[] ar2;
+    ar2 ~= 22;
+    assert(ar2.length == 1);
+    assert(ar2[0] == 22);
+
+    printf("array ~= array;\n");
+    ar2 ~= ar;
+    assert(ar2.length == 4);
+    assert(ar2[0] == 22);
+    assert(ar2[1] == 1);
+    printf("%d %d %d %d\n", ar2[0], ar2[1], ar2[2], ar2[3]);
+    assert(ar2[2] == 56);
+    assert(ar2[3] == 0);
+
+    printf("array ~ array;\n");
+    int[] ar5 = ar ~ ar2;
+    assert(ar5.length == 7);
+    assert(ar5[0] == 1);
+    assert(ar5[1] == 56);
+    assert(ar5[2] == 0);
+    assert(ar5[3] == 22);
+    assert(ar5[4] == 1);
+    assert(ar5[5] == 56);
+    assert(ar5[6] == 0);
+
+    printf("array ~ elem;\n");
+    int[] ar4 = ar2 ~ 123;
+    assert(ar4.length == 5);
+    assert(ar4[0] == 22);
+    assert(ar4[1] == 1);
+    assert(ar4[2] == 56);
+    assert(ar4[3] == 0);
+    assert(ar4[4] == 123);
+
+    printf("elem ~ array;\n");
+    int[] ar3 = 123 ~ ar2;
+    assert(ar3.length == 5);
+    assert(ar3[0] == 123);
+    assert(ar3[1] == 22);
+    assert(ar3[2] == 1);
+    assert(ar3[3] == 56);
+    assert(ar3[4] == 0);
+}
--- a/test/arrays.d	Mon May 12 23:49:07 2008 +0200
+++ b/test/arrays.d	Tue May 13 14:42:09 2008 +0200
@@ -1,3 +1,5 @@
+module arrays;
+
 extern(C) int printf(char*, ...);
 
 void integer()