[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / prelude / PrimOp.lhs
index a9cc05c..75635a8 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[PrimOp]{Primitive operations (machine-level)}
 
@@ -7,24 +7,18 @@
 module PrimOp (
        PrimOp(..), allThePrimOps,
        tagOf_PrimOp, -- ToDo: rm
-       primOp_str,   -- sigh
-       primOpType, isCompareOp,
-       commutableOp,
+       primOpType,
+       primOpUniq, primOpStr,
 
-       PrimOpResultInfo(..),
-       getPrimOpResultInfo,
+       commutableOp,
 
-       primOpCanTriggerGC, primOpNeedsWrapper,
+       primOpOutOfLine, primOpNeedsWrapper,
        primOpOkForSpeculation, primOpIsCheap,
-       fragilePrimOp,
-       HeapRequirement(..), primOpHeapReq,
-       StackRequirement(..), primOpStackRequired,      
+       primOpHasSideEffects,
 
-       -- export for the Native Code Generator
-       primOpInfo, -- needed for primOpNameInfo
-       PrimOpInfo(..),
+       getPrimOpResultInfo,  PrimOpResultInfo(..),
 
-       pprPrimOp, showPrimOp
+       pprPrimOp
     ) where
 
 #include "HsVersions.h"
@@ -34,20 +28,18 @@ import TysPrim
 import TysWiredIn
 
 import CStrings                ( identToC )
+import Var             ( TyVar )
 import CallConv                ( CallConv, pprCallConv )
-import Constants       ( mIN_MP_INT_SIZE, mP_STRUCT_SIZE )
-import HeapOffs                ( addOff, intOff, totHdrSize, HeapOffset )
-import Outputable
 import PprType         ( pprParendType )
-import SMRep           ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
-import TyCon           ( TyCon{-instances-} )
-import Type            ( mkForAllTys, mkFunTy, mkFunTys, mkTyConApp, typePrimRep,
-                         splitAlgTyConApp, Type
+import TyCon           ( TyCon )
+import Type            ( mkForAllTys, mkForAllTy, mkFunTy, mkFunTys, 
+                         mkTyConApp, typePrimRep,
+                         splitAlgTyConApp, Type, isUnboxedTupleType, 
+                         splitAlgTyConApp_maybe
                        )
-import TyVar           --( alphaTyVar, betaTyVar, gammaTyVar )
-import Unique          ( Unique{-instance Eq-} )
-import Util            ( panic#, assoc, panic{-ToDo:rm-} )
-
+import Unique          ( Unique, mkPrimOpIdUnique )
+import Outputable
+import Util            ( assoc )
 import GlaExts         ( Int(..), Int#, (==#) )
 \end{code}
 
@@ -76,7 +68,7 @@ data PrimOp
     | OrdOp | ChrOp
 
     -- Int#-related ops:
-    -- IntAbsOp unused?? ADR
+   -- IntAbsOp unused?? ADR
     | IntAddOp | IntSubOp | IntMulOp | IntQuotOp
     | IntRemOp | IntNegOp | IntAbsOp
     | ISllOp | ISraOp | ISrlOp -- shift {left,right} {arithmetic,logical}
@@ -117,14 +109,14 @@ data PrimOp
 
     -- Integer (and related...) ops:
     -- slightly weird -- to match GMP package.
-    | IntegerAddOp | IntegerSubOp | IntegerMulOp
+    | IntegerAddOp | IntegerSubOp | IntegerMulOp | IntegerGcdOp
     | IntegerQuotRemOp | IntegerDivModOp | IntegerNegOp
 
     | IntegerCmpOp
 
     | Integer2IntOp  | Integer2WordOp  
     | Int2IntegerOp  | Word2IntegerOp
-    | Addr2IntegerOp -- "Addr" is *always* a literal string
+    | Addr2IntegerOp
      -- casting to/from Integer and 64-bit (un)signed quantities.
     | IntegerToInt64Op | Int64ToIntegerOp
     | IntegerToWord64Op | Word64ToIntegerOp
@@ -147,24 +139,41 @@ data PrimOp
     | WriteByteArrayOp PrimRep
     | IndexByteArrayOp PrimRep
     | IndexOffAddrOp   PrimRep
+    | WriteOffAddrOp    PrimRep
        -- PrimRep can be one of {Char,Int,Addr,Float,Double}Kind.
        -- 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
-    | WriteOffAddrOp PrimRep
 
     | UnsafeFreezeArrayOp | UnsafeFreezeByteArrayOp
     | SizeofByteArrayOp   | SizeofMutableByteArrayOp
 
-    | NewSynchVarOp -- for MVars and IVars
+    -- Mutable variables
+    | NewMutVarOp
+    | ReadMutVarOp
+    | WriteMutVarOp
+    | SameMutVarOp
+
+    -- for MVars
+    | NewMVarOp
+    | TakeMVarOp 
+    | PutMVarOp
     | SameMVarOp
-    | TakeMVarOp | PutMVarOp
-    | ReadIVarOp | WriteIVarOp
 
-    | MakeForeignObjOp  -- foreign objects (malloc pointers or any old URL)
-    | WriteForeignObjOp -- modifying foreign objects [obscuro factor: 200]
-    | MakeStablePtrOp | DeRefStablePtrOp
+    -- exceptions
+    | CatchOp
+    | RaiseOp
+
+    | MakeForeignObjOp
+    | WriteForeignObjOp
+
+    | MkWeakOp
+    | DeRefWeakOp
+
+    | MakeStablePtrOp
+    | DeRefStablePtrOp
+    | EqStablePtrOp
 \end{code}
 
 A special ``trap-door'' to use in making calls direct to C functions:
@@ -178,9 +187,6 @@ A special ``trap-door'' to use in making calls direct to C functions:
                Bool                -- True <=> really a "casm"
                Bool                -- True <=> might invoke Haskell GC
                CallConv            -- calling convention to use.
-               [Type]              -- Unboxed arguments; the state-token
-                                   -- argument will have been put *first*
-               Type                -- Return type; one of the "StateAnd<blah>#" types
 
     -- (... to be continued ... )
 \end{code}
@@ -244,19 +250,17 @@ about using it this way?? ADR)
 \begin{code}
     -- (... continued from above ... )
 
-    -- one to support "errorIO" (and, thereby, "error")
-    | ErrorIOPrimOp
-
     -- Operation to test two closure addresses for equality (yes really!)
     -- BLAME ALASTAIR REID FOR THIS!  THE REST OF US ARE INNOCENT!
     | ReallyUnsafePtrEqualityOp
 
-    -- three for parallel stuff
+    -- parallel stuff
     | SeqOp
     | ParOp
-    | ForkOp
 
-    -- three for concurrency
+    -- concurrency
+    | ForkOp
+    | KillThreadOp
     | DelayOp
     | WaitReadOp
     | WaitWriteOp
@@ -269,13 +273,12 @@ about using it this way?? ADR)
     | ParAtForNowOp    -- specifies initial destination of global par
     | CopyableOp       -- marks copyable code
     | NoFollowOp       -- marks non-followup expression
-
 \end{code}
 
-Deriving Ix is what we really want! ToDo
-(Chk around before deleting...)
+Used for the Ord instance
+
 \begin{code}
-tagOf_PrimOp CharGtOp                        = (ILIT(1) :: FAST_INT)
+tagOf_PrimOp CharGtOp                        = (ILIT( 1) :: FAST_INT)
 tagOf_PrimOp CharGeOp                        = ILIT(  2)
 tagOf_PrimOp CharEqOp                        = ILIT(  3)
 tagOf_PrimOp CharNeOp                        = ILIT(  4)
@@ -356,6 +359,7 @@ tagOf_PrimOp FloatSinhOp                  = ILIT( 77)
 tagOf_PrimOp FloatCoshOp                     = ILIT( 78)
 tagOf_PrimOp FloatTanhOp                     = ILIT( 79)
 tagOf_PrimOp FloatPowerOp                    = ILIT( 80)
+
 tagOf_PrimOp DoubleAddOp                     = ILIT( 81)
 tagOf_PrimOp DoubleSubOp                     = ILIT( 82)
 tagOf_PrimOp DoubleMulOp                     = ILIT( 83)
@@ -378,130 +382,163 @@ tagOf_PrimOp DoubleSinhOp                     = ILIT( 99)
 tagOf_PrimOp DoubleCoshOp                    = ILIT(100)
 tagOf_PrimOp DoubleTanhOp                    = ILIT(101)
 tagOf_PrimOp DoublePowerOp                   = ILIT(102)
+
 tagOf_PrimOp IntegerAddOp                    = ILIT(103)
 tagOf_PrimOp IntegerSubOp                    = ILIT(104)
 tagOf_PrimOp IntegerMulOp                    = ILIT(105)
-tagOf_PrimOp IntegerQuotRemOp                = ILIT(106)
-tagOf_PrimOp IntegerDivModOp                 = ILIT(107)
-tagOf_PrimOp IntegerNegOp                    = ILIT(108)
-tagOf_PrimOp IntegerCmpOp                    = ILIT(109)
-tagOf_PrimOp Integer2IntOp                   = ILIT(110)
-tagOf_PrimOp Integer2WordOp                  = ILIT(111)
-tagOf_PrimOp Int2IntegerOp                   = ILIT(112)
-tagOf_PrimOp Word2IntegerOp                  = ILIT(113)
-tagOf_PrimOp Addr2IntegerOp                  = ILIT(114)
-tagOf_PrimOp IntegerToInt64Op                = ILIT(115)
-tagOf_PrimOp Int64ToIntegerOp                = ILIT(116)
-tagOf_PrimOp IntegerToWord64Op               = ILIT(117)
-tagOf_PrimOp Word64ToIntegerOp               = ILIT(118)
-tagOf_PrimOp FloatEncodeOp                   = ILIT(119)
-tagOf_PrimOp FloatDecodeOp                   = ILIT(120)
-tagOf_PrimOp DoubleEncodeOp                  = ILIT(121)
-tagOf_PrimOp DoubleDecodeOp                  = ILIT(122)
-tagOf_PrimOp NewArrayOp                              = ILIT(123)
-tagOf_PrimOp (NewByteArrayOp CharRep)        = ILIT(124)
-tagOf_PrimOp (NewByteArrayOp IntRep)         = ILIT(125)
-tagOf_PrimOp (NewByteArrayOp WordRep)        = ILIT(126)
-tagOf_PrimOp (NewByteArrayOp AddrRep)        = ILIT(127)
-tagOf_PrimOp (NewByteArrayOp FloatRep)       = ILIT(128)
-tagOf_PrimOp (NewByteArrayOp DoubleRep)       = ILIT(129)
-tagOf_PrimOp (NewByteArrayOp StablePtrRep)    = ILIT(130)
-tagOf_PrimOp SameMutableArrayOp                      = ILIT(131)
-tagOf_PrimOp SameMutableByteArrayOp          = ILIT(132)
-tagOf_PrimOp ReadArrayOp                     = ILIT(133)
-tagOf_PrimOp WriteArrayOp                    = ILIT(134)
-tagOf_PrimOp IndexArrayOp                    = ILIT(135)
-tagOf_PrimOp (ReadByteArrayOp CharRep)       = ILIT(136)
-tagOf_PrimOp (ReadByteArrayOp IntRep)        = ILIT(137)
-tagOf_PrimOp (ReadByteArrayOp WordRep)       = ILIT(138)
-tagOf_PrimOp (ReadByteArrayOp AddrRep)       = ILIT(139)
-tagOf_PrimOp (ReadByteArrayOp FloatRep)       = ILIT(140)
-tagOf_PrimOp (ReadByteArrayOp DoubleRep)      = ILIT(141)
-tagOf_PrimOp (ReadByteArrayOp StablePtrRep)   = ILIT(142)
-tagOf_PrimOp (ReadByteArrayOp Int64Rep)              = ILIT(143)
-tagOf_PrimOp (ReadByteArrayOp Word64Rep)      = ILIT(144)
-tagOf_PrimOp (WriteByteArrayOp CharRep)       = ILIT(145)
-tagOf_PrimOp (WriteByteArrayOp AddrRep)       = ILIT(146)
-tagOf_PrimOp (WriteByteArrayOp IntRep)        = ILIT(147)
-tagOf_PrimOp (WriteByteArrayOp WordRep)       = ILIT(148)
-tagOf_PrimOp (WriteByteArrayOp FloatRep)      = ILIT(149)
-tagOf_PrimOp (WriteByteArrayOp DoubleRep)     = ILIT(150)
-tagOf_PrimOp (WriteByteArrayOp StablePtrRep)  = ILIT(151)
-tagOf_PrimOp (WriteByteArrayOp Int64Rep)      = ILIT(152)
-tagOf_PrimOp (WriteByteArrayOp Word64Rep)     = ILIT(153)
-tagOf_PrimOp (IndexByteArrayOp CharRep)       = ILIT(154)
-tagOf_PrimOp (IndexByteArrayOp IntRep)       = ILIT(155)
-tagOf_PrimOp (IndexByteArrayOp WordRep)              = ILIT(156)
-tagOf_PrimOp (IndexByteArrayOp AddrRep)       = ILIT(157)
-tagOf_PrimOp (IndexByteArrayOp FloatRep)      = ILIT(158)
-tagOf_PrimOp (IndexByteArrayOp DoubleRep)     = ILIT(159)
-tagOf_PrimOp (IndexByteArrayOp StablePtrRep)  = ILIT(160)
-tagOf_PrimOp (IndexByteArrayOp Int64Rep)      = ILIT(161)
-tagOf_PrimOp (IndexByteArrayOp Word64Rep)     = ILIT(162)
-tagOf_PrimOp (IndexOffAddrOp CharRep)        = ILIT(163)
-tagOf_PrimOp (IndexOffAddrOp IntRep)         = ILIT(164)
-tagOf_PrimOp (IndexOffAddrOp WordRep)        = ILIT(165)
-tagOf_PrimOp (IndexOffAddrOp AddrRep)        = ILIT(166)
-tagOf_PrimOp (IndexOffAddrOp FloatRep)       = ILIT(167)
-tagOf_PrimOp (IndexOffAddrOp DoubleRep)       = ILIT(168)
-tagOf_PrimOp (IndexOffAddrOp StablePtrRep)    = ILIT(169)
-tagOf_PrimOp (IndexOffAddrOp Int64Rep)       = ILIT(170)
-tagOf_PrimOp (IndexOffAddrOp Word64Rep)              = ILIT(171)
-tagOf_PrimOp (IndexOffForeignObjOp CharRep)   = ILIT(172)
-tagOf_PrimOp (IndexOffForeignObjOp IntRep)    = ILIT(173)
-tagOf_PrimOp (IndexOffForeignObjOp WordRep)   = ILIT(174)
-tagOf_PrimOp (IndexOffForeignObjOp AddrRep)   = ILIT(175)
-tagOf_PrimOp (IndexOffForeignObjOp FloatRep)  = ILIT(176)
-tagOf_PrimOp (IndexOffForeignObjOp DoubleRep) = ILIT(177)
-tagOf_PrimOp (IndexOffForeignObjOp StablePtrRep) = ILIT(178)
-tagOf_PrimOp (IndexOffForeignObjOp Int64Rep)  = ILIT(179)
-tagOf_PrimOp (IndexOffForeignObjOp Word64Rep) = ILIT(180)
-tagOf_PrimOp (WriteOffAddrOp CharRep)         = ILIT(181)
-tagOf_PrimOp (WriteOffAddrOp IntRep)          = ILIT(182)
-tagOf_PrimOp (WriteOffAddrOp WordRep)         = ILIT(183)
-tagOf_PrimOp (WriteOffAddrOp AddrRep)         = ILIT(184)
-tagOf_PrimOp (WriteOffAddrOp FloatRep)        = ILIT(185)
-tagOf_PrimOp (WriteOffAddrOp DoubleRep)       = ILIT(186)
-tagOf_PrimOp (WriteOffAddrOp StablePtrRep)    = ILIT(187)
-tagOf_PrimOp (WriteOffAddrOp ForeignObjRep)   = ILIT(188)
-tagOf_PrimOp (WriteOffAddrOp Int64Rep)        = ILIT(189)
-tagOf_PrimOp (WriteOffAddrOp Word64Rep)       = ILIT(190)
-tagOf_PrimOp UnsafeFreezeArrayOp             = ILIT(191)
-tagOf_PrimOp UnsafeFreezeByteArrayOp         = ILIT(192)
-tagOf_PrimOp SizeofByteArrayOp               = ILIT(193)
-tagOf_PrimOp SizeofMutableByteArrayOp        = ILIT(194)
-tagOf_PrimOp NewSynchVarOp                   = ILIT(195)
-tagOf_PrimOp TakeMVarOp                              = ILIT(196)
-tagOf_PrimOp PutMVarOp                       = ILIT(197)
-tagOf_PrimOp ReadIVarOp                              = ILIT(198)
-tagOf_PrimOp WriteIVarOp                     = ILIT(199)
+tagOf_PrimOp IntegerGcdOp                    = ILIT(106)
+tagOf_PrimOp IntegerQuotRemOp                = ILIT(107)
+tagOf_PrimOp IntegerDivModOp                 = ILIT(108)
+tagOf_PrimOp IntegerNegOp                    = ILIT(109)
+tagOf_PrimOp IntegerCmpOp                    = ILIT(110)
+tagOf_PrimOp Integer2IntOp                   = ILIT(111)
+tagOf_PrimOp Integer2WordOp                  = ILIT(112)
+tagOf_PrimOp Int2IntegerOp                   = ILIT(113)
+tagOf_PrimOp Word2IntegerOp                  = ILIT(114)
+tagOf_PrimOp Addr2IntegerOp                  = ILIT(115)
+tagOf_PrimOp IntegerToInt64Op                = ILIT(116)
+tagOf_PrimOp Int64ToIntegerOp                = ILIT(117)
+tagOf_PrimOp IntegerToWord64Op               = ILIT(118)
+tagOf_PrimOp Word64ToIntegerOp               = ILIT(119)
+
+tagOf_PrimOp FloatEncodeOp                   = ILIT(120)
+tagOf_PrimOp FloatDecodeOp                   = ILIT(121)
+tagOf_PrimOp DoubleEncodeOp                  = ILIT(122)
+tagOf_PrimOp DoubleDecodeOp                  = ILIT(123)
+
+tagOf_PrimOp NewArrayOp                              = ILIT(124)
+tagOf_PrimOp (NewByteArrayOp CharRep)        = ILIT(125)
+tagOf_PrimOp (NewByteArrayOp IntRep)         = ILIT(126)
+tagOf_PrimOp (NewByteArrayOp WordRep)        = ILIT(127)
+tagOf_PrimOp (NewByteArrayOp AddrRep)        = ILIT(128)
+tagOf_PrimOp (NewByteArrayOp FloatRep)       = ILIT(129)
+tagOf_PrimOp (NewByteArrayOp DoubleRep)       = ILIT(130)
+tagOf_PrimOp (NewByteArrayOp StablePtrRep)    = ILIT(131)
+tagOf_PrimOp SameMutableArrayOp                      = ILIT(132)
+tagOf_PrimOp SameMutableByteArrayOp          = ILIT(133)
+tagOf_PrimOp ReadArrayOp                     = ILIT(134)
+tagOf_PrimOp WriteArrayOp                    = ILIT(135)
+tagOf_PrimOp IndexArrayOp                    = ILIT(136)
+
+tagOf_PrimOp (ReadByteArrayOp CharRep)       = ILIT(137)
+tagOf_PrimOp (ReadByteArrayOp IntRep)        = ILIT(138)
+tagOf_PrimOp (ReadByteArrayOp WordRep)       = ILIT(139)
+tagOf_PrimOp (ReadByteArrayOp AddrRep)       = ILIT(140)
+tagOf_PrimOp (ReadByteArrayOp FloatRep)       = ILIT(141)
+tagOf_PrimOp (ReadByteArrayOp DoubleRep)      = ILIT(142)
+tagOf_PrimOp (ReadByteArrayOp StablePtrRep)   = ILIT(143)
+tagOf_PrimOp (ReadByteArrayOp Int64Rep)              = ILIT(144)
+tagOf_PrimOp (ReadByteArrayOp Word64Rep)      = ILIT(145)
+
+tagOf_PrimOp (WriteByteArrayOp CharRep)       = ILIT(146)
+tagOf_PrimOp (WriteByteArrayOp IntRep)       = ILIT(147)
+tagOf_PrimOp (WriteByteArrayOp WordRep)              = ILIT(148)
+tagOf_PrimOp (WriteByteArrayOp AddrRep)       = ILIT(149)
+tagOf_PrimOp (WriteByteArrayOp FloatRep)      = ILIT(150)
+tagOf_PrimOp (WriteByteArrayOp DoubleRep)     = ILIT(151)
+tagOf_PrimOp (WriteByteArrayOp StablePtrRep)  = ILIT(152)
+tagOf_PrimOp (WriteByteArrayOp Int64Rep)      = ILIT(153)
+tagOf_PrimOp (WriteByteArrayOp Word64Rep)     = ILIT(154)
+
+tagOf_PrimOp (IndexByteArrayOp CharRep)       = ILIT(155)
+tagOf_PrimOp (IndexByteArrayOp IntRep)       = ILIT(156)
+tagOf_PrimOp (IndexByteArrayOp WordRep)              = ILIT(157)
+tagOf_PrimOp (IndexByteArrayOp AddrRep)       = ILIT(158)
+tagOf_PrimOp (IndexByteArrayOp FloatRep)      = ILIT(159)
+tagOf_PrimOp (IndexByteArrayOp DoubleRep)     = ILIT(160)
+tagOf_PrimOp (IndexByteArrayOp StablePtrRep)  = ILIT(161)
+tagOf_PrimOp (IndexByteArrayOp Int64Rep)      = ILIT(162)
+tagOf_PrimOp (IndexByteArrayOp Word64Rep)     = ILIT(163)
+
+tagOf_PrimOp (IndexOffAddrOp CharRep)        = ILIT(164)
+tagOf_PrimOp (IndexOffAddrOp IntRep)         = ILIT(165)
+tagOf_PrimOp (IndexOffAddrOp WordRep)        = ILIT(166)
+tagOf_PrimOp (IndexOffAddrOp AddrRep)        = ILIT(167)
+tagOf_PrimOp (IndexOffAddrOp FloatRep)       = ILIT(168)
+tagOf_PrimOp (IndexOffAddrOp DoubleRep)       = ILIT(169)
+tagOf_PrimOp (IndexOffAddrOp StablePtrRep)    = ILIT(170)
+tagOf_PrimOp (IndexOffAddrOp Int64Rep)       = ILIT(171)
+tagOf_PrimOp (IndexOffAddrOp Word64Rep)              = ILIT(172)
+tagOf_PrimOp (IndexOffForeignObjOp CharRep)   = ILIT(173)
+tagOf_PrimOp (IndexOffForeignObjOp IntRep)    = ILIT(174)
+tagOf_PrimOp (IndexOffForeignObjOp WordRep)   = ILIT(175)
+tagOf_PrimOp (IndexOffForeignObjOp AddrRep)   = ILIT(176)
+tagOf_PrimOp (IndexOffForeignObjOp FloatRep)  = ILIT(177)
+tagOf_PrimOp (IndexOffForeignObjOp DoubleRep) = ILIT(178)
+tagOf_PrimOp (IndexOffForeignObjOp StablePtrRep) = ILIT(179)
+tagOf_PrimOp (IndexOffForeignObjOp Int64Rep)  = ILIT(180)
+tagOf_PrimOp (IndexOffForeignObjOp Word64Rep) = ILIT(181)
+
+tagOf_PrimOp (WriteOffAddrOp CharRep)         = ILIT(182)
+tagOf_PrimOp (WriteOffAddrOp IntRep)          = ILIT(183)
+tagOf_PrimOp (WriteOffAddrOp WordRep)         = ILIT(184)
+tagOf_PrimOp (WriteOffAddrOp AddrRep)         = ILIT(185)
+tagOf_PrimOp (WriteOffAddrOp FloatRep)        = ILIT(186)
+tagOf_PrimOp (WriteOffAddrOp DoubleRep)       = ILIT(187)
+tagOf_PrimOp (WriteOffAddrOp StablePtrRep)    = ILIT(188)
+tagOf_PrimOp (WriteOffAddrOp ForeignObjRep)   = ILIT(189)
+tagOf_PrimOp (WriteOffAddrOp Int64Rep)        = ILIT(190)
+tagOf_PrimOp (WriteOffAddrOp Word64Rep)       = ILIT(191)
+
+tagOf_PrimOp UnsafeFreezeArrayOp             = ILIT(192)
+tagOf_PrimOp UnsafeFreezeByteArrayOp         = ILIT(193)
+tagOf_PrimOp SizeofByteArrayOp               = ILIT(194)
+tagOf_PrimOp SizeofMutableByteArrayOp        = ILIT(195)
+tagOf_PrimOp NewMVarOp                       = ILIT(196)
+tagOf_PrimOp TakeMVarOp                              = ILIT(197)
+tagOf_PrimOp PutMVarOp                       = ILIT(198)
+tagOf_PrimOp SameMVarOp                              = ILIT(199)
 tagOf_PrimOp MakeForeignObjOp                = ILIT(200)
 tagOf_PrimOp WriteForeignObjOp               = ILIT(201)
-tagOf_PrimOp MakeStablePtrOp                 = ILIT(202)
-tagOf_PrimOp DeRefStablePtrOp                = ILIT(203)
-tagOf_PrimOp (CCallOp _ _ _ _ _ _)           = ILIT(204)
-tagOf_PrimOp ErrorIOPrimOp                   = ILIT(205)
-tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(206)
-tagOf_PrimOp SeqOp                           = ILIT(207)
-tagOf_PrimOp ParOp                           = ILIT(208)
-tagOf_PrimOp ForkOp                          = ILIT(209)
-tagOf_PrimOp DelayOp                         = ILIT(210)
-tagOf_PrimOp WaitReadOp                              = ILIT(211)
-tagOf_PrimOp WaitWriteOp                     = ILIT(212)
-tagOf_PrimOp ParGlobalOp                     = ILIT(213)
-tagOf_PrimOp ParLocalOp                              = ILIT(214)
-tagOf_PrimOp ParAtOp                         = ILIT(215)
-tagOf_PrimOp ParAtAbsOp                              = ILIT(216)
-tagOf_PrimOp ParAtRelOp                              = ILIT(217)
-tagOf_PrimOp ParAtForNowOp                   = ILIT(218)
-tagOf_PrimOp CopyableOp                              = ILIT(219)
-tagOf_PrimOp NoFollowOp                              = ILIT(220)
-tagOf_PrimOp SameMVarOp                              = ILIT(221)
-
-tagOf_PrimOp _ = panic# "tagOf_PrimOp: pattern-match"
+tagOf_PrimOp MkWeakOp                        = ILIT(202)
+tagOf_PrimOp DeRefWeakOp                     = ILIT(203)
+tagOf_PrimOp MakeStablePtrOp                 = ILIT(204)
+tagOf_PrimOp DeRefStablePtrOp                = ILIT(205)
+tagOf_PrimOp EqStablePtrOp                   = ILIT(206)
+tagOf_PrimOp (CCallOp _ _ _ _)               = ILIT(207)
+tagOf_PrimOp ReallyUnsafePtrEqualityOp       = ILIT(208)
+tagOf_PrimOp SeqOp                           = ILIT(209)
+tagOf_PrimOp ParOp                           = ILIT(210)
+tagOf_PrimOp ForkOp                          = ILIT(211)
+tagOf_PrimOp KillThreadOp                    = ILIT(212)
+tagOf_PrimOp DelayOp                         = ILIT(213)
+tagOf_PrimOp WaitReadOp                              = ILIT(214)
+tagOf_PrimOp WaitWriteOp                     = ILIT(215)
+tagOf_PrimOp ParGlobalOp                     = ILIT(216)
+tagOf_PrimOp ParLocalOp                              = ILIT(217)
+tagOf_PrimOp ParAtOp                         = ILIT(218)
+tagOf_PrimOp ParAtAbsOp                              = ILIT(219)
+tagOf_PrimOp ParAtRelOp                              = ILIT(220)
+tagOf_PrimOp ParAtForNowOp                   = ILIT(221)
+tagOf_PrimOp CopyableOp                              = ILIT(222)
+tagOf_PrimOp NoFollowOp                              = ILIT(223)
+tagOf_PrimOp NewMutVarOp                     = ILIT(224)
+tagOf_PrimOp ReadMutVarOp                    = ILIT(225)
+tagOf_PrimOp WriteMutVarOp                   = ILIT(226)
+tagOf_PrimOp SameMutVarOp                    = ILIT(227)
+tagOf_PrimOp CatchOp                         = ILIT(228)
+tagOf_PrimOp RaiseOp                         = ILIT(229)
+
+tagOf_PrimOp op = pprPanic# "tagOf_PrimOp: pattern-match" (ppr op)
+--panic# "tagOf_PrimOp: pattern-match"
 
 instance Eq PrimOp where
-    op == op2 = tagOf_PrimOp op _EQ_ tagOf_PrimOp op2
+    op1 == op2 = tagOf_PrimOp op1 _EQ_ tagOf_PrimOp op2
+
+instance Ord PrimOp where
+    op1 <  op2 =  tagOf_PrimOp op1 _LT_ tagOf_PrimOp op2
+    op1 <= op2 =  tagOf_PrimOp op1 _LE_ tagOf_PrimOp op2
+    op1 >= op2 =  tagOf_PrimOp op1 _GE_ tagOf_PrimOp op2
+    op1 >  op2 =  tagOf_PrimOp op1 _GT_ tagOf_PrimOp op2
+    op1 `compare` op2 | op1 < op2  = LT
+                     | op1 == op2 = EQ
+                     | otherwise  = GT
+
+instance Outputable PrimOp where
+    ppr op = pprPrimOp op
+
+instance Show PrimOp where
+    showsPrec p op = showsPrecSDoc p (pprPrimOp op)
 \end{code}
 
 An @Enum@-derived list would be better; meanwhile... (ToDo)
@@ -612,6 +649,7 @@ allThePrimOps
        IntegerAddOp,
        IntegerSubOp,
        IntegerMulOp,
+       IntegerGcdOp,
        IntegerQuotRemOp,
        IntegerDivModOp,
        IntegerNegOp,
@@ -669,15 +707,6 @@ allThePrimOps
        IndexByteArrayOp StablePtrRep,
        IndexByteArrayOp Int64Rep,
        IndexByteArrayOp Word64Rep,
-       IndexOffAddrOp CharRep,
-       IndexOffAddrOp IntRep,
-       IndexOffAddrOp WordRep,
-       IndexOffAddrOp AddrRep,
-       IndexOffAddrOp FloatRep,
-       IndexOffAddrOp DoubleRep,
-       IndexOffAddrOp StablePtrRep,
-       IndexOffAddrOp Int64Rep,
-       IndexOffAddrOp Word64Rep,
        IndexOffForeignObjOp CharRep,
        IndexOffForeignObjOp AddrRep,
        IndexOffForeignObjOp IntRep,
@@ -687,33 +716,47 @@ allThePrimOps
        IndexOffForeignObjOp StablePtrRep,
        IndexOffForeignObjOp Int64Rep,
        IndexOffForeignObjOp Word64Rep,
+       IndexOffAddrOp CharRep,
+       IndexOffAddrOp IntRep,
+       IndexOffAddrOp WordRep,
+       IndexOffAddrOp AddrRep,
+       IndexOffAddrOp FloatRep,
+       IndexOffAddrOp DoubleRep,
+       IndexOffAddrOp StablePtrRep,
+       IndexOffAddrOp Int64Rep,
+       IndexOffAddrOp Word64Rep,
        WriteOffAddrOp CharRep,
        WriteOffAddrOp IntRep,
        WriteOffAddrOp WordRep,
        WriteOffAddrOp AddrRep,
        WriteOffAddrOp FloatRep,
        WriteOffAddrOp DoubleRep,
-       WriteOffAddrOp StablePtrRep,
        WriteOffAddrOp ForeignObjRep,
+       WriteOffAddrOp StablePtrRep,
        WriteOffAddrOp Int64Rep,
        WriteOffAddrOp Word64Rep,
        UnsafeFreezeArrayOp,
        UnsafeFreezeByteArrayOp,
        SizeofByteArrayOp,
        SizeofMutableByteArrayOp,
-       NewSynchVarOp,
-        SameMVarOp,
-       ReadArrayOp,
+       NewMutVarOp,
+       ReadMutVarOp,
+       WriteMutVarOp,
+       SameMutVarOp,
+        CatchOp,
+        RaiseOp,
+       NewMVarOp,
        TakeMVarOp,
        PutMVarOp,
-       ReadIVarOp,
-       WriteIVarOp,
+       SameMVarOp,
        MakeForeignObjOp,
        WriteForeignObjOp,
+       MkWeakOp,
+       DeRefWeakOp,
        MakeStablePtrOp,
        DeRefStablePtrOp,
+       EqStablePtrOp,
        ReallyUnsafePtrEqualityOp,
-       ErrorIOPrimOp,
        ParGlobalOp,
        ParLocalOp,
        ParAtOp,
@@ -725,6 +768,7 @@ allThePrimOps
        SeqOp,
        ParOp,
        ForkOp,
+       KillThreadOp,
        DelayOp,
        WaitReadOp,
        WaitWriteOp
@@ -754,23 +798,11 @@ data PrimOpInfo
                Type
   | Compare    FAST_STRING     -- string :: T -> T -> Bool
                Type
-  | Coercing   FAST_STRING     -- string :: T1 -> T2
-               Type
-               Type
 
-  | PrimResult FAST_STRING
-               [TyVar] [Type] TyCon PrimRep [Type]
-               -- "PrimResult tvs [t1,..,tn] D# kind [s1,..,sm]"
-               -- has type Forall tvs. t1 -> ... -> tn -> (D# s1 ... sm)
-               -- D# is a primitive type constructor.
-               -- (the kind is the same info as D#, in another convenient form)
-
-  | AlgResult  FAST_STRING
-               [TyVar] [Type] TyCon [Type]
-               -- "AlgResult tvs [t1,..,tn] T [s1,..,sm]"
-               -- has type Forall tvs. t1 -> ... -> tn -> (T s1 ... sm)
-
--- ToDo: Specialised calls to PrimOps are prohibited but may be desirable
+  | GenPrimOp   FAST_STRING    -- string :: \/a1..an . T1 -> .. -> Tk -> T
+               [TyVar] 
+               [Type] 
+               Type 
 \end{code}
 
 Utility bits:
@@ -783,15 +815,30 @@ an_Integer_and_Int_tys
   = [intPrimTy, intPrimTy, byteArrayPrimTy, -- Integer
      intPrimTy]
 
-integerMonadic name = AlgResult name [] one_Integer_ty integerTyCon []
+unboxedPair     = mkUnboxedTupleTy 2
+unboxedTriple    = mkUnboxedTupleTy 3
+unboxedQuadruple = mkUnboxedTupleTy 4
+unboxedSexTuple  = mkUnboxedTupleTy 6
 
-integerDyadic name = AlgResult name [] two_Integer_tys integerTyCon []
+integerMonadic name = GenPrimOp name [] one_Integer_ty 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
-integerDyadic2Results name = AlgResult name [] two_Integer_tys return2GMPsTyCon []
+integerDyadic name = GenPrimOp name [] two_Integer_tys 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
-integerCompare name = PrimResult name [] two_Integer_tys intPrimTyCon IntRep []
+integerDyadic2Results name = GenPrimOp name [] two_Integer_tys 
+    (unboxedSexTuple [intPrimTy, intPrimTy, byteArrayPrimTy, 
+                     intPrimTy, intPrimTy, byteArrayPrimTy])
+
+integerCompare name = GenPrimOp name [] two_Integer_tys intPrimTy
 \end{code}
 
+%************************************************************************
+%*                                                                     *
+\subsubsection[PrimOp-comparison]{PrimOpInfo basic comparison ops}
+%*                                                                     *
+%************************************************************************
+
 @primOpInfo@ gives all essential information (from which everything
 else, notably a type, can be constructed) for each @PrimOp@.
 
@@ -801,12 +848,6 @@ primOpInfo :: PrimOp -> PrimOpInfo
 
 There's plenty of this stuff!
 
-%************************************************************************
-%*                                                                     *
-\subsubsection[PrimOp-comparison]{PrimOpInfo basic comparison ops}
-%*                                                                     *
-%************************************************************************
-
 \begin{code}
 primOpInfo CharGtOp   = Compare SLIT("gtChar#")   charPrimTy
 primOpInfo CharGeOp   = Compare SLIT("geChar#")   charPrimTy
@@ -859,8 +900,8 @@ primOpInfo DoubleLeOp = Compare SLIT("<=##") doublePrimTy
 %************************************************************************
 
 \begin{code}
-primOpInfo OrdOp = Coercing SLIT("ord#") charPrimTy intPrimTy
-primOpInfo ChrOp = Coercing SLIT("chr#") intPrimTy charPrimTy
+primOpInfo OrdOp = GenPrimOp SLIT("ord#") [] [charPrimTy] intPrimTy
+primOpInfo ChrOp = GenPrimOp SLIT("chr#") [] [intPrimTy]  charPrimTy
 \end{code}
 
 %************************************************************************
@@ -898,19 +939,19 @@ primOpInfo XorOp    = Dyadic  SLIT("xor#")        wordPrimTy
 primOpInfo NotOp    = Monadic SLIT("not#")     wordPrimTy
 
 primOpInfo SllOp
-  = PrimResult SLIT("shiftL#")  [] [wordPrimTy, intPrimTy] wordPrimTyCon WordRep []
+  = GenPrimOp SLIT("shiftL#")  [] [wordPrimTy, intPrimTy] wordPrimTy
 primOpInfo SrlOp
-  = PrimResult SLIT("shiftRL#") [] [wordPrimTy, intPrimTy] wordPrimTyCon WordRep []
+  = GenPrimOp SLIT("shiftRL#") [] [wordPrimTy, intPrimTy] wordPrimTy
 
 primOpInfo ISllOp
-  = PrimResult SLIT("iShiftL#")  [] [intPrimTy, intPrimTy] intPrimTyCon IntRep []
+  = GenPrimOp SLIT("iShiftL#")  [] [intPrimTy, intPrimTy] intPrimTy
 primOpInfo ISraOp
-  = PrimResult SLIT("iShiftRA#") [] [intPrimTy, intPrimTy] intPrimTyCon IntRep []
+  = GenPrimOp SLIT("iShiftRA#") [] [intPrimTy, intPrimTy] intPrimTy
 primOpInfo ISrlOp
-  = PrimResult SLIT("iShiftRL#") [] [intPrimTy, intPrimTy] intPrimTyCon IntRep []
+  = GenPrimOp SLIT("iShiftRL#") [] [intPrimTy, intPrimTy] intPrimTy
 
-primOpInfo Int2WordOp = Coercing SLIT("int2Word#") intPrimTy wordPrimTy
-primOpInfo Word2IntOp = Coercing SLIT("word2Int#") wordPrimTy intPrimTy
+primOpInfo Int2WordOp = GenPrimOp SLIT("int2Word#") [] [intPrimTy] wordPrimTy
+primOpInfo Word2IntOp = GenPrimOp SLIT("word2Int#") [] [wordPrimTy] intPrimTy
 \end{code}
 
 %************************************************************************
@@ -920,8 +961,8 @@ primOpInfo Word2IntOp = Coercing SLIT("word2Int#") wordPrimTy intPrimTy
 %************************************************************************
 
 \begin{code}
-primOpInfo Int2AddrOp = Coercing SLIT("int2Addr#") intPrimTy addrPrimTy
-primOpInfo Addr2IntOp = Coercing SLIT("addr2Int#") addrPrimTy intPrimTy
+primOpInfo Int2AddrOp = GenPrimOp SLIT("int2Addr#") [] [intPrimTy] addrPrimTy
+primOpInfo Addr2IntOp = GenPrimOp SLIT("addr2Int#") [] [addrPrimTy] intPrimTy
 \end{code}
 
 
@@ -941,8 +982,8 @@ primOpInfo FloatMulOp       = Dyadic    SLIT("timesFloat#")   floatPrimTy
 primOpInfo FloatDivOp  = Dyadic    SLIT("divideFloat#")  floatPrimTy
 primOpInfo FloatNegOp  = Monadic   SLIT("negateFloat#")  floatPrimTy
 
-primOpInfo Float2IntOp = Coercing SLIT("float2Int#") floatPrimTy intPrimTy
-primOpInfo Int2FloatOp = Coercing SLIT("int2Float#") intPrimTy floatPrimTy
+primOpInfo Float2IntOp = GenPrimOp SLIT("float2Int#") [] [floatPrimTy] intPrimTy
+primOpInfo Int2FloatOp = GenPrimOp SLIT("int2Float#") [] [intPrimTy] floatPrimTy
 
 primOpInfo FloatExpOp  = Monadic   SLIT("expFloat#")      floatPrimTy
 primOpInfo FloatLogOp  = Monadic   SLIT("logFloat#")      floatPrimTy
@@ -975,11 +1016,11 @@ primOpInfo DoubleMulOp   = Dyadic    SLIT("*##")  doublePrimTy
 primOpInfo DoubleDivOp = Dyadic    SLIT("/##") doublePrimTy
 primOpInfo DoubleNegOp = Monadic   SLIT("negateDouble#") doublePrimTy
 
-primOpInfo Double2IntOp            = Coercing SLIT("double2Int#")   doublePrimTy intPrimTy
-primOpInfo Int2DoubleOp            = Coercing SLIT("int2Double#")   intPrimTy doublePrimTy
+primOpInfo Double2IntOp            = GenPrimOp SLIT("double2Int#") [] [doublePrimTy] intPrimTy
+primOpInfo Int2DoubleOp            = GenPrimOp SLIT("int2Double#") [] [intPrimTy] doublePrimTy
 
-primOpInfo Double2FloatOp   = Coercing SLIT("double2Float#") doublePrimTy floatPrimTy
-primOpInfo Float2DoubleOp   = Coercing SLIT("float2Double#") floatPrimTy doublePrimTy
+primOpInfo Double2FloatOp   = GenPrimOp SLIT("double2Float#") [] [doublePrimTy] floatPrimTy
+primOpInfo Float2DoubleOp   = GenPrimOp SLIT("float2Double#") [] [floatPrimTy] doublePrimTy
 
 primOpInfo DoubleExpOp = Monadic   SLIT("expDouble#")     doublePrimTy
 primOpInfo DoubleLogOp = Monadic   SLIT("logDouble#")     doublePrimTy
@@ -1008,6 +1049,7 @@ primOpInfo IntegerNegOp   = integerMonadic SLIT("negateInteger#")
 primOpInfo IntegerAddOp        = integerDyadic SLIT("plusInteger#")
 primOpInfo IntegerSubOp        = integerDyadic SLIT("minusInteger#")
 primOpInfo IntegerMulOp        = integerDyadic SLIT("timesInteger#")
+primOpInfo IntegerGcdOp        = integerDyadic SLIT("gcdInteger#")
 
 primOpInfo IntegerCmpOp        = integerCompare SLIT("cmpInteger#")
 
@@ -1015,31 +1057,36 @@ primOpInfo IntegerQuotRemOp = integerDyadic2Results SLIT("quotRemInteger#")
 primOpInfo IntegerDivModOp  = integerDyadic2Results SLIT("divModInteger#")
 
 primOpInfo Integer2IntOp
-  = PrimResult SLIT("integer2Int#") [] one_Integer_ty intPrimTyCon IntRep []
+  = GenPrimOp SLIT("integer2Int#") [] one_Integer_ty intPrimTy
 
 primOpInfo Integer2WordOp
-  = PrimResult SLIT("integer2Word#") [] one_Integer_ty wordPrimTyCon IntRep []
+  = GenPrimOp SLIT("integer2Word#") [] one_Integer_ty wordPrimTy
 
 primOpInfo Int2IntegerOp
-  = AlgResult SLIT("int2Integer#") [] [intPrimTy] integerTyCon []
+  = GenPrimOp SLIT("int2Integer#") [] [intPrimTy] 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
 primOpInfo Word2IntegerOp
-  = AlgResult SLIT("word2Integer#") [] [wordPrimTy] integerTyCon []
+  = GenPrimOp SLIT("word2Integer#") [] [wordPrimTy] 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
 primOpInfo Addr2IntegerOp
-  = AlgResult SLIT("addr2Integer#") [] [addrPrimTy] integerTyCon []
+  = GenPrimOp SLIT("addr2Integer#") [] [addrPrimTy] 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
 primOpInfo IntegerToInt64Op
-  = PrimResult SLIT("integerToInt64#") [] one_Integer_ty int64PrimTyCon Int64Rep []
+  = GenPrimOp SLIT("integerToInt64#") [] one_Integer_ty int64PrimTy
 
 primOpInfo Int64ToIntegerOp
-  = AlgResult SLIT("int64ToInteger#") [] [int64PrimTy] integerTyCon []
+  = GenPrimOp SLIT("int64ToInteger#") [] [int64PrimTy]
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
 primOpInfo Word64ToIntegerOp
-  = AlgResult SLIT("word64ToInteger#") [] [word64PrimTy] integerTyCon []
+  = GenPrimOp SLIT("word64ToInteger#") [] [word64PrimTy] 
+                       (unboxedTriple [intPrimTy, intPrimTy, byteArrayPrimTy])
 
 primOpInfo IntegerToWord64Op
-  = PrimResult SLIT("integerToWord64#") [] one_Integer_ty word64PrimTyCon Word64Rep []
+  = GenPrimOp SLIT("integerToWord64#") [] one_Integer_ty word64PrimTy
 \end{code}
 
 Encoding and decoding of floating-point numbers is sorta
@@ -1047,18 +1094,17 @@ Integer-related.
 
 \begin{code}
 primOpInfo FloatEncodeOp
-  = PrimResult SLIT("encodeFloat#") [] an_Integer_and_Int_tys
-        floatPrimTyCon FloatRep []
+  = GenPrimOp SLIT("encodeFloat#") [] an_Integer_and_Int_tys floatPrimTy
 
 primOpInfo DoubleEncodeOp
-  = PrimResult SLIT("encodeDouble#") [] an_Integer_and_Int_tys
-       doublePrimTyCon DoubleRep []
+  = GenPrimOp SLIT("encodeDouble#") [] an_Integer_and_Int_tys doublePrimTy
 
 primOpInfo FloatDecodeOp
-  = AlgResult SLIT("decodeFloat#") [] [floatPrimTy] returnIntAndGMPTyCon []
-
+  = GenPrimOp SLIT("decodeFloat#") [] [floatPrimTy] 
+       (unboxedQuadruple [intPrimTy, intPrimTy, intPrimTy, byteArrayPrimTy])
 primOpInfo DoubleDecodeOp
-  = AlgResult SLIT("decodeDouble#") [] [doublePrimTy] returnIntAndGMPTyCon []
+  = GenPrimOp SLIT("decodeDouble#") [] [doublePrimTy] 
+       (unboxedQuadruple [intPrimTy, intPrimTy, intPrimTy, byteArrayPrimTy])
 \end{code}
 
 %************************************************************************
@@ -1070,22 +1116,23 @@ primOpInfo DoubleDecodeOp
 \begin{code}
 primOpInfo NewArrayOp
   = let {
-       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
+       state = mkStatePrimTy s
     } in
-    AlgResult SLIT("newArray#") [s_tv, elt_tv] [intPrimTy, elt, mkStatePrimTy s]
-                               stateAndMutableArrayPrimTyCon [s, elt]
+    GenPrimOp SLIT("newArray#") [s_tv, elt_tv] 
+       [intPrimTy, elt, state]
+       (unboxedPair [state, mkMutableArrayPrimTy s elt])
 
 primOpInfo (NewByteArrayOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
 
-       (str, _, prim_tycon) = getPrimRepInfo kind
-
-       op_str         = _PK_ ("new" ++ str ++ "Array#")
+       op_str         = _PK_ ("new" ++ primRepString kind ++ "Array#")
+       state = mkStatePrimTy s
     in
-    AlgResult op_str [s_tv]
-       [intPrimTy, mkStatePrimTy s]
-       stateAndMutableByteArrayPrimTyCon [s]
+    GenPrimOp op_str [s_tv]
+       [intPrimTy, state]
+       (unboxedPair [state, mkMutableByteArrayPrimTy s])
 
 ---------------------------------------------------------------------------
 
@@ -1094,41 +1141,42 @@ primOpInfo SameMutableArrayOp
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
        mut_arr_ty = mkMutableArrayPrimTy s elt
     } in
-    AlgResult SLIT("sameMutableArray#") [s_tv, elt_tv] [mut_arr_ty, mut_arr_ty]
-                                  boolTyCon []
+    GenPrimOp SLIT("sameMutableArray#") [s_tv, elt_tv] [mut_arr_ty, mut_arr_ty]
+                                  boolTy
 
 primOpInfo SameMutableByteArrayOp
   = let {
        s = alphaTy; s_tv = alphaTyVar;
        mut_arr_ty = mkMutableByteArrayPrimTy s
     } in
-    AlgResult SLIT("sameMutableByteArray#") [s_tv] [mut_arr_ty, mut_arr_ty]
-                                  boolTyCon []
+    GenPrimOp SLIT("sameMutableByteArray#") [s_tv] [mut_arr_ty, mut_arr_ty]
+                                  boolTy
 
 ---------------------------------------------------------------------------
 -- Primitive arrays of Haskell pointers:
 
 primOpInfo ReadArrayOp
   = let {
-       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
+       state = mkStatePrimTy s
     } in
-    AlgResult SLIT("readArray#") [s_tv, elt_tv]
-       [mkMutableArrayPrimTy s elt, intPrimTy, mkStatePrimTy s]
-       stateAndPtrPrimTyCon [s, elt]
+    GenPrimOp SLIT("readArray#") [s_tv, elt_tv]
+       [mkMutableArrayPrimTy s elt, intPrimTy, state]
+       (unboxedPair [state, elt])
 
 
 primOpInfo WriteArrayOp
   = let {
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
     } in
-    PrimResult SLIT("writeArray#") [s_tv, elt_tv]
+    GenPrimOp SLIT("writeArray#") [s_tv, elt_tv]
        [mkMutableArrayPrimTy s elt, intPrimTy, elt, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+       (mkStatePrimTy s)
 
 primOpInfo IndexArrayOp
   = let { elt = alphaTy; elt_tv = alphaTyVar } in
-    AlgResult SLIT("indexArray#") [elt_tv] [mkArrayPrimTy elt, intPrimTy]
-                                  liftTyCon [elt]
+    GenPrimOp SLIT("indexArray#") [elt_tv] [mkArrayPrimTy elt, intPrimTy]
+       (unboxedPair [realWorldStatePrimTy, elt])
 
 ---------------------------------------------------------------------------
 -- Primitive arrays full of unboxed bytes:
@@ -1137,180 +1185,227 @@ primOpInfo (ReadByteArrayOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
 
-       (str, _, prim_tycon) = getPrimRepInfo kind
-
-       op_str         = _PK_ ("read" ++ str ++ "Array#")
-       relevant_tycon = (assoc "primOpInfo{ReadByteArrayOp}" tbl kind)
+       op_str         = _PK_ ("read" ++ primRepString kind ++ "Array#")
+       relevant_type  = assoc "primOpInfo{ReadByteArrayOp}" tbl kind
+       state          = mkStatePrimTy s
 
-        (tycon_args, tvs)
-         | kind == StablePtrRep = ([s, betaTy], [s_tv, betaTyVar])
-         | otherwise            = ([s], [s_tv])
+        tvs
+         | kind == StablePtrRep = [s_tv, betaTyVar]
+         | otherwise            = [s_tv]
     in
-    AlgResult op_str tvs
-       [mkMutableByteArrayPrimTy s, intPrimTy, mkStatePrimTy s]
-       relevant_tycon tycon_args
+    GenPrimOp op_str tvs
+       [mkMutableByteArrayPrimTy s, intPrimTy, state]
+       (unboxedPair [state, relevant_type])
   where
-    tbl = [ (CharRep,     stateAndCharPrimTyCon),
-           (IntRep,       stateAndIntPrimTyCon),
-           (WordRep,      stateAndWordPrimTyCon),
-           (AddrRep,      stateAndAddrPrimTyCon),
-           (FloatRep,     stateAndFloatPrimTyCon),
-           (StablePtrRep, stateAndStablePtrPrimTyCon),
-           (DoubleRep,    stateAndDoublePrimTyCon) ]
+    tbl = [ (CharRep,   charPrimTy),
+           (IntRep,     intPrimTy),
+           (WordRep,    wordPrimTy),
+           (AddrRep,    addrPrimTy),
+           (FloatRep,   floatPrimTy),
+           (StablePtrRep, mkStablePtrPrimTy betaTy),
+           (DoubleRep,  doublePrimTy) ]
 
   -- How come there's no Word byte arrays? ADR
 
 primOpInfo (WriteByteArrayOp kind)
   = let
        s = alphaTy; s_tv = alphaTyVar
-
-       (str, prim_ty, _) = getPrimRepInfo kind
-       op_str = _PK_ ("write" ++ str ++ "Array#")
+       op_str = _PK_ ("write" ++ primRepString kind ++ "Array#")
+       prim_ty = mkTyConApp (primRepTyCon kind) []
 
         (the_prim_ty, tvs)
          | kind == StablePtrRep = (mkStablePtrPrimTy betaTy, [s_tv, betaTyVar])
          | otherwise            = (prim_ty, [s_tv])
 
     in
-    -- NB: *Prim*Result --
-    PrimResult op_str tvs
+    GenPrimOp op_str tvs
        [mkMutableByteArrayPrimTy s, intPrimTy, the_prim_ty, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+       (mkStatePrimTy s)
 
 primOpInfo (IndexByteArrayOp kind)
   = let
-       (str, _, prim_tycon) = getPrimRepInfo kind
-       op_str = _PK_ ("index" ++ str ++ "Array#")
+       op_str = _PK_ ("index" ++ primRepString kind ++ "Array#")
 
         (prim_tycon_args, tvs)
          | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
          | otherwise            = ([],[])
     in
-    -- NB: *Prim*Result --
-    PrimResult op_str tvs [byteArrayPrimTy, intPrimTy] prim_tycon kind prim_tycon_args
+    GenPrimOp op_str tvs [byteArrayPrimTy, intPrimTy] 
+       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
 
-primOpInfo (IndexOffAddrOp kind)
+primOpInfo (IndexOffForeignObjOp kind)
   = let
-       (str, _, prim_tycon) = getPrimRepInfo kind
-       op_str = _PK_ ("index" ++ str ++ "OffAddr#")
+       op_str = _PK_ ("index" ++ primRepString kind ++ "OffForeignObj#")
 
         (prim_tycon_args, tvs)
          | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
          | otherwise            = ([], [])
     in
-    PrimResult op_str tvs [addrPrimTy, intPrimTy] prim_tycon kind prim_tycon_args
+    GenPrimOp op_str tvs [foreignObjPrimTy, intPrimTy] 
+       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
 
-primOpInfo (IndexOffForeignObjOp kind)
+primOpInfo (IndexOffAddrOp kind)
   = let
-       (str, _, prim_tycon) = getPrimRepInfo kind
-       op_str = _PK_ ("index" ++ str ++ "OffForeignObj#")
+       op_str = _PK_ ("index" ++ primRepString kind ++ "OffAddr#")
 
         (prim_tycon_args, tvs)
          | kind == StablePtrRep = ([alphaTy], [alphaTyVar])
          | otherwise            = ([], [])
     in
-    PrimResult op_str tvs [foreignObjPrimTy, intPrimTy] prim_tycon kind prim_tycon_args
+    GenPrimOp op_str tvs [addrPrimTy, intPrimTy] 
+       (mkTyConApp (primRepTyCon kind) prim_tycon_args)
 
 primOpInfo (WriteOffAddrOp kind)
   = let
-       s = betaTy; s_tv = betaTyVar
-
-       (str, prim_ty, _) = getPrimRepInfo kind
-       op_str = _PK_ ("write" ++ str ++ "OffAddr#")
-
-        tvs
-         | kind == StablePtrRep = [s_tv,alphaTyVar]
-         | otherwise            = [s_tv]
+       s = alphaTy; s_tv = alphaTyVar
+       op_str = _PK_ ("write" ++ primRepString kind ++ "OffAddr#")
+       prim_ty = mkTyConApp (primRepTyCon kind) []
     in
-    -- NB: *Prim*Result --
-    PrimResult op_str tvs
+    GenPrimOp op_str [s_tv]
        [addrPrimTy, intPrimTy, prim_ty, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+       (mkStatePrimTy s)
 
 ---------------------------------------------------------------------------
 primOpInfo UnsafeFreezeArrayOp
   = let {
-       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
+       state = mkStatePrimTy s
     } in
-    AlgResult SLIT("unsafeFreezeArray#") [s_tv, elt_tv]
-       [mkMutableArrayPrimTy s elt, mkStatePrimTy s]
-       stateAndArrayPrimTyCon [s, elt]
+    GenPrimOp SLIT("unsafeFreezeArray#") [s_tv, elt_tv]
+       [mkMutableArrayPrimTy s elt, state]
+       (unboxedPair [state, mkArrayPrimTy elt])
 
 primOpInfo UnsafeFreezeByteArrayOp
-  = let { s = alphaTy; s_tv = alphaTyVar } in
-    AlgResult SLIT("unsafeFreezeByteArray#") [s_tv]
-       [mkMutableByteArrayPrimTy s, mkStatePrimTy s]
-       stateAndByteArrayPrimTyCon [s]
+  = let { 
+       s = alphaTy; s_tv = alphaTyVar;
+       state = mkStatePrimTy s
+    } in
+    GenPrimOp SLIT("unsafeFreezeByteArray#") [s_tv]
+       [mkMutableByteArrayPrimTy s, state]
+       (unboxedPair [state, byteArrayPrimTy])
+
 ---------------------------------------------------------------------------
 primOpInfo SizeofByteArrayOp
-  = PrimResult 
+  = GenPrimOp
         SLIT("sizeofByteArray#") []
        [byteArrayPrimTy]
-        intPrimTyCon IntRep []
+        intPrimTy
 
 primOpInfo SizeofMutableByteArrayOp
   = let { s = alphaTy; s_tv = alphaTyVar } in
-    PrimResult 
+    GenPrimOp
         SLIT("sizeofMutableByteArray#") [s_tv]
        [mkMutableByteArrayPrimTy s]
-        intPrimTyCon IntRep []
-
+        intPrimTy
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsubsection[PrimOp-SynchVars]{PrimOpInfo for synchronizing Variables}
+\subsubsection[PrimOp-MutVars]{PrimOpInfo for mutable variable ops}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-primOpInfo NewSynchVarOp
+primOpInfo NewMutVarOp
   = let {
-       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
+       state = mkStatePrimTy s
     } in
-    AlgResult SLIT("newSynchVar#") [s_tv, elt_tv] [mkStatePrimTy s]
-                               stateAndSynchVarPrimTyCon [s, elt]
+    GenPrimOp SLIT("newMutVar#") [s_tv, elt_tv] 
+       [elt, state]
+       (unboxedPair [state, mkMutVarPrimTy s elt])
 
-primOpInfo SameMVarOp
+primOpInfo ReadMutVarOp
   = let {
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
-       mvar_ty = mkSynchVarPrimTy s elt
+       state = mkStatePrimTy s
     } in
-    AlgResult SLIT("sameMVar#") [s_tv, elt_tv] [mvar_ty, mvar_ty]
-       boolTyCon []
+    GenPrimOp SLIT("readMutVar#") [s_tv, elt_tv]
+       [mkMutVarPrimTy s elt, state]
+       (unboxedPair [state, elt])
 
-primOpInfo TakeMVarOp
+
+primOpInfo WriteMutVarOp
   = let {
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
     } in
-    AlgResult SLIT("takeMVar#") [s_tv, elt_tv]
-       [mkSynchVarPrimTy s elt, mkStatePrimTy s]
-       stateAndPtrPrimTyCon [s, elt]
+    GenPrimOp SLIT("writeMutVar#") [s_tv, elt_tv]
+       [mkMutVarPrimTy s elt, elt, mkStatePrimTy s]
+       (mkStatePrimTy s)
 
-primOpInfo PutMVarOp
+primOpInfo SameMutVarOp
   = let {
-       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar;
+       mut_var_ty = mkMutVarPrimTy s elt
     } in
-    AlgResult SLIT("putMVar#") [s_tv, elt_tv]
-       [mkSynchVarPrimTy s elt, elt, mkStatePrimTy s]
-       statePrimTyCon [s]
+    GenPrimOp SLIT("sameMutVar#") [s_tv, elt_tv] [mut_var_ty, mut_var_ty]
+                                  boolTy
+\end{code}
 
-primOpInfo ReadIVarOp
-  = let {
+%************************************************************************
+%*                                                                     *
+\subsubsection[PrimOp-Exceptions]{PrimOpInfo for exceptions}
+%*                                                                     *
+%************************************************************************
+
+catch :: IO a -> (IOError -> IO a) -> IO a
+catch :: a  -> (b -> a) -> a
+
+\begin{code}
+primOpInfo CatchOp   
+  = let
+       a = alphaTy; a_tv = alphaTyVar;
+       b = betaTy;  b_tv = betaTyVar;
+    in
+    GenPrimOp SLIT("catch#") [a_tv, b_tv] [a, mkFunTy b a] a
+
+primOpInfo RaiseOp
+  = let
+       a = alphaTy; a_tv = alphaTyVar;
+       b = betaTy;  b_tv = betaTyVar;
+    in
+    GenPrimOp SLIT("raise#") [a_tv, b_tv] [a] b
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsubsection[PrimOp-MVars]{PrimOpInfo for synchronizing Variables}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+primOpInfo NewMVarOp
+  = let
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
-    } in
-    AlgResult SLIT("readIVar#") [s_tv, elt_tv]
-       [mkSynchVarPrimTy s elt, mkStatePrimTy s]
-       stateAndPtrPrimTyCon [s, elt]
+       state = mkStatePrimTy s
+    in
+    GenPrimOp SLIT("newMVar#") [s_tv, elt_tv] [state]
+       (unboxedPair [state, mkMVarPrimTy s elt])
 
-primOpInfo WriteIVarOp
-  = let {
+primOpInfo TakeMVarOp
+  = let
        elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
-    } in
-    AlgResult SLIT("writeIVar#") [s_tv, elt_tv]
-       [mkSynchVarPrimTy s elt, elt, mkStatePrimTy s]
-       statePrimTyCon [s]
+       state = mkStatePrimTy s
+    in
+    GenPrimOp SLIT("takeMVar#") [s_tv, elt_tv]
+       [mkMVarPrimTy s elt, state]
+       (unboxedPair [state, elt])
 
+primOpInfo PutMVarOp
+  = let
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+    in
+    GenPrimOp SLIT("putMVar#") [s_tv, elt_tv]
+       [mkMVarPrimTy s elt, elt, mkStatePrimTy s]
+       (mkStatePrimTy s)
+
+primOpInfo SameMVarOp
+  = let
+       elt = alphaTy; elt_tv = alphaTyVar; s = betaTy; s_tv = betaTyVar
+       mvar_ty = mkMVarPrimTy s elt
+    in
+    GenPrimOp SLIT("sameMVar#") [s_tv, elt_tv] [mvar_ty, mvar_ty] boolTy
 \end{code}
 
 %************************************************************************
@@ -1325,88 +1420,105 @@ primOpInfo DelayOp
   = let {
        s = alphaTy; s_tv = alphaTyVar
     } in
-    PrimResult SLIT("delay#") [s_tv]
-       [intPrimTy, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+    GenPrimOp SLIT("delay#") [s_tv]
+       [intPrimTy, mkStatePrimTy s] (mkStatePrimTy s)
 
 primOpInfo WaitReadOp
   = let {
        s = alphaTy; s_tv = alphaTyVar
     } in
-    PrimResult SLIT("waitRead#") [s_tv]
-       [intPrimTy, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+    GenPrimOp SLIT("waitRead#") [s_tv]
+       [intPrimTy, mkStatePrimTy s] (mkStatePrimTy s)
 
 primOpInfo WaitWriteOp
   = let {
        s = alphaTy; s_tv = alphaTyVar
     } in
-    PrimResult SLIT("waitWrite#") [s_tv]
-       [intPrimTy, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+    GenPrimOp SLIT("waitWrite#") [s_tv]
+       [intPrimTy, mkStatePrimTy s] (mkStatePrimTy s)
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsubsection[PrimOps-ForeignObj]{PrimOpInfo for Foreign Objects}
+\subsubsection[PrimOp-Concurrency]{Concurrency Primitives}
 %*                                                                     *
 %************************************************************************
 
-Not everything should/can be in the Haskell heap. As an example, in an
-image processing application written in Haskell, you really would like
-to avoid heaving huge images between different space or generations of
-a garbage collector. Instead use @ForeignObj@ (formerly known as @MallocPtr@),
-which refer to some externally allocated structure/value. Using @ForeignObj@,
-just a reference to an image is present in the heap, the image could then
-be stored outside the Haskell heap, i.e., as a malloc'ed structure or in
-a completely separate address space alltogether. 
+\begin{code}
+-- fork# :: a -> State# RealWorld -> (# State# RealWorld, ThreadId# #)
+primOpInfo ForkOp      
+  = GenPrimOp SLIT("fork#") [alphaTyVar] 
+       [alphaTy, realWorldStatePrimTy]
+       (unboxedPair [realWorldStatePrimTy, threadIdPrimTy])
+
+-- killThread# :: ThreadId# -> State# RealWorld -> State# RealWorld
+primOpInfo KillThreadOp
+  = GenPrimOp SLIT("killThread#") [] 
+       [threadIdPrimTy, realWorldStatePrimTy]
+       realWorldStatePrimTy
+\end{code}
 
-When a @ForeignObj@ becomes garbage, a user-defined finalisation routine
-associated with the object is invoked (currently, each ForeignObj has a
-direct reference to its finaliser).  -- SOF
+************************************************************************
+%*                                                                     *
+\subsubsection[PrimOps-Foreign]{PrimOpInfo for Foreign Objects}
+%*                                                                     *
+%************************************************************************
 
-A @ForeignObj@ is created by the @makeForeignObj#@ primitive:
+\begin{code}
+primOpInfo MakeForeignObjOp
+  = GenPrimOp SLIT("makeForeignObj#") [] 
+       [addrPrimTy, realWorldStatePrimTy] 
+       (unboxedPair [realWorldStatePrimTy, foreignObjPrimTy])
 
-\begin{pseudocode}
-makeForeignObj# :: Addr#  -- foreign object
-                -> Addr#  -- ptr to its finaliser routine
-               -> StateAndForeignObj# _RealWorld# ForeignObj#
-\end{pseudocode}
+primOpInfo WriteForeignObjOp
+ = let {
+       s = alphaTy; s_tv = alphaTyVar
+    } in
+   GenPrimOp SLIT("writeForeignObj#") [s_tv]
+       [foreignObjPrimTy, addrPrimTy, mkStatePrimTy s] (mkStatePrimTy s)
+\end{code}
 
+************************************************************************
+%*                                                                     *
+\subsubsection[PrimOps-Weak]{PrimOpInfo for Weak Pointers}
+%*                                                                     *
+%************************************************************************
+
+A @Weak@ Pointer is created by the @mkWeak#@ primitive:
+
+       mkWeak# :: k -> v -> f -> State# RealWorld 
+                       -> (# State# RealWorld, Weak# v #)
+
+In practice, you'll use the higher-level
+
+       data Weak v = Weak# v
+       mkWeak :: k -> v -> IO () -> IO (Weak v)
 
 \begin{code}
-primOpInfo MakeForeignObjOp
-  = AlgResult SLIT("makeForeignObj#") [] 
-       [addrPrimTy, addrPrimTy, realWorldStatePrimTy] 
-       stateAndForeignObjPrimTyCon [realWorldTy]
+primOpInfo MkWeakOp
+  = GenPrimOp SLIT("mkWeak#") [alphaTyVar, betaTyVar, gammaTyVar] 
+       [alphaTy, betaTy, gammaTy, realWorldStatePrimTy]
+       (unboxedPair [realWorldStatePrimTy, mkWeakPrimTy betaTy])
 \end{code}
 
-[Experimental--SOF]
-In addition, another @ForeignObj@ primitive is provided for destructively modifying
-the external object wrapped up inside a @ForeignObj@. This primitive is used
-when a mixed programming interface of implicit and explicit de-allocation is used,
-e.g., if @ForeignObj@s are used to implement @Handle@s, then @Handle@s can be
-released either explicitly (through @hClose@) or implicitly (via a finaliser).
-When releasing/closing the @Handle@ explicitly, care must be taken to avoid having 
-the finaliser for the embedded @ForeignObj@ attempt the same thing later.
-We deal with this situation, by allowing the programmer to destructively modify
-the data field of the @ForeignObj@ to hold a special value the finaliser recognises,
-and does not attempt to free (e.g., filling the data slot with \tr{NULL}).
+The following operation dereferences a weak pointer.  The weak pointer
+may have been finalised, so the operation returns a result code which
+must be inspected before looking at the dereferenced value.
 
-\begin{pseudocode}
-writeForeignObj# :: ForeignObj#  -- foreign object
-                -> Addr#        -- new data value
-               -> StateAndForeignObj# _RealWorld# ForeignObj#
-\end{pseudocode}
+       deRefWeak# :: Weak# v -> State# RealWorld ->
+                       (# State# RealWorld, v, Int# #)
+
+Only look at v if the Int# returned is /= 0 !!
+
+The higher-level op is
+
+       deRefWeak :: Weak v -> IO (Maybe v)
 
 \begin{code}
-primOpInfo WriteForeignObjOp
- = let {
-       s = alphaTy; s_tv = alphaTyVar
-    } in
-   PrimResult SLIT("writeForeignObj#") [s_tv]
-       [foreignObjPrimTy, addrPrimTy, mkStatePrimTy s]
-       statePrimTyCon VoidRep [s]
+primOpInfo DeRefWeakOp
+ = GenPrimOp SLIT("deRefWeak#") [alphaTyVar]
+       [mkWeakPrimTy alphaTy, realWorldStatePrimTy]
+       (unboxedTriple [realWorldStatePrimTy, intPrimTy, alphaTy])
 \end{code}
 
 %************************************************************************
@@ -1424,9 +1536,10 @@ Here's what the operations and types are supposed to be (from
 state-interface document).
 
 \begin{verbatim}
-makeStablePtr#  :: a -> State# _RealWorld -> StateAndStablePtr# _RealWorld a
+makeStablePtr#  :: a -> State# _RealWorld -> (# State# _RealWorld, a #)
 freeStablePtr#  :: StablePtr# a -> State# _RealWorld -> State# _RealWorld
-deRefStablePtr# :: StablePtr# a -> State# _RealWorld -> StateAndPtr _RealWorld a
+deRefStablePtr# :: StablePtr# a -> State# _RealWorld -> (# State# _RealWorld, a #)
+eqStablePtr#    :: StablePtr# a -> StablePtr# a -> Int#
 \end{verbatim}
 
 It may seem a bit surprising that @makeStablePtr#@ is a @PrimIO@
@@ -1446,14 +1559,20 @@ Question: Why @_RealWorld@ - won't any instance of @_ST@ do the job? [ADR]
 
 \begin{code}
 primOpInfo MakeStablePtrOp
-  = AlgResult SLIT("makeStablePtr#") [alphaTyVar]
+  = GenPrimOp SLIT("makeStablePtr#") [alphaTyVar]
        [alphaTy, realWorldStatePrimTy]
-       stateAndStablePtrPrimTyCon [realWorldTy, alphaTy]
+       (unboxedPair [realWorldStatePrimTy, 
+                       mkTyConApp stablePtrPrimTyCon [alphaTy]])
 
 primOpInfo DeRefStablePtrOp
-  = AlgResult SLIT("deRefStablePtr#") [alphaTyVar]
+  = GenPrimOp SLIT("deRefStablePtr#") [alphaTyVar]
        [mkStablePtrPrimTy alphaTy, realWorldStatePrimTy]
-       stateAndPtrPrimTyCon [realWorldTy, alphaTy]
+       (unboxedPair [realWorldStatePrimTy, alphaTy])
+
+primOpInfo EqStablePtrOp
+  = GenPrimOp SLIT("eqStablePtr#") [alphaTyVar, betaTyVar]
+       [mkStablePtrPrimTy alphaTy, mkStablePtrPrimTy betaTy]
+       intPrimTy
 \end{code}
 
 %************************************************************************
@@ -1497,8 +1616,8 @@ removed...)
 
 \begin{code}
 primOpInfo ReallyUnsafePtrEqualityOp
-  = PrimResult SLIT("reallyUnsafePtrEquality#") [alphaTyVar]
-       [alphaTy, alphaTy] intPrimTyCon IntRep []
+  = GenPrimOp SLIT("reallyUnsafePtrEquality#") [alphaTyVar]
+       [alphaTy, alphaTy] intPrimTy
 \end{code}
 
 %************************************************************************
@@ -1509,14 +1628,10 @@ primOpInfo ReallyUnsafePtrEqualityOp
 
 \begin{code}
 primOpInfo SeqOp       -- seq# :: a -> Int#
-  = PrimResult SLIT("seq#")    [alphaTyVar] [alphaTy] intPrimTyCon IntRep []
+  = GenPrimOp SLIT("seq#")     [alphaTyVar] [alphaTy] intPrimTy
 
 primOpInfo ParOp       -- par# :: a -> Int#
-  = PrimResult SLIT("par#")    [alphaTyVar] [alphaTy] intPrimTyCon IntRep []
-
-primOpInfo ForkOp      -- fork# :: a -> Int#
-  = PrimResult SLIT("fork#")   [alphaTyVar] [alphaTy] intPrimTyCon IntRep []
-
+  = GenPrimOp SLIT("par#")     [alphaTyVar] [alphaTy] intPrimTy
 \end{code}
 
 \begin{code}
@@ -1525,42 +1640,28 @@ primOpInfo ForkOp       -- fork# :: a -> Int#
 --      Same  structure as _seq_ i.e. returns Int#
 
 primOpInfo ParGlobalOp -- parGlobal# :: Int# -> Int# -> Int# -> Int# -> a -> b -> b
-  = PrimResult SLIT("parGlobal#")      [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTyCon IntRep []   -- liftTyCon [betaTy]
+  = GenPrimOp SLIT("parGlobal#")       [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTy
 
 primOpInfo ParLocalOp  -- parLocal# :: Int# -> Int# -> Int# -> Int# -> a -> b -> b
-  = PrimResult SLIT("parLocal#")       [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTyCon IntRep []   -- liftTyCon [betaTy]
+  = GenPrimOp SLIT("parLocal#")        [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTy
 
 primOpInfo ParAtOp     -- parAt# :: Int# -> Int# -> Int# -> Int# -> a -> b -> c -> c
-  = PrimResult SLIT("parAt#")  [alphaTyVar,betaTyVar,gammaTyVar] [betaTy,alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,gammaTy] intPrimTyCon IntRep []   -- liftTyCon [gammaTy]
+  = GenPrimOp SLIT("parAt#")   [alphaTyVar,betaTyVar,gammaTyVar] [betaTy,alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,gammaTy] intPrimTy
 
 primOpInfo ParAtAbsOp  -- parAtAbs# :: Int# -> Int# -> Int# -> Int# -> Int# -> a -> b -> b
-  = PrimResult SLIT("parAtAbs#")       [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTyCon IntRep []   -- liftTyCon [betaTy]
+  = GenPrimOp SLIT("parAtAbs#")        [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTy
 
 primOpInfo ParAtRelOp  -- parAtRel# :: Int# -> Int# -> Int# -> Int# -> Int# -> a -> b -> b
-  = PrimResult SLIT("parAtRel#")       [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTyCon IntRep []   -- liftTyCon [betaTy]
+  = GenPrimOp SLIT("parAtRel#")        [alphaTyVar,betaTyVar] [alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,betaTy] intPrimTy
 
 primOpInfo ParAtForNowOp       -- parAtForNow# :: Int# -> Int# -> Int# -> Int# -> a -> b -> c -> c
-  = PrimResult SLIT("parAtForNow#")    [alphaTyVar,betaTyVar,gammaTyVar] [betaTy,alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,gammaTy] intPrimTyCon IntRep []   -- liftTyCon [gammaTy]
+  = GenPrimOp SLIT("parAtForNow#")     [alphaTyVar,betaTyVar,gammaTyVar] [betaTy,alphaTy,intPrimTy,intPrimTy,intPrimTy,intPrimTy,gammaTy] intPrimTy
 
 primOpInfo CopyableOp  -- copyable# :: a -> a
-  = PrimResult SLIT("copyable#")       [alphaTyVar] [alphaTy] intPrimTyCon IntRep []   -- liftTyCon [alphaTy]
+  = GenPrimOp SLIT("copyable#")        [alphaTyVar] [alphaTy] intPrimTy
 
 primOpInfo NoFollowOp  -- noFollow# :: a -> a
-  = PrimResult SLIT("noFollow#")       [alphaTyVar] [alphaTy] intPrimTyCon IntRep []   -- liftTyCon [alphaTy]
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsubsection[PrimOp-errorIO]{PrimOpInfo for @errorIO#@}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
--- errorIO# :: (State# RealWorld# -> a) -> State# RealWorld#
-primOpInfo ErrorIOPrimOp
-  = PrimResult SLIT("errorIO#") [alphaTyVar]
-       [mkFunTy realWorldStatePrimTy alphaTy]
-       statePrimTyCon VoidRep [realWorldTy]
+  = GenPrimOp SLIT("noFollow#")        [alphaTyVar] [alphaTy] intPrimTy
 \end{code}
 
 %************************************************************************
@@ -1570,157 +1671,58 @@ primOpInfo ErrorIOPrimOp
 %************************************************************************
 
 \begin{code}
+primOpInfo (CCallOp _ _ _ _)
+     = GenPrimOp SLIT("ccall#") [alphaTyVar] [] alphaTy
+
+{-
 primOpInfo (CCallOp _ _ _ _ arg_tys result_ty)
-  = AlgResult SLIT("ccall#") [] arg_tys result_tycon tys_applied
+  = GenPrimOp SLIT("ccall#") [] arg_tys result_tycon tys_applied
   where
     (result_tycon, tys_applied, _) = splitAlgTyConApp result_ty
-
+-}
 #ifdef DEBUG
 primOpInfo op = panic ("primOpInfo:"++ show (I# (tagOf_PrimOp op)))
 #endif
 \end{code}
 
-%************************************************************************
-%*                                                                     *
-\subsection[PrimOp-utils]{Utilities for @PrimitiveOps@}
-%*                                                                     *
-%************************************************************************
-
-The primitive-array-creation @PrimOps@ and {\em most} of those to do
-with @Integers@ can trigger GC.  Here we describe the heap requirements
-of the various @PrimOps@.  For most, no heap is required.  For a few,
-a fixed amount of heap is required, and the needs of the @PrimOp@ can
-be combined with the rest of the heap usage in the basic block.  For an
-unfortunate few, some unknown amount of heap is required (these are the
-ops which can trigger GC).
+Some PrimOps need to be called out-of-line because they either need to
+perform a heap check or they block.
 
 \begin{code}
-data HeapRequirement
-    = NoHeapRequired
-    | FixedHeapRequired HeapOffset
-    | VariableHeapRequired
-
-primOpHeapReq :: PrimOp -> HeapRequirement
-
-primOpHeapReq NewArrayOp       = VariableHeapRequired
-primOpHeapReq (NewByteArrayOp _)= VariableHeapRequired
-
-primOpHeapReq IntegerAddOp     = VariableHeapRequired
-primOpHeapReq IntegerSubOp     = VariableHeapRequired
-primOpHeapReq IntegerMulOp     = VariableHeapRequired
-primOpHeapReq IntegerQuotRemOp = VariableHeapRequired
-primOpHeapReq IntegerDivModOp  = VariableHeapRequired
-primOpHeapReq IntegerNegOp     = VariableHeapRequired
-primOpHeapReq Int2IntegerOp    = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq Word2IntegerOp   = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq Addr2IntegerOp   = VariableHeapRequired
-primOpHeapReq IntegerToInt64Op = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq Word64ToIntegerOp        = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq Int64ToIntegerOp = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq IntegerToWord64Op        = FixedHeapRequired
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE))
-primOpHeapReq FloatDecodeOp    = FixedHeapRequired
-                                 (addOff (intOff (getPrimRepSize IntRep + mP_STRUCT_SIZE))
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE)))
-primOpHeapReq DoubleDecodeOp   = FixedHeapRequired
-                                 (addOff (intOff (getPrimRepSize IntRep + mP_STRUCT_SIZE))
-                                 (addOff (totHdrSize (DataRep mIN_MP_INT_SIZE))
-                                         (intOff mIN_MP_INT_SIZE)))
-
-{-
-  ccall may allocate heap if it is explicitly allowed to (_ccall_gc_)
-  or if it returns a ForeignObj.
-
-  Hmm..the allocation for makeForeignObj# is known (and fixed), so
-  why do we need to be so indeterminate about it? --SOF
--}
-primOpHeapReq (CCallOp _ _ mayGC@True  _ _ _) = VariableHeapRequired
-primOpHeapReq (CCallOp _ _ mayGC@False _ _ _) = NoHeapRequired
-
-primOpHeapReq MakeForeignObjOp = VariableHeapRequired
-primOpHeapReq WriteForeignObjOp        = NoHeapRequired
-
--- this occasionally has to expand the Stable Pointer table
-primOpHeapReq MakeStablePtrOp  = VariableHeapRequired
-
--- These four only need heap space with the native code generator
--- ToDo!: parameterize, so we know if native code generation is taking place(JSM)
-
-primOpHeapReq IntegerCmpOp     = FixedHeapRequired (intOff (2 * mP_STRUCT_SIZE))
-primOpHeapReq Integer2IntOp            = FixedHeapRequired (intOff mP_STRUCT_SIZE)
-primOpHeapReq Integer2WordOp           = FixedHeapRequired (intOff mP_STRUCT_SIZE)
-primOpHeapReq FloatEncodeOp            = FixedHeapRequired (intOff mP_STRUCT_SIZE)
-primOpHeapReq DoubleEncodeOp           = FixedHeapRequired (intOff mP_STRUCT_SIZE)
-
--- a NewSynchVarOp creates a three-word mutuple in the heap.
-primOpHeapReq NewSynchVarOp    = FixedHeapRequired
-                                 (addOff (totHdrSize (MuTupleRep 3)) (intOff 3))
-
--- Sparking ops no longer allocate any heap; however, _fork_ may
--- require a context switch to clear space in the required thread
--- pool, and that requires liveness information.
-
-primOpHeapReq ParOp            = NoHeapRequired
-primOpHeapReq ForkOp           = VariableHeapRequired
-
--- A SeqOp requires unknown space to evaluate its argument
-primOpHeapReq SeqOp            = VariableHeapRequired
-
--- GranSim sparks are stgMalloced i.e. no heap required
-primOpHeapReq ParGlobalOp      = NoHeapRequired
-primOpHeapReq ParLocalOp       = NoHeapRequired
-primOpHeapReq ParAtOp          = NoHeapRequired
-primOpHeapReq ParAtAbsOp       = NoHeapRequired
-primOpHeapReq ParAtRelOp       = NoHeapRequired
-primOpHeapReq ParAtForNowOp    = NoHeapRequired
--- CopyableOp and NoFolowOp don't require heap; don't rely on default
-primOpHeapReq CopyableOp       = NoHeapRequired
-primOpHeapReq NoFollowOp       = NoHeapRequired
-
-primOpHeapReq other_op         = NoHeapRequired
-\end{code}
-
-The amount of stack required by primops.
-
-\begin{code}
-data StackRequirement
-  = NoStackRequired 
-  | FixedStackRequired Int {-AStack-} Int {-BStack-}
-  | VariableStackRequired
-     
-primOpStackRequired SeqOp = FixedStackRequired 0 {-AStack-} 2 {-BStack-}
-primOpStackRequired _     = VariableStackRequired 
--- ToDo: be more specific for certain primops (currently only used for seq)
-\end{code}
-
-Primops which can trigger GC have to be called carefully.
-In particular, their arguments are guaranteed to be in registers,
-and a liveness mask tells which regs are live.
-
-\begin{code}
-primOpCanTriggerGC op
+primOpOutOfLine op
   = case op of
-       TakeMVarOp  -> True
-       ReadIVarOp  -> True
-       DelayOp     -> True
-       WaitReadOp  -> True
-       WaitWriteOp -> True
-       _           ->
-           case primOpHeapReq op of
-               VariableHeapRequired -> True
-               _                    -> False
+       TakeMVarOp              -> True
+       PutMVarOp               -> True
+       DelayOp                 -> True
+       WaitReadOp              -> True
+       WaitWriteOp             -> True
+       CatchOp                 -> True
+       RaiseOp                 -> True
+       NewArrayOp              -> True
+       NewByteArrayOp _        -> True
+       IntegerAddOp            -> True
+       IntegerSubOp            -> True
+       IntegerMulOp            -> True
+       IntegerGcdOp            -> True
+       IntegerQuotRemOp        -> True
+       IntegerDivModOp         -> True
+       Int2IntegerOp           -> True
+       Word2IntegerOp          -> True
+       Addr2IntegerOp          -> True
+       Word64ToIntegerOp       -> True
+       Int64ToIntegerOp        -> True
+       FloatDecodeOp           -> True
+       DoubleDecodeOp          -> True
+       MkWeakOp                -> True
+       DeRefWeakOp             -> True
+       MakeForeignObjOp        -> True
+       MakeStablePtrOp         -> True
+       NewMutVarOp             -> True
+       NewMVarOp               -> True
+       ForkOp                  -> True
+       KillThreadOp            -> True
+       CCallOp _ _ may_gc@True _ -> True       -- _ccall_GC_
+       _                       -> False
 \end{code}
 
 Sometimes we may choose to execute a PrimOp even though it isn't
@@ -1731,117 +1733,100 @@ this is OK, because PrimOps are usually cheap, but it isn't OK for
 
 See also @primOpIsCheap@ (below).
 
-There should be no worries about side effects; that's all taken care
-of by data dependencies.
+PrimOps that have side effects also should not be executed speculatively
+or by data dependencies.
 
 \begin{code}
 primOpOkForSpeculation :: PrimOp -> Bool
+primOpOkForSpeculation op 
+  = not (primOpCanFail op || primOpHasSideEffects op || primOpOutOfLine op)
+\end{code}
+
+@primOpIsCheap@, as used in \tr{SimplUtils.lhs}.  For now (HACK
+WARNING), we just borrow some other predicates for a
+what-should-be-good-enough test.  "Cheap" means willing to call it more
+than once.  Evaluation order is unaffected.
 
+\begin{code}
+primOpIsCheap op = not (primOpHasSideEffects op || primOpOutOfLine op)
+\end{code}
+
+\begin{code}
+primOpCanFail :: PrimOp -> Bool
 -- Int.
-primOpOkForSpeculation IntQuotOp       = False         -- Divide by zero
-primOpOkForSpeculation IntRemOp                = False         -- Divide by zero
+primOpCanFail IntQuotOp        = True          -- Divide by zero
+primOpCanFail IntRemOp         = True          -- Divide by zero
 
 -- Integer
-primOpOkForSpeculation IntegerQuotRemOp = False                -- Divide by zero
-primOpOkForSpeculation IntegerDivModOp = False         -- Divide by zero
+primOpCanFail IntegerQuotRemOp = True          -- Divide by zero
+primOpCanFail IntegerDivModOp  = True          -- Divide by zero
 
 -- Float.  ToDo: tan? tanh?
-primOpOkForSpeculation FloatDivOp      = False         -- Divide by zero
-primOpOkForSpeculation FloatLogOp      = False         -- Log of zero
-primOpOkForSpeculation FloatAsinOp     = False         -- Arg out of domain
-primOpOkForSpeculation FloatAcosOp     = False         -- Arg out of domain
+primOpCanFail FloatDivOp       = True          -- Divide by zero
+primOpCanFail FloatLogOp       = True          -- Log of zero
+primOpCanFail FloatAsinOp      = True          -- Arg out of domain
+primOpCanFail FloatAcosOp      = True          -- Arg out of domain
 
 -- Double.  ToDo: tan? tanh?
-primOpOkForSpeculation DoubleDivOp     = False         -- Divide by zero
-primOpOkForSpeculation DoubleLogOp     = False         -- Log of zero
-primOpOkForSpeculation DoubleAsinOp    = False         -- Arg out of domain
-primOpOkForSpeculation DoubleAcosOp    = False         -- Arg out of domain
-
--- CCall
-primOpOkForSpeculation (CCallOp        _ _ _ _ _ _) = False    -- Could be expensive!
-
--- errorIO#
-primOpOkForSpeculation ErrorIOPrimOp   = False         -- Could be disastrous!
-
--- parallel
-primOpOkForSpeculation ParOp           = False         -- Could be expensive!
-primOpOkForSpeculation ForkOp          = False         -- Likewise
-primOpOkForSpeculation SeqOp           = False         -- Likewise
-
-primOpOkForSpeculation ParGlobalOp     = False         -- Could be expensive!
-primOpOkForSpeculation ParLocalOp      = False         -- Could be expensive!
-primOpOkForSpeculation ParAtOp         = False         -- Could be expensive!
-primOpOkForSpeculation ParAtAbsOp      = False         -- Could be expensive!
-primOpOkForSpeculation ParAtRelOp      = False         -- Could be expensive!
-primOpOkForSpeculation ParAtForNowOp   = False         -- Could be expensive!
-primOpOkForSpeculation CopyableOp      = False         -- only tags closure
-primOpOkForSpeculation NoFollowOp      = False         -- only tags closure
+primOpCanFail DoubleDivOp      = True          -- Divide by zero
+primOpCanFail DoubleLogOp      = True          -- Log of zero
+primOpCanFail DoubleAsinOp     = True          -- Arg out of domain
+primOpCanFail DoubleAcosOp     = True          -- Arg out of domain
 
 -- The default is "yes it's ok for speculation"
-primOpOkForSpeculation other_op                = True
-\end{code}
-
-@primOpIsCheap@, as used in \tr{SimplUtils.lhs}.  For now (HACK
-WARNING), we just borrow some other predicates for a
-what-should-be-good-enough test.
-\begin{code}
-primOpIsCheap op
-  = primOpOkForSpeculation op && not (primOpCanTriggerGC op)
+primOpCanFail other_op         = True
 \end{code}
 
 And some primops have side-effects and so, for example, must not be
 duplicated.
 
 \begin{code}
-fragilePrimOp :: PrimOp -> Bool
-
-fragilePrimOp ParOp = True
-fragilePrimOp ForkOp = True
-fragilePrimOp SeqOp = True
-fragilePrimOp MakeForeignObjOp  = True  -- SOF
-fragilePrimOp WriteForeignObjOp = True  -- SOF
-fragilePrimOp MakeStablePtrOp  = True
-fragilePrimOp DeRefStablePtrOp = True  -- ??? JSM & ADR
-
-fragilePrimOp ParGlobalOp = True
-fragilePrimOp ParLocalOp = True
-fragilePrimOp ParAtOp = True
-fragilePrimOp ParAtAbsOp = True
-fragilePrimOp ParAtRelOp = True
-fragilePrimOp ParAtForNowOp = True
-fragilePrimOp CopyableOp = True  -- Possibly not.  ASP 
-fragilePrimOp NoFollowOp = True  -- Possibly not.  ASP
-
-fragilePrimOp other = False
+primOpHasSideEffects :: PrimOp -> Bool
+
+primOpHasSideEffects TakeMVarOp        = True
+primOpHasSideEffects DelayOp           = True
+primOpHasSideEffects WaitReadOp        = True
+primOpHasSideEffects WaitWriteOp       = True
+
+primOpHasSideEffects ParOp            = True
+primOpHasSideEffects ForkOp           = True
+primOpHasSideEffects KillThreadOp      = True
+primOpHasSideEffects SeqOp            = True
+
+primOpHasSideEffects MakeForeignObjOp  = True
+primOpHasSideEffects WriteForeignObjOp = True
+primOpHasSideEffects MkWeakOp                 = True
+primOpHasSideEffects DeRefWeakOp       = True
+primOpHasSideEffects MakeStablePtrOp   = True
+primOpHasSideEffects EqStablePtrOp     = True  -- SOF
+primOpHasSideEffects DeRefStablePtrOp  = True  -- ??? JSM & ADR
+
+primOpHasSideEffects ParGlobalOp       = True
+primOpHasSideEffects ParLocalOp                = True
+primOpHasSideEffects ParAtOp           = True
+primOpHasSideEffects ParAtAbsOp                = True
+primOpHasSideEffects ParAtRelOp                = True
+primOpHasSideEffects ParAtForNowOp     = True
+primOpHasSideEffects CopyableOp                = True  -- Possibly not.  ASP 
+primOpHasSideEffects NoFollowOp                = True  -- Possibly not.  ASP
+
+-- CCall
+primOpHasSideEffects (CCallOp  _ _ _ _) = True
+
+primOpHasSideEffects other = False
 \end{code}
 
-Primitive operations that perform calls need wrappers to save any live variables
-that are stored in caller-saves registers
+Inline primitive operations that perform calls need wrappers to save
+any live variables that are stored in caller-saves registers.
 
 \begin{code}
 primOpNeedsWrapper :: PrimOp -> Bool
 
-primOpNeedsWrapper (CCallOp _ _ _ _ _ _) = True
-
-primOpNeedsWrapper NewArrayOp           = True -- ToDo: for nativeGen only!(JSM)
-primOpNeedsWrapper (NewByteArrayOp _)           = True
-
-primOpNeedsWrapper IntegerAddOp                 = True
-primOpNeedsWrapper IntegerSubOp                 = True
-primOpNeedsWrapper IntegerMulOp                 = True
-primOpNeedsWrapper IntegerQuotRemOp     = True
-primOpNeedsWrapper IntegerDivModOp      = True
-primOpNeedsWrapper IntegerNegOp                 = True
-primOpNeedsWrapper IntegerCmpOp                 = True
-primOpNeedsWrapper Integer2IntOp        = True
-primOpNeedsWrapper Integer2WordOp       = True
-primOpNeedsWrapper Int2IntegerOp        = True
-primOpNeedsWrapper Word2IntegerOp       = True
-primOpNeedsWrapper Addr2IntegerOp       = True
-primOpNeedsWrapper IntegerToInt64Op     = True
-primOpNeedsWrapper IntegerToWord64Op    = True
-primOpNeedsWrapper Word64ToIntegerOp    = True
-primOpNeedsWrapper Int64ToIntegerOp     = True
+primOpNeedsWrapper (CCallOp _ _ _ _)    = True
+
+primOpNeedsWrapper Integer2IntOp       = True
+primOpNeedsWrapper Integer2WordOp      = True
+primOpNeedsWrapper IntegerCmpOp                = True
 
 primOpNeedsWrapper FloatExpOp          = True
 primOpNeedsWrapper FloatLogOp          = True
@@ -1856,8 +1841,7 @@ primOpNeedsWrapper FloatSinhOp            = True
 primOpNeedsWrapper FloatCoshOp         = True
 primOpNeedsWrapper FloatTanhOp         = True
 primOpNeedsWrapper FloatPowerOp                = True
-primOpNeedsWrapper FloatEncodeOp       = True
-primOpNeedsWrapper FloatDecodeOp       = True
+primOpNeedsWrapper FloatEncodeOp       = True
 
 primOpNeedsWrapper DoubleExpOp         = True
 primOpNeedsWrapper DoubleLogOp         = True
@@ -1872,18 +1856,11 @@ primOpNeedsWrapper DoubleSinhOp         = True
 primOpNeedsWrapper DoubleCoshOp                = True
 primOpNeedsWrapper DoubleTanhOp                = True
 primOpNeedsWrapper DoublePowerOp       = True
-primOpNeedsWrapper DoubleEncodeOp      = True
-primOpNeedsWrapper DoubleDecodeOp      = True
+primOpNeedsWrapper DoubleEncodeOp      = True
 
-primOpNeedsWrapper MakeForeignObjOp    = True
-primOpNeedsWrapper WriteForeignObjOp   = True
 primOpNeedsWrapper MakeStablePtrOp     = True
 primOpNeedsWrapper DeRefStablePtrOp    = True
 
-primOpNeedsWrapper TakeMVarOp          = True
-primOpNeedsWrapper PutMVarOp           = True
-primOpNeedsWrapper ReadIVarOp          = True
-
 primOpNeedsWrapper DelayOp             = True
 primOpNeedsWrapper WaitReadOp          = True
 primOpNeedsWrapper WaitWriteOp         = True
@@ -1892,33 +1869,27 @@ primOpNeedsWrapper other_op             = False
 \end{code}
 
 \begin{code}
-primOp_str op
+primOpStr op
   = case (primOpInfo op) of
       Dyadic     str _        -> str
       Monadic    str _        -> str
       Compare    str _        -> str
-      Coercing   str _ _       -> str
-      PrimResult str _ _ _ _ _ -> str
-      AlgResult  str _ _ _ _   -> str
+      GenPrimOp  str _ _ _     -> str
 \end{code}
 
-@primOpType@ duplicates some work of @primOpId@, but since we
-grab types pretty often...
 \begin{code}
-primOpType :: PrimOp -> Type
+primOpUniq :: PrimOp -> Unique
+primOpUniq op = mkPrimOpIdUnique (IBOX(tagOf_PrimOp op))
 
+primOpType :: PrimOp -> Type
 primOpType op
   = case (primOpInfo op) of
       Dyadic str ty ->     dyadic_fun_ty ty
       Monadic str ty ->            monadic_fun_ty ty
       Compare str ty ->            compare_fun_ty ty
-      Coercing str ty1 ty2 -> mkFunTy ty1 ty2
 
-      PrimResult str tyvars arg_tys prim_tycon kind res_tys ->
-       mkForAllTys tyvars (mkFunTys arg_tys (mkTyConApp prim_tycon res_tys))
-
-      AlgResult str tyvars arg_tys tycon res_tys ->
-       mkForAllTys tyvars (mkFunTys arg_tys (mkTyConApp tycon res_tys))
+      GenPrimOp str tyvars arg_tys res_ty -> 
+       mkForAllTys tyvars (mkFunTys arg_tys res_ty)
 \end{code}
 
 \begin{code}
@@ -1926,8 +1897,9 @@ data PrimOpResultInfo
   = ReturnsPrim            PrimRep
   | ReturnsAlg     TyCon
 
--- ToDo: Deal with specialised PrimOps
---      Will need to return specialised tycon and data constructors
+-- Some PrimOps need not return a manifest primitive or algebraic value
+-- (i.e. they might return a polymorphic value).  These PrimOps *must*
+-- be out of line, or the code generator won't work.
 
 getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo
 
@@ -1936,9 +1908,13 @@ getPrimOpResultInfo op
       Dyadic  _ ty              -> ReturnsPrim (typePrimRep ty)
       Monadic _ ty              -> ReturnsPrim (typePrimRep ty)
       Compare _ ty              -> ReturnsAlg  boolTyCon
-      Coercing  _ _ ty          -> ReturnsPrim (typePrimRep ty)
-      PrimResult _ _ _ _ kind _         -> ReturnsPrim kind
-      AlgResult _ _ _ tycon _   -> ReturnsAlg  tycon
+      GenPrimOp _ _ _ ty        -> 
+       let rep = typePrimRep ty in
+       case rep of
+          PtrRep -> case splitAlgTyConApp_maybe ty of
+                       Nothing -> panic "getPrimOpResultInfo"
+                       Just (tc,_,_) -> ReturnsAlg tc
+          other -> ReturnsPrim other
 
 isCompareOp :: PrimOp -> Bool
 
@@ -1965,6 +1941,7 @@ commutableOp IntEqOp        = True
 commutableOp IntNeOp     = True
 commutableOp IntegerAddOp = True
 commutableOp IntegerMulOp = True
+commutableOp IntegerGcdOp = True
 commutableOp FloatAddOp          = True
 commutableOp FloatMulOp          = True
 commutableOp FloatEqOp   = True
@@ -1986,27 +1963,21 @@ compare_fun_ty ty = mkFunTys [ty, ty] boolTy
 Output stuff:
 \begin{code}
 pprPrimOp  :: PrimOp -> SDoc
-showPrimOp :: PrimOp -> String
-
-showPrimOp op = showSDoc (pprPrimOp op)
 
-pprPrimOp (CCallOp fun is_casm may_gc cconv arg_tys res_ty)
+pprPrimOp (CCallOp fun is_casm may_gc cconv)
   = let
         callconv = text "{-" <> pprCallConv cconv <> text "-}"
 
        before
-         | is_casm && may_gc = "_casm_GC_ ``"
-         | is_casm           = "_casm_ ``"
-         | may_gc            = "_ccall_GC_ "
-         | otherwise         = "_ccall_ "
+         | is_casm && may_gc = "__casm_GC ``"
+         | is_casm           = "__casm ``"
+         | may_gc            = "__ccall_GC "
+         | otherwise         = "__ccall "
 
        after
          | is_casm   = text "''"
          | otherwise = empty
 
-       pp_tys
-         = hsep (map pprParendType (res_ty:arg_tys))
-
        ppr_fun =
         case fun of
           Right _ -> ptext SLIT("<dynamic>")
@@ -2014,7 +1985,7 @@ pprPrimOp (CCallOp fun is_casm may_gc cconv arg_tys res_ty)
         
     in
     hcat [ ifPprDebug callconv
-         , text before , ppr_fun , after, space, brackets pp_tys]
+         , text before , ppr_fun , after]
 
 pprPrimOp other_op
   = getPprStyle $ \ sty ->
@@ -2025,9 +1996,5 @@ pprPrimOp other_op
     else                       -- Unqualified is good enough
        ptext str
   where
-    str = primOp_str other_op
-
-
-instance Outputable PrimOp where
-    ppr op = pprPrimOp op
+    str = primOpStr other_op
 \end{code}