Mercurial > projects > ldc
comparison gen/arrays.cpp @ 442:76078c8ab5b9
Move DtoArrayBoundsCheck from llvmhelpers to arrays.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Thu, 31 Jul 2008 19:14:49 +0200 |
parents | 944d43f3779f |
children | 672eb4893b55 |
comparison
equal
deleted
inserted
replaced
441:ca80e42d11e0 | 442:76078c8ab5b9 |
---|---|
1026 return new DSliceValue(to, rval2, rval); | 1026 return new DSliceValue(to, rval2, rval); |
1027 } | 1027 } |
1028 | 1028 |
1029 return new DImValue(to, rval); | 1029 return new DImValue(to, rval); |
1030 } | 1030 } |
1031 | |
1032 | |
1033 ////////////////////////////////////////////////////////////////////////////////////////// | |
1034 void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice) | |
1035 { | |
1036 Type* arrty = arr->getType()->toBasetype(); | |
1037 assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays"); | |
1038 | |
1039 // static arrays can get static checks for static indices | |
1040 | |
1041 if(arr->getType()->ty == Tsarray) | |
1042 { | |
1043 TypeSArray* tsa = (TypeSArray*)arrty; | |
1044 size_t tdim = tsa->dim->toInteger(); | |
1045 | |
1046 if(llvm::ConstantInt* cindex = llvm::dyn_cast<llvm::ConstantInt>(index->getRVal())) | |
1047 if(cindex->uge(tdim + (isslice ? 1 : 0))) { | |
1048 size_t cindexval = cindex->getValue().getZExtValue(); | |
1049 if(!isslice) | |
1050 error(loc, "index %u is larger or equal array size %u", cindexval, tdim); | |
1051 else | |
1052 error(loc, "slice upper bound %u is larger than array size %u", cindexval, tdim); | |
1053 return; | |
1054 } | |
1055 } | |
1056 | |
1057 // runtime check | |
1058 | |
1059 llvm::BasicBlock* oldend = gIR->scopeend(); | |
1060 llvm::BasicBlock* failbb = llvm::BasicBlock::Create("arrayboundscheckfail", gIR->topfunc(), oldend); | |
1061 llvm::BasicBlock* okbb = llvm::BasicBlock::Create("arrayboundsok", gIR->topfunc(), oldend); | |
1062 | |
1063 llvm::ICmpInst::Predicate cmpop = isslice ? llvm::ICmpInst::ICMP_ULE : llvm::ICmpInst::ICMP_ULT; | |
1064 LLValue* cond = gIR->ir->CreateICmp(cmpop, index->getRVal(), DtoArrayLen(arr), "boundscheck"); | |
1065 gIR->ir->CreateCondBr(cond, okbb, failbb); | |
1066 | |
1067 // set up failbb to call the array bounds error runtime function | |
1068 | |
1069 gIR->scope() = IRScope(failbb, okbb); | |
1070 | |
1071 std::vector<LLValue*> args; | |
1072 llvm::PAListPtr palist; | |
1073 | |
1074 // file param | |
1075 // FIXME: every array bounds check creates a global for the filename !!! | |
1076 LLConstant* c = DtoConstString(loc.filename); | |
1077 | |
1078 llvm::AllocaInst* alloc = gIR->func()->srcfileArg; | |
1079 if (!alloc) | |
1080 { | |
1081 alloc = new llvm::AllocaInst(c->getType(), ".srcfile", gIR->topallocapoint()); | |
1082 gIR->func()->srcfileArg = alloc; | |
1083 } | |
1084 LLValue* ptr = DtoGEPi(alloc, 0,0, "tmp"); | |
1085 DtoStore(c->getOperand(0), ptr); | |
1086 ptr = DtoGEPi(alloc, 0,1, "tmp"); | |
1087 DtoStore(c->getOperand(1), ptr); | |
1088 | |
1089 args.push_back(alloc); | |
1090 palist = palist.addAttr(1, llvm::ParamAttr::ByVal); | |
1091 | |
1092 // line param | |
1093 c = DtoConstUint(loc.linnum); | |
1094 args.push_back(c); | |
1095 | |
1096 // call | |
1097 llvm::Function* errorfn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_bounds"); | |
1098 CallOrInvoke* call = gIR->CreateCallOrInvoke(errorfn, args.begin(), args.end()); | |
1099 call->setParamAttrs(palist); | |
1100 | |
1101 // the function does not return | |
1102 gIR->ir->CreateUnreachable(); | |
1103 | |
1104 | |
1105 // if ok, proceed in okbb | |
1106 gIR->scope() = IRScope(okbb, oldend); | |
1107 } |