# HG changeset patch # User lindquist # Date 1210682529 -7200 # Node ID e881c9b1c738a7f15b8886758c469484f253195f # Parent 56e0c5b1d4287dbcf1e0d3e2f0290e8e8086f467 [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. diff -r 56e0c5b1d428 -r e881c9b1c738 gen/arrays.cpp --- 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 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 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()) { diff -r 56e0c5b1d428 -r e881c9b1c738 gen/arrays.h --- 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); diff -r 56e0c5b1d428 -r e881c9b1c738 gen/runtime.cpp --- 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 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 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 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) diff -r 56e0c5b1d428 -r e881c9b1c738 gen/toir.cpp --- 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 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; } ////////////////////////////////////////////////////////////////////////////////////////// diff -r 56e0c5b1d428 -r e881c9b1c738 gen/tollvm.cpp --- 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 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 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 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); +} + + + + + + + + + + + + diff -r 56e0c5b1d428 -r e881c9b1c738 gen/tollvm.h --- 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); diff -r 56e0c5b1d428 -r e881c9b1c738 ir/irfunction.cpp --- 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() diff -r 56e0c5b1d428 -r e881c9b1c738 ir/irfunction.h --- 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(); }; diff -r 56e0c5b1d428 -r e881c9b1c738 tango/lib/compiler/llvmdc/lifetime.d --- 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[]. diff -r 56e0c5b1d428 -r e881c9b1c738 tango/lib/compiler/llvmdc/llvmdc.mak --- 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 \ diff -r 56e0c5b1d428 -r e881c9b1c738 tango/lib/compiler/llvmdc/mem.d --- 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); -} diff -r 56e0c5b1d428 -r e881c9b1c738 tango/lib/gc/basic/gcx.d --- 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 } diff -r 56e0c5b1d428 -r e881c9b1c738 tango/lib/llvmdc-posix.mak --- 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 diff -r 56e0c5b1d428 -r e881c9b1c738 tangotests/mem1.d --- /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); +} diff -r 56e0c5b1d428 -r e881c9b1c738 test/arrays.d --- 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()