From 5b5d7404b46c21bb30525b233d2453ba819f75ce Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 30 Jul 2008 19:02:13 +0200 Subject: [PATCH] Insert array bound checks for slices. --- gen/llvmhelpers.cpp | 13 +++++++++---- gen/llvmhelpers.h | 2 +- gen/toir.cpp | 7 +++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 4425eda7..a97906c3 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -158,7 +158,7 @@ void DtoAssert(Loc* loc, DValue* msg) // ARRAY BOUNDS HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ -void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index) +void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice) { Type* arrty = arr->getType(); assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays"); @@ -171,8 +171,12 @@ void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index) size_t tdim = tsa->dim->toInteger(); if(llvm::ConstantInt* cindex = llvm::dyn_cast(index->getRVal())) - if(cindex->uge(tdim)) { - error(loc, "index %d is larger than array size %d", index, tdim); + if(cindex->uge(tdim + (isslice ? 1 : 0))) { + size_t cindexval = cindex->getValue().getZExtValue(); + if(!isslice) + error(loc, "index %u is larger or equal array size %u", cindexval, tdim); + else + error(loc, "slice upper bound %u is larger than array size %u", cindexval, tdim); return; } } @@ -183,7 +187,8 @@ void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index) llvm::BasicBlock* failbb = llvm::BasicBlock::Create("arrayboundscheckfail", gIR->topfunc(), oldend); llvm::BasicBlock* okbb = llvm::BasicBlock::Create("arrayboundsok", gIR->topfunc(), oldend); - LLValue* cond = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_ULT, index->getRVal(), DtoArrayLen(arr), "boundscheck"); + 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); // set up failbb to call the array bounds error runtime function diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index 19beb97c..2359e52c 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -14,7 +14,7 @@ void DtoDeleteArray(DValue* arr); // assertion generator void DtoAssert(Loc* loc, DValue* msg); // array boundary check generator -void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index); +void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice); // return the LabelStatement from the current function with the given identifier or NULL if not found LabelStatement* DtoLabelStatement(Identifier* ident); diff --git a/gen/toir.cpp b/gen/toir.cpp index 5639251f..44e90b3c 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1009,12 +1009,12 @@ DValue* IndexExp::toElem(IRState* p) } else if (e1type->ty == Tsarray) { if(global.params.useArrayBounds) - DtoArrayBoundsCheck(loc, l, r); + DtoArrayBoundsCheck(loc, l, r, false); arrptr = DtoGEP(l->getRVal(), zero, r->getRVal()); } else if (e1type->ty == Tarray) { if(global.params.useArrayBounds) - DtoArrayBoundsCheck(loc, l, r); + DtoArrayBoundsCheck(loc, l, r, false); arrptr = DtoArrayPtr(l); arrptr = DtoGEP1(arrptr,r->getRVal()); } @@ -1071,6 +1071,9 @@ DValue* SliceExp::toElem(IRState* p) LLValue* vlo = lo->getRVal(); LLValue* vup = up->getRVal(); + if(global.params.useArrayBounds && (etype->ty == Tsarray || etype->ty == Tarray)) + DtoArrayBoundsCheck(loc, e, up, true); + // offset by lower eptr = DtoGEP1(eptr, vlo);