[project @ 2004-08-13 13:04:50 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / SMRep.lhs
index 7c46adf..92b9513 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[SMRep]{Storage manager representations of closure}
 
@@ -7,266 +7,348 @@ This is here, rather than in ClosureInfo, just to keep nhc happy.
 Other modules should access this info through ClosureInfo.
 
 \begin{code}
-#include "HsVersions.h"
-
 module SMRep (
-       SMRep(..), SMSpecRepKind(..), SMUpdateKind(..),
-       getSMInfoStr, getSMInitHdrStr, getSMUpdInplaceHdrStr,
-       ltSMRepHdr,
-       isConstantRep, isSpecRep, isStaticRep, isPhantomRep,
-       isIntLikeRep
+       -- Words and bytes
+       StgWord, StgHalfWord, 
+       hALF_WORD_SIZE, hALF_WORD_SIZE_IN_BITS,
+       WordOff, ByteOff,
+
+       -- Argument/return representations
+       CgRep(..), nonVoidArg,
+       argMachRep, primRepToCgRep, primRepHint,
+       isFollowableArg, isVoidArg, 
+       isFloatingArg, isNonPtrArg, is64BitArg,
+       separateByPtrFollowness,
+       cgRepSizeW, cgRepSizeB,
+       retAddrSizeW,
+
+       typeCgRep, idCgRep, tyConCgRep, typeHint,
+
+       -- Closure repesentation
+       SMRep(..), ClosureType(..),
+       isStaticRep,
+       fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize,
+       profHdrSize,
+       tablesNextToCode,
+       smRepClosureType, smRepClosureTypeInt,
+
+       rET_SMALL, rET_VEC_SMALL, rET_BIG, rET_VEC_BIG
     ) where
 
-IMP_Ubiq(){-uitous-}
+#include "HsVersions.h"
+#include "../includes/MachDeps.h"
+
+import Id              ( Id, idType )
+import Type            ( Type, typePrimRep, PrimRep(..) )
+import TyCon           ( TyCon, tyConPrimRep )
+import MachOp          ( MachRep(..), MachHint(..), wordRep )
+import CmdLineOpts     ( opt_SccProfilingOn, opt_GranMacros, opt_Unregisterised )
+import Constants
+import Outputable
 
-import Pretty          ( ppStr )
-import Util            ( panic )
+import DATA_WORD
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
+               Words and bytes
 %*                                                                     *
 %************************************************************************
 
-Ways in which a closure may be represented by the storage manager;
-this list slavishly follows the storage-manager interface document.
+\begin{code}
+type WordOff = Int     -- Word offset, or word count
+type ByteOff = Int     -- Byte offset, or byte count
+\end{code}
+
+StgWord is a type representing an StgWord on the target platform.
 
 \begin{code}
-data SMSpecRepKind
-  = SpecRep            -- Normal Spec representation
+#if SIZEOF_HSWORD == 4
+type StgWord     = Word32
+type StgHalfWord = Word16
+hALF_WORD_SIZE = 2 :: ByteOff
+hALF_WORD_SIZE_IN_BITS = 16 :: Int
+#elif SIZEOF_HSWORD == 8
+type StgWord     = Word64
+type StgHalfWord = Word32
+hALF_WORD_SIZE = 4 :: ByteOff
+hALF_WORD_SIZE_IN_BITS = 32 :: Int
+#else
+#error unknown SIZEOF_HSWORD
+#endif
+\end{code}
+
 
-  | ConstantRep                -- Common me up with single global copy
-                       -- Used for nullary constructors
+%************************************************************************
+%*                                                                     *
+                       CgRep
+%*                                                                     *
+%************************************************************************
+
+An CgRep is an abstraction of a Type which tells the code generator
+all it needs to know about the calling convention for arguments (and
+results) of that type.  In particular, the ArgReps of a function's
+arguments are used to decide which of the RTS's generic apply
+functions to call when applying an unknown function.
+
+It contains more information than the back-end data type MachRep,
+so one can easily convert from CgRep -> MachRep.  (Except that
+there's no MachRep for a VoidRep.)
+
+It distinguishes 
+       pointers from non-pointers (we sort the pointers together
+       when building closures)
+
+       void from other types: a void argument is different from no argument
+
+All 64-bit types map to the same CgRep, because they're passed in the
+same register, but a PtrArg is still different from an NonPtrArg
+because the function's entry convention has to take into account the
+pointer-hood of arguments for the purposes of describing the stack on
+entry to the garbage collector.
+
+\begin{code}
+data CgRep 
+  = VoidArg    -- Void
+  | PtrArg     -- Word-sized Ptr
+  | NonPtrArg  -- Word-sized non-pointer
+  | LongArg    -- 64-bit non-pointer
+  | FloatArg   -- 32-bit float
+  | DoubleArg  -- 64-bit float
+  deriving Eq
+
+instance Outputable CgRep where
+    ppr VoidArg   = ptext SLIT("V_")
+    ppr PtrArg    = ptext SLIT("P_")
+    ppr NonPtrArg = ptext SLIT("I_")
+    ppr LongArg   = ptext SLIT("L_")
+    ppr FloatArg  = ptext SLIT("F_")
+    ppr DoubleArg = ptext SLIT("D_")
+
+argMachRep :: CgRep -> MachRep
+argMachRep PtrArg    = wordRep
+argMachRep NonPtrArg = wordRep
+argMachRep LongArg   = I64
+argMachRep FloatArg  = F32
+argMachRep DoubleArg = F64
+argMachRep VoidArg   = panic "argMachRep:VoidRep"
+
+primRepToCgRep :: PrimRep -> CgRep
+primRepToCgRep VoidRep    = VoidArg
+primRepToCgRep PtrRep     = PtrArg
+primRepToCgRep IntRep    = NonPtrArg
+primRepToCgRep WordRep   = NonPtrArg
+primRepToCgRep Int64Rep   = LongArg
+primRepToCgRep Word64Rep  = LongArg
+primRepToCgRep AddrRep    = NonPtrArg
+primRepToCgRep FloatRep   = FloatArg
+primRepToCgRep DoubleRep  = DoubleArg
+
+primRepHint :: PrimRep -> MachHint
+primRepHint VoidRep    = panic "primRepHint:VoidRep"
+primRepHint PtrRep     = PtrHint
+primRepHint IntRep     = SignedHint
+primRepHint WordRep    = NoHint
+primRepHint Int64Rep   = SignedHint
+primRepHint Word64Rep  = NoHint
+primRepHint AddrRep     = PtrHint -- NB! PtrHint, but NonPtrArg
+primRepHint FloatRep   = FloatHint
+primRepHint DoubleRep  = FloatHint
+
+idCgRep :: Id -> CgRep
+idCgRep = typeCgRep . idType
+
+tyConCgRep :: TyCon -> CgRep
+tyConCgRep = primRepToCgRep . tyConPrimRep
+
+typeCgRep :: Type -> CgRep
+typeCgRep = primRepToCgRep . typePrimRep
+
+typeHint :: Type -> MachHint
+typeHint = primRepHint . typePrimRep
+\end{code}
+
+Whether or not the thing is a pointer that the garbage-collector
+should follow. Or, to put it another (less confusing) way, whether
+the object in question is a heap object. 
+
+Depending on the outcome, this predicate determines what stack
+the pointer/object possibly will have to be saved onto, and the
+computation of GC liveness info.
+
+\begin{code}
+isFollowableArg :: CgRep -> Bool  -- True <=> points to a heap object
+isFollowableArg PtrArg  = True
+isFollowableArg other = False
+
+isVoidArg :: CgRep -> Bool
+isVoidArg VoidArg = True
+isVoidArg other   = False
+
+nonVoidArg :: CgRep -> Bool
+nonVoidArg VoidArg = False
+nonVoidArg other   = True
+
+-- isFloatingArg is used to distinguish @Double@ and @Float@ which
+-- cause inadvertent numeric conversions if you aren't jolly careful.
+-- See codeGen/CgCon:cgTopRhsCon.
+
+isFloatingArg :: CgRep -> Bool
+isFloatingArg DoubleArg = True
+isFloatingArg FloatArg  = True
+isFloatingArg _         = False
+
+isNonPtrArg :: CgRep -> Bool
+-- Identify anything which is one word large and not a pointer.
+isNonPtrArg NonPtrArg = True
+isNonPtrArg other     = False
+
+is64BitArg :: CgRep -> Bool
+is64BitArg LongArg = True
+is64BitArg _       = False
+\end{code}
 
-  | CharLikeRep                -- Common me up with entry from global table
+\begin{code}
+separateByPtrFollowness :: [(CgRep,a)] -> ([(CgRep,a)], [(CgRep,a)])
+-- Returns (ptrs, non-ptrs)
+separateByPtrFollowness things
+  = sep_things things [] []
+    -- accumulating params for follow-able and don't-follow things...
+  where
+    sep_things []             bs us = (reverse bs, reverse us)
+    sep_things ((PtrArg,a):ts) bs us = sep_things ts ((PtrArg,a):bs) us
+    sep_things (t         :ts) bs us = sep_things ts bs                     (t:us)
+\end{code}
 
-  | IntLikeRep         -- Common me up with entry from global table,
-                       -- if the intlike field is in range.
+\begin{code}
+cgRepSizeB :: CgRep -> ByteOff
+cgRepSizeB DoubleArg = dOUBLE_SIZE
+cgRepSizeB LongArg   = wORD64_SIZE
+cgRepSizeB VoidArg   = 0
+cgRepSizeB _         = wORD_SIZE
+
+cgRepSizeW :: CgRep -> ByteOff
+cgRepSizeW DoubleArg = dOUBLE_SIZE `quot` wORD_SIZE
+cgRepSizeW LongArg   = wORD64_SIZE `quot` wORD_SIZE
+cgRepSizeW VoidArg   = 0
+cgRepSizeW _         = 1
+
+retAddrSizeW :: WordOff
+retAddrSizeW = 1       -- One word
+\end{code}
 
-data SMUpdateKind
-  = SMNormalForm       -- Normal form, no update
-  | SMSingleEntry      -- Single entry thunk, non-updatable
-  | SMUpdatable                -- Shared thunk, updatable
+%************************************************************************
+%*                                                                     *
+\subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
+%*                                                                     *
+%************************************************************************
 
+\begin{code}
 data SMRep
-  = StaticRep          -- Don't move me, Oh garbage collector!
-                       -- Used for all statically-allocated closures.
-       Int             -- # ptr words (useful for interpreter, debugger, etc)
-       Int             -- # non-ptr words
-
-  | SpecialisedRep     -- GC routines know size etc
-                       -- All have same _HS = SPEC_HS and no _VHS
-       SMSpecRepKind   -- Which kind of specialised representation
-       Int             -- # ptr words
-       Int             -- # non-ptr words
-       SMUpdateKind    -- Updatable?
-
-  | GenericRep         -- GC routines consult sizes in info tbl
-       Int             -- # ptr words
-       Int             -- # non-ptr words
-       SMUpdateKind    -- Updatable?
-
-  | BigTupleRep                -- All ptrs, size in var-hdr field
-                       -- Used for big tuples
-       Int             -- # ptr words
-
-  | DataRep            -- All non-ptrs, size in var-hdr field
-                       -- Used for arbitrary-precision integers, strings
-       Int             -- # non-ptr words
-
-  | DynamicRep         -- Size and # ptrs in var-hdr field
-                       -- Used by RTS for partial applications
-
-  | BlackHoleRep       -- for black hole closures
-
-  | PhantomRep         -- for "phantom" closures that only exist in registers
-
-  | MuTupleRep         -- All ptrs, size in var-hdr field
-                       -- Used for mutable tuples
-       Int             -- # ptr words
-
-{- Mattson review:
-
-To: simonpj@dcs.gla.ac.uk, partain@dcs.gla.ac.uk
-Cc: kh@dcs.gla.ac.uk, trinder@dcs.gla.ac.uk, areid@dcs.gla.ac.uk
-Subject: Correct me if I'm wrong...
-Date: Fri, 17 Feb 1995 18:09:00 +0000
-From: Jim Mattson <mattson@dcs.gla.ac.uk>
-
-BigTupleRep == TUPLE
-
-    Never generated by the compiler, and only used in the RTS when
-    mutuples don't require special attention at GC time (e.g. 2s)
-    When it is used, it is a primitive object (never entered).
-    May be mutable...probably should never be used in the parallel
-    system, since we need to distinguish mutables from immutables when
-    deciding whether to copy or move closures across processors.
-
-DataRep == DATA (aka MutableByteArray & ByteArray)
-    Never generated by the compiler, and only used in the RTS for
-    ArrayOfData.  Always a primitive object (never entered).  May
-    be mutable...though we don't distinguish between mutable and
-    immutable data arrays in the sequential world, it would probably
-    be useful in the parallel world to know when it is safe to just
-    copy one of these.  I believe the hooks are in place for changing
-    the InfoPtr on a MutableByteArray when it's frozen to a ByteArray
-    if we want to do so.
-
-DynamicRep == DYN
-    Never generated by the compiler, and only used in the RTS for
-    PAPs and the Stable Pointer table.  PAPs are non-primitive,
-    non-updatable, normal-form objects, but the SPT is a primitive,
-    mutable object.  At the moment, there is no SPT in the parallel
-    world.  Presumably, it would be possible to have an SPT on each
-    processor, and we could identify a stable pointer as a (processor,
-    SPT-entry) pair, but would it be worth it?
-
-MuTupleRep == MUTUPLE
-    Never generated by the compiler, and only used in the RTS when
-    mutuples *do* require special attention at GC time.
-    When it is used, it is a primitive object (never entered).
-    Always mutable...there is an IMMUTUPLE in the RTS, but no
-    corresponding type in the compiler.
-
---jim
--}
+     -- static closure have an extra static link field at the end.
+  = GenericRep         -- GC routines consult sizes in info tbl
+       Bool            -- True <=> This is a static closure.  Affects how 
+                       --          we garbage-collect it
+       !Int            -- # ptr words
+       !Int            -- # non-ptr words
+       ClosureType     -- closure type
+
+  | BlackHoleRep
+
+data ClosureType       -- Corresponds 1-1 with the varieties of closures
+                       -- implemented by the RTS.  Compare with ghc/includes/ClosureTypes.h
+    = Constr
+    | ConstrNoCaf
+    | Fun
+    | Thunk
+    | ThunkSelector
 \end{code}
 
+Size of a closure header.
+
 \begin{code}
-isConstantRep, isSpecRep, isStaticRep, isPhantomRep, isIntLikeRep :: SMRep -> Bool
-isConstantRep (SpecialisedRep ConstantRep _ _ _)   = True
-isConstantRep other                               = False
+fixedHdrSize :: WordOff
+fixedHdrSize = sTD_HDR_SIZE + profHdrSize + granHdrSize
 
-isSpecRep (SpecialisedRep kind _ _ _)  = True    -- All the kinds of Spec closures
-isSpecRep other                                = False   -- True indicates that the _VHS is 0 !
+profHdrSize  :: WordOff
+profHdrSize  | opt_SccProfilingOn   = pROF_HDR_SIZE
+            | otherwise            = 0
 
-isStaticRep (StaticRep _ _) = True
-isStaticRep _              = False
+granHdrSize  :: WordOff
+granHdrSize  | opt_GranMacros      = gRAN_HDR_SIZE
+            | otherwise            = 0
 
-isPhantomRep PhantomRep        = True
-isPhantomRep _         = False
+arrWordsHdrSize   :: ByteOff
+arrWordsHdrSize   = fixedHdrSize*wORD_SIZE + sIZEOF_StgArrWords_NoHdr
 
-isIntLikeRep (SpecialisedRep IntLikeRep _ _ _)   = True
-isIntLikeRep other                              = False
+arrPtrsHdrSize    :: ByteOff
+arrPtrsHdrSize    = fixedHdrSize*wORD_SIZE + sIZEOF_StgMutArrPtrs_NoHdr
 \end{code}
 
 \begin{code}
-instance Eq SMRep where
-    (SpecialisedRep k1 a1 b1 _) == (SpecialisedRep k2 a2 b2 _) = (tagOf_SMSpecRepKind k1) _EQ_ (tagOf_SMSpecRepKind k2)
-                                                              && a1 == a2 && b1 == b2
-    (GenericRep a1 b1 _)      == (GenericRep a2 b2 _)     = a1 == a2 && b1 == b2
-    (BigTupleRep a1)         == (BigTupleRep a2)          = a1 == a2
-    (MuTupleRep a1)          == (MuTupleRep a2)           = a1 == a2
-    (DataRep a1)             == (DataRep a2)              = a1 == a2
-    a                        == b                         = (tagOf_SMRep a) _EQ_ (tagOf_SMRep b)
-
-ltSMRepHdr :: SMRep -> SMRep -> Bool
-a `ltSMRepHdr` b = (tagOf_SMRep a) _LT_ (tagOf_SMRep b)
-
-instance Ord SMRep where
-    -- ToDo: cmp-ify?  This instance seems a bit weird (WDP 94/10)
-    rep1 <= rep2 = rep1 < rep2 || rep1 == rep2
-    rep1 < rep2
-      =        let tag1 = tagOf_SMRep rep1
-           tag2 = tagOf_SMRep rep2
-       in
-       if      tag1 _LT_ tag2 then True
-       else if tag1 _GT_ tag2 then False
-       else {- tags equal -}    rep1 `lt` rep2
-      where
-       (SpecialisedRep k1 a1 b1 _) `lt` (SpecialisedRep k2 a2 b2 _) =
-               t1 _LT_ t2 || (t1 _EQ_ t2 && (a1 < a2 || (a1 == a2 && b1 < b2)))
-               where t1 = tagOf_SMSpecRepKind k1
-                     t2 = tagOf_SMSpecRepKind k2
-       (GenericRep a1 b1 _)      `lt` (GenericRep a2 b2 _)      = a1 < a2 || (a1 == a2 && b1 < b2)
-       (BigTupleRep a1)          `lt` (BigTupleRep a2)          = a1 < a2
-       (MuTupleRep a1)           `lt` (MuTupleRep a2)           = a1 < a2
-       (DataRep a1)              `lt` (DataRep a2)              = a1 < a2
-       a                         `lt` b                         = True
-
-tagOf_SMSpecRepKind SpecRep    = (ILIT(1) :: FAST_INT)
-tagOf_SMSpecRepKind ConstantRep        = ILIT(2)
-tagOf_SMSpecRepKind CharLikeRep        = ILIT(3)
-tagOf_SMSpecRepKind IntLikeRep = ILIT(4)
-
-tagOf_SMRep (StaticRep _ _)         = (ILIT(1) :: FAST_INT)
-tagOf_SMRep (SpecialisedRep k _ _ _) = ILIT(2)
-tagOf_SMRep (GenericRep _ _ _)      = ILIT(3)
-tagOf_SMRep (BigTupleRep _)         = ILIT(4)
-tagOf_SMRep (DataRep _)                     = ILIT(5)
-tagOf_SMRep DynamicRep              = ILIT(6)
-tagOf_SMRep BlackHoleRep            = ILIT(7)
-tagOf_SMRep PhantomRep              = ILIT(8)
-tagOf_SMRep (MuTupleRep _)          = ILIT(9)
-
-instance Text SMRep where
-    showsPrec d rep
-      = showString (case rep of
-          StaticRep _ _                         -> "STATIC"
-          SpecialisedRep kind _ _ SMNormalForm  -> "SPEC_N"
-          SpecialisedRep kind _ _ SMSingleEntry -> "SPEC_S"
-          SpecialisedRep kind _ _ SMUpdatable   -> "SPEC_U"
-          GenericRep _ _ SMNormalForm           -> "GEN_N"
-          GenericRep _ _ SMSingleEntry          -> "GEN_S"
-          GenericRep _ _ SMUpdatable            -> "GEN_U"
-          BigTupleRep _                         -> "TUPLE"
-          DataRep       _                       -> "DATA"
-          DynamicRep                            -> "DYN"
-          BlackHoleRep                          -> "BH"
-          PhantomRep                            -> "INREGS"
-          MuTupleRep _                          -> "MUTUPLE")
-
-instance Outputable SMRep where
-    ppr sty rep = ppStr (show rep)
-
-getSMInfoStr :: SMRep -> String
-getSMInfoStr (StaticRep _ _)                           = "STATIC"
-getSMInfoStr (SpecialisedRep ConstantRep _ _ _)                = "CONST"
-getSMInfoStr (SpecialisedRep CharLikeRep _ _ _)                = "CHARLIKE"
-getSMInfoStr (SpecialisedRep IntLikeRep _ _ _)         = "INTLIKE"
-getSMInfoStr (SpecialisedRep SpecRep _ _ SMNormalForm) = "SPEC_N"
-getSMInfoStr (SpecialisedRep SpecRep _ _ SMSingleEntry)        = "SPEC_S"
-getSMInfoStr (SpecialisedRep SpecRep _ _ SMUpdatable)  = "SPEC_U"
-getSMInfoStr (GenericRep _ _ SMNormalForm)             = "GEN_N"
-getSMInfoStr (GenericRep _ _ SMSingleEntry)            = "GEN_S"
-getSMInfoStr (GenericRep _ _ SMUpdatable)              = "GEN_U"
-getSMInfoStr (BigTupleRep _)                           = "TUPLE"
-getSMInfoStr (DataRep _ )                              = "DATA"
-getSMInfoStr DynamicRep                                        = "DYN"
-getSMInfoStr BlackHoleRep                              = panic "getSMInfoStr.BlackHole"
-getSMInfoStr PhantomRep                                        = "INREGS"
-getSMInfoStr (MuTupleRep _)                            = "MUTUPLE"
-
-getSMInitHdrStr :: SMRep -> String
-getSMInitHdrStr (SpecialisedRep IntLikeRep _ _ _)  = "SET_INTLIKE"
-getSMInitHdrStr (SpecialisedRep SpecRep _ _ _)            = "SET_SPEC"
-getSMInitHdrStr (GenericRep _ _        _)                 = "SET_GEN"
-getSMInitHdrStr (BigTupleRep _)                   = "SET_TUPLE"
-getSMInitHdrStr (DataRep _ )                              = "SET_DATA"
-getSMInitHdrStr DynamicRep                        = "SET_DYN"
-getSMInitHdrStr BlackHoleRep                      = "SET_BH"
-#ifdef DEBUG
-getSMInitHdrStr (StaticRep _ _)                           = panic "getSMInitHdrStr.Static"
-getSMInitHdrStr PhantomRep                        = panic "getSMInitHdrStr.Phantom"
-getSMInitHdrStr (MuTupleRep _)                    = panic "getSMInitHdrStr.Mutuple"
-getSMInitHdrStr (SpecialisedRep ConstantRep _ _ _) = panic "getSMInitHdrStr.Constant"
-getSMInitHdrStr (SpecialisedRep CharLikeRep _ _ _) = panic "getSMInitHdrStr.CharLike"
+-- IA64 mangler doesn't place tables next to code
+tablesNextToCode :: Bool
+#ifdef ia64_TARGET_ARCH
+tablesNextToCode = False
+#else
+tablesNextToCode = not opt_Unregisterised
 #endif
+\end{code}
 
-getSMUpdInplaceHdrStr :: SMRep -> String
-getSMUpdInplaceHdrStr (SpecialisedRep ConstantRep _ _ _) = "INPLACE_UPD"
-getSMUpdInplaceHdrStr (SpecialisedRep CharLikeRep _ _ _) = "INPLACE_UPD"
-getSMUpdInplaceHdrStr (SpecialisedRep IntLikeRep _ _ _)         = "INPLACE_UPD"
-getSMUpdInplaceHdrStr (SpecialisedRep SpecRep _ _ _)    = "INPLACE_UPD"
-#ifdef DEBUG
-getSMUpdInplaceHdrStr (StaticRep _ _)                   = panic "getSMUpdInplaceHdrStr.Static"
-getSMUpdInplaceHdrStr (GenericRep _ _ _)                = panic "getSMUpdInplaceHdrStr.Generic"
-getSMUpdInplaceHdrStr (BigTupleRep _ )                  = panic "getSMUpdInplaceHdrStr.BigTuple"
-getSMUpdInplaceHdrStr (DataRep _ )                      = panic "getSMUpdInplaceHdrStr.Data"
-getSMUpdInplaceHdrStr DynamicRep                        = panic "getSMUpdInplaceHdrStr.Dynamic"
-getSMUpdInplaceHdrStr BlackHoleRep                      = panic "getSMUpdInplaceHdrStr.BlackHole"
-getSMUpdInplaceHdrStr PhantomRep                        = panic "getSMUpdInplaceHdrStr.Phantom"
-getSMUpdInplaceHdrStr (MuTupleRep _ )                   = panic "getSMUpdInplaceHdrStr.MuTuple"
-#endif
+\begin{code}
+isStaticRep :: SMRep -> Bool
+isStaticRep (GenericRep is_static _ _ _) = is_static
+isStaticRep BlackHoleRep                = False
 \end{code}
+
+\begin{code}
+#include "../includes/ClosureTypes.h"
+-- Defines CONSTR, CONSTR_1_0 etc
+
+
+smRepClosureType :: SMRep -> ClosureType
+smRepClosureType (GenericRep _ _ _ ty) = ty
+smRepClosureType BlackHoleRep         = panic "smRepClosureType: black hole"
+
+smRepClosureTypeInt :: SMRep -> Int
+smRepClosureTypeInt (GenericRep False 1 0 Constr) = CONSTR_1_0
+smRepClosureTypeInt (GenericRep False 0 1 Constr) = CONSTR_0_1
+smRepClosureTypeInt (GenericRep False 2 0 Constr) = CONSTR_2_0
+smRepClosureTypeInt (GenericRep False 1 1 Constr) = CONSTR_1_1
+smRepClosureTypeInt (GenericRep False 0 2 Constr) = CONSTR_0_2
+smRepClosureTypeInt (GenericRep False _ _ Constr) = CONSTR
+
+smRepClosureTypeInt (GenericRep False 1 0 Fun) = FUN_1_0
+smRepClosureTypeInt (GenericRep False 0 1 Fun) = FUN_0_1
+smRepClosureTypeInt (GenericRep False 2 0 Fun) = FUN_2_0
+smRepClosureTypeInt (GenericRep False 1 1 Fun) = FUN_1_1
+smRepClosureTypeInt (GenericRep False 0 2 Fun) = FUN_0_2
+smRepClosureTypeInt (GenericRep False _ _ Fun) = FUN
+
+smRepClosureTypeInt (GenericRep False 1 0 Thunk) = THUNK_1_0
+smRepClosureTypeInt (GenericRep False 0 1 Thunk) = THUNK_0_1
+smRepClosureTypeInt (GenericRep False 2 0 Thunk) = THUNK_2_0
+smRepClosureTypeInt (GenericRep False 1 1 Thunk) = THUNK_1_1
+smRepClosureTypeInt (GenericRep False 0 2 Thunk) = THUNK_0_2
+smRepClosureTypeInt (GenericRep False _ _ Thunk) = THUNK
+
+smRepClosureTypeInt (GenericRep False _ _ ThunkSelector) =  THUNK_SELECTOR
+
+smRepClosureTypeInt (GenericRep True _ _ Constr)      = CONSTR_STATIC
+smRepClosureTypeInt (GenericRep True _ _ ConstrNoCaf) = CONSTR_NOCAF_STATIC
+smRepClosureTypeInt (GenericRep True _ _ Fun)         = FUN_STATIC
+smRepClosureTypeInt (GenericRep True _ _ Thunk)       = THUNK_STATIC
+
+smRepClosureTypeInt BlackHoleRep = BLACKHOLE
+
+smRepClosureTypeInt rep = panic "smRepClosuretypeint"
+
+
+-- We export these ones
+rET_SMALL     = (RET_SMALL     :: Int)
+rET_VEC_SMALL = (RET_VEC_SMALL :: Int)
+rET_BIG       = (RET_BIG       :: Int)
+rET_VEC_BIG   = (RET_VEC_BIG   :: Int)
+\end{code}
+