X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2Futils%2FPrimPacked.lhs;h=f2d034dcee619b86e0b92fd5fb78763130cdaf86;hb=2a2efb720c0fdc06fe749f96f284b00b30f8f3f7;hp=6c1989468e6f46583a7a35e052fff01e1f3d5447;hpb=5e374e1a474d06f851d01f66754143c1c3c847e0;p=ghc-hetmet.git diff --git a/ghc/compiler/utils/PrimPacked.lhs b/ghc/compiler/utils/PrimPacked.lhs index 6c19894..f2d034d 100644 --- a/ghc/compiler/utils/PrimPacked.lhs +++ b/ghc/compiler/utils/PrimPacked.lhs @@ -1,5 +1,5 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1997 +% (c) The GRASP/AQUA Project, Glasgow University, 1997-1998 % \section{Basic ops on packed representations} @@ -8,321 +8,258 @@ of bytes (character strings). Used by the interface lexer input subsystem, mostly. \begin{code} +{-# OPTIONS -optc-DNON_POSIX_SOURCE #-} + +module PrimPacked ( + Ptr(..), nullPtr, plusAddr#, + BA(..), + packString, -- :: String -> (Int, BA) + unpackNBytesBA, -- :: BA -> Int -> [Char] + strLength, -- :: Ptr CChar -> Int + copyPrefixStr, -- :: Addr# -> Int -> BA + copySubStrBA, -- :: BA -> Int -> Int -> BA + eqStrPrefix, -- :: Addr# -> ByteArray# -> Int# -> Bool + eqStrPrefixBA, -- :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool + ) where + +-- This #define suppresses the "import FastString" that +-- HsVersions otherwise produces +#define COMPILING_FAST_STRING #include "HsVersions.h" -module PrimPacked - ( - strLength, -- :: _Addr -> Int - copyPrefixStr, -- :: _Addr -> Int -> _ByteArray Int - copySubStr, -- :: _Addr -> Int -> Int -> _ByteArray Int - copySubStrFO, -- :: ForeignObj -> Int -> Int -> _ByteArray Int - copySubStrBA, -- :: _ByteArray Int -> Int -> Int -> _ByteArray Int - -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205 - stringToByteArray, -- :: String -> _ByteArray Int - byteArrayToString, -- :: _ByteArray Int -> String -#endif +import GLAEXTS +import UNSAFE_IO ( unsafePerformIO ) + +import MONAD_ST +import Foreign - eqStrPrefix, -- :: Addr# -> ByteArray# -> Int# -> Bool - eqCharStrPrefix, -- :: Addr# -> Addr# -> Int# -> Bool - eqStrPrefixBA, -- :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool - eqCharStrPrefixBA, -- :: Addr# -> ByteArray# -> Int# -> Int# -> Bool - eqStrPrefixFO, -- :: ForeignObj# -> ByteArray# -> Int# -> Int# -> Bool +#if __GLASGOW_HASKELL__ < 503 +import PrelST +#else +import GHC.ST +#endif - addrOffset#, -- :: Addr# -> Int# -> Addr# - indexCharOffFO# -- :: ForeignObj# -> Int# -> Char# - ) where +#if __GLASGOW_HASKELL__ >= 504 +import GHC.Ptr ( Ptr(..) ) +#elif __GLASGOW_HASKELL__ >= 500 +import Ptr ( Ptr(..) ) +#endif -#if __GLASGOW_HASKELL__ <= 201 -import PreludeGlaST -import PreludeGlaMisc +#if __GLASGOW_HASKELL__ < 504 +import PrelIOBase ( IO(..) ) #else -import GlaExts -import Foreign -import GHC -import ArrBase -import ST -import STBase +import GHC.IOBase ( IO(..) ) +#endif +\end{code} -# if __GLASGOW_HASKELL__ == 202 -import PrelBase ( Char(..) ) -# endif +Compatibility: 4.08 didn't have the Ptr type. -# if __GLASGOW_HASKELL__ >= 206 -import PackBase -# endif +\begin{code} +#if __GLASGOW_HASKELL__ <= 408 +data Ptr a = Ptr Addr# deriving (Eq, Ord) +nullPtr :: Ptr a +nullPtr = Ptr (int2Addr# 0#) #endif -\end{code} +#if __GLASGOW_HASKELL__ <= 500 +-- plusAddr# is a primop in GHC > 5.00 +plusAddr# :: Addr# -> Int# -> Addr# +plusAddr# a# i# = int2Addr# (addr2Int# a# +# i#) +#endif +\end{code} -Return the length of a @\\NUL@ terminated character string: +Wrapper types for bytearrays \begin{code} -strLength :: _Addr -> Int -strLength a = - unsafePerformPrimIO ( - _ccall_ strlen a `thenPrimIO` \ len@(I# _) -> - returnPrimIO len - ) - +data BA = BA ByteArray# +data MBA s = MBA (MutableByteArray# s) \end{code} -Copying a char string prefix into a byte array, -{\em assuming} the prefix does not contain any -NULs. - \begin{code} -copyPrefixStr :: _Addr -> Int -> _ByteArray Int -copyPrefixStr (A# a) len@(I# length#) = - unsafePerformPrimIO ( - {- allocate an array that will hold the string - (not forgetting the NUL at the end) - -} - (new_ps_array (length# +# 1#)) `thenPrimIO` \ ch_array -> -{- Revert back to Haskell-only solution for the moment. - _ccall_ memcpy ch_array (A# a) len `thenPrimIO` \ () -> - write_ps_array ch_array length# (chr# 0#) `seqPrimIO` --} - -- fill in packed string from "addr" - fill_in ch_array 0# `seqPrimIO` - -- freeze the puppy: - freeze_ps_array ch_array) - where - fill_in :: _MutableByteArray s Int -> Int# -> _ST s () - - fill_in arr_in# idx - | idx ==# length# - = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST` - returnStrictlyST () - | otherwise - = case (indexCharOffAddr# a idx) of { ch -> - write_ps_array arr_in# idx ch `seqStrictlyST` - fill_in arr_in# (idx +# 1#) } +packString :: String -> (Int, BA) +packString str = (l, arr) + where + l@(I# length#) = length str + arr = runST (do + ch_array <- new_ps_array length# + -- fill in packed string from "str" + fill_in ch_array 0# str + -- freeze the puppy: + freeze_ps_array ch_array length# + ) + + fill_in :: MBA s -> Int# -> [Char] -> ST s () + fill_in arr_in# idx [] = + return () + fill_in arr_in# idx (C# c : cs) = + write_ps_array arr_in# idx c >> + fill_in arr_in# (idx +# 1#) cs \end{code} -Copying out a substring, assume a 0-indexed string: -(and positive lengths, thank you). +Unpacking a string \begin{code} -copySubStr :: _Addr -> Int -> Int -> _ByteArray Int -copySubStr a start length = - unsafePerformPrimIO ( - _casm_ `` %r= (char *)((char *)%0 + (int)%1); '' a start - `thenPrimIO` \ a_start -> - returnPrimIO (copyPrefixStr a_start length)) +unpackNBytesBA :: BA -> Int -> [Char] +unpackNBytesBA (BA bytes) (I# len) + = unpack 0# + where + unpack nh + | nh >=# len = [] + | otherwise = C# ch : unpack (nh +# 1#) + where + ch = indexCharArray# bytes nh \end{code} -Copying a sub-string out of a ForeignObj +Copying a char string prefix into a byte array. \begin{code} -copySubStrFO :: _ForeignObj -> Int -> Int -> _ByteArray Int -copySubStrFO (_ForeignObj fo) (I# start#) len@(I# length#) = - unsafePerformPrimIO ( - {- allocate an array that will hold the string - (not forgetting the NUL at the end) - -} - new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array -> - -- fill in packed string from "addr" - fill_in ch_array 0# `seqStrictlyST` - -- freeze the puppy: - freeze_ps_array ch_array) - where - fill_in :: _MutableByteArray s Int -> Int# -> _ST s () - - fill_in arr_in# idx +copyPrefixStr :: Addr# -> Int -> BA +copyPrefixStr a# len@(I# length#) = copy' length# + where + copy' length# = runST (do + {- allocate an array that will hold the string + -} + ch_array <- new_ps_array length# + {- Revert back to Haskell-only solution for the moment. + _ccall_ memcpy ch_array (A# a) len >>= \ () -> + write_ps_array ch_array length# (chr# 0#) >> + -} + -- fill in packed string from "addr" + fill_in ch_array 0# + -- freeze the puppy: + freeze_ps_array ch_array length# + ) + + fill_in :: MBA s -> Int# -> ST s () + fill_in arr_in# idx | idx ==# length# - = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST` - returnStrictlyST () + = return () | otherwise - = case (indexCharOffFO# fo (idx +# start#)) of { ch -> - write_ps_array arr_in# idx ch `seqStrictlyST` + = case (indexCharOffAddr# a# idx) of { ch -> + write_ps_array arr_in# idx ch >> fill_in arr_in# (idx +# 1#) } +\end{code} -{- ToDo: add FO primitives.. -} -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <=205 -indexCharOffFO# :: ForeignObj# -> Int# -> Char# -indexCharOffFO# fo# i# = - case unsafePerformPrimIO (_casm_ ``%r=(char)*((char *)%0 + (int)%1); '' (_ForeignObj fo#) (I# i#)) of - C# c -> c -#else -indexCharOffFO# :: ForeignObj# -> Int# -> Char# -indexCharOffFO# fo i = indexCharOffForeignObj# fo i +Copying out a substring, assume a 0-indexed string: +(and positive lengths, thank you). + +\begin{code} +#ifdef UNUSED +copySubStr :: Addr# -> Int -> Int -> BA +copySubStr a# (I# start#) length = + copyPrefixStr (a# `plusAddr#` start#) length #endif --- step on (char *) pointer by x units. -addrOffset# :: Addr# -> Int# -> Addr# -addrOffset# a# i# = - case unsafePerformPrimIO (_casm_ ``%r=(char *)((char *)%0 + (int)%1); '' (A# a#) (I# i#)) of - A# a -> a - -copySubStrBA :: _ByteArray Int -> Int -> Int -> _ByteArray Int -copySubStrBA (_ByteArray _ barr#) (I# start#) len@(I# length#) = - unsafePerformPrimIO ( - {- allocate an array that will hold the string - (not forgetting the NUL at the end) - -} - new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array -> - -- fill in packed string from "addr" - fill_in ch_array 0# `seqStrictlyST` - -- freeze the puppy: - freeze_ps_array ch_array) - where - fill_in :: _MutableByteArray s Int -> Int# -> _ST s () - - fill_in arr_in# idx +copySubStrBA :: BA -> Int -> Int -> BA +copySubStrBA (BA barr#) (I# start#) len@(I# length#) = ba + where + ba = runST (do + -- allocate an array that will hold the string + ch_array <- new_ps_array length# + -- fill in packed string from "addr" + fill_in ch_array 0# + -- freeze the puppy: + freeze_ps_array ch_array length# + ) + + fill_in :: MBA s -> Int# -> ST s () + fill_in arr_in# idx | idx ==# length# - = write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST` - returnStrictlyST () + = return () | otherwise = case (indexCharArray# barr# (start# +# idx)) of { ch -> - write_ps_array arr_in# idx ch `seqStrictlyST` + write_ps_array arr_in# idx ch >> fill_in arr_in# (idx +# 1#) } - \end{code} (Very :-) ``Specialised'' versions of some CharArray things... +[Copied from PackBase; no real reason -- UGH] \begin{code} -new_ps_array :: Int# -> _ST s (_MutableByteArray s Int) -write_ps_array :: _MutableByteArray s Int -> Int# -> Char# -> _ST s () -freeze_ps_array :: _MutableByteArray s Int -> _ST s (_ByteArray Int) +new_ps_array :: Int# -> ST s (MBA s) +write_ps_array :: MBA s -> Int# -> Char# -> ST s () +freeze_ps_array :: MBA s -> Int# -> ST s BA + +#if __GLASGOW_HASKELL__ < 411 +#define NEW_BYTE_ARRAY newCharArray# +#else +#define NEW_BYTE_ARRAY newPinnedByteArray# +#endif -new_ps_array size = - MkST ( \ (S# s) -> - case (newCharArray# size s) of { StateAndMutableByteArray# s2# barr# -> - (_MutableByteArray (0, max 0 (I# (size -# 1#))) barr#, S# s2#)}) +new_ps_array size = ST $ \ s -> + case (NEW_BYTE_ARRAY size s) of { (# s2#, barr# #) -> + (# s2#, MBA barr# #) } -write_ps_array (_MutableByteArray _ barr#) n ch = - MkST ( \ (S# s#) -> +write_ps_array (MBA barr#) n ch = ST $ \ s# -> case writeCharArray# barr# n ch s# of { s2# -> - ((), S# s2#)}) + (# s2#, () #) } -- same as unsafeFreezeByteArray -freeze_ps_array (_MutableByteArray ixs arr#) = - MkST ( \ (S# s#) -> - case unsafeFreezeByteArray# arr# s# of { StateAndByteArray# s2# frozen# -> - (_ByteArray ixs frozen#, S# s2#) }) +freeze_ps_array (MBA arr#) len# = ST $ \ s# -> + case unsafeFreezeByteArray# arr# s# of { (# s2#, frozen# #) -> + (# s2#, BA frozen# #) } \end{code} + Compare two equal-length strings for equality: \begin{code} eqStrPrefix :: Addr# -> ByteArray# -> Int# -> Bool eqStrPrefix a# barr# len# = - unsafePerformPrimIO ( - _ccall_ strncmp (A# a#) (_ByteArray bottom barr#) (I# len#) `thenPrimIO` \ (I# x#) -> - returnPrimIO (x# ==# 0#)) - where - bottom :: (Int,Int) - bottom = error "eqStrPrefix" + inlinePerformIO $ do + x <- memcmp_ba a# barr# (I# len#) + return (x == 0) +#ifdef UNUSED eqCharStrPrefix :: Addr# -> Addr# -> Int# -> Bool eqCharStrPrefix a1# a2# len# = - unsafePerformPrimIO ( - _ccall_ strncmp (A# a1#) (A# a2#) (I# len#) `thenPrimIO` \ (I# x#) -> - returnPrimIO (x# ==# 0#)) - where - bottom :: (Int,Int) - bottom = error "eqStrPrefix" + inlinePerformIO $ do + x <- memcmp a1# a2# (I# len#) + return (x == 0) +#endif eqStrPrefixBA :: ByteArray# -> ByteArray# -> Int# -> Int# -> Bool eqStrPrefixBA b1# b2# start# len# = - unsafePerformPrimIO ( - _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); '' - (_ByteArray bottom b2#) - (I# start#) - (_ByteArray bottom b1#) - (I# len#) `thenPrimIO` \ (I# x#) -> - returnPrimIO (x# ==# 0#)) - where - bottom :: (Int,Int) - bottom = error "eqStrPrefixBA" + inlinePerformIO $ do + x <- memcmp_baoff_ba b2# (I# start#) b1# (I# len#) + return (x == 0) +#ifdef UNUSED eqCharStrPrefixBA :: Addr# -> ByteArray# -> Int# -> Int# -> Bool eqCharStrPrefixBA a# b2# start# len# = - unsafePerformPrimIO ( - _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); '' - (_ByteArray bottom b2#) - (I# start#) - (A# a#) - (I# len#) `thenPrimIO` \ (I# x#) -> - returnPrimIO (x# ==# 0#)) - where - bottom :: (Int,Int) - bottom = error "eqCharStrPrefixBA" - -eqStrPrefixFO :: ForeignObj# -> ByteArray# -> Int# -> Int# -> Bool -eqStrPrefixFO fo# barr# start# len# = - unsafePerformPrimIO ( - _casm_ ``%r=(int)strncmp((char *)%0+(int)%1,%2,%3); '' - (_ForeignObj fo#) - (I# start#) - (_ByteArray bottom barr#) - (I# len#) `thenPrimIO` \ (I# x#) -> - returnPrimIO (x# ==# 0#)) - where - bottom :: (Int,Int) - bottom = error "eqStrPrefixFO" + inlinePerformIO $ do + x <- memcmp_baoff b2# (I# start#) a# (I# len#) + return (x == 0) +#endif \end{code} \begin{code} -#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 205 -byteArrayToString :: _ByteArray Int -> String -byteArrayToString (_ByteArray (I# start#,I# end#) barr#) = - unpack start# - where - unpack nh# - | nh# >=# end# = [] - | otherwise = C# ch : unpack (nh# +# 1#) - where - ch = indexCharArray# barr# nh# -#elif defined(__GLASGOW_HASKELL__) -byteArrayToString :: _ByteArray Int -> String -byteArrayToString = unpackCStringBA +-- Just like unsafePerformIO, but we inline it. This is safe when +-- there are no side effects, and improves performance. +{-# INLINE inlinePerformIO #-} +inlinePerformIO :: IO a -> a +inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r + +#if __GLASGOW_HASKELL__ <= 408 +strLength (Ptr a#) = ghc_strlen a# +foreign import ccall unsafe "ghc_strlen" + ghc_strlen :: Addr# -> Int #else -#error "byteArrayToString: cannot handle this!" +foreign import ccall unsafe "ghc_strlen" + strLength :: Ptr () -> Int #endif -\end{code} - +foreign import ccall unsafe "ghc_memcmp" + memcmp :: Addr# -> Addr# -> Int -> IO Int -\begin{code} -stringToByteArray :: String -> (_ByteArray Int) -#if __GLASGOW_HASKELL__ >= 206 -stringToByteArray = packString -#elif defined(__GLASGOW_HASKELL__) -stringToByteArray str = _runST (packStringST str) - -packStringST :: [Char] -> _ST s (_ByteArray Int) -packStringST str = - let len = length str in - packNCharsST len str - -packNCharsST :: Int -> [Char] -> _ST s (_ByteArray Int) -packNCharsST len@(I# length#) str = - {- - allocate an array that will hold the string - (not forgetting the NUL byte at the end) - -} - new_ps_array (length# +# 1#) `thenStrictlyST` \ ch_array -> - -- fill in packed string from "str" - fill_in ch_array 0# str `seqStrictlyST` - -- freeze the puppy: - freeze_ps_array ch_array `thenStrictlyST` \ (_ByteArray _ frozen#) -> - returnStrictlyST (_ByteArray (0,len) frozen#) - where - fill_in :: _MutableByteArray s Int -> Int# -> [Char] -> _ST s () - fill_in arr_in# idx [] = - write_ps_array arr_in# idx (chr# 0#) `seqStrictlyST` - returnStrictlyST () +foreign import ccall unsafe "ghc_memcmp" + memcmp_ba :: Addr# -> ByteArray# -> Int -> IO Int - fill_in arr_in# idx (C# c : cs) = - write_ps_array arr_in# idx c `seqStrictlyST` - fill_in arr_in# (idx +# 1#) cs -#else -#error "stringToByteArray: cannot handle this" -#endif +foreign import ccall unsafe "ghc_memcmp_off" + memcmp_baoff :: ByteArray# -> Int -> Addr# -> Int -> IO Int +foreign import ccall unsafe "ghc_memcmp_off" + memcmp_baoff_ba :: ByteArray# -> Int -> ByteArray# -> Int -> IO Int \end{code}