mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-09 12:32:33 +03:00
Insert array bound checks for slices.
This commit is contained in:
parent
7882f4858e
commit
5b5d7404b4
3 changed files with 15 additions and 7 deletions
|
@ -158,7 +158,7 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||||
// ARRAY BOUNDS HELPER
|
// 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();
|
Type* arrty = arr->getType();
|
||||||
assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays");
|
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();
|
size_t tdim = tsa->dim->toInteger();
|
||||||
|
|
||||||
if(llvm::ConstantInt* cindex = llvm::dyn_cast<llvm::ConstantInt>(index->getRVal()))
|
if(llvm::ConstantInt* cindex = llvm::dyn_cast<llvm::ConstantInt>(index->getRVal()))
|
||||||
if(cindex->uge(tdim)) {
|
if(cindex->uge(tdim + (isslice ? 1 : 0))) {
|
||||||
error(loc, "index %d is larger than array size %d", index, tdim);
|
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;
|
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* failbb = llvm::BasicBlock::Create("arrayboundscheckfail", gIR->topfunc(), oldend);
|
||||||
llvm::BasicBlock* okbb = llvm::BasicBlock::Create("arrayboundsok", 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);
|
gIR->ir->CreateCondBr(cond, okbb, failbb);
|
||||||
|
|
||||||
// set up failbb to call the array bounds error runtime function
|
// set up failbb to call the array bounds error runtime function
|
||||||
|
|
|
@ -14,7 +14,7 @@ void DtoDeleteArray(DValue* arr);
|
||||||
// assertion generator
|
// assertion generator
|
||||||
void DtoAssert(Loc* loc, DValue* msg);
|
void DtoAssert(Loc* loc, DValue* msg);
|
||||||
// array boundary check generator
|
// 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
|
// return the LabelStatement from the current function with the given identifier or NULL if not found
|
||||||
LabelStatement* DtoLabelStatement(Identifier* ident);
|
LabelStatement* DtoLabelStatement(Identifier* ident);
|
||||||
|
|
|
@ -1009,12 +1009,12 @@ DValue* IndexExp::toElem(IRState* p)
|
||||||
}
|
}
|
||||||
else if (e1type->ty == Tsarray) {
|
else if (e1type->ty == Tsarray) {
|
||||||
if(global.params.useArrayBounds)
|
if(global.params.useArrayBounds)
|
||||||
DtoArrayBoundsCheck(loc, l, r);
|
DtoArrayBoundsCheck(loc, l, r, false);
|
||||||
arrptr = DtoGEP(l->getRVal(), zero, r->getRVal());
|
arrptr = DtoGEP(l->getRVal(), zero, r->getRVal());
|
||||||
}
|
}
|
||||||
else if (e1type->ty == Tarray) {
|
else if (e1type->ty == Tarray) {
|
||||||
if(global.params.useArrayBounds)
|
if(global.params.useArrayBounds)
|
||||||
DtoArrayBoundsCheck(loc, l, r);
|
DtoArrayBoundsCheck(loc, l, r, false);
|
||||||
arrptr = DtoArrayPtr(l);
|
arrptr = DtoArrayPtr(l);
|
||||||
arrptr = DtoGEP1(arrptr,r->getRVal());
|
arrptr = DtoGEP1(arrptr,r->getRVal());
|
||||||
}
|
}
|
||||||
|
@ -1071,6 +1071,9 @@ DValue* SliceExp::toElem(IRState* p)
|
||||||
LLValue* vlo = lo->getRVal();
|
LLValue* vlo = lo->getRVal();
|
||||||
LLValue* vup = up->getRVal();
|
LLValue* vup = up->getRVal();
|
||||||
|
|
||||||
|
if(global.params.useArrayBounds && (etype->ty == Tsarray || etype->ty == Tarray))
|
||||||
|
DtoArrayBoundsCheck(loc, e, up, true);
|
||||||
|
|
||||||
// offset by lower
|
// offset by lower
|
||||||
eptr = DtoGEP1(eptr, vlo);
|
eptr = DtoGEP1(eptr, vlo);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue