From dfea022a86586cae64927f9e20f225a4e1b63e8e Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Sun, 10 May 2009 02:23:05 +0200 Subject: [PATCH] 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. --- gen/arrays.cpp | 26 ++++++++++++++++++++++---- gen/runtime.cpp | 6 ++++++ runtime/internal/arrayInit.d | 11 +++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 66abca1a..59934b2f 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -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 @@ static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz) 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 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src) 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 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src) 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); + } } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 512b3238..e5f52f79 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -402,8 +402,12 @@ static void LLVM_D_BuildRuntimeModule() // 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 types; types.push_back(voidPtrTy); types.push_back(sizeTy); @@ -412,6 +416,8 @@ static void LLVM_D_BuildRuntimeModule() 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); } ///////////////////////////////////////////////////////////////////////////////////// diff --git a/runtime/internal/arrayInit.d b/runtime/internal/arrayInit.d index c597fb29..56e88d87 100644 --- a/runtime/internal/arrayInit.d +++ b/runtime/internal/arrayInit.d @@ -156,3 +156,14 @@ size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz) } 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"); +}