[svn r329] Cleaned up a bunch of array code for handling special slice cases no

longer relevant.
This commit is contained in:
Tomas Lindquist Olsen 2008-06-28 05:57:16 +02:00
parent 86d299a641
commit ac3744a59d
5 changed files with 92 additions and 247 deletions

View file

@ -241,6 +241,7 @@ void DtoArrayInit(DValue* array, DValue* value)
void DtoSetArray(LLValue* arr, LLValue* dim, LLValue* ptr)
{
Logger::println("SetArray");
assert(isaStruct(arr->getType()->getContainedType(0)));
DtoStore(dim, DtoGEPi(arr,0,0));
DtoStore(ptr, DtoGEPi(arr,0,1));
}
@ -349,48 +350,10 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
//////////////////////////////////////////////////////////////////////////////////////////
static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz)
{
assert(e->len != 0);
const LLType* t = e->ptr->getType()->getContainedType(0);
LLValue* ret = 0;
if (e->len != 0) {
// this means it's a real slice
ret = e->ptr;
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
if (isaConstantInt(e->len)) {
sz = llvm::ConstantExpr::getMul(elemsz, isaConstant(e->len));
}
else {
sz = llvm::BinaryOperator::createMul(elemsz,e->len,"tmp",gIR->scopebb());
}
}
else if (isaArray(t)) {
ret = DtoGEPi(e->ptr, 0, 0);
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
size_t numelements = isaArray(t)->getNumElements();
llvm::ConstantInt* nelems = llvm::ConstantInt::get(DtoSize_t(), numelements, false);
sz = llvm::ConstantExpr::getMul(elemsz, nelems);
}
else if (isaStruct(t)) {
ret = DtoGEPi(e->ptr, 0, 1);
ret = DtoLoad(ret);
size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0));
llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false);
LLValue* len = DtoGEPi(e->ptr, 0, 0);
len = DtoLoad(len);
sz = llvm::BinaryOperator::createMul(len,elemsz,"tmp",gIR->scopebb());
}
else {
assert(0);
}
return ret;
sz = gIR->ir->CreateMul(DtoConstSize_t(getABITypeSize(t)), e->len, "tmp");
return e->ptr;
}
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
@ -895,37 +858,28 @@ LLValue* DtoArrayCastLength(LLValue* len, const LLType* elemty, const LLType* ne
}
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoDynArrayIs(TOK op, LLValue* l, LLValue* r)
LLValue* DtoDynArrayIs(TOK op, DValue* l, DValue* r)
{
llvm::ICmpInst::Predicate pred = (op == TOKidentity) ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
LLValue *len1, *ptr1, *len2, *ptr2;
if (r == NULL) {
LLValue* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0),"tmp");
LLValue* rl = llvm::Constant::getNullValue(ll->getType());//DtoConstSize_t(0);
LLValue* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
assert(l);
assert(r);
LLValue* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1),"tmp");
const LLPointerType* pty = isaPointer(lp->getType());
LLValue* rp = llvm::ConstantPointerNull::get(pty);
LLValue* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
// compare lengths
len1 = DtoArrayLen(l);
len2 = DtoArrayLen(r);
LLValue* b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,len1,len2,"tmp");
LLValue* b = gIR->ir->CreateAnd(b1,b2,"tmp");
return b;
}
else {
assert(l->getType() == r->getType());
// compare pointers
ptr1 = DtoArrayPtr(l);
ptr2 = DtoArrayPtr(r);
LLValue* b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,ptr1,ptr2,"tmp");
LLValue* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0),"tmp");
LLValue* rl = gIR->ir->CreateLoad(DtoGEPi(r, 0,0),"tmp");
LLValue* b1 = gIR->ir->CreateICmp(pred,ll,rl,"tmp");
// combine
LLValue* res = gIR->ir->CreateAnd(b1,b2,"tmp");
LLValue* lp = gIR->ir->CreateLoad(DtoGEPi(l, 0,1),"tmp");
LLValue* rp = gIR->ir->CreateLoad(DtoGEPi(r, 0,1),"tmp");
LLValue* b2 = gIR->ir->CreateICmp(pred,lp,rp,"tmp");
LLValue* b = gIR->ir->CreateAnd(b1,b2,"tmp");
return b;
}
// return result
return (op == TOKnotidentity) ? gIR->ir->CreateNot(res) : res;
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -954,26 +908,21 @@ LLValue* DtoArrayLen(DValue* v)
Type* t = DtoDType(v->getType());
if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) {
if (s->len) {
return s->len;
}
const LLArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
if (arrTy)
return DtoConstSize_t(arrTy->getNumElements());
else
return DtoLoad(DtoGEPi(s->ptr, 0,0));
}
if (DSliceValue* s = v->isSlice())
return s->len;
else if (v->isNull())
return DtoConstSize_t(0);
return DtoLoad(DtoGEPi(v->getRVal(), 0,0));
}
else if (t->ty == Tsarray) {
assert(!v->isSlice());
assert(!v->isNull());
LLValue* rv = v->getRVal();
Logger::cout() << "casting: " << *rv << '\n';
const LLArrayType* t = isaArray(rv->getType()->getContainedType(0));
assert(t);
return DtoConstSize_t(t->getNumElements());
}
assert(0);
assert(0 && "unsupported array for len");
return 0;
}
@ -985,19 +934,15 @@ LLValue* DtoArrayPtr(DValue* v)
Type* t = DtoDType(v->getType());
if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) {
if (s->len) return s->ptr;
const LLType* t = s->ptr->getType()->getContainedType(0);
Logger::cout() << "ptr of full slice: " << *s->ptr << '\n';
const LLArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0));
if (arrTy)
return DtoGEPi(s->ptr, 0,0);
else
return DtoLoad(DtoGEPi(s->ptr, 0,1));
}
if (DSliceValue* s = v->isSlice())
return s->ptr;
else if (v->isNull())
return getNullPtr(getPtrToType(DtoType(t->next)));
return DtoLoad(DtoGEPi(v->getRVal(), 0,1));
}
else if (t->ty == Tsarray) {
assert(!v->isSlice());
assert(!v->isNull());
return DtoGEPi(v->getRVal(), 0,0);
}
assert(0);

View file

@ -33,7 +33,7 @@ void DtoStaticArrayCopy(LLValue* dst, LLValue* src);
LLValue* DtoArrayEquals(TOK op, DValue* l, DValue* r);
LLValue* DtoArrayCompare(TOK op, DValue* l, DValue* r);
LLValue* DtoDynArrayIs(TOK op, LLValue* l, LLValue* r);
LLValue* DtoDynArrayIs(TOK op, DValue* l, DValue* r);
LLValue* DtoArrayCastLength(LLValue* len, const LLType* elemty, const LLType* newelemty);

View file

@ -912,45 +912,8 @@ void ForeachStatement::toIR(IRState* p)
Type* aggrtype = DtoDType(aggr->type);
// get length and pointer
LLValue* val = 0;
LLValue* niters = 0;
// static array
if (aggrtype->ty == Tsarray)
{
Logger::println("foreach over static array");
val = aggrval->getRVal();
assert(isaPointer(val->getType()));
const llvm::ArrayType* arrty = isaArray(val->getType()->getContainedType(0));
assert(arrty);
size_t nelems = arrty->getNumElements();
if(nelems == 0)
return;
niters = llvm::ConstantInt::get(keytype,nelems,false);
}
// dynamic array
else if (aggrtype->ty == Tarray)
{
if (DSliceValue* slice = aggrval->isSlice()) {
Logger::println("foreach over slice");
niters = slice->len;
assert(niters);
val = slice->ptr;
assert(val);
}
else {
Logger::println("foreach over dynamic array");
val = aggrval->getRVal();
niters = DtoGEPi(val,0,0);
niters = DtoLoad(niters, "numiterations");
val = DtoGEPi(val,0,1);
val = DtoLoad(val, "collection");
}
}
else
{
assert(0 && "aggregate type is not Tarray or Tsarray");
}
LLValue* niters = DtoArrayLen(aggrval);
LLValue* val = DtoArrayPtr(aggrval);
if (niters->getType() != keytype)
{
@ -1001,10 +964,7 @@ void ForeachStatement::toIR(IRState* p)
// get value for this iteration
LLConstant* zero = llvm::ConstantInt::get(keytype,0,false);
LLValue* loadedKey = p->ir->CreateLoad(keyvar,"tmp");
if (aggrtype->ty == Tsarray)
value->ir.irLocal->value = DtoGEP(val,zero,loadedKey,"tmp");
else if (aggrtype->ty == Tarray)
value->ir.irLocal->value = llvm::GetElementPtrInst::Create(val,loadedKey,"tmp",p->scopebb());
value->ir.irLocal->value = DtoGEP1(val,loadedKey);
if (!value->isRef() && !value->isOut()) {
DValue* dst = new DVarValue(value->type, valvar, true);

View file

@ -1529,108 +1529,56 @@ DValue* SliceExp::toElem(IRState* p)
Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
Type* t = DtoDType(type);
Type* e1type = DtoDType(e1->type);
// this is the new slicing code, it's different in that a full slice will no longer retain the original pointer.
// but this was broken if there *was* no original pointer, ie. a slice of a slice...
// now all slices have *both* the 'len' and 'ptr' fields set to != null.
DValue* v = e1->toElem(p);
LLValue* vmem = v->getRVal();
assert(vmem);
// value being sliced
LLValue* elen;
LLValue* eptr;
DValue* e = e1->toElem(p);
LLValue* zero = DtoConstUint(0);
LLValue* one = DtoConstUint(1);
LLValue* emem = 0;
LLValue* earg = 0;
// partial slice
if (lwr)
// handle pointer slicing
Type* etype = e1->type->toBasetype();
if (etype->ty == Tpointer)
{
assert(upr);
p->arrays.push_back(v);
DValue* lo = lwr->toElem(p);
bool lwr_is_zero = false;
if (DConstValue* cv = lo->isConst())
{
assert(llvm::isa<llvm::ConstantInt>(cv->c));
if (e1type->ty == Tpointer) {
emem = v->getRVal();
}
else if (e1type->ty == Tarray) {
LLValue* tmp = DtoGEP(vmem,zero,one);
emem = DtoLoad(tmp);
}
else if (e1type->ty == Tsarray) {
emem = DtoGEP(vmem,zero,zero);
}
else
assert(emem);
llvm::ConstantInt* c = llvm::cast<llvm::ConstantInt>(cv->c);
if (!(lwr_is_zero = c->isZero())) {
emem = DtoGEP1(emem,cv->c);
}
}
else
{
if (e1type->ty == Tarray) {
LLValue* tmp = DtoGEP(vmem,zero,one);
tmp = DtoLoad(tmp);
emem = DtoGEP1(tmp,lo->getRVal());
}
else if (e1type->ty == Tsarray) {
emem = DtoGEP(vmem,zero,lo->getRVal());
}
else if (e1type->ty == Tpointer) {
emem = DtoGEP1(v->getRVal(),lo->getRVal());
}
else {
Logger::println("type = %s", e1type->toChars());
assert(0);
}
}
DValue* up = upr->toElem(p);
p->arrays.pop_back();
if (DConstValue* cv = up->isConst())
{
assert(llvm::isa<llvm::ConstantInt>(cv->c));
if (lwr_is_zero) {
earg = cv->c;
}
else {
if (lo->isConst()) {
LLConstant* clo = llvm::cast<llvm::Constant>(lo->getRVal());
LLConstant* cup = llvm::cast<llvm::Constant>(cv->c);
earg = llvm::ConstantExpr::getSub(cup, clo);
}
else {
earg = llvm::BinaryOperator::createSub(cv->c, lo->getRVal(), "tmp", p->scopebb());
}
}
}
else
{
if (lwr_is_zero) {
earg = up->getRVal();
}
else {
earg = llvm::BinaryOperator::createSub(up->getRVal(), lo->getRVal(), "tmp", p->scopebb());
}
}
assert(lwr);
eptr = e->getRVal();
}
// full slice
// array slice
else
{
emem = vmem;
eptr = DtoArrayPtr(e);
}
if (earg) Logger::cout() << "slice exp result, length = " << *earg << '\n';
Logger::cout() << "slice exp result, ptr = " << *emem << '\n';
// has lower bound, pointer needs adjustment
if (lwr)
{
// must have upper bound too then
assert(upr);
return new DSliceValue(type,earg,emem);
// get bounds (make sure $ works)
p->arrays.push_back(e);
DValue* lo = lwr->toElem(p);
DValue* up = upr->toElem(p);
p->arrays.pop_back();
LLValue* vlo = lo->getRVal();
LLValue* vup = up->getRVal();
// offset by lower
eptr = DtoGEP1(eptr, vlo);
// adjust length
elen = p->ir->CreateSub(vup, vlo, "tmp");
}
// no bounds or full slice -> just convert to slice
else
{
assert(e1->type->toBasetype()->ty != Tpointer);
elen = DtoArrayLen(e);
}
return new DSliceValue(type, elen, eptr);
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -2340,23 +2288,17 @@ DValue* IdentityExp::toElem(IRState* p)
DValue* u = e1->toElem(p);
DValue* v = e2->toElem(p);
Type* t1 = e1->type->toBasetype();
// handle dynarray specially
if (t1->ty == Tarray)
return new DImValue(type, DtoDynArrayIs(op,u,v));
LLValue* l = u->getRVal();
LLValue* r = v->getRVal();
Type* t1 = DtoDType(e1->type);
LLValue* eval = 0;
if (t1->ty == Tarray) {
if (v->isNull()) {
r = NULL;
}
else {
assert(l->getType() == r->getType());
}
eval = DtoDynArrayIs(op,l,r);
}
else if (t1->ty == Tdelegate) {
if (t1->ty == Tdelegate) {
if (v->isNull()) {
r = NULL;
}
@ -2623,9 +2565,10 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
// slice assignment (copy)
if (DSliceValue* s = topval->isSlice())
{
dstMem = s->ptr;
assert(s->ptr->getType()->getContainedType(0) == llStoType->getContainedType(0));
dstMem = DtoBitCast(s->ptr, getPtrToType(llStoType));
sliceInPlace = true;
assert(s->len == NULL);
// FIXME: insert bounds checks
}
// static array assignment
else if (topval->getType()->toBasetype()->ty == Tsarray)

View file

@ -87,13 +87,8 @@ const LLType* DtoType(Type* t)
return DtoComplexType(t);
// pointers
case Tpointer: {
assert(t->next);
if (t->next->ty == Tvoid)
return (const LLType*)getPtrToType(LLType::Int8Ty);
else
return (const LLType*)getPtrToType(DtoType(t->next));
}
case Tpointer:
return getPtrToType(DtoType(t->next));
// arrays
case Tarray:
@ -612,6 +607,8 @@ llvm::GlobalVariable* isaGlobalVar(LLValue* v)
const LLPointerType* getPtrToType(const LLType* t)
{
if (t == LLType::VoidTy)
t = LLType::Int8Ty;
return LLPointerType::get(t, 0);
}