# HG changeset patch # User Christian Kamm # Date 1217524489 -7200 # Node ID 76078c8ab5b9f797a8e828e550c86425e10059c4 # Parent ca80e42d11e0ff70e70a15903a227a96e5d9ef61 Move DtoArrayBoundsCheck from llvmhelpers to arrays. diff -r ca80e42d11e0 -r 76078c8ab5b9 gen/arrays.cpp --- a/gen/arrays.cpp Wed Jul 30 20:25:46 2008 +0200 +++ b/gen/arrays.cpp Thu Jul 31 19:14:49 2008 +0200 @@ -1028,3 +1028,80 @@ 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(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 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); +} diff -r ca80e42d11e0 -r 76078c8ab5b9 gen/arrays.h --- a/gen/arrays.h Wed Jul 30 20:25:46 2008 +0200 +++ b/gen/arrays.h Thu Jul 31 19:14:49 2008 +0200 @@ -42,4 +42,7 @@ 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 diff -r ca80e42d11e0 -r 76078c8ab5b9 gen/llvmhelpers.cpp --- a/gen/llvmhelpers.cpp Wed Jul 30 20:25:46 2008 +0200 +++ b/gen/llvmhelpers.cpp Thu Jul 31 19:14:49 2008 +0200 @@ -153,85 +153,6 @@ 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(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 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); -} /****************************************************************************************/ /*//////////////////////////////////////////////////////////////////////////////////////// diff -r ca80e42d11e0 -r 76078c8ab5b9 gen/llvmhelpers.h --- a/gen/llvmhelpers.h Wed Jul 30 20:25:46 2008 +0200 +++ b/gen/llvmhelpers.h Thu Jul 31 19:14:49 2008 +0200 @@ -13,8 +13,6 @@ // 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);