mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-14 15:16:07 +03:00
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.
This commit is contained in:
parent
54d9955abc
commit
dfea022a86
3 changed files with 39 additions and 4 deletions
|
@ -16,6 +16,8 @@
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
#include "ir/irmodule.h"
|
#include "ir/irmodule.h"
|
||||||
|
|
||||||
|
#include "gen/cl_options.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const LLStructType* DtoArrayType(Type* arrayTy)
|
const LLStructType* DtoArrayType(Type* arrayTy)
|
||||||
|
@ -334,7 +336,7 @@ static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz)
|
||||||
assert(e->len != 0);
|
assert(e->len != 0);
|
||||||
const LLType* t = e->ptr->getType()->getContainedType(0);
|
const LLType* t = e->ptr->getType()->getContainedType(0);
|
||||||
sz = gIR->ir->CreateMul(DtoConstSize_t(getTypePaddedSize(t)), e->len, "tmp");
|
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)
|
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||||
|
@ -345,8 +347,16 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||||
LLValue* dstarr = get_slice_ptr(dst,sz1);
|
LLValue* dstarr = get_slice_ptr(dst,sz1);
|
||||||
LLValue* srcarr = get_slice_ptr(src,sz2);
|
LLValue* srcarr = get_slice_ptr(src,sz2);
|
||||||
|
|
||||||
|
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);
|
DtoMemCpy(dstarr, srcarr, sz1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||||
{
|
{
|
||||||
|
@ -354,10 +364,18 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||||
|
|
||||||
LLValue* sz1;
|
LLValue* sz1;
|
||||||
LLValue* dstarr = get_slice_ptr(dst,sz1);
|
LLValue* dstarr = get_slice_ptr(dst,sz1);
|
||||||
LLValue* srcarr = DtoArrayPtr(src);
|
LLValue* srcarr = DtoBitCast(DtoArrayPtr(src), getVoidPtrType());
|
||||||
|
|
||||||
|
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);
|
DtoMemCpy(dstarr, srcarr, sz1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
void DtoStaticArrayCopy(LLValue* dst, LLValue* src)
|
||||||
|
|
|
@ -402,8 +402,12 @@ static void LLVM_D_BuildRuntimeModule()
|
||||||
|
|
||||||
// array init mem
|
// array init mem
|
||||||
// void _d_array_init_mem(void* a, size_t na, void* v, size_t nv)
|
// 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 fname("_d_array_init_mem");
|
||||||
|
std::string fname2("_d_array_slice_copy");
|
||||||
std::vector<const LLType*> types;
|
std::vector<const LLType*> types;
|
||||||
types.push_back(voidPtrTy);
|
types.push_back(voidPtrTy);
|
||||||
types.push_back(sizeTy);
|
types.push_back(sizeTy);
|
||||||
|
@ -412,6 +416,8 @@ static void LLVM_D_BuildRuntimeModule()
|
||||||
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
|
||||||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||||||
->setAttributes(Attr_1_3_NoCapture);
|
->setAttributes(Attr_1_3_NoCapture);
|
||||||
|
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
|
||||||
|
->setAttributes(Attr_1_3_NoCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -156,3 +156,14 @@ size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
|
||||||
}
|
}
|
||||||
return (len*elemsz)/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");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue