mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 23:50:43 +03:00
Move DtoArrayBoundsCheck from llvmhelpers to arrays.
This commit is contained in:
parent
fcd784d14f
commit
8f14ece3af
4 changed files with 80 additions and 81 deletions
|
@ -1028,3 +1028,80 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
|||
|
||||
return new DImValue(to, rval);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice)
|
||||
{
|
||||
Type* arrty = arr->getType()->toBasetype();
|
||||
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 + (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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -42,4 +42,7 @@ 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);
|
||||
|
||||
#endif // LLVMC_GEN_ARRAYS_H
|
||||
|
|
|
@ -153,85 +153,6 @@ void DtoAssert(Loc* loc, DValue* msg)
|
|||
gIR->ir->CreateUnreachable();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ARRAY BOUNDS HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice)
|
||||
{
|
||||
Type* arrty = arr->getType()->toBasetype();
|
||||
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 + (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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -13,8 +13,6 @@ void DtoDeleteArray(DValue* arr);
|
|||
|
||||
// assertion generator
|
||||
void DtoAssert(Loc* loc, DValue* msg);
|
||||
// array boundary check generator
|
||||
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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue