# HG changeset patch # User lindquist # Date 1214625436 -7200 # Node ID 6b62e8cdf970255574b3833714d98dae3c7f6b87 # Parent 7ade5e035beb4c8c8e4711542f66e61963edd861 [svn r329] Cleaned up a bunch of array code for handling special slice cases no longer relevant. diff -r 7ade5e035beb -r 6b62e8cdf970 gen/arrays.cpp --- 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); diff -r 7ade5e035beb -r 6b62e8cdf970 gen/arrays.h --- 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); diff -r 7ade5e035beb -r 6b62e8cdf970 gen/statements.cpp --- 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); diff -r 7ade5e035beb -r 6b62e8cdf970 gen/toir.cpp --- 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(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(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(cv->c)); - if (lwr_is_zero) { - earg = cv->c; - } - else { - if (lo->isConst()) { - LLConstant* clo = llvm::cast(lo->getRVal()); - LLConstant* cup = llvm::cast(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) diff -r 7ade5e035beb -r 6b62e8cdf970 gen/tollvm.cpp --- 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); }