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 }