changeset 1328:c78fd2d30da1

Changed array slice copying to call a runtime function when assertions or array bound checks are enabled instead of just doing a memcpy. This makes sure an exception is thrown if the copy is invalid (ie. different lengths or overlap). Fixes ticket #283 . Rebuilding the runtime is necessary.
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Sun, 10 May 2009 02:23:05 +0200
parents 49fd0c8040e6
children e5b57fd8307c
files gen/arrays.cpp gen/runtime.cpp runtime/internal/arrayInit.d
diffstat 3 files changed, 39 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/gen/arrays.cpp	Sun May 10 00:50:35 2009 +0200
+++ b/gen/arrays.cpp	Sun May 10 02:23:05 2009 +0200
@@ -16,6 +16,8 @@
 #include "gen/dvalue.h"
 #include "ir/irmodule.h"
 
+#include "gen/cl_options.h"
+
 //////////////////////////////////////////////////////////////////////////////////////////
 
 const LLStructType* DtoArrayType(Type* arrayTy)
@@ -334,7 +336,7 @@
     assert(e->len != 0);
     const LLType* t = e->ptr->getType()->getContainedType(0);
     sz = gIR->ir->CreateMul(DtoConstSize_t(getTypePaddedSize(t)), e->len, "tmp");
-    return e->ptr;
+    return DtoBitCast(e->ptr, getVoidPtrType());
 }
 
 void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
@@ -345,7 +347,15 @@
     LLValue* dstarr = get_slice_ptr(dst,sz1);
     LLValue* srcarr = get_slice_ptr(src,sz2);
 
-    DtoMemCpy(dstarr, srcarr, sz1);
+    if (global.params.useAssert || global.params.useArrayBounds)
+    {
+        LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy");
+        gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, sz2);
+    }
+    else
+    {
+        DtoMemCpy(dstarr, srcarr, sz1);
+    }
 }
 
 void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
@@ -354,9 +364,17 @@
 
     LLValue* sz1;
     LLValue* dstarr = get_slice_ptr(dst,sz1);
-    LLValue* srcarr = DtoArrayPtr(src);
+    LLValue* srcarr = DtoBitCast(DtoArrayPtr(src), getVoidPtrType());
 
-    DtoMemCpy(dstarr, srcarr, sz1);
+    if (global.params.useAssert || global.params.useArrayBounds)
+    {
+        LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy");
+        gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, DtoArrayLen(src));
+    }
+    else
+    {
+        DtoMemCpy(dstarr, srcarr, sz1);
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
--- a/gen/runtime.cpp	Sun May 10 00:50:35 2009 +0200
+++ b/gen/runtime.cpp	Sun May 10 02:23:05 2009 +0200
@@ -402,8 +402,12 @@
 
     // array init mem
     // void _d_array_init_mem(void* a, size_t na, void* v, size_t nv)
+    // +
+    // array slice copy when assertions are on!
+    // void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen)
     {
         std::string fname("_d_array_init_mem");
+        std::string fname2("_d_array_slice_copy");
         std::vector<const LLType*> types;
         types.push_back(voidPtrTy);
         types.push_back(sizeTy);
@@ -412,6 +416,8 @@
         const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
         llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
             ->setAttributes(Attr_1_3_NoCapture);
+        llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
+            ->setAttributes(Attr_1_3_NoCapture);
     }
 
     /////////////////////////////////////////////////////////////////////////////////////
--- a/runtime/internal/arrayInit.d	Sun May 10 00:50:35 2009 +0200
+++ b/runtime/internal/arrayInit.d	Sun May 10 02:23:05 2009 +0200
@@ -156,3 +156,14 @@
     }
     return (len*elemsz)/newelemsz;
 }
+
+// slice copy when assertions are enabled
+void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen)
+{
+    if (dstlen != srclen)
+        throw new Exception("lengths don't match for array copy");
+    else if (dst+dstlen <= src || src+srclen <= dst)
+        llvm_memcpy(dst, src, dstlen, 0);
+    else
+        throw new Exception("overlapping array copy");
+}