changeset 440:d8dc221d3db7

Insert array bound checks for slices.
author Christian Kamm <kamm incasoftware de>
date Wed, 30 Jul 2008 19:02:13 +0200
parents 47b64d06eb9f
children ca80e42d11e0
files gen/llvmhelpers.cpp gen/llvmhelpers.h gen/toir.cpp
diffstat 3 files changed, 15 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/gen/llvmhelpers.cpp	Wed Jul 30 18:38:56 2008 +0200
+++ b/gen/llvmhelpers.cpp	Wed Jul 30 19:02:13 2008 +0200
@@ -158,7 +158,7 @@
 // ARRAY BOUNDS HELPER
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
-void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index)
+void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index, bool isslice)
 {
     Type* arrty = arr->getType();
     assert((arrty->ty == Tsarray || arrty->ty == Tarray) && "Can only array bounds check for static or dynamic arrays");
@@ -171,8 +171,12 @@
         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);
+            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;
             }
     }
@@ -183,7 +187,8 @@
     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");
+    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
--- a/gen/llvmhelpers.h	Wed Jul 30 18:38:56 2008 +0200
+++ b/gen/llvmhelpers.h	Wed Jul 30 19:02:13 2008 +0200
@@ -14,7 +14,7 @@
 // assertion generator
 void DtoAssert(Loc* loc, DValue* msg);
 // array boundary check generator
-void DtoArrayBoundsCheck(Loc& loc, DValue* arr, DValue* index);
+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);
--- a/gen/toir.cpp	Wed Jul 30 18:38:56 2008 +0200
+++ b/gen/toir.cpp	Wed Jul 30 19:02:13 2008 +0200
@@ -1009,12 +1009,12 @@
     }
     else if (e1type->ty == Tsarray) {
         if(global.params.useArrayBounds) 
-            DtoArrayBoundsCheck(loc, l, r);
+            DtoArrayBoundsCheck(loc, l, r, false);
         arrptr = DtoGEP(l->getRVal(), zero, r->getRVal());
     }
     else if (e1type->ty == Tarray) {
         if(global.params.useArrayBounds) 
-            DtoArrayBoundsCheck(loc, l, r);
+            DtoArrayBoundsCheck(loc, l, r, false);
         arrptr = DtoArrayPtr(l);
         arrptr = DtoGEP1(arrptr,r->getRVal());
     }
@@ -1071,6 +1071,9 @@
         LLValue* vlo = lo->getRVal();
         LLValue* vup = up->getRVal();
 
+        if(global.params.useArrayBounds && (etype->ty == Tsarray || etype->ty == Tarray))
+            DtoArrayBoundsCheck(loc, e, up, true);
+
         // offset by lower
         eptr = DtoGEP1(eptr, vlo);