-- |
-- Module      : Data.Memory.Internal.Scrubber
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : stable
-- Portability : Compat
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
#include "MachDeps.h"
module Data.Memory.Internal.Scrubber
    ( getScrubber
    ) where

import GHC.Prim
import Data.Memory.Internal.CompatPrim (booleanPrim)

getScrubber :: Int# -> (Addr# -> State# RealWorld -> State# RealWorld)
getScrubber :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
getScrubber sz :: Int#
sz 
    | Int# -> Bool
booleanPrim (Int#
sz Int# -> Int# -> Int#
==# 4#)  = Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
scrub4
    | Int# -> Bool
booleanPrim (Int#
sz Int# -> Int# -> Int#
==# 8#)  = Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
scrub8
    | Int# -> Bool
booleanPrim (Int#
sz Int# -> Int# -> Int#
==# 16#) = Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
scrub16
    | Int# -> Bool
booleanPrim (Int#
sz Int# -> Int# -> Int#
==# 32#) = Addr# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> State# d -> State# d
scrub32
    | Bool
otherwise                = Int# -> Addr# -> State# RealWorld -> State# RealWorld
scrubBytes Int#
sz
  where
        scrub4 :: Addr# -> State# d -> State# d
scrub4 a :: Addr#
a = \s :: State# d
s -> Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 0# 0## State# d
s
        {-# INLINE scrub4 #-}
#if WORD_SIZE_IN_BITS == 64
        scrub8 a = \s -> writeWord64OffAddr# a 0# 0## s
        {-# INLINE scrub8 #-}
        scrub16 a = \s1 ->
            let !s2 = writeWord64OffAddr# a 0# 0## s1
                !s3 = writeWord64OffAddr# a 1# 0## s2
             in s3
        {-# INLINE scrub16 #-}
        scrub32 a = \s1 ->
            let !s2 = writeWord64OffAddr# a 0# 0## s1
                !s3 = writeWord64OffAddr# a 1# 0## s2
                !s4 = writeWord64OffAddr# a 2# 0## s3
                !s5 = writeWord64OffAddr# a 3# 0## s4
             in s5
        {-# INLINE scrub32 #-}
#else
        scrub8 :: Addr# -> State# d -> State# d
scrub8 a :: Addr#
a = \s1 :: State# d
s1 ->
            let !s2 :: State# d
s2 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 0# 0## State# d
s1
                !s3 :: State# d
s3 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 1# 0## State# d
s2
             in State# d
s3
        {-# INLINE scrub8 #-}
        scrub16 :: Addr# -> State# d -> State# d
scrub16 a :: Addr#
a = \s1 :: State# d
s1 ->
            let !s2 :: State# d
s2 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 0# 0## State# d
s1
                !s3 :: State# d
s3 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 1# 0## State# d
s2
                !s4 :: State# d
s4 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 2# 0## State# d
s3
                !s5 :: State# d
s5 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 3# 0## State# d
s4
             in State# d
s5
        {-# INLINE scrub16 #-}
        scrub32 :: Addr# -> State# d -> State# d
scrub32 a :: Addr#
a = \s1 :: State# d
s1 ->
            let !s2 :: State# d
s2 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 0# 0## State# d
s1
                !s3 :: State# d
s3 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 1# 0## State# d
s2
                !s4 :: State# d
s4 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 2# 0## State# d
s3
                !s5 :: State# d
s5 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 3# 0## State# d
s4
                !s6 :: State# d
s6 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 4# 0## State# d
s5
                !s7 :: State# d
s7 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 5# 0## State# d
s6
                !s8 :: State# d
s8 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 6# 0## State# d
s7
                !s9 :: State# d
s9 = Addr# -> Int# -> Word# -> State# d -> State# d
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord32OffAddr# Addr#
a 7# 0## State# d
s8
             in State# d
s9
        {-# INLINE scrub32 #-}
#endif

scrubBytes :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
scrubBytes :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
scrubBytes sz8 :: Int#
sz8 addr :: Addr#
addr = \s :: State# RealWorld
s -> Int# -> Addr# -> State# RealWorld -> State# RealWorld
loop Int#
sz8 Addr#
addr State# RealWorld
s
  where loop :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
        loop :: Int# -> Addr# -> State# RealWorld -> State# RealWorld
loop n :: Int#
n a :: Addr#
a s :: State# RealWorld
s
            | Int# -> Bool
booleanPrim (Int#
n Int# -> Int# -> Int#
==# 0#) = State# RealWorld
s
            | Bool
otherwise              =
                case Addr# -> Int# -> Word# -> State# RealWorld -> State# RealWorld
forall d. Addr# -> Int# -> Word# -> State# d -> State# d
writeWord8OffAddr# Addr#
a 0# 0## State# RealWorld
s of
                    s' :: State# RealWorld
s' -> Int# -> Addr# -> State# RealWorld -> State# RealWorld
loop (Int#
n Int# -> Int# -> Int#
-# 1#) (Addr# -> Int# -> Addr#
plusAddr# Addr#
a 1#) State# RealWorld
s'
        {-# INLINE loop #-}
{-# INLINE scrubBytes #-}