From 1c59eed83a49e9b30fc36c86fc104dd9ceccfee8 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Mon, 3 Jan 2011 16:50:08 +0300 Subject: [PATCH] Check for lower slice bound when bounds checking is enabled --- gen/arrays.cpp | 35 ++++++++++++++++++++++++++++++----- gen/arrays.h | 2 +- gen/toir.cpp | 10 +++++++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 9d9449be..c4de5dd2 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -1274,7 +1274,7 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to) else { size_t i = (tosize * totype->nextOf()->size() - 1) / fromtype->nextOf()->size(); DConstValue index(Type::tsize_t, DtoConstSize_t(i)); - DtoArrayBoundsCheck(loc, u, &index, false); + DtoArrayBoundsCheck(loc, u, &index); rval = DtoArrayPtr(u); rval = DtoBitCast(rval, getPtrToType(tolltype)); @@ -1302,24 +1302,49 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to) } ////////////////////////////////////////////////////////////////////////////////////////// -void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice) +void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, DValue* lowerBound) { Type* arrty = arr->getType()->toBasetype(); +#if DMDV2 + assert((arrty->ty == Tsarray || arrty->ty == Tarray || arrty->ty == Tpointer) && + "Can only array bounds check for static or dynamic arrays"); +#else assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays"); +#endif // static arrays could get static checks for static indices // but shouldn't since it might be generic code that's never executed // runtime check + bool lengthUnknown = arrty->ty == Tpointer; + llvm::BasicBlock* oldend = gIR->scopeend(); llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "arrayboundscheckfail", gIR->topfunc(), oldend); llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "arrayboundsok", gIR->topfunc(), oldend); + LLValue* cond = 0; - llvm::ICmpInst::Predicate cmpop = isslice ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_ULT; - LLValue* cond = gIR->ir->CreateICmp(cmpop, index->getRVal(), DtoArrayLen(arr), "boundscheck"); - gIR->ir->CreateCondBr(cond, okbb, failbb); + if (!lengthUnknown) { + // if lowerBound is not NULL, we're checking slice + llvm::ICmpInst::Predicate cmpop = lowerBound ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_ULT; + // check for upper bound + cond = gIR->ir->CreateICmp(cmpop, index->getRVal(), DtoArrayLen(arr), "boundscheck"); + } + + if (!lowerBound) { + assert(cond); + gIR->ir->CreateCondBr(cond, okbb, failbb); + } else { + if (!lengthUnknown) { + llvm::BasicBlock* locheckbb = llvm::BasicBlock::Create(gIR->context(), "arrayboundschecklowerbound", gIR->topfunc(), oldend); + gIR->ir->CreateCondBr(cond, locheckbb, failbb); + gIR->scope() = IRScope(locheckbb, failbb); + } + // check for lower bound + cond = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_ULE, lowerBound->getRVal(), index->getRVal(), "boundscheck"); + gIR->ir->CreateCondBr(cond, okbb, failbb); + } // set up failbb to call the array bounds error runtime function diff --git a/gen/arrays.h b/gen/arrays.h index e61a7d5d..93c955d7 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -51,6 +51,6 @@ LLValue* DtoArrayPtr(DValue* v); DValue* DtoCastArray(Loc& loc, DValue* val, Type* to); // generates an array bounds check -void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice); +void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, DValue* lowerBound = 0); #endif // LLVMC_GEN_ARRAYS_H diff --git a/gen/toir.cpp b/gen/toir.cpp index 1dbbb563..fe6b4938 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1268,7 +1268,7 @@ DValue* IndexExp::toElem(IRState* p) } else if (e1type->ty == Tsarray) { if(global.params.useArrayBounds) - DtoArrayBoundsCheck(loc, l, r, false); + DtoArrayBoundsCheck(loc, l, r); arrptr = DtoGEP(l->getRVal(), zero, r->getRVal()); } else if (e1type->ty == Tarray) { @@ -1303,7 +1303,7 @@ DValue* IndexExp::toElem(IRState* p) r = new DVarValue(r->getType(), tmp); } #endif - DtoArrayBoundsCheck(loc, l, r, false); + DtoArrayBoundsCheck(loc, l, r); } arrptr = DtoArrayPtr(l); arrptr = DtoGEP1(arrptr,r->getRVal()); @@ -1361,8 +1361,12 @@ DValue* SliceExp::toElem(IRState* p) LLValue* vlo = lo->getRVal(); LLValue* vup = up->getRVal(); +#if DMDV2 + if(global.params.useArrayBounds) +#else if(global.params.useArrayBounds && (etype->ty == Tsarray || etype->ty == Tarray)) - DtoArrayBoundsCheck(loc, e, up, true); +#endif + DtoArrayBoundsCheck(loc, e, up, lo); // offset by lower eptr = DtoGEP1(eptr, vlo);