changeset 308:6b62e8cdf970 trunk

[svn r329] Cleaned up a bunch of array code for handling special slice cases no longer relevant.
author lindquist
date Sat, 28 Jun 2008 05:57:16 +0200
parents 7ade5e035beb
children d59c363fccad
files gen/arrays.cpp gen/arrays.h gen/statements.cpp gen/toir.cpp gen/tollvm.cpp
diffstat 5 files changed, 90 insertions(+), 245 deletions(-) [+]
line wrap: on
line diff
--- a/gen/arrays.cpp	Sat Jun 28 03:45:18 2008 +0200
+++ b/gen/arrays.cpp	Sat Jun 28 05:57:16 2008 +0200
@@ -241,6 +241,7 @@
 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 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 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* 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");
-
-        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");
+    assert(l);
+    assert(r);
 
-        LLValue* b = gIR->ir->CreateAnd(b1,b2,"tmp");
-        return b;
-    }
-    else {
-        assert(l->getType() == r->getType());
+    // compare lengths
+    len1 = DtoArrayLen(l);
+    len2 = DtoArrayLen(r);
+    LLValue* b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,len1,len2,"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");
+    // compare pointers
+    ptr1 = DtoArrayPtr(l);
+    ptr2 = DtoArrayPtr(r);
+    LLValue* b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ,ptr1,ptr2,"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");
+    // combine
+    LLValue* res = gIR->ir->CreateAnd(b1,b2,"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 @@
 
     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 @@
 
     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);
--- a/gen/arrays.h	Sat Jun 28 03:45:18 2008 +0200
+++ b/gen/arrays.h	Sat Jun 28 05:57:16 2008 +0200
@@ -33,7 +33,7 @@
 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);
 
--- a/gen/statements.cpp	Sat Jun 28 03:45:18 2008 +0200
+++ b/gen/statements.cpp	Sat Jun 28 05:57:16 2008 +0200
@@ -912,45 +912,8 @@
     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 @@
     // 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);
--- a/gen/toir.cpp	Sat Jun 28 03:45:18 2008 +0200
+++ b/gen/toir.cpp	Sat Jun 28 05:57:16 2008 +0200
@@ -1529,108 +1529,56 @@
     Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
     LOG_SCOPE;
 
-    Type* t = DtoDType(type);
-    Type* e1type = DtoDType(e1->type);
-
-    DValue* v = e1->toElem(p);
-    LLValue* vmem = v->getRVal();
-    assert(vmem);
-
-    LLValue* zero = DtoConstUint(0);
-    LLValue* one = DtoConstUint(1);
-
-    LLValue* emem = 0;
-    LLValue* earg = 0;
-
-    // partial slice
+    // 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.
+
+    // value being sliced
+    LLValue* elen;
+    LLValue* eptr;
+    DValue* e = e1->toElem(p);
+
+    // handle pointer slicing
+    Type* etype = e1->type->toBasetype();
+    if (etype->ty == Tpointer)
+    {
+        assert(lwr);
+        eptr = e->getRVal();
+    }
+    // array slice
+    else
+    {
+        eptr = DtoArrayPtr(e);
+    }
+
+    // has lower bound, pointer needs adjustment
     if (lwr)
     {
+        // must have upper bound too then
         assert(upr);
-        p->arrays.push_back(v);
+
+        // get bounds (make sure $ works)
+        p->arrays.push_back(e);
         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());
-            }
-        }
+        LLValue* vlo = lo->getRVal();
+        LLValue* vup = up->getRVal();
+
+        // offset by lower
+        eptr = DtoGEP1(eptr, vlo);
+
+        // adjust length
+        elen = p->ir->CreateSub(vup, vlo, "tmp");
     }
-    // full slice
+    // no bounds or full slice -> just convert to slice
     else
     {
-        emem = vmem;
+        assert(e1->type->toBasetype()->ty != Tpointer);
+        elen = DtoArrayLen(e);
     }
 
-    if (earg) Logger::cout() << "slice exp result, length = " << *earg << '\n';
-    Logger::cout() << "slice exp result, ptr = " << *emem << '\n';
-
-    return new DSliceValue(type,earg,emem);
+    return new DSliceValue(type, elen, eptr);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -2340,23 +2288,17 @@
     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 @@
         // 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)
--- a/gen/tollvm.cpp	Sat Jun 28 03:45:18 2008 +0200
+++ b/gen/tollvm.cpp	Sat Jun 28 05:57:16 2008 +0200
@@ -87,13 +87,8 @@
         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 @@
 
 const LLPointerType* getPtrToType(const LLType* t)
 {
+    if (t == LLType::VoidTy)
+        t = LLType::Int8Ty;
     return LLPointerType::get(t, 0);
 }