emitCopySmallArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff
                       -> FCode ())  -- ^ copy function
                   -> CmmExpr        -- ^ source array
                   -> CmmExpr        -- ^ offset in source array
                   -> CmmExpr        -- ^ destination array
                   -> CmmExpr        -- ^ offset in destination array
                   -> WordOff        -- ^ number of elements to copy
                   -> FCode ()
emitCopySmallArray copy src0 src_off dst0 dst_off n = do
    dflags <- getDynFlags

    -- Passed as arguments (be careful)
    src     <- assignTempE src0
    dst     <- assignTempE dst0

    -- Set the dirty bit in the header.
    emit (setInfo dst (CmmLit (CmmLabel mkSMAP_DIRTY_infoLabel)))

    dst_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags dst (smallArrPtrsHdrSize dflags)) dst_off
    src_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags src (smallArrPtrsHdrSize dflags)) src_off
    let bytes = wordsToBytes dflags n

    copy src dst dst_p src_p bytes

-- | Takes an info table label, a register to return the newly
-- allocated array in, a source array, an offset in the source array,
-- and the number of elements to copy. Allocates a new array and
-- initializes it from the source array.
emitCopySmallArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff
                       -> FCode ())  -- ^ copy function
                   -> CmmExpr        -- ^ source array
                   -> CmmExpr        -- ^ offset in source array
                   -> CmmExpr        -- ^ destination array
                   -> CmmExpr        -- ^ offset in destination array
                   -> WordOff        -- ^ number of elements to copy
                   -> FCode ()
emitCopySmallArray copy src0 src_off dst0 dst_off n = do
    dflags <- getDynFlags

    -- Passed as arguments (be careful)
    src     <- assignTempE src0
    dst     <- assignTempE dst0

    -- Set the dirty bit in the header.
    emit (setInfo dst (CmmLit (CmmLabel mkSMAP_DIRTY_infoLabel)))

    dst_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags dst (smallArrPtrsHdrSize dflags)) dst_off
    src_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags src (smallArrPtrsHdrSize dflags)) src_off
    let bytes = wordsToBytes dflags n

    copy src dst dst_p src_p bytes

-- | Takes an info table label, a register to return the newly
-- allocated array in, a source array, an offset in the source array,
-- and the number of elements to copy. Allocates a new array and
-- initializes it from the source array.
emitCopySmallArray copy src0 src_off dst0 dst_off n = do
    dflags <- getDynFlags

    -- Passed as arguments (be careful)
    src     <- assignTempE src0
    dst     <- assignTempE dst0

    -- Set the dirty bit in the header.
    emit (setInfo dst (CmmLit (CmmLabel mkSMAP_DIRTY_infoLabel)))

    dst_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags dst (smallArrPtrsHdrSize dflags)) dst_off
    src_p <- assignTempE $ cmmOffsetExprW dflags
             (cmmOffsetB dflags src (smallArrPtrsHdrSize dflags)) src_off
    let bytes = wordsToBytes dflags n

    copy src dst dst_p src_p bytes

-- | Takes an info table label, a register to return the newly
-- allocated array in, a source array, an offset in the source array,
-- and the number of elements to copy. Allocates a new array and
-- initializes it from the source array.