[project @ 2000-06-30 13:11:07 by simonpj]
[ghc-hetmet.git] / ghc / compiler / prelude / PrimOp.lhs
index 4aa237f..34d49c7 100644 (file)
@@ -6,18 +6,21 @@
 \begin{code}
 module PrimOp (
        PrimOp(..), allThePrimOps,
-       primOpType, primOpSig, primOpUsg,
-       mkPrimOpIdName, primOpRdrName, primOpTag,
+       primOpType, primOpSig, primOpUsg, primOpArity,
+       mkPrimOpIdName, primOpRdrName, primOpTag, primOpOcc,
 
        commutableOp,
 
-       primOpOutOfLine, primOpNeedsWrapper, primOpStrictness,
+       primOpOutOfLine, primOpNeedsWrapper, 
        primOpOkForSpeculation, primOpIsCheap, primOpIsDupable,
        primOpHasSideEffects,
 
        getPrimOpResultInfo,  PrimOpResultInfo(..),
 
-       pprPrimOp
+       pprPrimOp,
+
+       CCall(..), CCallTarget(..), ccallMayGC, ccallIsCasm, pprCCallOp,
+       isDynamicTarget, dynamicTarget, setCCallUnique
     ) where
 
 #include "HsVersions.h"
@@ -26,7 +29,7 @@ import PrimRep                -- most of it
 import TysPrim
 import TysWiredIn
 
-import Demand          ( Demand, wwLazy, wwPrim, wwStrict )
+import Demand          ( Demand, wwLazy, wwPrim, wwStrict, StrictnessInfo(..) )
 import Var             ( TyVar, Id )
 import CallConv                ( CallConv, pprCallConv )
 import PprType         ( pprParendType )
@@ -40,7 +43,9 @@ import Type           ( Type, mkForAllTys, mkForAllTy, mkFunTy, mkFunTys, mkTyVarTys,
                           UsageAnn(..), mkUsgTy
                        )
 import Unique          ( Unique, mkPrimOpIdUnique )
-import PrelMods                ( pREL_GHC, pREL_GHC_Name )
+import BasicTypes      ( Arity, Boxity(..) )
+import CStrings                ( CLabelString, pprCLabelString )
+import PrelNames       ( pREL_GHC, pREL_GHC_Name )
 import Outputable
 import Util            ( assoc, zipWithEqual )
 import GlaExts         ( Int(..), Int#, (==#) )
@@ -147,16 +152,18 @@ data PrimOp
     | ReadByteArrayOp  PrimRep
     | WriteByteArrayOp PrimRep
     | IndexByteArrayOp PrimRep
-    | IndexOffAddrOp   PrimRep
+    | ReadOffAddrOp    PrimRep
     | WriteOffAddrOp    PrimRep
-       -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
+    | IndexOffAddrOp   PrimRep
+       -- PrimRep can be one of :
+       --      {Char,Int,Word,Addr,Float,Double,StablePtr,Int64,Word64}Rep.
        -- This is just a cheesy encoding of a bunch of ops.
        -- Note that ForeignObjRep is not included -- the only way of
        -- creating a ForeignObj is with a ccall or casm.
     | IndexOffForeignObjOp PrimRep
 
     | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
-    | UnsafeThawArrayOp   | UnsafeThawByteArrayOp
+    | UnsafeThawArrayOp
     | SizeofByteArrayOp   | SizeofMutableByteArrayOp
 
     -- Mutable variables
@@ -170,6 +177,7 @@ data PrimOp
     | TakeMVarOp 
     | PutMVarOp
     | SameMVarOp
+    | TryTakeMVarOp 
     | IsEmptyMVarOp
 
     -- exceptions
@@ -179,7 +187,7 @@ data PrimOp
     | UnblockAsyncExceptionsOp
 
     -- foreign objects
-    | MakeForeignObjOp
+    | MkForeignObjOp
     | WriteForeignObjOp
 
     -- weak pointers
@@ -196,83 +204,9 @@ data PrimOp
     | MakeStablePtrOp
     | DeRefStablePtrOp
     | EqStablePtrOp
-\end{code}
-
-A special ``trap-door'' to use in making calls direct to C functions:
-\begin{code}
-    | CCallOp  (Either 
-                   FAST_STRING    -- Left fn => An "unboxed" ccall# to `fn'.
-                   Unique)        -- Right u => first argument (an Addr#) is the function pointer
-                                  --   (unique is used to generate a 'typedef' to cast
-                                  --    the function pointer if compiling the ccall# down to
-                                  --    .hc code - can't do this inline for tedious reasons.)
-                                   
-               Bool                -- True <=> really a "casm"
-               Bool                -- True <=> might invoke Haskell GC
-               CallConv            -- calling convention to use.
-
-    -- (... to be continued ... )
-\end{code}
-
-The ``type'' of @CCallOp foo [t1, ... tm] r@ is @t1 -> ... tm -> r@.
-(See @primOpInfo@ for details.)
-
-Note: that first arg and part of the result should be the system state
-token (which we carry around to fool over-zealous optimisers) but
-which isn't actually passed.
-
-For example, we represent
-\begin{pseudocode}
-((ccall# foo [StablePtr# a, Int] Float) sp# i#) :: (Float, IoWorld)
-\end{pseudocode}
-by
-\begin{pseudocode}
-Case
-  ( Prim
-      (CCallOp "foo" [Universe#, StablePtr# a, Int#] FloatPrimAndUniverse False)
-       -- :: Universe# -> StablePtr# a -> Int# -> FloatPrimAndUniverse
-      []
-      [w#, sp# i#]
-  )
-  (AlgAlts [ ( FloatPrimAndIoWorld,
-                [f#, w#],
-                Con (TupleCon 2) [Float, IoWorld] [F# f#, World w#]
-              ) ]
-            NoDefault
-  )
-\end{pseudocode}
-
-Nota Bene: there are some people who find the empty list of types in
-the @Prim@ somewhat puzzling and would represent the above by
-\begin{pseudocode}
-Case
-  ( Prim
-      (CCallOp "foo" [alpha1, alpha2, alpha3] alpha4 False)
-       -- :: /\ alpha1, alpha2 alpha3, alpha4.
-       --       alpha1 -> alpha2 -> alpha3 -> alpha4
-      [Universe#, StablePtr# a, Int#, FloatPrimAndIoWorld]
-      [w#, sp# i#]
-  )
-  (AlgAlts [ ( FloatPrimAndIoWorld,
-                [f#, w#],
-                Con (TupleCon 2) [Float, IoWorld] [F# f#, World w#]
-              ) ]
-            NoDefault
-  )
-\end{pseudocode}
-
-But, this is a completely different way of using @CCallOp@.  The most
-major changes required if we switch to this are in @primOpInfo@, and
-the desugarer. The major difficulty is in moving the HeapRequirement
-stuff somewhere appropriate.  (The advantage is that we could simplify
-@CCallOp@ and record just the number of arguments with corresponding
-simplifications in reading pragma unfoldings, the simplifier,
-instantiation (etc) of core expressions, ... .  Maybe we should think
-about using it this way?? ADR)
-
-\begin{code}
-    -- (... continued from above ... )
 
+    -- Foreign calls
+    | CCallOp CCall
     -- Operation to test two closure addresses for equality (yes really!)
     -- BLAME ALASTAIR REID FOR THIS!  THE REST OF US ARE INNOCENT!
     | ReallyUnsafePtrEqualityOp
@@ -498,70 +432,78 @@ tagOf_PrimOp (IndexOffForeignObjOp DoubleRep) = ILIT(187)
 tagOf_PrimOp (IndexOffForeignObjOp StablePtrRep) = ILIT(188)
 tagOf_PrimOp (IndexOffForeignObjOp Int64Rep)  = ILIT(189)
 tagOf_PrimOp (IndexOffForeignObjOp Word64Rep) = ILIT(190)
-tagOf_PrimOp (WriteOffAddrOp CharRep)         = ILIT(191)
-tagOf_PrimOp (WriteOffAddrOp IntRep)          = ILIT(192)
-tagOf_PrimOp (WriteOffAddrOp WordRep)         = ILIT(193)
-tagOf_PrimOp (WriteOffAddrOp AddrRep)         = ILIT(194)
-tagOf_PrimOp (WriteOffAddrOp FloatRep)        = ILIT(195)
-tagOf_PrimOp (WriteOffAddrOp DoubleRep)       = ILIT(196)
-tagOf_PrimOp (WriteOffAddrOp StablePtrRep)    = ILIT(197)
-tagOf_PrimOp (WriteOffAddrOp ForeignObjRep)   = ILIT(198)
-tagOf_PrimOp (WriteOffAddrOp Int64Rep)        = ILIT(199)
-tagOf_PrimOp (WriteOffAddrOp Word64Rep)       = ILIT(200)
-tagOf_PrimOp UnsafeFreezeArrayOp             = ILIT(201)
-tagOf_PrimOp UnsafeFreezeByteArrayOp         = ILIT(202)
-tagOf_PrimOp UnsafeThawArrayOp               = ILIT(203)
-tagOf_PrimOp UnsafeThawByteArrayOp           = ILIT(204)
-tagOf_PrimOp SizeofByteArrayOp               = ILIT(205)
-tagOf_PrimOp SizeofMutableByteArrayOp        = ILIT(206)
-tagOf_PrimOp NewMVarOp                       = ILIT(207)
-tagOf_PrimOp TakeMVarOp                              = ILIT(208)
-tagOf_PrimOp PutMVarOp                       = ILIT(209)
-tagOf_PrimOp SameMVarOp                              = ILIT(210)
-tagOf_PrimOp IsEmptyMVarOp                   = ILIT(211)
-tagOf_PrimOp MakeForeignObjOp                = ILIT(212)
-tagOf_PrimOp WriteForeignObjOp               = ILIT(213)
-tagOf_PrimOp MkWeakOp                        = ILIT(214)
-tagOf_PrimOp DeRefWeakOp                     = ILIT(215)
-tagOf_PrimOp FinalizeWeakOp                  = ILIT(216)
-tagOf_PrimOp MakeStableNameOp                = ILIT(217)
-tagOf_PrimOp EqStableNameOp                  = ILIT(218)
-tagOf_PrimOp StableNameToIntOp               = ILIT(219)
-tagOf_PrimOp MakeStablePtrOp                 = ILIT(220)
-tagOf_PrimOp DeRefStablePtrOp                = ILIT(221)
-tagOf_PrimOp EqStablePtrOp                   = ILIT(222)
-tagOf_PrimOp (CCallOp _ _ _ _)               = ILIT(223)
-tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(224)
-tagOf_PrimOp SeqOp                           = ILIT(225)
-tagOf_PrimOp ParOp                           = ILIT(226)
-tagOf_PrimOp ForkOp                          = ILIT(227)
-tagOf_PrimOp KillThreadOp                    = ILIT(228)
-tagOf_PrimOp YieldOp                         = ILIT(229)
-tagOf_PrimOp MyThreadIdOp                    = ILIT(230)
-tagOf_PrimOp DelayOp                         = ILIT(231)
-tagOf_PrimOp WaitReadOp                              = ILIT(232)
-tagOf_PrimOp WaitWriteOp                     = ILIT(233)
-tagOf_PrimOp ParGlobalOp                     = ILIT(234)
-tagOf_PrimOp ParLocalOp                              = ILIT(235)
-tagOf_PrimOp ParAtOp                         = ILIT(236)
-tagOf_PrimOp ParAtAbsOp                              = ILIT(237)
-tagOf_PrimOp ParAtRelOp                              = ILIT(238)
-tagOf_PrimOp ParAtForNowOp                   = ILIT(239)
-tagOf_PrimOp CopyableOp                              = ILIT(240)
-tagOf_PrimOp NoFollowOp                              = ILIT(241)
-tagOf_PrimOp NewMutVarOp                     = ILIT(242)
-tagOf_PrimOp ReadMutVarOp                    = ILIT(243)
-tagOf_PrimOp WriteMutVarOp                   = ILIT(244)
-tagOf_PrimOp SameMutVarOp                    = ILIT(245)
-tagOf_PrimOp CatchOp                         = ILIT(246)
-tagOf_PrimOp RaiseOp                         = ILIT(247)
-tagOf_PrimOp BlockAsyncExceptionsOp          = ILIT(248)
-tagOf_PrimOp UnblockAsyncExceptionsOp        = ILIT(249)
-tagOf_PrimOp DataToTagOp                     = ILIT(250)
-tagOf_PrimOp TagToEnumOp                     = ILIT(251)
+tagOf_PrimOp (ReadOffAddrOp CharRep)          = ILIT(191)
+tagOf_PrimOp (ReadOffAddrOp IntRep)           = ILIT(192)
+tagOf_PrimOp (ReadOffAddrOp WordRep)          = ILIT(193)
+tagOf_PrimOp (ReadOffAddrOp AddrRep)          = ILIT(194)
+tagOf_PrimOp (ReadOffAddrOp FloatRep)         = ILIT(195)
+tagOf_PrimOp (ReadOffAddrOp DoubleRep)        = ILIT(196)
+tagOf_PrimOp (ReadOffAddrOp StablePtrRep)     = ILIT(197)
+tagOf_PrimOp (ReadOffAddrOp ForeignObjRep)    = ILIT(198)
+tagOf_PrimOp (ReadOffAddrOp Int64Rep)         = ILIT(199)
+tagOf_PrimOp (ReadOffAddrOp Word64Rep)        = ILIT(200)
+tagOf_PrimOp (WriteOffAddrOp CharRep)         = ILIT(201)
+tagOf_PrimOp (WriteOffAddrOp IntRep)          = ILIT(202)
+tagOf_PrimOp (WriteOffAddrOp WordRep)         = ILIT(203)
+tagOf_PrimOp (WriteOffAddrOp AddrRep)         = ILIT(205)
+tagOf_PrimOp (WriteOffAddrOp FloatRep)        = ILIT(206)
+tagOf_PrimOp (WriteOffAddrOp DoubleRep)       = ILIT(207)
+tagOf_PrimOp (WriteOffAddrOp StablePtrRep)    = ILIT(208)
+tagOf_PrimOp (WriteOffAddrOp ForeignObjRep)   = ILIT(209)
+tagOf_PrimOp (WriteOffAddrOp Int64Rep)        = ILIT(210)
+tagOf_PrimOp (WriteOffAddrOp Word64Rep)       = ILIT(211)
+tagOf_PrimOp UnsafeFreezeArrayOp             = ILIT(212)
+tagOf_PrimOp UnsafeFreezeByteArrayOp         = ILIT(213)
+tagOf_PrimOp UnsafeThawArrayOp               = ILIT(214)
+tagOf_PrimOp SizeofByteArrayOp               = ILIT(215)
+tagOf_PrimOp SizeofMutableByteArrayOp        = ILIT(216)
+tagOf_PrimOp NewMVarOp                       = ILIT(217)
+tagOf_PrimOp TakeMVarOp                              = ILIT(218)
+tagOf_PrimOp PutMVarOp                       = ILIT(219)
+tagOf_PrimOp SameMVarOp                              = ILIT(220)
+tagOf_PrimOp TryTakeMVarOp                   = ILIT(221)
+tagOf_PrimOp IsEmptyMVarOp                   = ILIT(222)
+tagOf_PrimOp MkForeignObjOp                  = ILIT(223)
+tagOf_PrimOp WriteForeignObjOp               = ILIT(224)
+tagOf_PrimOp MkWeakOp                        = ILIT(225)
+tagOf_PrimOp DeRefWeakOp                     = ILIT(226)
+tagOf_PrimOp FinalizeWeakOp                  = ILIT(227)
+tagOf_PrimOp MakeStableNameOp                = ILIT(228)
+tagOf_PrimOp EqStableNameOp                  = ILIT(229)
+tagOf_PrimOp StableNameToIntOp               = ILIT(230)
+tagOf_PrimOp MakeStablePtrOp                 = ILIT(231)
+tagOf_PrimOp DeRefStablePtrOp                = ILIT(232)
+tagOf_PrimOp EqStablePtrOp                   = ILIT(234)
+tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(235)
+tagOf_PrimOp SeqOp                           = ILIT(236)
+tagOf_PrimOp ParOp                           = ILIT(237)
+tagOf_PrimOp ForkOp                          = ILIT(238)
+tagOf_PrimOp KillThreadOp                    = ILIT(239)
+tagOf_PrimOp YieldOp                         = ILIT(240)
+tagOf_PrimOp MyThreadIdOp                    = ILIT(241)
+tagOf_PrimOp DelayOp                         = ILIT(242)
+tagOf_PrimOp WaitReadOp                              = ILIT(243)
+tagOf_PrimOp WaitWriteOp                     = ILIT(244)
+tagOf_PrimOp ParGlobalOp                     = ILIT(245)
+tagOf_PrimOp ParLocalOp                              = ILIT(246)
+tagOf_PrimOp ParAtOp                         = ILIT(247)
+tagOf_PrimOp ParAtAbsOp                              = ILIT(248)
+tagOf_PrimOp ParAtRelOp                              = ILIT(249)
+tagOf_PrimOp ParAtForNowOp                   = ILIT(250)
+tagOf_PrimOp CopyableOp                              = ILIT(251)
+tagOf_PrimOp NoFollowOp                              = ILIT(252)
+tagOf_PrimOp NewMutVarOp                     = ILIT(253)
+tagOf_PrimOp ReadMutVarOp                    = ILIT(254)
+tagOf_PrimOp WriteMutVarOp                   = ILIT(255)
+tagOf_PrimOp SameMutVarOp                    = ILIT(256)
+tagOf_PrimOp CatchOp                         = ILIT(257)
+tagOf_PrimOp RaiseOp                         = ILIT(258)
+tagOf_PrimOp BlockAsyncExceptionsOp          = ILIT(259)
+tagOf_PrimOp UnblockAsyncExceptionsOp        = ILIT(260)
+tagOf_PrimOp DataToTagOp                     = ILIT(261)
+tagOf_PrimOp TagToEnumOp                     = ILIT(262)
 
 tagOf_PrimOp op = pprPanic# "tagOf_PrimOp: pattern-match" (ppr op)
---panic# "tagOf_PrimOp: pattern-match"
 
 instance Eq PrimOp where
     op1 == op2 = tagOf_PrimOp op1 _EQ_ tagOf_PrimOp op2
@@ -584,7 +526,7 @@ instance Show PrimOp where
 
 An @Enum@-derived list would be better; meanwhile... (ToDo)
 \begin{code}
-allThePrimOps
+allThePrimOps          -- Except CCall, which is really a family of primops
   = [  CharGtOp,
        CharGeOp,
        CharEqOp,
@@ -773,6 +715,16 @@ allThePrimOps
        IndexOffAddrOp StablePtrRep,
        IndexOffAddrOp Int64Rep,
        IndexOffAddrOp Word64Rep,
+       ReadOffAddrOp CharRep,
+       ReadOffAddrOp IntRep,
+       ReadOffAddrOp WordRep,
+       ReadOffAddrOp AddrRep,
+       ReadOffAddrOp FloatRep,
+       ReadOffAddrOp DoubleRep,
+       ReadOffAddrOp ForeignObjRep,
+       ReadOffAddrOp StablePtrRep,
+       ReadOffAddrOp Int64Rep,
+       ReadOffAddrOp Word64Rep,
        WriteOffAddrOp CharRep,
        WriteOffAddrOp IntRep,
        WriteOffAddrOp WordRep,
@@ -786,7 +738,6 @@ allThePrimOps
        UnsafeFreezeArrayOp,
        UnsafeFreezeByteArrayOp,
        UnsafeThawArrayOp,
-       UnsafeThawByteArrayOp,
        SizeofByteArrayOp,
        SizeofMutableByteArrayOp,
        NewMutVarOp,
@@ -801,8 +752,9 @@ allThePrimOps
        TakeMVarOp,
        PutMVarOp,
        SameMVarOp,
+       TryTakeMVarOp,
        IsEmptyMVarOp,
-       MakeForeignObjOp,
+       MkForeignObjOp,
        WriteForeignObjOp,
        MkWeakOp,
        DeRefWeakOp,
@@ -881,9 +833,13 @@ an_Integer_and_Int_tys
   = [intPrimTy, byteArrayPrimTy, -- Integer
      intPrimTy]
 
-unboxedPair     = mkUnboxedTupleTy 2
-unboxedTriple    = mkUnboxedTupleTy 3
-unboxedQuadruple = mkUnboxedTupleTy 4
+unboxedSingleton = mkTupleTy Unboxed 1
+unboxedPair     = mkTupleTy Unboxed 2
+unboxedTriple    = mkTupleTy Unboxed 3
+unboxedQuadruple = mkTupleTy Unboxed 4
+
+mkIOTy ty = mkFunTy realWorldStatePrimTy 
+                   (unboxedPair [realWorldStatePrimTy,ty])
 
 integerMonadic name = mkGenPrimOp name [] one_Integer_ty 
                        (unboxedPair one_Integer_ty)
@@ -906,42 +862,45 @@ integerCompare name = mkGenPrimOp name [] two_Integer_tys intPrimTy
 Not all primops are strict!
 
 \begin{code}
-primOpStrictness :: PrimOp -> ([Demand], Bool)
-       -- See IdInfo.StrictnessInfo for discussion of what the results
-       -- **NB** as a cheap hack, to avoid having to look up the PrimOp's arity,
-       -- the list of demands may be infinite!
-       -- Use only the ones you ned.
+primOpStrictness :: Arity -> PrimOp -> StrictnessInfo
+       -- See Demand.StrictnessInfo for discussion of what the results
+       -- The arity should be the arity of the primop; that's why
+       -- this function isn't exported.
 
-primOpStrictness SeqOp            = ([wwStrict], False)
+primOpStrictness arity SeqOp            = StrictnessInfo [wwStrict] False
        -- Seq is strict in its argument; see notes in ConFold.lhs
 
-primOpStrictness ParOp            = ([wwLazy], False)
-       -- But Par is lazy, to avoid that the sparked thing
+primOpStrictness arity ParOp            = StrictnessInfo [wwLazy] False
+       -- Note that Par is lazy to avoid that the sparked thing
        -- gets evaluted strictly, which it should *not* be
 
-primOpStrictness ForkOp                  = ([wwLazy, wwPrim], False)
+primOpStrictness arity ForkOp          = StrictnessInfo [wwLazy, wwPrim] False
+
+primOpStrictness arity NewArrayOp       = StrictnessInfo [wwPrim, wwLazy, wwPrim] False
+primOpStrictness arity WriteArrayOp     = StrictnessInfo [wwPrim, wwPrim, wwLazy, wwPrim] False
 
-primOpStrictness NewArrayOp       = ([wwPrim, wwLazy, wwPrim], False)
-primOpStrictness WriteArrayOp     = ([wwPrim, wwPrim, wwLazy, wwPrim], False)
+primOpStrictness arity NewMutVarOp     = StrictnessInfo [wwLazy, wwPrim] False
+primOpStrictness arity WriteMutVarOp   = StrictnessInfo [wwPrim, wwLazy, wwPrim] False
 
-primOpStrictness NewMutVarOp     = ([wwLazy, wwPrim], False)
-primOpStrictness WriteMutVarOp   = ([wwPrim, wwLazy, wwPrim], False)
+primOpStrictness arity PutMVarOp       = StrictnessInfo [wwPrim, wwLazy, wwPrim] False
 
-primOpStrictness PutMVarOp       = ([wwPrim, wwLazy, wwPrim], False)
+primOpStrictness arity CatchOp                 = StrictnessInfo [wwLazy, wwLazy, wwPrim] False
+       -- Catch is actually strict in its first argument
+       -- but we don't want to tell the strictness
+       -- analyser about that!
 
-primOpStrictness CatchOp         = ([wwLazy, wwLazy], False)
-primOpStrictness RaiseOp         = ([wwLazy], True)    -- NB: True => result is bottom
-primOpStrictness BlockAsyncExceptionsOp    = ([wwLazy], False)
-primOpStrictness UnblockAsyncExceptionsOp  = ([wwLazy], False)
+primOpStrictness arity RaiseOp                 = StrictnessInfo [wwLazy] True  -- NB: True => result is bottom
+primOpStrictness arity BlockAsyncExceptionsOp   = StrictnessInfo [wwLazy] False
+primOpStrictness arity UnblockAsyncExceptionsOp = StrictnessInfo [wwLazy] False
 
-primOpStrictness MkWeakOp        = ([wwLazy, wwLazy, wwLazy, wwPrim], False)
-primOpStrictness MakeStableNameOp = ([wwLazy, wwPrim], False)
-primOpStrictness MakeStablePtrOp  = ([wwLazy, wwPrim], False)
+primOpStrictness arity MkWeakOp                = StrictnessInfo [wwLazy, wwLazy, wwLazy, wwPrim] False
+primOpStrictness arity MakeStableNameOp = StrictnessInfo [wwLazy, wwPrim] False
+primOpStrictness arity MakeStablePtrOp  = StrictnessInfo [wwLazy, wwPrim] False
 
-primOpStrictness DataToTagOp      = ([wwLazy], False)
+primOpStrictness arity DataToTagOp      = StrictnessInfo [wwLazy] False
 
        -- The rest all have primitive-typed arguments
-primOpStrictness other           = (repeat wwPrim, False)
+primOpStrictness arity other           = StrictnessInfo (replicate arity wwPrim) False
 \end{code}
 
 %************************************************************************
@@ -1313,7 +1272,7 @@ primOpInfo WriteArrayOp
 primOpInfo IndexArrayOp
   = let { elt = alphaTy; elt_tv = alphaTyVar } in
     mkGenPrimOp SLIT("indexArray#") [elt_tv] [mkArrayPrimTy elt, intPrimTy]
-       (mkUnboxedTupleTy 1 [elt])
+       (unboxedSingleton [elt])
 
 ---------------------------------------------------------------------------
 -- Primitive arrays full of unboxed bytes:
@@ -1361,6 +1320,17 @@ primOpInfo (IndexOffAddrOp kind)
     in
     mkGenPrimOp op_str tvs [addrPrimTy, intPrimTy] prim_ty
 
+primOpInfo (ReadOffAddrOp kind)
+  = let
+       s = alphaTy; s_tv = alphaTyVar
+       op_str = _PK_ ("read" ++ primRepString kind ++ "OffAddr#")
+        (tvs, prim_ty) = mkPrimTyApp betaTyVars kind
+       state          = mkStatePrimTy s
+    in
+    mkGenPrimOp op_str (s_tv:tvs)
+       [addrPrimTy, intPrimTy, state]
+       (unboxedPair [state, prim_ty])
+
 primOpInfo (WriteOffAddrOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
@@ -1376,7 +1346,6 @@ primOpInfo (WriteOffAddrOp kind)
 unsafeFreezeArray#     :: MutArr# s a -> State# s -> (# State# s, Array# a #)
 unsafeFreezeByteArray# :: MutByteArr# s -> State# s -> (# State# s, ByteArray# #)
 unsafeThawArray#       :: Array# a -> State# s -> (# State# s, MutArr# s a #)
-unsafeThawByteArray#   :: ByteArray# -> State# s -> (# State# s, MutByteArr# s #)
 -}
 
 primOpInfo UnsafeFreezeArrayOp
@@ -1406,15 +1375,6 @@ primOpInfo UnsafeThawArrayOp
        [mkArrayPrimTy elt, state]
        (unboxedPair [state, mkMutableArrayPrimTy s elt])
 
-primOpInfo UnsafeThawByteArrayOp
-  = let { 
-       s = alphaTy; s_tv = alphaTyVar;
-       state = mkStatePrimTy s
-    } in
-    mkGenPrimOp SLIT("unsafeThawByteArray#") [s_tv]
-       [byteArrayPrimTy, state]
-       (unboxedPair [state, mkMutableByteArrayPrimTy s])
-
 ---------------------------------------------------------------------------
 primOpInfo SizeofByteArrayOp
   = mkGenPrimOp
@@ -1480,8 +1440,10 @@ primOpInfo SameMutVarOp
 %*                                                                     *
 %************************************************************************
 
-catch  :: IO a -> (IOError -> IO a) -> IO a
-catch# :: a  -> (b -> a) -> a
+catch# :: (State# RealWorld -> (# State# RealWorld, a))
+       -> (b -> State# RealWorld -> (# State# RealWorld, a)) 
+       -> State# RealWorld
+       -> (# State# RealWorld, a)
 
 throw  :: Exception -> a
 raise# :: a -> b
@@ -1494,8 +1456,11 @@ primOpInfo CatchOp
   = let
        a = alphaTy; a_tv = alphaTyVar
        b = betaTy;  b_tv = betaTyVar;
+       io_a = mkIOTy a
     in
-    mkGenPrimOp SLIT("catch#") [a_tv, b_tv] [a, mkFunTy b a] a
+    mkGenPrimOp SLIT("catch#") [a_tv, b_tv] 
+         [io_a, mkFunTy b io_a, realWorldStatePrimTy]
+         (unboxedPair [realWorldStatePrimTy, a])
 
 primOpInfo RaiseOp
   = let
@@ -1509,9 +1474,7 @@ primOpInfo BlockAsyncExceptionsOp
       a = alphaTy; a_tv = alphaTyVar
     in
     mkGenPrimOp SLIT("blockAsyncExceptions#") [a_tv]
-       [ mkFunTy realWorldStatePrimTy (unboxedPair [realWorldStatePrimTy,a]),
-         realWorldStatePrimTy
-       ]
+       [ mkIOTy a, realWorldStatePrimTy ]
        (unboxedPair [realWorldStatePrimTy,a])
        
 primOpInfo UnblockAsyncExceptionsOp
@@ -1519,9 +1482,7 @@ primOpInfo UnblockAsyncExceptionsOp
       a = alphaTy; a_tv = alphaTyVar
     in
     mkGenPrimOp SLIT("unblockAsyncExceptions#") [a_tv]
-       [ mkFunTy realWorldStatePrimTy (unboxedPair [realWorldStatePrimTy,a]),
-         realWorldStatePrimTy
-       ]
+       [ mkIOTy a, realWorldStatePrimTy ]
        (unboxedPair [realWorldStatePrimTy,a])
 \end{code}
 
@@ -1564,6 +1525,15 @@ primOpInfo SameMVarOp
     in
     mkGenPrimOp SLIT("sameMVar#") [s_tv, elt_tv] [mvar_ty, mvar_ty] boolTy
 
+primOpInfo TryTakeMVarOp
+  = let
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       state = mkStatePrimTy s
+    in
+    mkGenPrimOp SLIT("tryTakeMVar#") [s_tv, elt_tv]
+       [mkMVarPrimTy s elt, state]
+       (unboxedTriple [state, intPrimTy, elt])
+
 primOpInfo IsEmptyMVarOp
   = let
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
@@ -1644,8 +1614,8 @@ primOpInfo MyThreadIdOp
 %************************************************************************
 
 \begin{code}
-primOpInfo MakeForeignObjOp
-  = mkGenPrimOp SLIT("makeForeignObj#") [] 
+primOpInfo MkForeignObjOp
+  = mkGenPrimOp SLIT("mkForeignObj#") [] 
        [addrPrimTy, realWorldStatePrimTy] 
        (unboxedPair [realWorldStatePrimTy, foreignObjPrimTy])
 
@@ -1909,24 +1879,6 @@ primOpInfo NoFollowOp    -- noFollow# :: a -> Int#
 
 %************************************************************************
 %*                                                                     *
-\subsubsection[PrimOp-IO-etc]{PrimOpInfo for C calls, and I/O-ish things}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-primOpInfo (CCallOp _ _ _ _)
-     = mkGenPrimOp SLIT("ccall#") [alphaTyVar] [] alphaTy
-
-{-
-primOpInfo (CCallOp _ _ _ _ arg_tys result_ty)
-  = mkGenPrimOp SLIT("ccall#") [] arg_tys result_tycon tys_applied
-  where
-    (result_tycon, tys_applied, _) = splitAlgTyConApp result_ty
--}
-\end{code}
-
-%************************************************************************
-%*                                                                     *
 \subsubsection[PrimOp-tag]{PrimOpInfo for @dataToTag#@ and @tagToEnum#@}
 %*                                                                     *
 %************************************************************************
@@ -1947,7 +1899,7 @@ primOpInfo TagToEnumOp
   = mkGenPrimOp SLIT("tagToEnum#") [alphaTyVar] [intPrimTy] alphaTy
 
 #ifdef DEBUG
-primOpInfo op = panic ("primOpInfo:"++ show (I# (tagOf_PrimOp op)))
+primOpInfo op = pprPanic "primOpInfo:" (ppr op)
 #endif
 \end{code}
 
@@ -1963,49 +1915,53 @@ perform a heap check or they block.
 \begin{code}
 primOpOutOfLine op
   = case op of
-       TakeMVarOp                -> True
-       PutMVarOp                 -> True
-       DelayOp                   -> True
-       WaitReadOp                -> True
-       WaitWriteOp               -> True
-       CatchOp                   -> True
-       RaiseOp                   -> True
-       BlockAsyncExceptionsOp    -> True
-       UnblockAsyncExceptionsOp  -> True
-       NewArrayOp                -> True
-       NewByteArrayOp _          -> True
-       IntegerAddOp              -> True
-       IntegerSubOp              -> True
-       IntegerMulOp              -> True
-       IntegerGcdOp              -> True
-       IntegerDivExactOp         -> True
-       IntegerQuotOp             -> True
-       IntegerRemOp              -> True
-       IntegerQuotRemOp          -> True
-       IntegerDivModOp           -> True
-       Int2IntegerOp             -> True
-       Word2IntegerOp            -> True
-       Addr2IntegerOp            -> True
-       Word64ToIntegerOp         -> True
-       Int64ToIntegerOp          -> True
-       FloatDecodeOp             -> True
-       DoubleDecodeOp            -> True
-       MkWeakOp                  -> True
-       FinalizeWeakOp            -> True
-       MakeStableNameOp          -> True
-       MakeForeignObjOp          -> True
-       NewMutVarOp               -> True
-       NewMVarOp                 -> True
-       ForkOp                    -> True
-       KillThreadOp              -> True
-       YieldOp                   -> True
-       CCallOp _ _ may_gc@True _ -> True       -- _ccall_GC_
-         -- the next one doesn't perform any heap checks,
+       TakeMVarOp                   -> True
+       TryTakeMVarOp                -> True
+       PutMVarOp                    -> True
+       DelayOp                      -> True
+       WaitReadOp                   -> True
+       WaitWriteOp                  -> True
+       CatchOp                      -> True
+       RaiseOp                      -> True
+       BlockAsyncExceptionsOp       -> True
+       UnblockAsyncExceptionsOp     -> True
+       NewArrayOp                   -> True
+       NewByteArrayOp _             -> True
+       IntegerAddOp                 -> True
+       IntegerSubOp                 -> True
+       IntegerMulOp                 -> True
+       IntegerGcdOp                 -> True
+       IntegerDivExactOp            -> True
+       IntegerQuotOp                -> True
+       IntegerRemOp                 -> True
+       IntegerQuotRemOp             -> True
+       IntegerDivModOp              -> True
+       Int2IntegerOp                -> True
+       Word2IntegerOp               -> True
+       Addr2IntegerOp               -> True
+       Word64ToIntegerOp            -> True
+       Int64ToIntegerOp             -> True
+       FloatDecodeOp                -> True
+       DoubleDecodeOp               -> True
+       MkWeakOp                     -> True
+       FinalizeWeakOp               -> True
+       MakeStableNameOp             -> True
+       MkForeignObjOp               -> True
+       NewMutVarOp                  -> True
+       NewMVarOp                    -> True
+       ForkOp                       -> True
+       KillThreadOp                 -> True
+       YieldOp                      -> True
+
+       UnsafeThawArrayOp            -> True
+         -- UnsafeThawArrayOp doesn't perform any heap checks,
          -- but it is of such an esoteric nature that
          -- it is done out-of-line rather than require
          -- the NCG to implement it.
-       UnsafeThawArrayOp       -> True
-       _                       -> False
+
+       CCallOp c_call -> ccallMayGC c_call
+
+       other -> False
 \end{code}
 
 
@@ -2058,10 +2014,8 @@ duplicate into different case branches.  See CoreUtils.exprIsDupable.
 \begin{code}
 primOpIsDupable :: PrimOp -> Bool
        -- See comments with CoreUtils.exprIsDupable
-primOpIsDupable (CCallOp _ _ might_gc _) = not might_gc
-       -- If the ccall can't GC then the call is pretty cheap, and
-       -- we're happy to duplicate
-primOpIsDupable op                      = not (primOpOutOfLine op)
+       -- We say it's dupable it isn't implemented by a C call with a wrapper
+primOpIsDupable op = not (primOpNeedsWrapper op)
 \end{code}
 
 
@@ -2102,7 +2056,7 @@ primOpHasSideEffects KillThreadOp      = True
 primOpHasSideEffects YieldOp          = True
 primOpHasSideEffects SeqOp            = True
 
-primOpHasSideEffects MakeForeignObjOp  = True
+primOpHasSideEffects MkForeignObjOp    = True
 primOpHasSideEffects WriteForeignObjOp = True
 primOpHasSideEffects MkWeakOp                 = True
 primOpHasSideEffects DeRefWeakOp       = True
@@ -2125,9 +2079,9 @@ primOpHasSideEffects WriteMutVarOp           = True
 primOpHasSideEffects UnsafeFreezeArrayOp       = True
 primOpHasSideEffects UnsafeFreezeByteArrayOp   = True
 primOpHasSideEffects UnsafeThawArrayOp         = True
-primOpHasSideEffects UnsafeThawByteArrayOp     = True
 
 primOpHasSideEffects TakeMVarOp        = True
+primOpHasSideEffects TryTakeMVarOp     = True
 primOpHasSideEffects PutMVarOp         = True
 primOpHasSideEffects DelayOp           = True
 primOpHasSideEffects WaitReadOp        = True
@@ -2141,9 +2095,7 @@ primOpHasSideEffects ParAtRelOp           = True
 primOpHasSideEffects ParAtForNowOp     = True
 primOpHasSideEffects CopyableOp                = True  -- Possibly not.  ASP 
 primOpHasSideEffects NoFollowOp                = True  -- Possibly not.  ASP
-
--- CCall
-primOpHasSideEffects (CCallOp  _ _ _ _) = True
+primOpHasSideEffects (CCallOp _)       = True
 
 primOpHasSideEffects other = False
 \end{code}
@@ -2154,7 +2106,7 @@ any live variables that are stored in caller-saves registers.
 \begin{code}
 primOpNeedsWrapper :: PrimOp -> Bool
 
-primOpNeedsWrapper (CCallOp _ _ _ _)    = True
+primOpNeedsWrapper (CCallOp _)                 = True
 
 primOpNeedsWrapper Integer2IntOp       = True
 primOpNeedsWrapper Integer2WordOp      = True
@@ -2200,6 +2152,14 @@ primOpNeedsWrapper other_op              = False
 \end{code}
 
 \begin{code}
+primOpArity :: PrimOp -> Arity
+primOpArity op 
+  = case (primOpInfo op) of
+      Monadic occ ty                     -> 1
+      Dyadic occ ty                      -> 2
+      Compare occ ty                     -> 2
+      GenPrimOp occ tyvars arg_tys res_ty -> length arg_tys
+               
 primOpType :: PrimOp -> Type  -- you may want to use primOpSig instead
 primOpType op
   = case (primOpInfo op) of
@@ -2233,15 +2193,20 @@ primOpOcc op = case (primOpInfo op) of
 
 -- primOpSig is like primOpType but gives the result split apart:
 -- (type variables, argument types, result type)
+-- It also gives arity, strictness info
 
-primOpSig :: PrimOp -> ([TyVar],[Type],Type)
+primOpSig :: PrimOp -> ([TyVar], [Type], Type, Arity, StrictnessInfo)
 primOpSig op
-  = case (primOpInfo op) of
-      Monadic   occ ty -> ([],     [ty],    ty    )
-      Dyadic    occ ty -> ([],     [ty,ty], ty    )
-      Compare   occ ty -> ([],     [ty,ty], boolTy)
-      GenPrimOp occ tyvars arg_tys res_ty
-                       -> (tyvars, arg_tys, res_ty)
+  = (tyvars, arg_tys, res_ty, arity, primOpStrictness arity op)
+  where
+    arity = length arg_tys
+    (tyvars, arg_tys, res_ty)
+      = case (primOpInfo op) of
+         Monadic   occ ty -> ([],     [ty],    ty    )
+         Dyadic    occ ty -> ([],     [ty,ty], ty    )
+         Compare   occ ty -> ([],     [ty,ty], boolTy)
+         GenPrimOp occ tyvars arg_tys res_ty
+                           -> (tyvars, arg_tys, res_ty)
 
 -- primOpUsg is like primOpSig but the types it yields are the
 -- appropriate sigma (i.e., usage-annotated) types,
@@ -2273,7 +2238,7 @@ primOpUsg op
       SameMutVarOp         -> mangle [mkP, mkP          ] mkM
 
       CatchOp              -> --     [mkO, mkO . (inFun mkM mkO)] mkO
-                              mangle [mkM, mkM . (inFun mkM mkM)] mkM
+                              mangle [mkM, mkM . (inFun mkM mkM), mkP] mkM
                               -- might use caught action multiply
       RaiseOp              -> mangle [mkM               ] mkM
 
@@ -2281,6 +2246,7 @@ primOpUsg op
       TakeMVarOp           -> mangle [mkM, mkP          ] mkM
       PutMVarOp            -> mangle [mkM, mkM, mkP     ] mkR
       SameMVarOp           -> mangle [mkP, mkP          ] mkM
+      TryTakeMVarOp        -> mangle [mkM, mkP          ] mkM
       IsEmptyMVarOp        -> mangle [mkP, mkP          ] mkM
 
       ForkOp               -> mangle [mkO, mkP          ] mkR
@@ -2310,7 +2276,7 @@ primOpUsg op
       CopyableOp           -> mangle [mkZ               ] mkR
       NoFollowOp           -> mangle [mkZ               ] mkR
 
-      CCallOp _ _ _ _      -> mangle [                  ] mkM
+      CCallOp _           -> mangle [                  ] mkM
 
       -- Things with no Haskell pointers inside: in actuality, usages are
       -- irrelevant here (hence it doesn't matter that some of these
@@ -2327,8 +2293,7 @@ primOpUsg op
         mkP          = mkUsgTy UsOnce  -- unpointed argument
         mkR          = mkUsgTy UsMany  -- unpointed result
   
-        (tyvars, arg_tys, res_ty)
-                     = primOpSig op
+        (tyvars, arg_tys, res_ty, _, _) = primOpSig op
 
         nomangle     = (tyvars, map mkP arg_tys, mkR res_ty)
 
@@ -2339,8 +2304,8 @@ primOpUsg op
                          Nothing    -> pprPanic "primOpUsg:inFun" (ppr op <+> ppr ty)
 
         inUB fs ty  = case splitTyConApp_maybe ty of
-                        Just (tc,tys) -> ASSERT( tc == unboxedTupleTyCon (length fs) )
-                                         mkUnboxedTupleTy (length fs) (zipWithEqual "primOpUsg"
+                        Just (tc,tys) -> ASSERT( tc == tupleTyCon Unboxed (length fs) )
+                                         mkTupleTy Unboxed (length fs) (zipWithEqual "primOpUsg"
                                                                          ($) fs tys)
                         Nothing       -> pprPanic "primOpUsg:inUB" (ppr op <+> ppr ty)
 \end{code}
@@ -2355,6 +2320,8 @@ data PrimOpResultInfo
 -- be out of line, or the code generator won't work.
 
 getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo
+getPrimOpResultInfo (CCallOp _)
+  = ReturnsAlg unboxedPairTyCon
 getPrimOpResultInfo op
   = case (primOpInfo op) of
       Dyadic  _ ty              -> ReturnsPrim (typePrimRep ty)
@@ -2367,12 +2334,6 @@ getPrimOpResultInfo op
                        Nothing -> panic "getPrimOpResultInfo"
                        Just (tc,_,_) -> ReturnsAlg tc
           other -> ReturnsPrim other
-
-isCompareOp :: PrimOp -> Bool
-isCompareOp op
-  = case primOpInfo op of
-      Compare _ _ -> True
-      _                  -> False
 \end{code}
 
 The commutable ops are those for which we will try to move constants
@@ -2425,8 +2386,75 @@ Output stuff:
 \begin{code}
 pprPrimOp  :: PrimOp -> SDoc
 
-pprPrimOp (CCallOp fun is_casm may_gc cconv)
-  = let
+pprPrimOp (CCallOp c_call) = pprCCallOp c_call
+pprPrimOp other_op
+  = getPprStyle $ \ sty ->
+    if ifaceStyle sty then     -- For interfaces Print it qualified with PrelGHC.
+       ptext SLIT("PrelGHC.") <> pprOccName occ
+    else
+       pprOccName occ
+  where
+    occ = primOpOcc other_op
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsubsection{CCalls}
+%*                                                                     *
+%************************************************************************
+
+A special ``trap-door'' to use in making calls direct to C functions:
+\begin{code}
+data CCall
+  =  CCall     CCallTarget
+               Bool            -- True <=> really a "casm"
+               Bool            -- True <=> might invoke Haskell GC
+               CallConv        -- calling convention to use.
+  deriving( Eq )
+
+data CCallTarget
+  = StaticTarget  CLabelString  -- An "unboxed" ccall# to `fn'.
+  | DynamicTarget Unique       -- First argument (an Addr#) is the function pointer
+                               --   (unique is used to generate a 'typedef' to cast
+                               --    the function pointer if compiling the ccall# down to
+                               --    .hc code - can't do this inline for tedious reasons.)
+
+instance Eq CCallTarget where
+  (StaticTarget l1) == (StaticTarget l2) = l1 == l2
+  (DynamicTarget _) == (DynamicTarget _) = True        
+       -- Ignore the arbitrary unique; this is important when comparing
+       -- a dynamic ccall read from an interface file A.hi with the
+       -- one constructed from A.hs, when deciding whether the interface
+       -- has changed
+  t1 == t2 = False
+
+ccallMayGC :: CCall -> Bool
+ccallMayGC (CCall _ _ may_gc _) = may_gc
+
+ccallIsCasm :: CCall -> Bool
+ccallIsCasm (CCall _ c_asm _ _) = c_asm
+
+isDynamicTarget (DynamicTarget _) = True
+isDynamicTarget (StaticTarget _)  = False
+
+dynamicTarget :: CCallTarget
+dynamicTarget = DynamicTarget (panic "Unique in DynamicTarget not yet set")
+       -- The unique is really only to do with code generation, so it
+       -- is only set in CoreToStg; before then it's just an error message
+
+setCCallUnique :: CCall -> Unique -> CCall
+setCCallUnique (CCall (DynamicTarget _) is_asm may_gc cconv) uniq
+  = CCall (DynamicTarget uniq) is_asm may_gc cconv
+setCCallUnique ccall uniq = ccall
+\end{code}
+
+\begin{code}
+pprCCallOp (CCall fun is_casm may_gc cconv)
+  = hcat [ ifPprDebug callconv
+        , text "__", ppr_dyn
+         , text before , ppr_fun , after]
+  where
         callconv = text "{-" <> pprCallConv cconv <> text "-}"
 
        before
@@ -2439,27 +2467,11 @@ pprPrimOp (CCallOp fun is_casm may_gc cconv)
          | is_casm   = text "''"
          | otherwise = empty
          
-       ppr_dyn =
-         case fun of
-           Right _ -> text "dyn_"
-           _       -> empty
-
-       ppr_fun =
-        case fun of
-          Right _ -> text "\"\""
-          Left fn -> ptext fn
-        
-    in
-    hcat [ ifPprDebug callconv
-        , text "__", ppr_dyn
-         , text before , ppr_fun , after]
+       ppr_dyn = case fun of
+                   DynamicTarget _ -> text "dyn_"
+                   _               -> empty
 
-pprPrimOp other_op
-  = getPprStyle $ \ sty ->
-   if ifaceStyle sty then      -- For interfaces Print it qualified with PrelGHC.
-       ptext SLIT("PrelGHC.") <> pprOccName occ
-   else
-       pprOccName occ
-  where
-    occ = primOpOcc other_op
+       ppr_fun = case fun of
+                    DynamicTarget _ -> text "\"\""
+                    StaticTarget fn -> pprCLabelString fn
 \end{code}