Commit f11289f6 authored by Duncan Coutts's avatar Duncan Coutts Committed by Austin Seipp

New primops for byte range copies ByteArray# <-> Addr#

We have primops for copying ranges of bytes between ByteArray#s:
 * ByteArray# -> MutableByteArray#
 * MutableByteArray# -> MutableByteArray#
This extends it with three further cases:
 * Addr# -> MutableByteArray#
 * ByteArray# -> Addr#
 * MutableByteArray# -> Addr#
One use case for these is copying between ForeignPtr-based
representations and in-heap arrays (like Text, UArray etc).

The implementation is essentially the same as for the existing
primops, and shares the memcpy stuff in the code generators.

Defficiencies / future directions: none of these primops (existing
or the new ones) let one take advantage of knowing that ByteArray#s
are word-aligned in memory. Though it is unclear that any of the
code generators would make use of this information unless the size
to copy is also known at compile time.
Signed-off-by: default avatarAustin Seipp <austin@well-typed.com>
parent 865956a6
......@@ -529,6 +529,12 @@ emitPrimOp _ [] CopyByteArrayOp [src,src_off,dst,dst_off,n] =
doCopyByteArrayOp src src_off dst dst_off n
emitPrimOp _ [] CopyMutableByteArrayOp [src,src_off,dst,dst_off,n] =
doCopyMutableByteArrayOp src src_off dst dst_off n
emitPrimOp _ [] CopyByteArrayToAddrOp [src,src_off,dst,n] =
doCopyByteArrayToAddrOp src src_off dst n
emitPrimOp _ [] CopyMutableByteArrayToAddrOp [src,src_off,dst,n] =
doCopyMutableByteArrayToAddrOp src src_off dst n
emitPrimOp _ [] CopyAddrToByteArrayOp [src,dst,dst_off,n] =
doCopyAddrToByteArrayOp src dst dst_off n
emitPrimOp _ [] SetByteArrayOp [ba,off,len,c] =
doSetByteArrayOp ba off len c
......@@ -1358,6 +1364,34 @@ emitCopyByteArray copy src src_off dst dst_off n = do
src_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags src (arrWordsHdrSize dflags)) src_off
copy src dst dst_p src_p n
-- | Takes a source 'ByteArray#', an offset in the source array, a
-- destination 'Addr#', and the number of bytes to copy. Copies the given
-- number of bytes from the source array to the destination memory region.
doCopyByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayToAddrOp src src_off dst_p bytes = do
-- Use memcpy (we are allowed to assume the arrays aren't overlapping)
dflags <- getDynFlags
src_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags src (arrWordsHdrSize dflags)) src_off
emitMemcpyCall dst_p src_p bytes (mkIntExpr dflags 1)
-- | Takes a source 'MutableByteArray#', an offset in the source array, a
-- destination 'Addr#', and the number of bytes to copy. Copies the given
-- number of bytes from the source array to the destination memory region.
doCopyMutableByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
-> FCode ()
doCopyMutableByteArrayToAddrOp = doCopyByteArrayToAddrOp
-- | Takes a source 'Addr#', a destination 'MutableByteArray#', an offset into
-- the destination array, and the number of bytes to copy. Copies the given
-- number of bytes from the source memory region to the destination array.
doCopyAddrToByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToByteArrayOp src_p dst dst_off bytes = do
-- Use memcpy (we are allowed to assume the arrays aren't overlapping)
dflags <- getDynFlags
dst_p <- assignTempE $ cmmOffsetExpr dflags (cmmOffsetB dflags dst (arrWordsHdrSize dflags)) dst_off
emitMemcpyCall dst_p src_p bytes (mkIntExpr dflags 1)
-- ----------------------------------------------------------------------------
-- Setting byte arrays
......
......@@ -1110,6 +1110,42 @@ primop CopyMutableByteArrayOp "copyMutableByteArray#" GenPrimOp
code_size = { primOpCodeSizeForeignCall + 4 }
can_fail = True
primop CopyByteArrayToAddrOp "copyByteArrayToAddr#" GenPrimOp
ByteArray# -> Int# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld
{Copy a range of the ByteArray# to the memory range starting at the Addr#.
The ByteArray# and the memory region at Addr# must fully contain the
specified ranges, but this is not checked. The Addr# must not point into the
ByteArray# (e.g. if the ByteArray# were pinned), but this is not checked
either.}
with
has_side_effects = True
code_size = { primOpCodeSizeForeignCall + 4}
can_fail = True
primop CopyMutableByteArrayToAddrOp "copyMutableByteArrayToAddr#" GenPrimOp
MutableByteArray# RealWorld -> Int# -> Addr# -> Int# -> State# RealWorld -> State# RealWorld
{Copy a range of the MutableByteArray# to the memory range starting at the
Addr#. The MutableByteArray# and the memory region at Addr# must fully
contain the specified ranges, but this is not checked. The Addr# must not
point into the MutableByteArray# (e.g. if the MutableByteArray# were
pinned), but this is not checked either.}
with
has_side_effects = True
code_size = { primOpCodeSizeForeignCall + 4}
can_fail = True
primop CopyAddrToByteArrayOp "copyAddrToByteArray#" GenPrimOp
Addr# -> MutableByteArray# s -> Int# -> Int# -> State# RealWorld -> State# RealWorld
{Copy a memory range starting at the Addr# to the specified range in the
MutableByteArray#. The memory region at Addr# and the ByteArray# must fully
contain the specified ranges, but this is not checked. The Addr# must not
point into the MutableByteArray# (e.g. if the MutableByteArray# were pinned),
but this is not checked either.}
with
has_side_effects = True
code_size = { primOpCodeSizeForeignCall + 4}
can_fail = True
primop SetByteArrayOp "setByteArray#" GenPrimOp
MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
{Set the range of the MutableByteArray# to the specified character.}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment