[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.
This commit is contained in:
Tomas Lindquist Olsen
2008-05-13 14:42:09 +02:00
parent 2912480136
commit c380f43929
15 changed files with 473 additions and 210 deletions

View File

@@ -62,6 +62,9 @@ const llvm::ArrayType* DtoStaticArrayType(Type* t)
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 DtoSetArrayToNull(llvm::Value* v)
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 DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
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 @@ static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty)
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 DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
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::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr)
}
//////////////////////////////////////////////////////////////////////////////////////////
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;
llvm::Value* nullptr = llvm::ConstantPointerNull::get(getPtrToType(ty));
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_newarrayT" : "_d_newarrayiT" );
llvm::Value* newptr = DtoRealloc(nullptr, bytesize);
llvm::SmallVector<llvm::Value*,2> args;
args.push_back(DtoTypeInfoOf(arrayType));
assert(DtoType(dim->getType()) == DtoSize_t());
args.push_back(dim->getRVal());
if (doinit) {
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");
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;
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());
assert(array);
assert(newdim);
assert(arrayType);
assert(arrayType->toBasetype()->ty == Tarray);
llvm::Value* newptr = DtoRealloc(ptrld, bytesz);
new llvm::StoreInst(newptr,ptr,gIR->scopebb());
bool zeroInit = arrayType->toBasetype()->nextOf()->isZeroInit();
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, zeroInit ? "_d_arraysetlengthT" : "_d_arraysetlengthiT" );
llvm::Value* len = DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
new llvm::StoreInst(sz,len,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"));
return newptr;
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");
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;
ptr = DtoLoad(DtoGEPi(arr, 0, 1, "tmp"));
assert(array);
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 @@ void DtoCatAssignElement(llvm::Value* arr, Expression* exp)
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 @@ void DtoCatArrays(llvm::Value* arr, Expression* exp1, Expression* exp2)
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");
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);
DVarValue* memval = new DVarValue(e1->getType(), mem, true);
DtoAssign(memval, e1);
DtoMemCpy(mem,src1,len1);
src1 = DtoArrayPtr(e2);
mem = gIR->ir->CreateGEP(mem,len1,"tmp");
DVarValue* memval = new DVarValue(e2->getType(), mem, true);
DtoAssign(memval, 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);
return slice;
}
// handle suffix case, eg. int[]~int
else
{
len1 = DtoArrayLen(e1);
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;
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 @@ llvm::Value* DtoArrayLen(DValue* v)
{
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* DtoArrayLen(DValue* v)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoArrayPtr(DValue* v)
{
Logger::println("DtoArrayPtr");
LOG_SCOPE;
Type* t = DtoDType(v->getType());
if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) {

View File

@@ -19,13 +19,13 @@ void DtoArrayAssign(llvm::Value* l, llvm::Value* r);
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);

View File

@@ -237,25 +237,41 @@ static void LLVM_D_BuildRuntimeModule()
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// 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(voidPtrTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
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(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)

View File

@@ -572,10 +572,15 @@ DValue* AssignExp::toElem(IRState* p)
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 @@ DValue* NewExp::toElem(IRState* p)
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 @@ DValue* NewExp::toElem(IRState* p)
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 @@ DValue* NewExp::toElem(IRState* p)
}
return new DImValue(type, emem, inplace);
*/
assert(0);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -2053,10 +2113,11 @@ DValue* ArrayLengthExp::toElem(IRState* p)
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 @@ DValue* CatExp::toElem(IRState* p)
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 @@ DValue* CatExp::toElem(IRState* p)
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 @@ DValue* CatAssignExp::toElem(IRState* p)
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;
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -655,41 +655,20 @@ llvm::Value* DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::stri
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
llvm::Value* DtoNew(Type* newtype)
{
/*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)
{
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 @@ void DtoAssert(Loc* loc, DValue* msg)
// 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 @@ void DtoAssign(DValue* lhs, DValue* rhs)
}
// 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* DtoConstStringPtr(const char* str, const char* section)
//////////////////////////////////////////////////////////////////////////////////////////
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 DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes)
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 @@ void DtoAnnotation(const char* str)
gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
}
//////////////////////////////////////////////////////////////////////////////////////////
const llvm::StructType* DtoInterfaceInfoType()
{
if (gIR->interfaceInfoType)
@@ -1831,3 +1808,28 @@ const llvm::StructType* DtoInterfaceInfoType()
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);
}

View File

@@ -39,6 +39,9 @@ llvm::Value* DtoBoolean(llvm::Value* val);
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, const std::string& var, llvm
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::ConstantFP* DtoConstFP(Type* t, long double value);
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);

View File

@@ -24,6 +24,8 @@ IrFunction::IrFunction(FuncDeclaration* fd)
_arguments = NULL;
_argptr = NULL;
dwarfSubProg = NULL;
srcfileArg = NULL;
}
IrFunction::~IrFunction()

View File

@@ -22,6 +22,8 @@ struct IrFunction : IrBase
llvm::Value* _argptr;
llvm::Constant* dwarfSubProg;
llvm::AllocaInst* srcfileArg;
IrFunction(FuncDeclaration* fd);
virtual ~IrFunction();
};

View File

@@ -189,31 +189,30 @@ extern (C) void _d_delclass(Object* p)
}
}
/**
*
*/
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 @@ extern (C) Array _d_newarrayT(TypeInfo ti, size_t length)
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 @@ extern (C) Array _d_newarrayiT(TypeInfo ti, size_t length)
memcpy(p + u, q, isize);
}
}
va_end(q);
result = Array(length, p);
result = p;
}
return result;
Loverflow:
onOutOfMemoryError();
return null;
}
/+
/**
*
*/
@@ -400,8 +402,6 @@ extern (C) Array _d_newarraymiT(TypeInfo ti, int ndims, ...)
return result;
}
+/
/**
*
*/
@@ -410,6 +410,16 @@ void* _d_allocmemory(size_t nbytes)
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 @@ extern (C) void rt_finalize(void* p, bool det = true)
}
}
/+
/**
* 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 @@ body
{
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 @@ body
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 @@ body
}
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 @@ Loverflow:
* 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 @@ body
{
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 @@ body
}
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 @@ body
}
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[].

View File

@@ -83,7 +83,6 @@ OBJ_BASE= \
eh.bc \
genobj.bc \
lifetime.bc \
mem.bc \
memory.bc \
qsort2.bc \
switch.bc \

View File

@@ -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);
}

View File

@@ -2056,7 +2056,12 @@ struct Gcx
// 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 @@ struct Gcx
}
}
result = fullcollect(sp);
version (GNU)
version(LLVMDC)
{
// nothing to do
}
else version (GNU)
{
// nothing to do
}

View File

@@ -17,6 +17,7 @@ LIB_MASK_C=libtango-base-c-llvmdc*.a
DIR_CC=./common/tango
DIR_RT=./compiler/llvmdc
#DIR_GC=./gc/basic
DIR_GC=./gc/stub
CP=cp -f

63
tangotests/mem1.d Normal file
View File

@@ -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);
}

View File

@@ -1,3 +1,5 @@
module arrays;
extern(C) int printf(char*, ...);
void integer()