Enable array bounds check and emit them in IndexExp.

This commit is contained in:
Christian Kamm
2008-07-30 18:38:56 +02:00
parent fc9ccb9f6a
commit 7882f4858e
4 changed files with 82 additions and 1 deletions

View File

@@ -270,7 +270,7 @@ int main(int argc, char *argv[])
global.params.useInvariants = 1;
global.params.useIn = 1;
global.params.useOut = 1;
global.params.useArrayBounds = 0;
global.params.useArrayBounds = 1;
global.params.useSwitchError = 1;
global.params.useInline = 0; // this one messes things up to a point where codegen breaks
global.params.llvmInline = 0; // use this one instead to know if inline passes should be run

View File

@@ -153,6 +153,81 @@ void DtoAssert(Loc* loc, DValue* msg)
gIR->ir->CreateUnreachable();
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// ARRAY BOUNDS HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index)
{
Type* arrty = arr->getType();
assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays");
// static arrays can get static checks for static indices
if(arr->getType()->ty == Tsarray)
{
TypeSArray* tsa = (TypeSArray*)arrty;
size_t tdim = tsa->dim->toInteger();
if(llvm::ConstantInt* cindex = llvm::dyn_cast<llvm::ConstantInt>(index->getRVal()))
if(cindex->uge(tdim)) {
error(loc, "index %d is larger than array size %d", index, tdim);
return;
}
}
// runtime check
llvm::BasicBlock* oldend = gIR->scopeend();
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");
gIR->ir->CreateCondBr(cond, okbb, failbb);
// set up failbb to call the array bounds error runtime function
gIR->scope() = IRScope(failbb, okbb);
std::vector<LLValue*> args;
llvm::PAListPtr palist;
// file param
// FIXME: every array bounds check creates a global for the filename !!!
LLConstant* c = DtoConstString(loc.filename);
llvm::AllocaInst* alloc = gIR->func()->srcfileArg;
if (!alloc)
{
alloc = new llvm::AllocaInst(c->getType(), ".srcfile", gIR->topallocapoint());
gIR->func()->srcfileArg = alloc;
}
LLValue* ptr = DtoGEPi(alloc, 0,0, "tmp");
DtoStore(c->getOperand(0), ptr);
ptr = DtoGEPi(alloc, 0,1, "tmp");
DtoStore(c->getOperand(1), ptr);
args.push_back(alloc);
palist = palist.addAttr(1, llvm::ParamAttr::ByVal);
// line param
c = DtoConstUint(loc.linnum);
args.push_back(c);
// call
llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds");
CallOrInvoke* call = gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end());
call->setParamAttrs(palist);
// the function does not return
gIR->ir->CreateUnreachable();
// if ok, proceed in okbb
gIR->scope() = IRScope(okbb, oldend);
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// LABEL HELPER

View File

@@ -13,6 +13,8 @@ void DtoDeleteArray(DValue* arr);
// assertion generator
void DtoAssert(Loc* loc, DValue* msg);
// array boundary check generator
void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index);
// return the LabelStatement from the current function with the given identifier or NULL if not found
LabelStatement* DtoLabelStatement(Identifier* ident);

View File

@@ -1008,9 +1008,13 @@ DValue* IndexExp::toElem(IRState* p)
arrptr = DtoGEP1(l->getRVal(),r->getRVal());
}
else if (e1type->ty == Tsarray) {
if(global.params.useArrayBounds)
DtoArrayBoundsCheck(loc, l, r);
arrptr = DtoGEP(l->getRVal(), zero, r->getRVal());
}
else if (e1type->ty == Tarray) {
if(global.params.useArrayBounds)
DtoArrayBoundsCheck(loc, l, r);
arrptr = DtoArrayPtr(l);
arrptr = DtoGEP1(arrptr,r->getRVal());
}