[svn r38] * resizing dynamic arrays support

* throw is replaced with assert(0)
* catch is ignored
* better foreach support
* various bugfixes
This commit is contained in:
Tomas Lindquist Olsen
2007-10-09 02:50:00 +02:00
parent e17f720cce
commit 3db5b9bb98
17 changed files with 296 additions and 94 deletions

View File

@@ -1173,12 +1173,11 @@ Statement *ForeachStatement::semantic(Scope *sc)
if (arg->storageClass & (STCout | STCref | STClazy))
error("no storage class for key %s", arg->ident->toChars());
TY keyty = arg->type->ty;
if ((keyty != Tint32 && keyty != Tuns32) ||
(global.params.is64bit &&
keyty != Tint64 && keyty != Tuns64)
if ((keyty != Tint32 && keyty != Tuns32) &&
(global.params.is64bit && keyty != Tint64 && keyty != Tuns64)
)
{
error("foreach: key type must be int or uint, not %s", arg->type->toChars());
error("foreach: key type must be %s, not %s", global.params.is64bit ? "int, uint, long or ulong" : "int or uint",arg->type->toChars());
}
Initializer *ie = new ExpInitializer(0, new IntegerExp(k));
VarDeclaration *var = new VarDeclaration(loc, arg->type, arg->ident, ie);
@@ -1315,13 +1314,12 @@ Statement *ForeachStatement::semantic(Scope *sc)
}
if (key &&
((key->type->ty != Tint32 && key->type->ty != Tuns32) ||
(global.params.is64bit &&
key->type->ty != Tint64 && key->type->ty != Tuns64)
((key->type->ty != Tint32 && key->type->ty != Tuns32) &&
(global.params.is64bit && key->type->ty != Tint64 && key->type->ty != Tuns64)
)
)
{
error("foreach: key type must be int or uint, not %s", key->type->toChars());
error("foreach: key type must be %s, not %s", global.params.is64bit ? "int, uint, long or ulong" : "int or uint", key->type->toChars());
}
if (key && key->storage_class & (STCout | STCref))

View File

@@ -98,7 +98,7 @@ llvm::Value* LLVM_DtoNullArray(llvm::Value* v)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
void LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
{
assert(gIR);
if (dst->getType() == src->getType())
@@ -118,7 +118,7 @@ llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
}
else
{
@@ -130,14 +130,11 @@ llvm::Value* LLVM_DtoArrayAssign(llvm::Value* dst, llvm::Value* src)
const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(src->getType()->getContainedType(0));
llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType());
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
llvm::Value* dstlen = LLVM_DtoGEP(dst,zero,zero,"tmp",gIR->scopebb());
llvm::Value* dstlen = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
llvm::Value* srclen = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
new llvm::StoreInst(srclen, dstlen, gIR->scopebb());
llvm::Value* dstptr = LLVM_DtoGEP(dst,zero,one,"tmp",gIR->scopebb());
llvm::Value* dstptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
llvm::Value* srcptr = new llvm::BitCastInst(src,dstty,"tmp",gIR->scopebb());
new llvm::StoreInst(srcptr, dstptr, gIR->scopebb());
}
@@ -350,6 +347,7 @@ static llvm::Value* get_slice_ptr(elem* e, llvm::Value*& sz)
return ret;
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoArrayCopy(elem* dst, elem* src)
{
Logger::cout() << "Array copy ((((" << *src->mem << ")))) into ((((" << *dst->mem << "))))\n";
@@ -387,3 +385,34 @@ llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr)
values.push_back(ptr);
return llvm::ConstantStruct::get(type,values);
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, const llvm::Type* ty)
{
size_t sz = gTargetData->getTypeSize(ty);
llvm::ConstantInt* n = llvm::ConstantInt::get(LLVM_DtoSize_t(), sz, false);
llvm::Value* bytesize = llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb());
llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty));
llvm::Value* newptr = LLVM_DtoRealloc(nullptr, bytesize);
llvm::Value* lenptr = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
new llvm::StoreInst(dim,lenptr,gIR->scopebb());
llvm::Value* ptrptr = LLVM_DtoGEPi(dst,0,1,"tmp",gIR->scopebb());
new llvm::StoreInst(newptr,ptrptr,gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz)
{
llvm::Value* ptr = LLVM_DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb());
llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb());
llvm::Value* newptr = LLVM_DtoRealloc(ptrld, sz);
new llvm::StoreInst(newptr,ptr,gIR->scopebb());
llvm::Value* len = LLVM_DtoGEPi(arr, 0, 0, "tmp", gIR->scopebb());
new llvm::StoreInst(sz,len,gIR->scopebb());
}

View File

@@ -2,21 +2,18 @@
#define LLVMC_GEN_ARRAYS_H
const llvm::StructType* LLVM_DtoArrayType(Type* t);
const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
llvm::Value* LLVM_DtoNullArray(llvm::Value* v);
llvm::Value* LLVM_DtoArrayAssign(llvm::Value* l, llvm::Value* r);
void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* si);
void LLVM_DtoArrayCopy(elem* dst, elem* src);
void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);
llvm::Constant* LLVM_DtoConstantSlice(llvm::Constant* dim, llvm::Constant* ptr);
void LLVM_DtoArrayCopy(elem* dst, elem* src);
void LLVM_DtoArrayInit(llvm::Value* l, llvm::Value* r);
void LLVM_DtoArrayAssign(llvm::Value* l, llvm::Value* r);
void LLVM_DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr);
llvm::Value* LLVM_DtoNullArray(llvm::Value* v);
void LLVM_DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, const llvm::Type* ty);
void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
#endif // LLVMC_GEN_ARRAYS_H

View File

@@ -34,7 +34,8 @@ llvm::Value* elem::getValue()
break;
case VAR:
case REF: {
case REF:
case ARRAYLEN:
if (val) {
return val;
}
@@ -52,7 +53,6 @@ llvm::Value* elem::getValue()
return new llvm::LoadInst(mem, "tmp", gIR->scopebb());
}
}
}
case VAL:
case NUL:

View File

@@ -19,7 +19,8 @@ struct elem : Object
CONST,
NUL,
REF,
SLICE
SLICE,
ARRAYLEN
};
public:

View File

@@ -35,40 +35,17 @@ void CompoundStatement::toIR(IRState* p)
Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars());
LOG_SCOPE;
/*
const char* labelname;
bool insterm = false;
if (!p->scopes()) {
labelname = "bb";
insterm = true;
}
else
labelname = "entry";
//if (!llvm::isa<llvm::TerminatorInst>(p->topfunc()->back().back()))
// insterm = true;
llvm::BasicBlock* bb = new llvm::BasicBlock(labelname, p->topfunc());
if (insterm) {
new llvm::BranchInst(bb,p->topbb());
}
p->bbs.push(bb);
*/
size_t n = statements->dim;
for (size_t i=0; i<n; i++)
for (int i=0; i<statements->dim; i++)
{
Statement* s = (Statement*)statements->data[i];
if (s)
s->toIR(p);
else
Logger::println("NULL statement found in CompoundStatement !! :S");
s->toIR(p);
else {
Logger::println("NULL statement found in CompoundStatement !! :S");
assert(0);
}
}
//p->bbs.pop();
}
//////////////////////////////////////////////////////////////////////////////
@@ -476,17 +453,17 @@ void TryCatchStatement::toIR(IRState* p)
Logger::println("TryCatchStatement::toIR(%d): %s", wsi++, toChars());
LOG_SCOPE;
assert(0 && "try-catch is not properly");
Logger::println("*** ATTENTION: try-catch is not yet fully implemented, only the try block will be emitted.");
assert(body);
body->toIR(p);
assert(catches);
/*assert(catches);
for(size_t i=0; i<catches->dim; ++i)
{
Catch* c = (Catch*)catches->data[i];
c->handler->toIR(p);
}
}*/
}
//////////////////////////////////////////////////////////////////////////////
@@ -497,11 +474,16 @@ void ThrowStatement::toIR(IRState* p)
Logger::println("ThrowStatement::toIR(%d): %s", wsi++, toChars());
LOG_SCOPE;
assert(0 && "throw is not implemented");
Logger::println("*** ATTENTION: throw is not yet implemented, replacing expression with assert(0);");
llvm::Value* line = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
LLVM_DtoAssert(NULL, line, NULL);
/*
assert(exp);
elem* e = exp->toElem(p);
delete e;
*/
}
//////////////////////////////////////////////////////////////////////////////
@@ -622,7 +604,6 @@ void ForeachStatement::toIR(IRState* p)
LOG_SCOPE;
//assert(arguments->dim == 1);
assert(key == 0);
assert(value != 0);
assert(body != 0);
assert(aggr != 0);
@@ -642,6 +623,7 @@ void ForeachStatement::toIR(IRState* p)
const llvm::Type* keytype = key ? LLVM_DtoType(key->type) : LLVM_DtoSize_t();
llvm::Value* keyvar = new llvm::AllocaInst(keytype, "foreachkey", p->topallocapoint());
if (key) key->llvmValue = keyvar;
const llvm::Type* valtype = LLVM_DtoType(value->type);
llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint());

View File

@@ -118,8 +118,10 @@ elem* VarExp::toElem(IRState* p)
e->mem = tid->llvmValue;
e->type = elem::VAR;
}
else
assert(0 && "only magic supported is typeinfo");
else {
Logger::println("unsupported: %s\n", vd->toChars());
assert(0 && "only magic supported is typeinfo");
}
}
return e;
}
@@ -331,9 +333,23 @@ elem* AssignExp::toElem(IRState* p)
elem* r = e2->toElem(p);
p->lvals.pop_back();
if (l->type == elem::ARRAYLEN)
{
LLVM_DtoResizeDynArray(l->mem, r->getValue());
delete r;
delete l;
return 0;
}
// handle function argument - allocate temp storage for it :/ annoying
if (l->mem == 0) {
LLVM_DtoGiveArgumentStorage(l);
assert(l->val);
if (llvm::isa<llvm::Argument>(l->val))
LLVM_DtoGiveArgumentStorage(l);
else {
Logger::cout() << "here it comes... " << *l->val << '\n';
assert(0);
}
}
//e->val = l->store(r->getValue());
@@ -1826,12 +1842,16 @@ elem* NewExp::toElem(IRState* p)
if (arguments->dim == 1) {
elem* sz = ((Expression*)arguments->data[0])->toElem(p);
llvm::Value* dimval = sz->getValue();
llvm::Value* usedimval = dimval;
/*llvm::Value* usedimval = dimval;
if (dimval->getType() != llvm::Type::Int32Ty)
usedimval = new llvm::TruncInst(dimval, llvm::Type::Int32Ty,"tmp",p->scopebb());
e->mem = new llvm::MallocInst(t,usedimval,"tmp",p->scopebb());
usedimval = new llvm::TruncInst(dimval, llvm::Type::Int32Ty,"tmp",p->scopebb());*/
LLVM_DtoSetArray(p->toplval(), dimval, e->mem);
//e->mem = LLVM_DtoRealloc(0,t);
//new llvm::MallocInst(t,usedimval,"tmp",p->scopebb());
//LLVM_DtoSetArray(p->toplval(), dimval, e->mem);
LLVM_DtoNewDynArray(p->toplval(), dimval, t);
delete sz;
}
else {
@@ -1948,11 +1968,18 @@ elem* ArrayLengthExp::toElem(IRState* p)
elem* e = new elem;
elem* u = e1->toElem(p);
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
llvm::Value* ptr = LLVM_DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
e->type = elem::VAL;
if (p->inLvalue)
{
e->mem = u->mem;
e->type = elem::ARRAYLEN;
}
else
{
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
llvm::Value* ptr = LLVM_DtoGEP(u->mem,zero,zero,"tmp",p->scopebb());
e->val = new llvm::LoadInst(ptr, "tmp", p->scopebb());
e->type = elem::VAL;
}
delete u;
return e;
@@ -1965,27 +1992,16 @@ elem* AssertExp::toElem(IRState* p)
Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
elem* e = new elem;
elem* u = e1->toElem(p);
elem* m = msg ? msg->toElem(p) : 0;
elem* m = msg ? msg->toElem(p) : NULL;
llvm::Value* loca = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
LLVM_DtoAssert(u->getValue(), loca, m ? m->val : NULL);
std::vector<llvm::Value*> llargs;
llargs.resize(3);
llargs[0] = LLVM_DtoBoolean(u->getValue());
llargs[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, loc.linnum, false);
llargs[2] = m ? m->val : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
delete m;
delete u;
//Logger::cout() << *llargs[0] << '|' << *llargs[1] << '\n';
llvm::Function* fn = LLVM_D_GetRuntimeFunction(p->module, "_d_assert");
assert(fn);
llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", p->scopebb());
call->setCallingConv(llvm::CallingConv::C);
return e;
return new elem;
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -997,3 +997,66 @@ void LLVM_DtoGiveArgumentStorage(elem* l)
l->mem = allocainst;
l->vardecl->llvmValue = l->mem;
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, const llvm::Type* ty)
{
/*size_t sz = gTargetData->getTypeSize(ty);
llvm::ConstantInt* n = llvm::ConstantInt::get(LLVM_DtoSize_t(), sz, false);
if (ptr == 0) {
llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
ptr = llvm::ConstantPointerNull::get(i8pty);
}
return LLVM_DtoRealloc(ptr, n);*/
return NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_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;
llvm::PointerType* i8pty = llvm::PointerType::get(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());
}
//////////////////////////////////////////////////////////////////////////////////////////
void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg)
{
assert(loc);
std::vector<llvm::Value*> llargs;
llargs.resize(3);
llargs[0] = cond ? LLVM_DtoBoolean(cond) : llvm::ConstantInt::getFalse();
llargs[1] = loc;
llargs[2] = msg ? msg : llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty));
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert");
assert(fn);
llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
call->setCallingConv(llvm::CallingConv::C);
}

View File

@@ -44,4 +44,9 @@ llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std:
void LLVM_DtoGiveArgumentStorage(elem* e);
llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, const llvm::Type* ty);
llvm::Value* LLVM_DtoRealloc(llvm::Value* ptr, llvm::Value* len);
void LLVM_DtoAssert(llvm::Value* cond, llvm::Value* loc, llvm::Value* msg);
#include "enums.h"

View File

@@ -9,14 +9,15 @@ fi
# build runtime
$dc_cmd internal/contract.d \
internal/arrays.d \
internal/mem.d \
internal/moduleinit.d \
-c -noruntime -odobj || exit 1
llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1
llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1
llvm-link -f -o=../lib/llvmdcore.bc obj/contract.bc obj/arrays.bc obj/mem.bc obj/moduleinit.bc obj/moduleinit_backend.bc || exit 1
$dc_cmd internal/objectimpl.d -c -odobj || exit 1
llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1
llvm-link -f -o=obj/all.bc obj/contract.bc obj/arrays.bc obj/mem.bc obj/moduleinit.bc obj/objectimpl.bc obj/moduleinit_backend.bc || exit 1
opt -f -std-compile-opts -o=../lib/llvmdcore.bc obj/all.bc || exit 1

16
lphobos/internal/mem.d Normal file
View File

@@ -0,0 +1,16 @@
module internal.mem;
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);
}

10
test/arrays3.d Normal file
View File

@@ -0,0 +1,10 @@
module arrays3;
void main()
{
int[] arr;
{arr = new int[25];}
{assert(arr.length == 25);}
{arr.length = arr.length + 5;}
{assert(arr.length == 30);}
}

14
test/bug7.d Normal file
View File

@@ -0,0 +1,14 @@
module bug7;
class love { }
void bug() {
love[] child;
child.length=1;
assert(child[0] is null);
child[0]=null;
assert(child[0] is null);
}
void main()
{
bug();
}

15
test/foreach2.d Normal file
View File

@@ -0,0 +1,15 @@
module foreach2;
void main()
{
static arr = [1.0, 2.0, 4.0, 8.0, 16.0];
foreach(i,v; arr)
{
printf("arr[%d] = %f\n", i, v);
}
printf("-------------------------------\n");
foreach_reverse(i,v; arr)
{
printf("arr[%d] = %f\n", i, v);
}
}

19
test/foreach3.d Normal file
View File

@@ -0,0 +1,19 @@
module foreach3;
void main()
{
static str = ['h','e','l','l','o'];
foreach(i,v; str) {
printf("%c",v);
}
printf("\n");
foreach(i,v; str) {
v++;
}
foreach(i,v; str) {
printf("%c",v);
}
printf("\n");
}

10
test/memory1.d Normal file
View File

@@ -0,0 +1,10 @@
module memory1;
void main()
{
auto a = new int[16];
{printf("array.length = %u\n", a.length);}
{a.length = a.length + 1;}
{printf("array.length = %u\n", a.length);}
{assert(a.length == 17);}
}

26
test/throw1.d Normal file
View File

@@ -0,0 +1,26 @@
module throw1;
extern(C) int rand();
class C
{
}
void func()
{
if (rand() & 1)
throw new C;
}
int main()
{
try
{
func();
}
catch(Object)
{
return 1;
}
return 0;
}