[project @ 2001-12-05 17:35:12 by sewardj]
authorsewardj <unknown>
Wed, 5 Dec 2001 17:35:15 +0000 (17:35 +0000)
committersewardj <unknown>
Wed, 5 Dec 2001 17:35:15 +0000 (17:35 +0000)
--------------------------------------------
        Translate out PrimOps at the AbstractC level
        --------------------------------------------

This is the first in what might be a series of changes intended
to make GHC less dependent on its C back end.  The main change is
to translate PrimOps into vanilla abstract C inside the compiler,
rather than having to duplicate that work in each code generation
route.  The main changes are:

* A new type, MachOp, in compiler/absCSyn/MachOp.hs.  A MachOp
  is a primitive operation which we can reasonably expect the
  native code generators to implement.  The set is quite small
  and unlikely to change much, if at all.

* Translations from PrimOps to MachOps, at the end of
  absCSyn/AbsCUtils.  This should perhaps be moved to a different
  module, but it is hard to see how to do this without creating
  a circular dep between it and AbsCUtils.

* The x86 insn selector has been updated to track these changes.  The
  sparc insn selector remains to be done.

As a result of this, it is possible to compile much more code via the
NCG than before.  Almost all the Prelude can be compiled with it.
Currently it does not know how to do 64-bit code generation.  Once
this is fixed, the entire Prelude should be compilable that way.

I also took the opportunity to clean up the NCG infrastructure.
The old Stix data type has been split into StixStmt (statements)
and StixExpr (now denoting values only).  This removes a class
of impossible constructions and clarifies the NCG.

Still to do, in no particular order:

* String and literal lifting, currently done in the NCG at the top
  of nativeGen/MachCode, should be done in the AbstractC flattener,
  for the benefit of all targets.

* Further cleaning up of Stix assignments.

* Remove word-size dependency from Abstract C.  (should be easy).

* Translate out MagicIds in the AbsC -> Stix translation, not
  in the Stix constant folder. (!)

Testsuite failures caused by this:

* memo001 - fails (segfaults) for some unknown reason now.
* arith003 - wrong answer in gcdInt boundary cases.
* arith011 - wrong answer for shifts >= word size.
* cg044 - wrong answer for some FP boundary cases.

These should be fixed, but I don't think they are mission-critical for
anyone.

33 files changed:
ghc/compiler/absCSyn/AbsCSyn.lhs
ghc/compiler/absCSyn/AbsCUtils.lhs
ghc/compiler/absCSyn/CLabel.lhs
ghc/compiler/absCSyn/MachOp.hs [new file with mode: 0644]
ghc/compiler/absCSyn/PprAbsC.lhs
ghc/compiler/codeGen/CgCase.lhs
ghc/compiler/main/ErrUtils.lhs
ghc/compiler/nativeGen/AbsCStixGen.lhs
ghc/compiler/nativeGen/AsmCodeGen.lhs
ghc/compiler/nativeGen/MachCode.lhs
ghc/compiler/nativeGen/MachMisc.lhs
ghc/compiler/nativeGen/MachRegs.lhs
ghc/compiler/nativeGen/PprMach.lhs
ghc/compiler/nativeGen/RegAllocInfo.lhs
ghc/compiler/nativeGen/Stix.lhs
ghc/compiler/nativeGen/StixInfo.lhs
ghc/compiler/nativeGen/StixInteger.lhs [deleted file]
ghc/compiler/nativeGen/StixMacro.lhs
ghc/compiler/nativeGen/StixPrim.hi-boot
ghc/compiler/nativeGen/StixPrim.hi-boot-5
ghc/compiler/nativeGen/StixPrim.lhs
ghc/compiler/prelude/PrimOp.lhs
ghc/compiler/prelude/PrimRep.lhs
ghc/compiler/prelude/primops.txt.pp
ghc/compiler/utils/Maybes.lhs
ghc/includes/PrimOps.h
ghc/includes/Stg.h
ghc/lib/std/PrelGHC.hi-boot.pp
ghc/lib/std/PrelInt.lhs
ghc/lib/std/PrelWord.lhs
ghc/lib/std/cbits/longlong.c
ghc/rts/Exception.hc
ghc/rts/PrimOps.hc

index 977027d..a850a9f 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: AbsCSyn.lhs,v 1.40 2001/11/23 11:58:00 simonmar Exp $
+% $Id: AbsCSyn.lhs,v 1.41 2001/12/05 17:35:12 sewardj Exp $
 %
 \section[AbstractC]{Abstract C: the last stop before machine code}
 
@@ -47,12 +47,15 @@ import CostCentre       ( CostCentre, CostCentreStack )
 import Literal         ( mkMachInt, Literal(..) )
 import ForeignCall     ( CCallSpec )
 import PrimRep         ( PrimRep(..) )
+import MachOp          ( MachOp(..) )
 import Unique           ( Unique )
 import StgSyn          ( StgOp )
 import TyCon           ( TyCon )
 import BitSet                          -- for liveness masks
+import Maybes          ( Maybe012(..) )
 import FastTypes
 
+import Outputable
 \end{code}
 
 @AbstractC@ is a list of Abstract~C statements, but the data structure
@@ -117,6 +120,25 @@ stored in a mixed type location.)
                        --   CReg CurCostCentre or CC_HDR(R1.p{-Node-})
        Int             -- size of closure, for profiling
 
+  -- NEW CASES FOR EXPANDED PRIMOPS
+
+  | CMachOpStmt                        -- Machine-level operation
+       (Maybe012 CAddrMode)    -- 0, 1 or 2 results
+       MachOp
+       [CAddrMode]             -- Arguments
+        (Maybe [MagicId])      -- list of regs which need to be preserved
+       -- across the primop.  This is allowed to be Nothing only if
+       -- machOpIsDefinitelyInline returns True.  And that in turn may
+       -- only return True if we are absolutely sure that the mach op
+       -- can be done inline on all platforms.  
+
+  | CSequential                -- Do the nested AbstractCs sequentially.
+       [AbstractC]     -- In particular, as far as the AbsCUtils.doSimultaneously
+                       -- is concerned, these stmts are to be treated as atomic
+                       -- and are not to be reordered.
+
+  -- end of NEW CASES FOR EXPANDED PRIMOPS
+
   | COpStmt
        [CAddrMode]     -- Results
        StgOp
@@ -349,6 +371,9 @@ data CAddrMode
        !PrimRep        -- the kind of the result
        CExprMacro      -- the macro to generate a value
        [CAddrMode]     -- and its arguments
+
+  | CMem   PrimRep     -- A value :: PrimRep, in memory, at the 
+           CAddrMode   -- specified address
 \end{code}
 
 Various C macros for values which are dependent on the back-end layout.
index 2d55bd0..46dc512 100644 (file)
@@ -13,27 +13,34 @@ module AbsCUtils (
        mixedTypeLocn, mixedPtrLocn,
        flattenAbsC,
        mkAbsCStmtList
-
        -- printing/forcing stuff comes from PprAbsC
     ) where
 
 #include "HsVersions.h"
 
 import AbsCSyn
+import CLabel          ( mkMAP_FROZEN_infoLabel )
 import Digraph         ( stronglyConnComp, SCC(..) )
 import DataCon         ( fIRST_TAG, ConTag )
-import Literal         ( literalPrimRep, mkMachWord )
+import Literal         ( literalPrimRep, mkMachWord, mkMachInt )
 import PrimRep         ( getPrimRepSize, PrimRep(..) )
+import PrimOp          ( PrimOp(..) )
+import MachOp          ( MachOp(..), isDefinitelyInlineMachOp )
 import Unique          ( Unique{-instance Eq-} )
 import UniqSupply      ( uniqFromSupply, uniqsFromSupply, splitUniqSupply, 
                          UniqSupply )
 import CmdLineOpts      ( opt_EmitCExternDecls )
-import ForeignCall     ( ForeignCall(..), CCallSpec(..), isDynamicTarget, isCasmTarget )
+import ForeignCall     ( ForeignCall(..), CCallSpec(..), CCallTarget(..), Safety(..),
+                         isDynamicTarget, isCasmTarget, defaultCCallConv )
 import StgSyn          ( StgOp(..) )
+import SMRep           ( arrPtrsHdrSize, arrWordsHdrSize, fixedHdrSize )
+import Constants       ( wORD_SIZE )
+import Maybes          ( Maybe012(..) )
+import Outputable
 import Panic           ( panic )
 import FastTypes
 
-import Maybe           ( isJust )
+import Maybe           ( isJust, maybeToList )
 
 infixr 9 `thenFlt`
 \end{code}
@@ -171,6 +178,7 @@ getAmodeRep (CIntLike _)                = PtrRep
 getAmodeRep (CLit lit)                     = literalPrimRep lit
 getAmodeRep (CMacroExpr kind _ _)          = kind
 getAmodeRep (CJoinPoint _)                 = panic "getAmodeRep:CJoinPoint"
+getAmodeRep (CMem rep addr)                 = rep
 \end{code}
 
 @mixedTypeLocn@ tells whether an amode identifies an ``StgWord''
@@ -342,8 +350,8 @@ flatAbsC (CSwitch discrim alts deflt)
        returnFlt ( (tag, alt_heres), alt_tops )
 
 flatAbsC stmt@(COpStmt results (StgFCallOp (CCall ccall@(CCallSpec target _ _)) uniq) args _)
-  |  is_dynamic                                                 -- Emit a typedef if its a dynamic call
-  || (opt_EmitCExternDecls && not (isCasmTarget target)) -- or we want extern decls
+  |  is_dynamic                                 -- Emit a typedef if its a dynamic call
+     || (opt_EmitCExternDecls && not (isCasmTarget target)) -- or we want extern decls
   = returnFlt (stmt, CCallTypedef is_dynamic ccall uniq results args)
   where
     is_dynamic = isDynamicTarget target
@@ -370,8 +378,44 @@ flatAbsC stmt@(CAssign dest source)                 = returnFlt (stmt, AbsCNop)
 flatAbsC stmt@(CJump target)                    = returnFlt (stmt, AbsCNop)
 flatAbsC stmt@(CFallThrough target)             = returnFlt (stmt, AbsCNop)
 flatAbsC stmt@(CReturn target return_info)      = returnFlt (stmt, AbsCNop)
-flatAbsC stmt@(CInitHdr a b cc _)               = returnFlt (stmt, AbsCNop)
-flatAbsC stmt@(COpStmt results op args vol_regs) = returnFlt (stmt, AbsCNop)
+flatAbsC stmt@(CInitHdr a b cc sz)              = returnFlt (stmt, AbsCNop)
+flatAbsC stmt@(CMachOpStmt res mop args m_vols)  = returnFlt (stmt, AbsCNop)
+flatAbsC stmt@(COpStmt results (StgFCallOp _ _) args vol_regs) 
+                                                 = returnFlt (stmt, AbsCNop)
+flatAbsC stmt@(COpStmt results (StgPrimOp op) args vol_regs) 
+   = dscCOpStmt (filter non_void_amode results) op 
+                (filter non_void_amode args) vol_regs  
+                               `thenFlt` \ simpl ->
+     case simpl of
+        COpStmt _ _ _ _ -> panic "flatAbsC - dscCOpStmt"   -- make sure we don't loop!
+        other           -> flatAbsC other
+     {-
+        A gruesome hack for printing the names of inline primops when they
+        are used. 
+                                  oink other
+     where
+        oink xxx 
+            = getUniqFlt `thenFlt` \ uu ->
+              flatAbsC (CSequential [moo uu (showSDoc (ppr op)), xxx])
+
+        moo uu op_str
+           = COpStmt 
+                []
+                (StgFCallOp
+                    (CCall (CCallSpec (CasmTarget (_PK_ (mktxt op_str))) 
+                                      defaultCCallConv PlaySafe))
+                    uu
+                )
+                [CReg VoidReg]
+                []
+        mktxt op_str
+            = " asm(\"pushal;\"); printf(\"%%s\\n\",\"" ++ op_str ++ "\"); asm(\"popal\"); "
+     -}
+
+flatAbsC (CSequential abcs)
+  = mapAndUnzipFlt flatAbsC abcs `thenFlt` \ (inlines, tops) ->
+    returnFlt (CSequential inlines, foldr AbsCStmts AbsCNop tops)
+
 
 -- Some statements only make sense at the top level, so we always float
 -- them.  This probably isn't necessary.
@@ -493,7 +537,6 @@ doSimultaneously1 vertices
       = or [dest1 `conflictsWith` src2 | dest1 <- dests1, src2 <- srcs2]
 \end{code}
 
-
 @conflictsWith@ tells whether an assignment to its first argument will
 screw up an access to its second.
 
@@ -540,3 +583,546 @@ rrConflictsWithRR s1b s2b rr1 rr2 = rr rr1 rr2
 
     rr other1           other2       = False
 \end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[flat-primops]{Translating COpStmts to CMachOpStmts}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+
+
+------------------------------------------------------------------------------
+
+-- Assumes no volatiles
+mkHalfWord_HIADDR res arg
+#  if WORDS_BIGENDIAN
+   = CMachOpStmt (Just1 res) MO_Nat_And [arg, CLit (mkMachWord halfword_mask)] Nothing
+#  else
+   = CMachOpStmt (Just1 res) MO_Nat_Shr [arg, CLit (mkMachWord halfword_shift)] Nothing
+#  endif
+   where
+      (halfword_mask, halfword_shift)
+         | wORD_SIZE == 4  = (65535,               16)
+         | wORD_SIZE == 8  = (4294967295::Integer, 32)
+
+
+mkTemp :: PrimRep -> FlatM CAddrMode
+mkTemp rep 
+   = getUniqFlt `thenFlt` \ uniq -> returnFlt (CTemp uniq rep)
+
+mkTemps = mapFlt mkTemp
+
+mkDerefOff :: PrimRep -> CAddrMode -> Int -> CAddrMode
+mkDerefOff rep base off
+   | off == 0  -- optimisation
+   = CMem rep base
+   | otherwise
+   = CMem rep (CAddr (CIndex base (CLit (mkMachInt (toInteger off))) rep))
+
+mkNoDerefOff :: PrimRep -> CAddrMode -> Int -> CAddrMode
+mkNoDerefOff rep base off
+   = CAddr (CIndex base (CLit (mkMachInt (toInteger off))) rep)
+
+-- Sigh.  This is done in 3 seperate places.  Should be
+-- commoned up (here, in pprAbsC of COpStmt, and presumably
+-- somewhere in the NCG).
+non_void_amode amode 
+   = case getAmodeRep amode of
+        VoidRep -> False
+        k       -> True
+
+doIndexOffForeignObjOp rep res addr idx
+   = Just (Just1 res, MO_ReadOSBI fixedHdrSize rep, [addr,idx])
+
+doIndexOffAddrOp rep res addr idx
+   = Just (Just1 res, MO_ReadOSBI 0 rep, [addr,idx])
+
+doIndexByteArrayOp rep res addr idx
+   = Just (Just1 res, MO_ReadOSBI arrWordsHdrSize rep, [addr,idx])
+
+doWriteOffAddrOp rep addr idx val
+   = Just (Just0, MO_WriteOSBI 0 rep, [addr,idx,val])
+
+doWriteByteArrayOp rep addr idx val
+   = Just (Just0, MO_WriteOSBI arrWordsHdrSize rep, [addr,idx,val])
+
+-- Simple dyadic op but one for which we need to cast first arg to
+-- be sure of correctness
+translateOp_dyadic_cast1 mop res cast_arg1_to arg1 arg2 vols
+   = mkTemp cast_arg1_to               `thenFlt` \ arg1casted ->
+     (returnFlt . CSequential) [
+        CAssign arg1casted arg1,
+        CMachOpStmt (Just1 res) mop [arg1casted,arg2]
+           (if isDefinitelyInlineMachOp mop then Nothing else Just vols)
+     ]
+
+------------------------------------------------------------------------------
+
+dscCOpStmt :: [CAddrMode]      -- Results
+           -> PrimOp
+           -> [CAddrMode]      -- Arguments
+           -> [MagicId]                -- Potentially volatile/live registers
+                               -- (to save/restore around the op)
+           -> FlatM AbstractC
+
+-- #define parzh(r,node) r = 1
+dscCOpStmt [res] ParOp [arg] vols
+   = returnFlt
+        (CAssign res (CLit (mkMachInt 1)))
+
+-- #define readMutVarzh(r,a)    r=(P_)(((StgMutVar *)(a))->var)
+dscCOpStmt [res] ReadMutVarOp [mutv] vols
+   = returnFlt
+        (CAssign res (mkDerefOff PtrRep mutv fixedHdrSize))
+
+-- #define writeMutVarzh(a,v)       (P_)(((StgMutVar *)(a))->var)=(v)
+dscCOpStmt [] WriteMutVarOp [mutv,var] vols
+   = returnFlt
+        (CAssign (mkDerefOff PtrRep mutv fixedHdrSize) var)
+
+
+-- #define ForeignObj_CLOSURE_DATA(c)  (((StgForeignObj *)c)->data)
+-- #define foreignObjToAddrzh(r,fo)    r=ForeignObj_CLOSURE_DATA(fo)
+dscCOpStmt [res] ForeignObjToAddrOp [fo] vols
+   = returnFlt
+        (CAssign res (mkDerefOff PtrRep fo fixedHdrSize))
+
+-- #define writeForeignObjzh(res,datum) \
+--    (ForeignObj_CLOSURE_DATA(res) = (P_)(datum))
+dscCOpStmt [] WriteForeignObjOp [fo,addr] vols
+   = returnFlt
+        (CAssign (mkDerefOff PtrRep fo fixedHdrSize) addr)
+
+
+-- #define sizzeofByteArrayzh(r,a) \
+--     r = (((StgArrWords *)(a))->words * sizeof(W_))
+dscCOpStmt [res] SizeofByteArrayOp [arg] vols
+   = mkTemp WordRep                    `thenFlt` \ w ->
+     (returnFlt . CSequential) [
+        CAssign w (mkDerefOff WordRep arg fixedHdrSize),
+        CMachOpStmt (Just1 w) 
+           MO_NatU_Mul [w, CLit (mkMachInt (toInteger wORD_SIZE))] (Just vols),
+        CAssign res w
+     ]
+
+-- #define sizzeofMutableByteArrayzh(r,a) \
+--      r = (((StgArrWords *)(a))->words * sizeof(W_))
+dscCOpStmt [res] SizeofMutableByteArrayOp [arg] vols
+   = dscCOpStmt [res] SizeofByteArrayOp [arg] vols
+
+
+-- #define touchzh(o)                  /* nothing */
+dscCOpStmt [] TouchOp [arg] vols
+   = returnFlt AbsCNop
+
+-- #define byteArrayContentszh(r,a) r = BYTE_ARR_CTS(a)
+dscCOpStmt [res] ByteArrayContents_Char [arg] vols
+   = mkTemp PtrRep                     `thenFlt` \ ptr ->
+     (returnFlt . CSequential) [
+         CMachOpStmt (Just1 ptr) MO_NatU_to_NatP [arg] Nothing,
+         CAssign ptr (mkNoDerefOff WordRep ptr arrWordsHdrSize),
+         CAssign res ptr
+     ]
+
+-- #define stableNameToIntzh(r,s)   (r = ((StgStableName *)s)->sn)
+dscCOpStmt [res] StableNameToIntOp [arg] vols
+   = returnFlt 
+        (CAssign res (mkDerefOff WordRep arg fixedHdrSize))
+
+-- #define eqStableNamezh(r,sn1,sn2)                                   \
+--    (r = (((StgStableName *)sn1)->sn == ((StgStableName *)sn2)->sn))
+dscCOpStmt [res] EqStableNameOp [arg1,arg2] vols
+   = mkTemps [WordRep, WordRep]        `thenFlt` \ [sn1,sn2] ->
+     (returnFlt . CSequential) [
+        CAssign sn1 (mkDerefOff WordRep arg1 fixedHdrSize),
+        CAssign sn2 (mkDerefOff WordRep arg2 fixedHdrSize),
+        CMachOpStmt (Just1 res) MO_Nat_Eq [sn1,sn2] Nothing
+     ]
+
+-- #define addrToHValuezh(r,a) r=(P_)a
+dscCOpStmt [res] AddrToHValueOp [arg] vols
+   = returnFlt 
+        (CAssign res arg)
+
+-- #define dataToTagzh(r,a)  r=(GET_TAG(((StgClosure *)a)->header.info))
+dscCOpStmt [res] DataToTagOp [arg] vols
+   = mkTemps [PtrRep, WordRep]         `thenFlt` \ [t_infoptr, t_theword] ->
+     (returnFlt . CSequential) [
+        CAssign t_infoptr (mkDerefOff PtrRep arg 0),
+        CAssign t_theword (mkDerefOff WordRep t_infoptr (-1)),
+        mkHalfWord_HIADDR res t_theword
+     ]
+
+
+{- Freezing arrays-of-ptrs requires changing an info table, for the
+   benefit of the generational collector.  It needs to scavenge mutable
+   objects, even if they are in old space.  When they become immutable,
+   they can be removed from this scavenge list.         -}
+
+-- #define unsafeFreezzeArrayzh(r,a)                                   \
+--     {                                                               \
+--        SET_INFO((StgClosure *)a,&stg_MUT_ARR_PTRS_FROZEN_info);        \
+--     r = a;                                                          \
+--     }
+dscCOpStmt [res] UnsafeFreezeArrayOp [arg] vols
+   = (returnFlt . CSequential) [
+        CAssign (mkDerefOff PtrRep arg 0) (CLbl mkMAP_FROZEN_infoLabel PtrRep),
+        CAssign res arg
+     ]
+
+-- #define unsafeFreezzeByteArrayzh(r,a)       r=(a)
+dscCOpStmt [res] UnsafeFreezeByteArrayOp [arg] vols
+   = returnFlt
+        (CAssign res arg)
+
+-- This ought to be trivial, but it's difficult to insert the casts
+-- required to keep the C compiler happy.
+dscCOpStmt [r] AddrRemOp [a1,a2] vols 
+   = mkTemp WordRep                    `thenFlt` \ a1casted ->
+     (returnFlt . CSequential) [
+        CMachOpStmt (Just1 a1casted) MO_NatP_to_NatU [a1] Nothing,
+        CMachOpStmt (Just1 r) MO_NatU_Rem [a1casted,a2] Nothing
+     ]
+
+-- not handled by translateOp because they need casts
+dscCOpStmt [r] SllOp [a1,a2] vols
+   = translateOp_dyadic_cast1 MO_Nat_Shl r WordRep a1 a2 vols
+dscCOpStmt [r] SrlOp [a1,a2] vols 
+   = translateOp_dyadic_cast1 MO_Nat_Shr r WordRep a1 a2 vols
+
+dscCOpStmt [r] ISllOp [a1,a2] vols 
+   = translateOp_dyadic_cast1 MO_Nat_Shl r IntRep a1 a2 vols
+dscCOpStmt [r] ISrlOp [a1,a2] vols 
+   = translateOp_dyadic_cast1 MO_Nat_Shr r IntRep a1 a2 vols
+dscCOpStmt [r] ISraOp [a1,a2] vols 
+   = translateOp_dyadic_cast1 MO_Nat_Sar r IntRep a1 a2 vols
+
+
+-- Handle all others as simply as possible.
+dscCOpStmt ress op args vols
+   = case translateOp ress op args of
+        Nothing 
+           -> pprPanic "dscCOpStmt: can't translate PrimOp" (ppr op)
+        Just (maybe_res, mop, args)
+           -> returnFlt (
+                 CMachOpStmt maybe_res mop args 
+                    (if isDefinitelyInlineMachOp mop then Nothing else Just vols)
+              )
+
+
+
+translateOp [r] ReadArrayOp [obj,ix] 
+   = Just (Just1 r, MO_ReadOSBI arrPtrsHdrSize PtrRep, [obj,ix])
+translateOp [r] IndexArrayOp [obj,ix] 
+   = Just (Just1 r, MO_ReadOSBI arrPtrsHdrSize PtrRep, [obj,ix])
+translateOp [] WriteArrayOp [obj,ix,v] 
+   = Just (Just0, MO_WriteOSBI arrPtrsHdrSize PtrRep, [obj,ix,v])
+
+-- IndexXXXoffForeignObj
+
+translateOp [r] IndexOffForeignObjOp_Char [a,i]  = doIndexOffForeignObjOp Word8Rep r a i
+translateOp [r] IndexOffForeignObjOp_WideChar [a,i]  = doIndexOffForeignObjOp Word32Rep r a i
+translateOp [r] IndexOffForeignObjOp_Int [a,i]  = doIndexOffForeignObjOp IntRep r a i
+translateOp [r] IndexOffForeignObjOp_Word [a,i]  = doIndexOffForeignObjOp WordRep r a i
+translateOp [r] IndexOffForeignObjOp_Addr [a,i]  = doIndexOffForeignObjOp AddrRep r a i
+translateOp [r] IndexOffForeignObjOp_Float [a,i]  = doIndexOffForeignObjOp FloatRep r a i
+translateOp [r] IndexOffForeignObjOp_Double [a,i]  = doIndexOffForeignObjOp DoubleRep r a i
+translateOp [r] IndexOffForeignObjOp_StablePtr [a,i]  = doIndexOffForeignObjOp StablePtrRep r a i
+
+translateOp [r] IndexOffForeignObjOp_Int8  [a,i] = doIndexOffForeignObjOp Int8Rep  r a i
+translateOp [r] IndexOffForeignObjOp_Int16 [a,i] = doIndexOffForeignObjOp Int16Rep r a i
+translateOp [r] IndexOffForeignObjOp_Int32 [a,i] = doIndexOffForeignObjOp Int32Rep r a i
+translateOp [r] IndexOffForeignObjOp_Int64 [a,i] = doIndexOffForeignObjOp Int64Rep r a i
+
+translateOp [r] IndexOffForeignObjOp_Word8  [a,i] = doIndexOffForeignObjOp Word8Rep  r a i
+translateOp [r] IndexOffForeignObjOp_Word16 [a,i] = doIndexOffForeignObjOp Word16Rep r a i
+translateOp [r] IndexOffForeignObjOp_Word32 [a,i] = doIndexOffForeignObjOp Word32Rep r a i
+translateOp [r] IndexOffForeignObjOp_Word64 [a,i] = doIndexOffForeignObjOp Word64Rep r a i
+
+-- IndexXXXoffAddr
+
+translateOp [r] IndexOffAddrOp_Char [a,i]  = doIndexOffAddrOp Word8Rep r a i
+translateOp [r] IndexOffAddrOp_WideChar [a,i]  = doIndexOffAddrOp Word32Rep r a i
+translateOp [r] IndexOffAddrOp_Int [a,i]  = doIndexOffAddrOp IntRep r a i
+translateOp [r] IndexOffAddrOp_Word [a,i]  = doIndexOffAddrOp WordRep r a i
+translateOp [r] IndexOffAddrOp_Addr [a,i]  = doIndexOffAddrOp AddrRep r a i
+translateOp [r] IndexOffAddrOp_Float [a,i]  = doIndexOffAddrOp FloatRep r a i
+translateOp [r] IndexOffAddrOp_Double [a,i]  = doIndexOffAddrOp DoubleRep r a i
+translateOp [r] IndexOffAddrOp_StablePtr [a,i]  = doIndexOffAddrOp StablePtrRep r a i
+
+translateOp [r] IndexOffAddrOp_Int8  [a,i] = doIndexOffAddrOp Int8Rep  r a i
+translateOp [r] IndexOffAddrOp_Int16 [a,i] = doIndexOffAddrOp Int16Rep r a i
+translateOp [r] IndexOffAddrOp_Int32 [a,i] = doIndexOffAddrOp Int32Rep r a i
+translateOp [r] IndexOffAddrOp_Int64 [a,i] = doIndexOffAddrOp Int64Rep r a i
+
+translateOp [r] IndexOffAddrOp_Word8  [a,i] = doIndexOffAddrOp Word8Rep  r a i
+translateOp [r] IndexOffAddrOp_Word16 [a,i] = doIndexOffAddrOp Word16Rep r a i
+translateOp [r] IndexOffAddrOp_Word32 [a,i] = doIndexOffAddrOp Word32Rep r a i
+translateOp [r] IndexOffAddrOp_Word64 [a,i] = doIndexOffAddrOp Word64Rep r a i
+
+-- ReadXXXoffAddr, which are identical, for our purposes, to IndexXXXoffAddr.
+
+translateOp [r] ReadOffAddrOp_Char [a,i]  = doIndexOffAddrOp Word8Rep r a i
+translateOp [r] ReadOffAddrOp_WideChar [a,i]  = doIndexOffAddrOp Word32Rep r a i
+translateOp [r] ReadOffAddrOp_Int [a,i]  = doIndexOffAddrOp IntRep r a i
+translateOp [r] ReadOffAddrOp_Word [a,i]  = doIndexOffAddrOp WordRep r a i
+translateOp [r] ReadOffAddrOp_Addr [a,i]  = doIndexOffAddrOp AddrRep r a i
+translateOp [r] ReadOffAddrOp_Float [a,i]  = doIndexOffAddrOp FloatRep r a i
+translateOp [r] ReadOffAddrOp_Double [a,i]  = doIndexOffAddrOp DoubleRep r a i
+translateOp [r] ReadOffAddrOp_StablePtr [a,i]  = doIndexOffAddrOp StablePtrRep r a i
+
+translateOp [r] ReadOffAddrOp_Int8  [a,i] = doIndexOffAddrOp Int8Rep  r a i
+translateOp [r] ReadOffAddrOp_Int16 [a,i] = doIndexOffAddrOp Int16Rep r a i
+translateOp [r] ReadOffAddrOp_Int32 [a,i] = doIndexOffAddrOp Int32Rep r a i
+translateOp [r] ReadOffAddrOp_Int64 [a,i] = doIndexOffAddrOp Int64Rep r a i
+
+translateOp [r] ReadOffAddrOp_Word8  [a,i] = doIndexOffAddrOp Word8Rep  r a i
+translateOp [r] ReadOffAddrOp_Word16 [a,i] = doIndexOffAddrOp Word16Rep r a i
+translateOp [r] ReadOffAddrOp_Word32 [a,i] = doIndexOffAddrOp Word32Rep r a i
+translateOp [r] ReadOffAddrOp_Word64 [a,i] = doIndexOffAddrOp Word64Rep r a i
+
+-- WriteXXXoffAddr
+
+translateOp [] WriteOffAddrOp_Char [a,i,x]  = doWriteOffAddrOp Word8Rep a i x
+translateOp [] WriteOffAddrOp_WideChar [a,i,x]  = doWriteOffAddrOp Word32Rep a i x
+translateOp [] WriteOffAddrOp_Int [a,i,x]  = doWriteOffAddrOp IntRep a i x
+translateOp [] WriteOffAddrOp_Word [a,i,x]  = doWriteOffAddrOp WordRep a i x
+translateOp [] WriteOffAddrOp_Addr [a,i,x]  = doWriteOffAddrOp AddrRep a i x
+translateOp [] WriteOffAddrOp_Float [a,i,x]  = doWriteOffAddrOp FloatRep a i x
+translateOp [] WriteOffAddrOp_ForeignObj [a,i,x]  = doWriteOffAddrOp ForeignObjRep a i x
+translateOp [] WriteOffAddrOp_Double [a,i,x]  = doWriteOffAddrOp DoubleRep a i x
+translateOp [] WriteOffAddrOp_StablePtr [a,i,x]  = doWriteOffAddrOp StablePtrRep a i x
+
+translateOp [] WriteOffAddrOp_Int8  [a,i,x] = doWriteOffAddrOp Int8Rep  a i x
+translateOp [] WriteOffAddrOp_Int16 [a,i,x] = doWriteOffAddrOp Int16Rep a i x
+translateOp [] WriteOffAddrOp_Int32 [a,i,x] = doWriteOffAddrOp Int32Rep a i x
+translateOp [] WriteOffAddrOp_Int64 [a,i,x] = doWriteOffAddrOp Int64Rep a i x
+
+translateOp [] WriteOffAddrOp_Word8  [a,i,x] = doWriteOffAddrOp Word8Rep  a i x
+translateOp [] WriteOffAddrOp_Word16 [a,i,x] = doWriteOffAddrOp Word16Rep a i x
+translateOp [] WriteOffAddrOp_Word32 [a,i,x] = doWriteOffAddrOp Word32Rep a i x
+translateOp [] WriteOffAddrOp_Word64 [a,i,x] = doWriteOffAddrOp Word64Rep a i x
+
+-- IndexXXXArray
+
+translateOp [r] IndexByteArrayOp_Char [a,i]  = doIndexByteArrayOp Word8Rep r a i
+translateOp [r] IndexByteArrayOp_WideChar [a,i]  = doIndexByteArrayOp Word32Rep r a i
+translateOp [r] IndexByteArrayOp_Int [a,i]  = doIndexByteArrayOp IntRep r a i
+translateOp [r] IndexByteArrayOp_Word [a,i]  = doIndexByteArrayOp WordRep r a i
+translateOp [r] IndexByteArrayOp_Addr [a,i]  = doIndexByteArrayOp AddrRep r a i
+translateOp [r] IndexByteArrayOp_Float [a,i]  = doIndexByteArrayOp FloatRep r a i
+translateOp [r] IndexByteArrayOp_Double [a,i]  = doIndexByteArrayOp DoubleRep r a i
+translateOp [r] IndexByteArrayOp_StablePtr [a,i]  = doIndexByteArrayOp StablePtrRep r a i
+
+translateOp [r] IndexByteArrayOp_Int8  [a,i] = doIndexByteArrayOp Int8Rep  r a i
+translateOp [r] IndexByteArrayOp_Int16 [a,i] = doIndexByteArrayOp Int16Rep  r a i
+translateOp [r] IndexByteArrayOp_Int32 [a,i] = doIndexByteArrayOp Int32Rep  r a i
+translateOp [r] IndexByteArrayOp_Int64 [a,i] = doIndexByteArrayOp Int64Rep  r a i
+
+translateOp [r] IndexByteArrayOp_Word8  [a,i] = doIndexByteArrayOp Word8Rep  r a i
+translateOp [r] IndexByteArrayOp_Word16 [a,i] = doIndexByteArrayOp Word16Rep  r a i
+translateOp [r] IndexByteArrayOp_Word32 [a,i] = doIndexByteArrayOp Word32Rep  r a i
+translateOp [r] IndexByteArrayOp_Word64 [a,i] = doIndexByteArrayOp Word64Rep  r a i
+
+-- ReadXXXArray, identical to IndexXXXArray.
+
+translateOp [r] ReadByteArrayOp_Char [a,i]  = doIndexByteArrayOp Word8Rep r a i
+translateOp [r] ReadByteArrayOp_WideChar [a,i]  = doIndexByteArrayOp Word32Rep r a i
+translateOp [r] ReadByteArrayOp_Int [a,i]  = doIndexByteArrayOp IntRep r a i
+translateOp [r] ReadByteArrayOp_Word [a,i]  = doIndexByteArrayOp WordRep r a i
+translateOp [r] ReadByteArrayOp_Addr [a,i]  = doIndexByteArrayOp AddrRep r a i
+translateOp [r] ReadByteArrayOp_Float [a,i]  = doIndexByteArrayOp FloatRep r a i
+translateOp [r] ReadByteArrayOp_Double [a,i]  = doIndexByteArrayOp DoubleRep r a i
+translateOp [r] ReadByteArrayOp_StablePtr [a,i]  = doIndexByteArrayOp StablePtrRep r a i
+
+translateOp [r] ReadByteArrayOp_Int8  [a,i] = doIndexByteArrayOp Int8Rep  r a i
+translateOp [r] ReadByteArrayOp_Int16 [a,i] = doIndexByteArrayOp Int16Rep  r a i
+translateOp [r] ReadByteArrayOp_Int32 [a,i] = doIndexByteArrayOp Int32Rep  r a i
+translateOp [r] ReadByteArrayOp_Int64 [a,i] = doIndexByteArrayOp Int64Rep  r a i
+
+translateOp [r] ReadByteArrayOp_Word8  [a,i] = doIndexByteArrayOp Word8Rep  r a i
+translateOp [r] ReadByteArrayOp_Word16 [a,i] = doIndexByteArrayOp Word16Rep  r a i
+translateOp [r] ReadByteArrayOp_Word32 [a,i] = doIndexByteArrayOp Word32Rep  r a i
+translateOp [r] ReadByteArrayOp_Word64 [a,i] = doIndexByteArrayOp Word64Rep  r a i
+
+-- WriteXXXArray
+
+translateOp [] WriteByteArrayOp_Char [a,i,x]  = doWriteByteArrayOp Word8Rep a i x
+translateOp [] WriteByteArrayOp_WideChar [a,i,x]  = doWriteByteArrayOp Word32Rep a i x
+translateOp [] WriteByteArrayOp_Int [a,i,x]  = doWriteByteArrayOp IntRep a i x
+translateOp [] WriteByteArrayOp_Word [a,i,x]  = doWriteByteArrayOp WordRep a i x
+translateOp [] WriteByteArrayOp_Addr [a,i,x]  = doWriteByteArrayOp AddrRep a i x
+translateOp [] WriteByteArrayOp_Float [a,i,x]  = doWriteByteArrayOp FloatRep a i x
+translateOp [] WriteByteArrayOp_Double [a,i,x]  = doWriteByteArrayOp DoubleRep a i x
+translateOp [] WriteByteArrayOp_StablePtr [a,i,x]  = doWriteByteArrayOp StablePtrRep a i x
+
+translateOp [] WriteByteArrayOp_Int8  [a,i,x] = doWriteByteArrayOp Int8Rep  a i x
+translateOp [] WriteByteArrayOp_Int16 [a,i,x] = doWriteByteArrayOp Int16Rep  a i x
+translateOp [] WriteByteArrayOp_Int32 [a,i,x] = doWriteByteArrayOp Int32Rep  a i x
+translateOp [] WriteByteArrayOp_Int64 [a,i,x] = doWriteByteArrayOp Int64Rep  a i x
+
+translateOp [] WriteByteArrayOp_Word8  [a,i,x] = doWriteByteArrayOp Word8Rep  a i x
+translateOp [] WriteByteArrayOp_Word16 [a,i,x] = doWriteByteArrayOp Word16Rep  a i x
+translateOp [] WriteByteArrayOp_Word32 [a,i,x] = doWriteByteArrayOp Word32Rep  a i x
+translateOp [] WriteByteArrayOp_Word64 [a,i,x] = doWriteByteArrayOp Word64Rep  a i x
+
+-- Native word signless ops
+
+translateOp [r] IntAddOp       [a1,a2] = Just (Just1 r, MO_Nat_Add,        [a1,a2])
+translateOp [r] IntSubOp       [a1,a2] = Just (Just1 r, MO_Nat_Sub,        [a1,a2])
+translateOp [r] WordAddOp      [a1,a2] = Just (Just1 r, MO_Nat_Add,        [a1,a2])
+translateOp [r] WordSubOp      [a1,a2] = Just (Just1 r, MO_Nat_Sub,        [a1,a2])
+translateOp [r] AddrAddOp      [a1,a2] = Just (Just1 r, MO_Nat_Add,        [a1,a2])
+translateOp [r] AddrSubOp      [a1,a2] = Just (Just1 r, MO_Nat_Sub,        [a1,a2])
+
+translateOp [r] IntEqOp        [a1,a2] = Just (Just1 r, MO_Nat_Eq,         [a1,a2])
+translateOp [r] IntNeOp        [a1,a2] = Just (Just1 r, MO_Nat_Ne,         [a1,a2])
+translateOp [r] WordEqOp       [a1,a2] = Just (Just1 r, MO_Nat_Eq,         [a1,a2])
+translateOp [r] WordNeOp       [a1,a2] = Just (Just1 r, MO_Nat_Ne,         [a1,a2])
+translateOp [r] AddrEqOp       [a1,a2] = Just (Just1 r, MO_Nat_Eq,         [a1,a2])
+translateOp [r] AddrNeOp       [a1,a2] = Just (Just1 r, MO_Nat_Ne,         [a1,a2])
+
+translateOp [r] AndOp          [a1,a2] = Just (Just1 r, MO_Nat_And,        [a1,a2])
+translateOp [r] OrOp           [a1,a2] = Just (Just1 r, MO_Nat_Or,         [a1,a2])
+translateOp [r] XorOp          [a1,a2] = Just (Just1 r, MO_Nat_Xor,        [a1,a2])
+translateOp [r] NotOp          [a1]    = Just (Just1 r, MO_Nat_Not,        [a1])
+
+-- Native word signed ops
+
+translateOp [r] IntMulOp       [a1,a2] = Just (Just1 r, MO_NatS_Mul,       [a1,a2])
+translateOp [r] IntQuotOp      [a1,a2] = Just (Just1 r, MO_NatS_Quot,      [a1,a2])
+translateOp [r] IntRemOp       [a1,a2] = Just (Just1 r, MO_NatS_Rem,       [a1,a2])
+translateOp [r] IntNegOp       [a1]    = Just (Just1 r, MO_NatS_Neg,       [a1])
+
+translateOp [r,c] IntAddCOp    [a1,a2] = Just (Just2 r c, MO_NatS_AddC,    [a1,a2])
+translateOp [r,c] IntSubCOp    [a1,a2] = Just (Just2 r c, MO_NatS_SubC,    [a1,a2])
+translateOp [r,c] IntMulCOp    [a1,a2] = Just (Just2 r c, MO_NatS_MulC,    [a1,a2])
+
+translateOp [r] IntGeOp        [a1,a2] = Just (Just1 r, MO_NatS_Ge,        [a1,a2])
+translateOp [r] IntLeOp        [a1,a2] = Just (Just1 r, MO_NatS_Le,        [a1,a2])
+translateOp [r] IntGtOp        [a1,a2] = Just (Just1 r, MO_NatS_Gt,        [a1,a2])
+translateOp [r] IntLtOp        [a1,a2] = Just (Just1 r, MO_NatS_Lt,        [a1,a2])
+
+-- Native word unsigned ops
+
+translateOp [r] WordGeOp       [a1,a2] = Just (Just1 r, MO_NatU_Ge,        [a1,a2])
+translateOp [r] WordLeOp       [a1,a2] = Just (Just1 r, MO_NatU_Le,        [a1,a2])
+translateOp [r] WordGtOp       [a1,a2] = Just (Just1 r, MO_NatU_Gt,        [a1,a2])
+translateOp [r] WordLtOp       [a1,a2] = Just (Just1 r, MO_NatU_Lt,        [a1,a2])
+
+translateOp [r] WordMulOp      [a1,a2] = Just (Just1 r, MO_NatU_Mul,       [a1,a2])
+translateOp [r] WordQuotOp     [a1,a2] = Just (Just1 r, MO_NatU_Quot,      [a1,a2])
+translateOp [r] WordRemOp      [a1,a2] = Just (Just1 r, MO_NatU_Rem,       [a1,a2])
+
+translateOp [r] AddrGeOp       [a1,a2] = Just (Just1 r, MO_NatU_Ge,        [a1,a2])
+translateOp [r] AddrLeOp       [a1,a2] = Just (Just1 r, MO_NatU_Le,        [a1,a2])
+translateOp [r] AddrGtOp       [a1,a2] = Just (Just1 r, MO_NatU_Gt,        [a1,a2])
+translateOp [r] AddrLtOp       [a1,a2] = Just (Just1 r, MO_NatU_Lt,        [a1,a2])
+
+-- 32-bit unsigned ops
+
+translateOp [r] CharEqOp       [a1,a2] = Just (Just1 r, MO_32U_Eq,        [a1,a2])
+translateOp [r] CharNeOp       [a1,a2] = Just (Just1 r, MO_32U_Ne,        [a1,a2])
+translateOp [r] CharGeOp       [a1,a2] = Just (Just1 r, MO_32U_Ge,        [a1,a2])
+translateOp [r] CharLeOp       [a1,a2] = Just (Just1 r, MO_32U_Le,        [a1,a2])
+translateOp [r] CharGtOp       [a1,a2] = Just (Just1 r, MO_32U_Gt,        [a1,a2])
+translateOp [r] CharLtOp       [a1,a2] = Just (Just1 r, MO_32U_Lt,        [a1,a2])
+
+-- Double ops
+
+translateOp [r] DoubleEqOp     [a1,a2] = Just (Just1 r, MO_Dbl_Eq,      [a1,a2])
+translateOp [r] DoubleNeOp     [a1,a2] = Just (Just1 r, MO_Dbl_Ne,      [a1,a2])
+translateOp [r] DoubleGeOp     [a1,a2] = Just (Just1 r, MO_Dbl_Ge,      [a1,a2])
+translateOp [r] DoubleLeOp     [a1,a2] = Just (Just1 r, MO_Dbl_Le,      [a1,a2])
+translateOp [r] DoubleGtOp     [a1,a2] = Just (Just1 r, MO_Dbl_Gt,      [a1,a2])
+translateOp [r] DoubleLtOp     [a1,a2] = Just (Just1 r, MO_Dbl_Lt,      [a1,a2])
+
+translateOp [r] DoubleAddOp    [a1,a2] = Just (Just1 r, MO_Dbl_Add,    [a1,a2])
+translateOp [r] DoubleSubOp    [a1,a2] = Just (Just1 r, MO_Dbl_Sub,    [a1,a2])
+translateOp [r] DoubleMulOp    [a1,a2] = Just (Just1 r, MO_Dbl_Mul,    [a1,a2])
+translateOp [r] DoubleDivOp    [a1,a2] = Just (Just1 r, MO_Dbl_Div,    [a1,a2])
+translateOp [r] DoublePowerOp  [a1,a2] = Just (Just1 r, MO_Dbl_Pwr,    [a1,a2])
+
+translateOp [r] DoubleSinOp    [a1]    = Just (Just1 r, MO_Dbl_Sin,    [a1])
+translateOp [r] DoubleCosOp    [a1]    = Just (Just1 r, MO_Dbl_Cos,    [a1])
+translateOp [r] DoubleTanOp    [a1]    = Just (Just1 r, MO_Dbl_Tan,    [a1])
+translateOp [r] DoubleSinhOp   [a1]    = Just (Just1 r, MO_Dbl_Sinh,   [a1])
+translateOp [r] DoubleCoshOp   [a1]    = Just (Just1 r, MO_Dbl_Cosh,   [a1])
+translateOp [r] DoubleTanhOp   [a1]    = Just (Just1 r, MO_Dbl_Tanh,   [a1])
+translateOp [r] DoubleAsinOp   [a1]    = Just (Just1 r, MO_Dbl_Asin,    [a1])
+translateOp [r] DoubleAcosOp   [a1]    = Just (Just1 r, MO_Dbl_Acos,    [a1])
+translateOp [r] DoubleAtanOp   [a1]    = Just (Just1 r, MO_Dbl_Atan,    [a1])
+translateOp [r] DoubleLogOp    [a1]    = Just (Just1 r, MO_Dbl_Log,    [a1])
+translateOp [r] DoubleExpOp    [a1]    = Just (Just1 r, MO_Dbl_Exp,    [a1])
+translateOp [r] DoubleSqrtOp   [a1]    = Just (Just1 r, MO_Dbl_Sqrt,    [a1])
+translateOp [r] DoubleNegOp    [a1]    = Just (Just1 r, MO_Dbl_Neg,    [a1])
+
+-- Float ops
+
+translateOp [r] FloatEqOp     [a1,a2] = Just (Just1 r, MO_Flt_Eq,      [a1,a2])
+translateOp [r] FloatNeOp     [a1,a2] = Just (Just1 r, MO_Flt_Ne,      [a1,a2])
+translateOp [r] FloatGeOp     [a1,a2] = Just (Just1 r, MO_Flt_Ge,      [a1,a2])
+translateOp [r] FloatLeOp     [a1,a2] = Just (Just1 r, MO_Flt_Le,      [a1,a2])
+translateOp [r] FloatGtOp     [a1,a2] = Just (Just1 r, MO_Flt_Gt,      [a1,a2])
+translateOp [r] FloatLtOp     [a1,a2] = Just (Just1 r, MO_Flt_Lt,      [a1,a2])
+
+translateOp [r] FloatAddOp    [a1,a2] = Just (Just1 r, MO_Flt_Add,    [a1,a2])
+translateOp [r] FloatSubOp    [a1,a2] = Just (Just1 r, MO_Flt_Sub,    [a1,a2])
+translateOp [r] FloatMulOp    [a1,a2] = Just (Just1 r, MO_Flt_Mul,    [a1,a2])
+translateOp [r] FloatDivOp    [a1,a2] = Just (Just1 r, MO_Flt_Div,    [a1,a2])
+translateOp [r] FloatPowerOp  [a1,a2] = Just (Just1 r, MO_Flt_Pwr,    [a1,a2])
+
+translateOp [r] FloatSinOp    [a1]    = Just (Just1 r, MO_Flt_Sin,    [a1])
+translateOp [r] FloatCosOp    [a1]    = Just (Just1 r, MO_Flt_Cos,    [a1])
+translateOp [r] FloatTanOp    [a1]    = Just (Just1 r, MO_Flt_Tan,    [a1])
+translateOp [r] FloatSinhOp   [a1]    = Just (Just1 r, MO_Flt_Sinh,   [a1])
+translateOp [r] FloatCoshOp   [a1]    = Just (Just1 r, MO_Flt_Cosh,   [a1])
+translateOp [r] FloatTanhOp   [a1]    = Just (Just1 r, MO_Flt_Tanh,   [a1])
+translateOp [r] FloatAsinOp   [a1]    = Just (Just1 r, MO_Flt_Asin,    [a1])
+translateOp [r] FloatAcosOp   [a1]    = Just (Just1 r, MO_Flt_Acos,    [a1])
+translateOp [r] FloatAtanOp   [a1]    = Just (Just1 r, MO_Flt_Atan,    [a1])
+translateOp [r] FloatLogOp    [a1]    = Just (Just1 r, MO_Flt_Log,    [a1])
+translateOp [r] FloatExpOp    [a1]    = Just (Just1 r, MO_Flt_Exp,    [a1])
+translateOp [r] FloatSqrtOp   [a1]    = Just (Just1 r, MO_Flt_Sqrt,    [a1])
+translateOp [r] FloatNegOp    [a1]    = Just (Just1 r, MO_Flt_Neg,    [a1])
+
+-- Conversions
+
+translateOp [r] Int2DoubleOp [a1]    = Just (Just1 r, MO_NatS_to_Dbl,    [a1])
+translateOp [r] Double2IntOp [a1]    = Just (Just1 r, MO_Dbl_to_NatS,    [a1])
+
+translateOp [r] Int2FloatOp  [a1]    = Just (Just1 r, MO_NatS_to_Flt,    [a1])
+translateOp [r] Float2IntOp  [a1]    = Just (Just1 r, MO_Flt_to_NatS,    [a1])
+
+translateOp [r] Float2DoubleOp [a1]    = Just (Just1 r, MO_Flt_to_Dbl,    [a1])
+translateOp [r] Double2FloatOp [a1]    = Just (Just1 r, MO_Dbl_to_Flt,    [a1])
+
+translateOp [r] Int2WordOp   [a1]    = Just (Just1 r, MO_NatS_to_NatU,   [a1])
+translateOp [r] Word2IntOp   [a1]    = Just (Just1 r, MO_NatU_to_NatS,   [a1])
+
+translateOp [r] Int2AddrOp   [a1]    = Just (Just1 r, MO_NatS_to_NatP,   [a1])
+translateOp [r] Addr2IntOp   [a1]    = Just (Just1 r, MO_NatP_to_NatS,   [a1])
+
+translateOp [r] OrdOp    [a1]    = Just (Just1 r, MO_32U_to_NatS,    [a1])
+translateOp [r] ChrOp    [a1]    = Just (Just1 r, MO_NatS_to_32U,    [a1])
+
+translateOp [r] Narrow8IntOp   [a1]    = Just (Just1 r, MO_8S_to_NatS,    [a1])
+translateOp [r] Narrow16IntOp  [a1]    = Just (Just1 r, MO_16S_to_NatS,    [a1])
+translateOp [r] Narrow32IntOp  [a1]    = Just (Just1 r, MO_32S_to_NatS,    [a1])
+
+translateOp [r] Narrow8WordOp   [a1]    = Just (Just1 r, MO_8U_to_NatU,    [a1])
+translateOp [r] Narrow16WordOp  [a1]    = Just (Just1 r, MO_16U_to_NatU,    [a1])
+translateOp [r] Narrow32WordOp  [a1]    = Just (Just1 r, MO_32U_to_NatU,    [a1])
+
+translateOp [r] SameMutVarOp   [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+translateOp [r] SameMVarOp     [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+translateOp [r] SameMutableArrayOp  [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+translateOp [r] SameMutableByteArrayOp [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+translateOp [r] EqForeignObj [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+translateOp [r] EqStablePtrOp [a1,a2]  = Just (Just1 r, MO_Nat_Eq,    [a1,a2])
+
+translateOp _ _ _ = Nothing
+
+\end{code}
index 4da5c57..ae46087 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CLabel.lhs,v 1.48 2001/11/08 12:56:01 simonmar Exp $
+% $Id: CLabel.lhs,v 1.49 2001/12/05 17:35:12 sewardj Exp $
 %
 \section[CLabel]{@CLabel@: Information to make C Labels}
 
@@ -348,6 +348,7 @@ labelType (RtsLabel (RtsBlackHoleInfoTbl _))  = InfoTblType
 labelType (RtsLabel (RtsSelectorInfoTbl _ _)) = InfoTblType
 labelType (RtsLabel (RtsApInfoTbl _ _))       = InfoTblType
 labelType (RtsLabel RtsUpdInfo)              = InfoTblType
+labelType (RtsLabel (Rts_Info _))             = InfoTblType
 labelType (CaseLabel _ CaseReturnInfo)        = InfoTblType
 labelType (CaseLabel _ CaseReturnPt)         = CodeType
 labelType (CaseLabel _ CaseVecTbl)            = VecTblType
diff --git a/ghc/compiler/absCSyn/MachOp.hs b/ghc/compiler/absCSyn/MachOp.hs
new file mode 100644 (file)
index 0000000..e17cde4
--- /dev/null
@@ -0,0 +1,478 @@
+
+module MachOp  ( MachOp(..), pprMachOp,
+                 isDefinitelyInlineMachOp, 
+                 isCommutableMachOp,
+                 isComparisonMachOp,
+                  resultRepsOfMachOp
+                 )
+where
+
+#include "HsVersions.h"
+
+import PrimRep         ( PrimRep(..) )
+import Maybes          ( Maybe012(..) )
+import Outputable
+
+
+{- Machine-level primops; ones which we can reasonably delegate to the
+   native code generators to handle.  Basically contains C's primops
+   and no others.
+
+   Nomenclature: all ops indicate width and signedness, where
+   appropriate.  Widths: 8/16/32/64 means the given size, obviously.
+   Nat means the native word size.  Signedness: S means signed, U
+   means unsigned.  For operations where signedness is irrelevant or
+   makes no difference (for example integer add), the signedness
+   component is omitted.
+
+   An exception: NatP is a ptr-typed native word.  From the point of
+   view of the native code generators this distinction is irrelevant,
+   but the C code generator sometimes needs this info to emit the
+   right casts.  
+-}
+
+data MachOp
+
+  -- OPS at the native word size
+  = MO_Nat_Add         -- +
+  | MO_Nat_Sub         -- -
+  | MO_Nat_Eq
+  | MO_Nat_Ne
+
+  | MO_NatS_Ge
+  | MO_NatS_Le
+  | MO_NatS_Gt
+  | MO_NatS_Lt
+
+  | MO_NatU_Ge
+  | MO_NatU_Le
+  | MO_NatU_Gt
+  | MO_NatU_Lt
+
+  | MO_NatS_Mul                -- signed *
+  | MO_NatS_Quot       -- signed / (same semantics as IntQuotOp)
+  | MO_NatS_Rem                -- signed % (same semantics as IntRemOp)
+  | MO_NatS_Neg                -- unary -
+
+  | MO_NatU_Mul                -- unsigned *
+  | MO_NatU_Quot       -- unsigned / (same semantics as WordQuotOp)
+  | MO_NatU_Rem                -- unsigned % (same semantics as WordRemOp)
+
+  | MO_NatS_AddC       -- signed +, first result sum, second result carry
+  | MO_NatS_SubC       -- signed -, first result sum, second result borrow
+  | MO_NatS_MulC       -- signed *, first result sum, second result carry
+
+  | MO_Nat_And
+  | MO_Nat_Or
+  | MO_Nat_Xor
+  | MO_Nat_Not
+  | MO_Nat_Shl
+  | MO_Nat_Shr
+  | MO_Nat_Sar
+
+  -- OPS at 32 bits regardless of word size
+  | MO_32U_Eq
+  | MO_32U_Ne
+  | MO_32U_Ge
+  | MO_32U_Le
+  | MO_32U_Gt
+  | MO_32U_Lt
+
+  -- IEEE754 Double ops
+  | MO_Dbl_Eq
+  | MO_Dbl_Ne
+  | MO_Dbl_Ge
+  | MO_Dbl_Le
+  | MO_Dbl_Gt
+  | MO_Dbl_Lt
+
+  | MO_Dbl_Add
+  | MO_Dbl_Sub
+  | MO_Dbl_Mul
+  | MO_Dbl_Div
+  | MO_Dbl_Pwr
+
+  | MO_Dbl_Sin
+  | MO_Dbl_Cos
+  | MO_Dbl_Tan
+  | MO_Dbl_Sinh
+  | MO_Dbl_Cosh
+  | MO_Dbl_Tanh
+  | MO_Dbl_Asin
+  | MO_Dbl_Acos
+  | MO_Dbl_Atan
+  | MO_Dbl_Log
+  | MO_Dbl_Exp
+  | MO_Dbl_Sqrt
+  | MO_Dbl_Neg
+
+  -- IEEE754 Float ops
+  | MO_Flt_Add
+  | MO_Flt_Sub
+  | MO_Flt_Mul
+  | MO_Flt_Div
+  | MO_Flt_Pwr
+
+  | MO_Flt_Eq
+  | MO_Flt_Ne
+  | MO_Flt_Ge
+  | MO_Flt_Le
+  | MO_Flt_Gt
+  | MO_Flt_Lt
+
+  | MO_Flt_Sin
+  | MO_Flt_Cos
+  | MO_Flt_Tan
+  | MO_Flt_Sinh
+  | MO_Flt_Cosh
+  | MO_Flt_Tanh
+  | MO_Flt_Asin
+  | MO_Flt_Acos
+  | MO_Flt_Atan
+  | MO_Flt_Log
+  | MO_Flt_Exp
+  | MO_Flt_Neg
+  | MO_Flt_Sqrt
+
+  -- Conversions.  Some of these are NOPs, in which case they
+  -- are here usually to placate the C code generator.
+  | MO_32U_to_NatS
+  | MO_NatS_to_32U
+
+  | MO_NatS_to_Dbl
+  | MO_Dbl_to_NatS
+
+  | MO_NatS_to_Flt
+  | MO_Flt_to_NatS
+
+  | MO_NatS_to_NatU
+  | MO_NatU_to_NatS
+
+  | MO_NatS_to_NatP
+  | MO_NatP_to_NatS
+  | MO_NatU_to_NatP
+  | MO_NatP_to_NatU
+
+  | MO_Dbl_to_Flt
+  | MO_Flt_to_Dbl
+
+  | MO_8S_to_NatS
+  | MO_16S_to_NatS
+  | MO_32S_to_NatS
+  | MO_8U_to_NatU
+  | MO_16U_to_NatU
+  | MO_32U_to_NatU
+
+  -- Reading/writing arrays
+  | MO_ReadOSBI Int PrimRep   -- [base_ptr, index_value]
+  | MO_WriteOSBI Int PrimRep  -- [base_ptr, index_value, value_to_write]
+    -- Read/write a value :: the PrimRep
+    -- at byte address 
+    --    sizeof(machine_word)*Int + base_ptr + sizeof(PrimRep)*index_value
+    deriving Eq
+
+
+
+-- Almost, but not quite == text . derived show
+pprMachOp :: MachOp -> SDoc
+
+pprMachOp MO_Nat_Add       = text "MO_Nat_Add"
+pprMachOp MO_Nat_Sub       = text "MO_Nat_Sub"
+pprMachOp MO_Nat_Eq        = text "MO_Nat_Eq"
+pprMachOp MO_Nat_Ne        = text "MO_Nat_Ne"
+
+pprMachOp MO_NatS_Ge       = text "MO_NatS_Ge"
+pprMachOp MO_NatS_Le       = text "MO_NatS_Le"
+pprMachOp MO_NatS_Gt       = text "MO_NatS_Gt"
+pprMachOp MO_NatS_Lt       = text "MO_NatS_Lt"
+
+pprMachOp MO_NatU_Ge       = text "MO_NatU_Ge"
+pprMachOp MO_NatU_Le       = text "MO_NatU_Le"
+pprMachOp MO_NatU_Gt       = text "MO_NatU_Gt"
+pprMachOp MO_NatU_Lt       = text "MO_NatU_Lt"
+
+pprMachOp MO_NatS_Mul      = text "MO_NatS_Mul"
+pprMachOp MO_NatS_Quot     = text "MO_NatS_Quot"
+pprMachOp MO_NatS_Rem      = text "MO_NatS_Rem"
+pprMachOp MO_NatS_Neg      = text "MO_NatS_Neg"
+
+pprMachOp MO_NatU_Mul      = text "MO_NatU_Mul"
+pprMachOp MO_NatU_Quot     = text "MO_NatU_Quot"
+pprMachOp MO_NatU_Rem      = text "MO_NatU_Rem"
+
+pprMachOp MO_NatS_AddC     = text "MO_NatS_AddC"
+pprMachOp MO_NatS_SubC     = text "MO_NatS_SubC"
+pprMachOp MO_NatS_MulC     = text "MO_NatS_MulC"
+
+pprMachOp MO_Nat_And       = text "MO_Nat_And"
+pprMachOp MO_Nat_Or        = text "MO_Nat_Or"
+pprMachOp MO_Nat_Xor       = text "MO_Nat_Xor"
+pprMachOp MO_Nat_Not       = text "MO_Nat_Not"
+pprMachOp MO_Nat_Shl       = text "MO_Nat_Shl"
+pprMachOp MO_Nat_Shr       = text "MO_Nat_Shr"
+pprMachOp MO_Nat_Sar       = text "MO_Nat_Sar"
+
+pprMachOp MO_32U_Eq        = text "MO_32U_Eq"
+pprMachOp MO_32U_Ne        = text "MO_32U_Ne"
+pprMachOp MO_32U_Ge        = text "MO_32U_Ge"
+pprMachOp MO_32U_Le        = text "MO_32U_Le"
+pprMachOp MO_32U_Gt        = text "MO_32U_Gt"
+pprMachOp MO_32U_Lt        = text "MO_32U_Lt"
+
+pprMachOp MO_Dbl_Eq        = text "MO_Dbl_Eq"
+pprMachOp MO_Dbl_Ne        = text "MO_Dbl_Ne"
+pprMachOp MO_Dbl_Ge        = text "MO_Dbl_Ge"
+pprMachOp MO_Dbl_Le        = text "MO_Dbl_Le"
+pprMachOp MO_Dbl_Gt        = text "MO_Dbl_Gt"
+pprMachOp MO_Dbl_Lt        = text "MO_Dbl_Lt"
+
+pprMachOp MO_Dbl_Add       = text "MO_Dbl_Add"
+pprMachOp MO_Dbl_Sub       = text "MO_Dbl_Sub"
+pprMachOp MO_Dbl_Mul       = text "MO_Dbl_Mul"
+pprMachOp MO_Dbl_Div       = text "MO_Dbl_Div"
+pprMachOp MO_Dbl_Pwr       = text "MO_Dbl_Pwr"
+
+pprMachOp MO_Dbl_Sin       = text "MO_Dbl_Sin"
+pprMachOp MO_Dbl_Cos       = text "MO_Dbl_Cos"
+pprMachOp MO_Dbl_Tan       = text "MO_Dbl_Tan"
+pprMachOp MO_Dbl_Sinh      = text "MO_Dbl_Sinh"
+pprMachOp MO_Dbl_Cosh      = text "MO_Dbl_Cosh"
+pprMachOp MO_Dbl_Tanh      = text "MO_Dbl_Tanh"
+pprMachOp MO_Dbl_Asin      = text "MO_Dbl_Asin"
+pprMachOp MO_Dbl_Acos      = text "MO_Dbl_Acos"
+pprMachOp MO_Dbl_Atan      = text "MO_Dbl_Atan"
+pprMachOp MO_Dbl_Log       = text "MO_Dbl_Log"
+pprMachOp MO_Dbl_Exp       = text "MO_Dbl_Exp"
+pprMachOp MO_Dbl_Sqrt      = text "MO_Dbl_Sqrt"
+pprMachOp MO_Dbl_Neg       = text "MO_Dbl_Neg"
+
+pprMachOp MO_Flt_Add       = text "MO_Flt_Add"
+pprMachOp MO_Flt_Sub       = text "MO_Flt_Sub"
+pprMachOp MO_Flt_Mul       = text "MO_Flt_Mul"
+pprMachOp MO_Flt_Div       = text "MO_Flt_Div"
+pprMachOp MO_Flt_Pwr       = text "MO_Flt_Pwr"
+
+pprMachOp MO_Flt_Eq        = text "MO_Flt_Eq"
+pprMachOp MO_Flt_Ne        = text "MO_Flt_Ne"
+pprMachOp MO_Flt_Ge        = text "MO_Flt_Ge"
+pprMachOp MO_Flt_Le        = text "MO_Flt_Le"
+pprMachOp MO_Flt_Gt        = text "MO_Flt_Gt"
+pprMachOp MO_Flt_Lt        = text "MO_Flt_Lt"
+
+pprMachOp MO_Flt_Sin       = text "MO_Flt_Sin"
+pprMachOp MO_Flt_Cos       = text "MO_Flt_Cos"
+pprMachOp MO_Flt_Tan       = text "MO_Flt_Tan"
+pprMachOp MO_Flt_Sinh      = text "MO_Flt_Sinh"
+pprMachOp MO_Flt_Cosh      = text "MO_Flt_Cosh"
+pprMachOp MO_Flt_Tanh      = text "MO_Flt_Tanh"
+pprMachOp MO_Flt_Asin      = text "MO_Flt_Asin"
+pprMachOp MO_Flt_Acos      = text "MO_Flt_Acos"
+pprMachOp MO_Flt_Atan      = text "MO_Flt_Atan"
+pprMachOp MO_Flt_Log       = text "MO_Flt_Log"
+pprMachOp MO_Flt_Exp       = text "MO_Flt_Exp"
+pprMachOp MO_Flt_Sqrt      = text "MO_Flt_Sqrt"
+pprMachOp MO_Flt_Neg       = text "MO_Flt_Neg"
+
+pprMachOp MO_32U_to_NatS   = text "MO_32U_to_NatS"
+pprMachOp MO_NatS_to_32U   = text "MO_NatS_to_32U"
+
+pprMachOp MO_NatS_to_Dbl   = text "MO_NatS_to_Dbl"
+pprMachOp MO_Dbl_to_NatS   = text "MO_Dbl_to_NatS"
+
+pprMachOp MO_NatS_to_Flt   = text "MO_NatS_to_Flt"
+pprMachOp MO_Flt_to_NatS   = text "MO_Flt_to_NatS"
+
+pprMachOp MO_NatS_to_NatU  = text "MO_NatS_to_NatU"
+pprMachOp MO_NatU_to_NatS  = text "MO_NatU_to_NatS"
+
+pprMachOp MO_NatS_to_NatP  = text "MO_NatS_to_NatP"
+pprMachOp MO_NatP_to_NatS  = text "MO_NatP_to_NatS"
+pprMachOp MO_NatU_to_NatP  = text "MO_NatU_to_NatP"
+pprMachOp MO_NatP_to_NatU  = text "MO_NatP_to_NatU"
+
+pprMachOp MO_Dbl_to_Flt    = text "MO_Dbl_to_Flt"
+pprMachOp MO_Flt_to_Dbl    = text "MO_Flt_to_Dbl"
+
+pprMachOp MO_8S_to_NatS    = text "MO_8S_to_NatS"
+pprMachOp MO_16S_to_NatS   = text "MO_16S_to_NatS"
+pprMachOp MO_32S_to_NatS   = text "MO_32S_to_NatS"
+
+pprMachOp MO_8U_to_NatU    = text "MO_8U_to_NatU"
+pprMachOp MO_16U_to_NatU   = text "MO_16U_to_NatU"
+pprMachOp MO_32U_to_NatU   = text "MO_32U_to_NatU"
+
+pprMachOp (MO_ReadOSBI offset rep)
+   = text "MO_ReadOSBI" <> parens (int offset <> comma <> ppr rep)
+pprMachOp (MO_WriteOSBI offset rep)
+   = text "MO_WriteOSBI" <> parens (int offset <> comma <> ppr rep)
+
+
+
+-- Non-exported helper enumeration:
+data MO_Prop 
+   = MO_Commutable 
+   | MO_DefinitelyInline 
+   | MO_Comparison
+     deriving Eq
+
+comm   = MO_Commutable
+inline = MO_DefinitelyInline
+comp   = MO_Comparison
+
+
+-- If in doubt, return False.  This generates worse code on the
+-- via-C route, but has no effect on the native code routes.
+-- Remember that claims about definitely inline have to be true
+-- regardless of what the C compiler does, so we need to be 
+-- careful about boundary cases like sqrt which are sometimes
+-- implemented in software and sometimes in hardware.
+isDefinitelyInlineMachOp :: MachOp -> Bool
+isDefinitelyInlineMachOp mop = inline `elem` snd (machOpProps mop)
+
+-- If in doubt, return False.  This generates worse code on the
+-- native routes, but is otherwise harmless.
+isCommutableMachOp :: MachOp -> Bool
+isCommutableMachOp mop = comm `elem` snd (machOpProps mop)
+
+-- If in doubt, return False.  This generates worse code on the
+-- native routes, but is otherwise harmless.
+isComparisonMachOp :: MachOp -> Bool
+isComparisonMachOp mop = comp `elem` snd (machOpProps mop)
+
+-- Find the PrimReps for the returned value(s) of the MachOp.
+resultRepsOfMachOp :: MachOp -> Maybe012 PrimRep
+resultRepsOfMachOp mop = fst (machOpProps mop)
+
+-- This bit does the real work.
+machOpProps :: MachOp -> (Maybe012 PrimRep, [MO_Prop])
+
+machOpProps MO_Nat_Add       = (Just1 IntRep, [inline, comm])
+machOpProps MO_Nat_Sub       = (Just1 IntRep, [inline])
+machOpProps MO_Nat_Eq        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_Nat_Ne        = (Just1 IntRep, [inline, comp, comm])
+
+machOpProps MO_NatS_Ge       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatS_Le       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatS_Gt       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatS_Lt       = (Just1 IntRep, [inline, comp])
+
+machOpProps MO_NatU_Ge       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatU_Le       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatU_Gt       = (Just1 IntRep, [inline, comp])
+machOpProps MO_NatU_Lt       = (Just1 IntRep, [inline, comp])
+
+machOpProps MO_NatS_Mul      = (Just1 IntRep, [inline, comm])
+machOpProps MO_NatS_Quot     = (Just1 IntRep, [inline])
+machOpProps MO_NatS_Rem      = (Just1 IntRep, [inline])
+machOpProps MO_NatS_Neg      = (Just1 IntRep, [inline])
+
+machOpProps MO_NatU_Mul      = (Just1 WordRep, [inline, comm])
+machOpProps MO_NatU_Quot     = (Just1 WordRep, [inline])
+machOpProps MO_NatU_Rem      = (Just1 WordRep, [inline])
+
+machOpProps MO_NatS_AddC     = (Just2 IntRep IntRep, [])
+machOpProps MO_NatS_SubC     = (Just2 IntRep IntRep, [])
+machOpProps MO_NatS_MulC     = (Just2 IntRep IntRep, [])
+
+machOpProps MO_Nat_And       = (Just1 IntRep, [inline, comm])
+machOpProps MO_Nat_Or        = (Just1 IntRep, [inline, comm])
+machOpProps MO_Nat_Xor       = (Just1 IntRep, [inline, comm])
+machOpProps MO_Nat_Not       = (Just1 IntRep, [inline])
+machOpProps MO_Nat_Shl       = (Just1 IntRep, [inline])
+machOpProps MO_Nat_Shr       = (Just1 IntRep, [inline])
+machOpProps MO_Nat_Sar       = (Just1 IntRep, [inline])
+
+machOpProps MO_32U_Eq        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_32U_Ne        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_32U_Ge        = (Just1 IntRep, [inline, comp])
+machOpProps MO_32U_Le        = (Just1 IntRep, [inline, comp])
+machOpProps MO_32U_Gt        = (Just1 IntRep, [inline, comp])
+machOpProps MO_32U_Lt        = (Just1 IntRep, [inline, comp])
+
+machOpProps MO_Dbl_Eq        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_Dbl_Ne        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_Dbl_Ge        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Dbl_Le        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Dbl_Gt        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Dbl_Lt        = (Just1 IntRep, [inline, comp])
+
+machOpProps MO_Dbl_Add       = (Just1 DoubleRep, [inline, comm])
+machOpProps MO_Dbl_Sub       = (Just1 DoubleRep, [inline])
+machOpProps MO_Dbl_Mul       = (Just1 DoubleRep, [inline, comm])
+machOpProps MO_Dbl_Div       = (Just1 DoubleRep, [inline])
+machOpProps MO_Dbl_Pwr       = (Just1 DoubleRep, [])
+
+machOpProps MO_Dbl_Sin       = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Cos       = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Tan       = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Sinh      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Cosh      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Tanh      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Asin      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Acos      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Atan      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Log       = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Exp       = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Sqrt      = (Just1 DoubleRep, [])
+machOpProps MO_Dbl_Neg       = (Just1 DoubleRep, [inline])
+
+machOpProps MO_Flt_Add       = (Just1 FloatRep, [inline, comm])
+machOpProps MO_Flt_Sub       = (Just1 FloatRep, [inline])
+machOpProps MO_Flt_Mul       = (Just1 FloatRep, [inline, comm])
+machOpProps MO_Flt_Div       = (Just1 FloatRep, [inline])
+machOpProps MO_Flt_Pwr       = (Just1 FloatRep, [])
+
+machOpProps MO_Flt_Eq        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_Flt_Ne        = (Just1 IntRep, [inline, comp, comm])
+machOpProps MO_Flt_Ge        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Flt_Le        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Flt_Gt        = (Just1 IntRep, [inline, comp])
+machOpProps MO_Flt_Lt        = (Just1 IntRep, [inline, comp])
+
+machOpProps MO_Flt_Sin       = (Just1 FloatRep, [])
+machOpProps MO_Flt_Cos       = (Just1 FloatRep, [])
+machOpProps MO_Flt_Tan       = (Just1 FloatRep, [])
+machOpProps MO_Flt_Sinh      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Cosh      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Tanh      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Asin      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Acos      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Atan      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Log       = (Just1 FloatRep, [])
+machOpProps MO_Flt_Exp       = (Just1 FloatRep, [])
+machOpProps MO_Flt_Sqrt      = (Just1 FloatRep, [])
+machOpProps MO_Flt_Neg       = (Just1 FloatRep, [inline])
+
+machOpProps MO_32U_to_NatS   = (Just1 IntRep, [inline])
+machOpProps MO_NatS_to_32U   = (Just1 WordRep, [inline])
+
+machOpProps MO_NatS_to_Dbl   = (Just1 DoubleRep, [inline])
+machOpProps MO_Dbl_to_NatS   = (Just1 IntRep, [inline])
+
+machOpProps MO_NatS_to_Flt   = (Just1 FloatRep, [inline])
+machOpProps MO_Flt_to_NatS   = (Just1 IntRep, [inline])
+
+machOpProps MO_NatS_to_NatU  = (Just1 WordRep, [inline])
+machOpProps MO_NatU_to_NatS  = (Just1 IntRep, [inline])
+
+machOpProps MO_NatS_to_NatP  = (Just1 PtrRep, [inline])
+machOpProps MO_NatP_to_NatS  = (Just1 IntRep, [inline])
+machOpProps MO_NatU_to_NatP  = (Just1 PtrRep, [inline])
+machOpProps MO_NatP_to_NatU  = (Just1 WordRep, [inline])
+
+machOpProps MO_Dbl_to_Flt    = (Just1 FloatRep, [inline])
+machOpProps MO_Flt_to_Dbl    = (Just1 DoubleRep, [inline])
+
+machOpProps MO_8S_to_NatS    = (Just1 IntRep, [inline])
+machOpProps MO_16S_to_NatS   = (Just1 IntRep, [inline])
+machOpProps MO_32S_to_NatS   = (Just1 IntRep, [inline])
+
+machOpProps MO_8U_to_NatU    = (Just1 WordRep, [inline])
+machOpProps MO_16U_to_NatU   = (Just1 WordRep, [inline])
+machOpProps MO_32U_to_NatU   = (Just1 WordRep, [inline])
+
+machOpProps (MO_ReadOSBI offset rep)  = (Just1 rep, [inline])
+machOpProps (MO_WriteOSBI offset rep) = (Just0, [inline])
+
+
+
index 765971f..48a90b4 100644 (file)
@@ -19,13 +19,14 @@ module PprAbsC (
 
 import IO      ( Handle )
 
+import PrimRep 
 import AbsCSyn
 import ClosureInfo
 import AbsCUtils       ( getAmodeRep, nonemptyAbsC,
                          mixedPtrLocn, mixedTypeLocn
                        )
 
-import Constants       ( mIN_UPD_SIZE )
+import Constants       ( mIN_UPD_SIZE, wORD_SIZE )
 import ForeignCall     ( CCallSpec(..), CCallTarget(..), playSafe, ccallConvAttribute )
 import CLabel          ( externallyVisibleCLabel,
                          needsCDecl, pprCLabel,
@@ -44,10 +45,11 @@ import Literal              ( Literal(..) )
 import TyCon           ( tyConDataCons )
 import Name            ( NamedThing(..) )
 import DataCon         ( dataConWrapId )
-import Maybes          ( maybeToBool, catMaybes )
+import Maybes          ( Maybe012(..), maybe012ToList, maybeToBool, catMaybes )
 import PrimOp          ( primOpNeedsWrapper )
+import MachOp          ( MachOp(..) )
 import ForeignCall     ( ForeignCall(..) )
-import PrimRep         ( isFloatingRep, PrimRep(..), getPrimRepSize )
+import PrimRep         ( isFloatingRep, PrimRep(..), getPrimRepSize, getPrimRepArrayElemSize )
 import SMRep           ( pprSMRep )
 import Unique          ( pprUnique, Unique{-instance NamedThing-} )
 import UniqSet         ( emptyUniqSet, elementOfUniqSet,
@@ -58,6 +60,7 @@ import BitSet         ( BitSet, intBS )
 import Outputable
 import GlaExts
 import Util            ( nOfThem, lengthExceeds, listLengthCmp )
+import Maybe           ( isNothing )
 
 import ST
 
@@ -249,6 +252,70 @@ pprAbsC stmt@(COpStmt results (StgPrimOp op) args vol_regs) _
       -- primop macros do their own casting of result;
       -- hence we can toss the provided cast...
 
+-- NEW CASES FOR EXPANDED PRIMOPS
+
+-- We have to deal with some of these specially
+pprAbsC (CMachOpStmt (Just1 res) (MO_ReadOSBI offw scaleRep)
+                     [baseAmode, indexAmode] maybe_vols) 
+        _
+  | isNothing maybe_vols
+  = hcat [ -- text " /* ReadOSBI */ ",
+           ppr_amode res, equals, 
+           ppr_array_expression offw scaleRep baseAmode indexAmode, 
+           semi ]
+  | otherwise
+  = panic "pprAbsC:MO_ReadOSBI -- out-of-line array indexing ?!?!"
+
+pprAbsC (CMachOpStmt Just0 (MO_WriteOSBI offw scaleRep)
+                     [baseAmode, indexAmode, vAmode] maybe_vols)
+        _
+  | isNothing maybe_vols
+  = hcat [ -- text " /* WriteOSBI */ ",
+           ppr_array_expression offw scaleRep baseAmode indexAmode, 
+           equals, pprAmode vAmode,
+           semi ]
+  | otherwise
+  = panic "pprAbsC:MO_WriteOSBI -- out-of-line array indexing ?!?!"
+
+pprAbsC (CMachOpStmt (Just2 res carry) mop [arg1,arg2] maybe_vols) _
+  | mop `elem` [MO_NatS_AddC, MO_NatS_SubC, MO_NatS_MulC]
+  = hcat [ pprMachOp_for_C mop, 
+           lparen,
+           ppr_amode res, comma, ppr_amode carry, comma,
+           pprAmode arg1, comma, pprAmode arg2, 
+           rparen, semi ]
+
+-- The rest generically.
+
+pprAbsC stmt@(CMachOpStmt (Just1 res) mop [arg1,arg2] maybe_vols) _
+  = let prefix_fn = mop `elem` [MO_Dbl_Pwr, MO_Flt_Pwr]
+    in
+    case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
+    saves $$
+    hcat (
+       [ppr_amode res, equals]
+       ++ (if prefix_fn 
+           then [pprMachOp_for_C mop, parens (pprAmode arg1 <> comma <> pprAmode arg2)]
+           else [pprAmode arg1, pprMachOp_for_C mop, pprAmode arg2])
+       ++ [semi]
+    )
+    $$ restores
+    }
+
+pprAbsC stmt@(CMachOpStmt (Just1 res) mop [arg1] maybe_vols) _
+  = case ppr_maybe_vol_regs maybe_vols of {(saves,restores) ->
+    saves $$
+    hcat [ppr_amode res, equals, 
+          pprMachOp_for_C mop, parens (pprAmode arg1),
+          semi]
+    $$ restores
+    }
+
+pprAbsC stmt@(CSequential stuff) c
+  = vcat (map (flip pprAbsC c) stuff)
+
+-- end of NEW CASES FOR EXPANDED PRIMOPS
+
 pprAbsC stmt@(CSRT lbl closures) c
   = case (pprTempAndExternDecls stmt) of { (_, pp_exts) ->
          pp_exts
@@ -580,6 +647,151 @@ pprAbsC (CCostCentreStackDecl ccs)    _ = pprCostCentreStackDecl ccs
 \end{code}
 
 \begin{code}
+-- Print a CMachOp in a way suitable for emitting via C.
+pprMachOp_for_C MO_Nat_Add       = char '+'
+pprMachOp_for_C MO_Nat_Sub       = char '-'
+pprMachOp_for_C MO_Nat_Eq        = text "==" 
+pprMachOp_for_C MO_Nat_Ne        = text "!="
+
+pprMachOp_for_C MO_NatS_Ge       = text ">="
+pprMachOp_for_C MO_NatS_Le       = text "<="
+pprMachOp_for_C MO_NatS_Gt       = text ">"
+pprMachOp_for_C MO_NatS_Lt       = text "<"
+
+pprMachOp_for_C MO_NatU_Ge       = text ">="
+pprMachOp_for_C MO_NatU_Le       = text "<="
+pprMachOp_for_C MO_NatU_Gt       = text ">"
+pprMachOp_for_C MO_NatU_Lt       = text "<"
+
+pprMachOp_for_C MO_NatS_Mul      = char '*'
+pprMachOp_for_C MO_NatS_Quot     = char '/'
+pprMachOp_for_C MO_NatS_Rem      = char '%'
+pprMachOp_for_C MO_NatS_Neg      = char '-'
+
+pprMachOp_for_C MO_NatU_Mul      = char '*'
+pprMachOp_for_C MO_NatU_Quot     = char '/'
+pprMachOp_for_C MO_NatU_Rem      = char '%'
+
+pprMachOp_for_C MO_NatS_AddC    = text "addIntCzh"
+pprMachOp_for_C MO_NatS_SubC    = text "subIntCzh"
+pprMachOp_for_C MO_NatS_MulC    = text "mulIntCzh"
+
+pprMachOp_for_C MO_Nat_And       = text "&"
+pprMachOp_for_C MO_Nat_Or        = text "|"
+pprMachOp_for_C MO_Nat_Xor       = text "^"
+pprMachOp_for_C MO_Nat_Not       = text "~"
+pprMachOp_for_C MO_Nat_Shl       = text "<<"
+pprMachOp_for_C MO_Nat_Shr       = text ">>"
+pprMachOp_for_C MO_Nat_Sar       = text ">>"
+
+pprMachOp_for_C MO_32U_Eq        = text "=="
+pprMachOp_for_C MO_32U_Ne        = text "!="
+pprMachOp_for_C MO_32U_Ge        = text ">="
+pprMachOp_for_C MO_32U_Le        = text "<="
+pprMachOp_for_C MO_32U_Gt        = text ">"
+pprMachOp_for_C MO_32U_Lt        = text "<"
+
+pprMachOp_for_C MO_Dbl_Eq        = text "=="
+pprMachOp_for_C MO_Dbl_Ne        = text "!="
+pprMachOp_for_C MO_Dbl_Ge        = text ">="
+pprMachOp_for_C MO_Dbl_Le        = text "<="
+pprMachOp_for_C MO_Dbl_Gt        = text ">"
+pprMachOp_for_C MO_Dbl_Lt        = text "<"
+
+pprMachOp_for_C MO_Dbl_Add       = text "+"
+pprMachOp_for_C MO_Dbl_Sub       = text "-"
+pprMachOp_for_C MO_Dbl_Mul       = text "*"
+pprMachOp_for_C MO_Dbl_Div       = text "/"
+pprMachOp_for_C MO_Dbl_Pwr       = text "pow"
+
+pprMachOp_for_C MO_Dbl_Sin       = text "sin"
+pprMachOp_for_C MO_Dbl_Cos       = text "cos"
+pprMachOp_for_C MO_Dbl_Tan       = text "tan"
+pprMachOp_for_C MO_Dbl_Sinh      = text "sinh"
+pprMachOp_for_C MO_Dbl_Cosh      = text "cosh"
+pprMachOp_for_C MO_Dbl_Tanh      = text "tanh"
+pprMachOp_for_C MO_Dbl_Asin      = text "asin"
+pprMachOp_for_C MO_Dbl_Acos      = text "acos"
+pprMachOp_for_C MO_Dbl_Atan      = text "atan"
+pprMachOp_for_C MO_Dbl_Log       = text "log"
+pprMachOp_for_C MO_Dbl_Exp       = text "exp"
+pprMachOp_for_C MO_Dbl_Sqrt      = text "sqrt"
+pprMachOp_for_C MO_Dbl_Neg       = text "-"
+
+pprMachOp_for_C MO_Flt_Add       = text "+"
+pprMachOp_for_C MO_Flt_Sub       = text "-"
+pprMachOp_for_C MO_Flt_Mul       = text "*"
+pprMachOp_for_C MO_Flt_Div       = text "/"
+pprMachOp_for_C MO_Flt_Pwr       = text "pow"
+
+pprMachOp_for_C MO_Flt_Eq        = text "=="
+pprMachOp_for_C MO_Flt_Ne        = text "!="
+pprMachOp_for_C MO_Flt_Ge        = text ">="
+pprMachOp_for_C MO_Flt_Le        = text "<="
+pprMachOp_for_C MO_Flt_Gt        = text ">"
+pprMachOp_for_C MO_Flt_Lt        = text "<"
+
+pprMachOp_for_C MO_Flt_Sin       = text "sin"
+pprMachOp_for_C MO_Flt_Cos       = text "cos"
+pprMachOp_for_C MO_Flt_Tan       = text "tan"
+pprMachOp_for_C MO_Flt_Sinh      = text "sinh"
+pprMachOp_for_C MO_Flt_Cosh      = text "cosh"
+pprMachOp_for_C MO_Flt_Tanh      = text "tanh"
+pprMachOp_for_C MO_Flt_Asin      = text "asin"
+pprMachOp_for_C MO_Flt_Acos      = text "acos"
+pprMachOp_for_C MO_Flt_Atan      = text "atan"
+pprMachOp_for_C MO_Flt_Log       = text "log"
+pprMachOp_for_C MO_Flt_Exp       = text "exp"
+pprMachOp_for_C MO_Flt_Sqrt      = text "sqrt"
+pprMachOp_for_C MO_Flt_Neg       = text "-"
+
+pprMachOp_for_C MO_32U_to_NatS   = text "(StgInt)"
+pprMachOp_for_C MO_NatS_to_32U   = text "(StgWord32)"
+
+pprMachOp_for_C MO_NatS_to_Dbl   = text "(StgDouble)"
+pprMachOp_for_C MO_Dbl_to_NatS   = text "(StgInt)"
+
+pprMachOp_for_C MO_NatS_to_Flt   = text "(StgFloat)"
+pprMachOp_for_C MO_Flt_to_NatS   = text "(StgInt)"
+
+pprMachOp_for_C MO_NatS_to_NatU  = text "(StgWord)"
+pprMachOp_for_C MO_NatU_to_NatS  = text "(StgInt)"
+
+pprMachOp_for_C MO_NatS_to_NatP  = text "(void*)"
+pprMachOp_for_C MO_NatP_to_NatS  = text "(StgInt)"
+pprMachOp_for_C MO_NatU_to_NatP  = text "(void*)"
+pprMachOp_for_C MO_NatP_to_NatU  = text "(StgWord)"
+
+pprMachOp_for_C MO_Dbl_to_Flt    = text "(StgFloat)"
+pprMachOp_for_C MO_Flt_to_Dbl    = text "(StgDouble)"
+
+pprMachOp_for_C MO_8S_to_NatS    = text "(StgInt8)(StgInt)"
+pprMachOp_for_C MO_16S_to_NatS   = text "(StgInt16)(StgInt)"
+pprMachOp_for_C MO_32S_to_NatS   = text "(StgInt32)(StgInt)"
+
+pprMachOp_for_C MO_8U_to_NatU    = text "(StgWord8)(StgWord)"
+pprMachOp_for_C MO_16U_to_NatU   = text "(StgWord16)(StgWord)"
+pprMachOp_for_C MO_32U_to_NatU   = text "(StgWord32)(StgWord)"
+
+pprMachOp_for_C (MO_ReadOSBI _ _)  = panic "pprMachOp_for_C:MO_ReadOSBI"
+pprMachOp_for_C (MO_WriteOSBI _ _) = panic "pprMachOp_for_C:MO_WriteOSBI"
+
+
+-- Helper for printing array expressions.
+ppr_array_expression offw scaleRep baseAmode indexAmode
+   -- create:
+   -- * (scaleRep*) (
+   --      ((char*)baseAmode) + offw*bytes_per_word + indexAmode*bytes_per_scaleRep
+   --   )
+   = let offb  = parens (int offw <> char '*' <> int wORD_SIZE)
+         indb  = parens (parens (pprAmode indexAmode) 
+                         <> char '*' <> int (getPrimRepArrayElemSize scaleRep))
+         baseb = text "(char*)" <> parens (pprAmode baseAmode)
+         addr  = parens baseb <+> char '+' <+> offb <+> char '+' <+> indb
+     in
+         char '*' <> parens (ppr scaleRep <> char '*') <> parens addr
+
+
 ppLocalness lbl
   = if (externallyVisibleCLabel lbl) 
                then empty 
@@ -626,6 +838,15 @@ non_void amode
 \end{code}
 
 \begin{code}
+ppr_maybe_vol_regs :: Maybe [MagicId] -> (SDoc, SDoc)
+ppr_maybe_vol_regs Nothing
+   = (empty, empty)
+ppr_maybe_vol_regs (Just vrs)
+   = case ppr_vol_regs vrs of
+        (saves, restores) 
+           -> (pp_basic_saves $$ saves,
+               pp_basic_restores $$ restores)
+
 ppr_vol_regs :: [MagicId] -> (SDoc, SDoc)
 
 ppr_vol_regs [] = (empty, empty)
@@ -677,33 +898,27 @@ if_profiling pretty
 -- ---------------------------------------------------------------------------
 
 do_if_stmt discrim tag alt_code deflt c
-  = case tag of
-      -- This special case happens when testing the result of a comparison.
-      -- We can just avoid some redundant clutter in the output.
-      MachInt n | n==0 -> ppr_if_stmt (pprAmode discrim)
-                                     deflt alt_code
-                                     (addrModeCosts discrim Rhs) c
-      other            -> let
-                              cond = hcat [ pprAmode discrim
-                                          , ptext SLIT(" == ")
-                                          , tcast
-                                          , pprAmode (CLit tag)
-                                          ]
-                               -- to be absolutely sure that none of the 
-                               -- conversion rules hit, e.g.,
-                               --
-                               --     minInt is different to (int)minInt
-                               --
-                               -- in C (when minInt is a number not a constant
-                               --  expression which evaluates to it.)
-                               -- 
-                              tcast = case other of
-                                          MachInt _  -> ptext SLIT("(I_)")
-                                          _          -> empty
-                           in
-                           ppr_if_stmt cond
-                                        alt_code deflt
-                                        (addrModeCosts discrim Rhs) c
+   = let
+       cond = hcat [ pprAmode discrim
+                  , ptext SLIT(" == ")
+                  , tcast
+                  , pprAmode (CLit tag)
+                  ]
+       -- to be absolutely sure that none of the 
+       -- conversion rules hit, e.g.,
+       --
+       --     minInt is different to (int)minInt
+        --
+       -- in C (when minInt is a number not a constant
+       --  expression which evaluates to it.)
+       -- 
+       tcast = case tag of
+                  MachInt _  -> ptext SLIT("(I_)")
+                  _          -> empty
+     in
+     ppr_if_stmt cond
+                alt_code deflt
+                (addrModeCosts discrim Rhs) c
 
 ppr_if_stmt pp_pred then_part else_part discrim_costs c
   = vcat [
@@ -1093,6 +1308,10 @@ That is, the indexing is done in units of kind1, but the resulting
 amode has kind2.
 
 \begin{code}
+ppr_amode (CMem rep addr)
+  = let txt_rep = pprPrimKind rep
+    in  hcat [ char '*', parens (txt_rep <> char '*'), parens (ppr_amode addr) ]
+
 ppr_amode (CVal reg_rel@(CIndex _ _ _) kind)
   = case (pprRegRelative False{-no sign wanted-} reg_rel) of
        (pp_reg, Nothing)     -> panic "ppr_amode: CIndex"
@@ -1177,6 +1396,9 @@ cCheckMacroText   HP_CHK_UT_ALT           = SLIT("HP_CHK_UT_ALT")
 cCheckMacroText        HP_CHK_GEN              = SLIT("HP_CHK_GEN")
 \end{code}
 
+\begin{code}
+\end{code}
+
 %************************************************************************
 %*                                                                     *
 \subsection[ppr-liveness-masks]{Liveness Masks}
@@ -1493,9 +1715,15 @@ ppr_decls_AbsC (CInitHdr cl_info reg_rel cost_centre _)
   where
     info_lbl = infoTableLabelFromCI cl_info
 
+ppr_decls_AbsC (CMachOpStmt res        _ args _) = ppr_decls_Amodes (maybe012ToList res ++ args)
 ppr_decls_AbsC (COpStmt        results _ args _) = ppr_decls_Amodes (results ++ args)
+
 ppr_decls_AbsC (CSimultaneous abc)       = ppr_decls_AbsC abc
 
+ppr_decls_AbsC (CSequential abcs) 
+  = mapTE ppr_decls_AbsC abcs  `thenTE` \ t_and_e_s ->
+    returnTE (maybe_vcat t_and_e_s)
+
 ppr_decls_AbsC (CCheck             _ amodes code) = 
      ppr_decls_Amodes amodes `thenTE` \p1 ->
      ppr_decls_AbsC code     `thenTE` \p2 ->
index 379c397..a863c75 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgCase.lhs,v 1.54 2001/10/11 14:31:45 sewardj Exp $
+% $Id: CgCase.lhs,v 1.55 2001/12/05 17:35:13 sewardj Exp $
 %
 %********************************************************
 %*                                                     *
@@ -156,7 +156,8 @@ cgCase (StgOpApp op args _)
                tag_amode = CTemp (newTagUnique (getUnique bndr) 'C') IntRep
              in
              getVolatileRegs live_in_alts                      `thenFC` \ vol_regs ->
-             absC (COpStmt [tag_amode] op arg_amodes vol_regs) `thenC`
+             absC (COpStmt [tag_amode] op arg_amodes vol_regs)
+                                                               `thenC`
                                -- NB: no liveness arg
              returnFC tag_amode
     }                                          `thenFC` \ tag_amode ->
index dbd6bf1..c8beedd 100644 (file)
@@ -29,7 +29,7 @@ import CmdLineOpts    ( DynFlags(..), DynFlag(..), dopt )
 
 import List             ( replicate )
 import System          ( ExitCode(..), exitWith )
-import IO              ( hPutStr, hPutStrLn, stderr )
+import IO              ( hPutStr, hPutStrLn, stderr, stdout )
 \end{code}
 
 \begin{code}
@@ -146,8 +146,12 @@ dumpIfSet_core dflags flag hdr doc
 
 dumpIfSet_dyn :: DynFlags -> DynFlag -> String -> SDoc -> IO ()
 dumpIfSet_dyn dflags flag hdr doc
-  | dopt flag dflags || verbosity dflags >= 4 = printDump (dump hdr doc)
-  | otherwise                                 = return ()
+  | dopt flag dflags || verbosity dflags >= 4 
+  = if   flag `elem` [Opt_D_dump_stix, Opt_D_dump_asm]
+    then printForC stdout (dump hdr doc)
+    else printDump (dump hdr doc)
+  | otherwise
+  = return ()
 
 dumpIfSet_dyn_or :: DynFlags -> [DynFlag] -> String -> SDoc -> IO ()
 dumpIfSet_dyn_or dflags flags hdr doc
index 5ee35ab..aee085a 100644 (file)
@@ -21,7 +21,7 @@ import SMRep          ( fixedItblSize,
                          rET_SMALL, rET_BIG, 
                          rET_VEC_SMALL, rET_VEC_BIG 
                        )
-import Constants       ( mIN_UPD_SIZE )
+import Constants       ( mIN_UPD_SIZE, wORD_SIZE )
 import CLabel           ( CLabel, mkReturnInfoLabel, mkReturnPtLabel,
                           mkClosureTblLabel, mkClosureLabel,
                          labelDynamic, mkSplitMarkerLabel )
@@ -30,14 +30,14 @@ import ClosureInfo  ( infoTableLabelFromCI, entryLabelFromCI,
                          staticClosureNeedsLink
                        )
 import Literal         ( Literal(..), word2IntLit )
-import Maybes          ( maybeToBool )
+import Maybes          ( Maybe012(..), maybeToBool )
 import StgSyn          ( StgOp(..) )
-import PrimOp          ( primOpNeedsWrapper, PrimOp(..) )
+import MachOp          ( MachOp(..), resultRepsOfMachOp )
 import PrimRep         ( isFloatingRep, PrimRep(..) )
 import StixInfo                ( genCodeInfoTable, genBitmapInfoTable,
                          livenessIsSmall, bitmapToIntegers )
 import StixMacro       ( macroCode, checkCode )
-import StixPrim                ( primCode, foreignCallCode, amodeToStix, amodeToStix' )
+import StixPrim                ( foreignCallCode, amodeToStix, amodeToStix' )
 import Outputable       ( pprPanic, ppr )
 import UniqSupply      ( returnUs, thenUs, mapUs, getUniqueUs, UniqSM )
 import Util            ( naturalMergeSortLe )
@@ -47,6 +47,12 @@ import DataCon               ( dataConWrapId )
 import Name             ( NamedThing(..) )
 import CmdLineOpts     ( opt_Static, opt_EnsureSplittableC )
 import Outputable      ( assertPanic )
+
+-- DEBUGGING ONLY
+--import IOExts                ( trace )
+--import Outputable    ( showSDoc )
+--import MachOp                ( pprMachOp )
+
 \end{code}
 
 For each independent chunk of AbstractC code, we generate a list of
@@ -55,7 +61,7 @@ We leave the chunks separated so that register allocation can be
 performed locally within the chunk.
 
 \begin{code}
-genCodeAbstractC :: AbstractC -> UniqSM [StixTree]
+genCodeAbstractC :: AbstractC -> UniqSM [StixStmt]
 
 genCodeAbstractC absC
   = gentopcode absC
@@ -64,7 +70,6 @@ genCodeAbstractC absC
  a2stix'     = amodeToStix'
  volsaves    = volatileSaves
  volrestores = volatileRestores
- p2stix      = primCode
  macro_code  = macroCode
  -- real code follows... ---------
 \end{code}
@@ -151,7 +156,7 @@ Here we handle top-level things, like @CCodeBlock@s and
             , StData DataPtrRep (map mk_StCLbl_for_SRT closures)
             ]
     where
-       mk_StCLbl_for_SRT :: CLabel -> StixTree
+       mk_StCLbl_for_SRT :: CLabel -> StixExpr
        mk_StCLbl_for_SRT label
           | labelDynamic label
           = StIndex Int8Rep (StCLbl label) (StInt 1)
@@ -183,15 +188,15 @@ Here we handle top-level things, like @CCodeBlock@s and
             : StData IntRep [StInt 0]
             : StSegment TextSegment
             : StLabel lbl
-            : StCondJump tmp_lbl (StPrim IntNeOp       
+            : StCondJump tmp_lbl (StMachOp MO_Nat_Ne
                                     [StInd IntRep (StCLbl flag_lbl),
                                      StInt 0])
-            : StAssign IntRep (StInd IntRep (StCLbl flag_lbl)) (StInt 1)
+            : StAssignMem IntRep (StCLbl flag_lbl) (StInt 1)
             : code 
             [ StLabel tmp_lbl
-            , StAssign PtrRep stgSp
-                        (StIndex PtrRep stgSp (StInt (-1)))
-            , StJump NoDestInfo (StInd WordRep stgSp)
+            , StAssignReg PtrRep stgSp
+                           (StIndex PtrRep (StReg stgSp) (StInt (-1)))
+            , StJump NoDestInfo (StInd WordRep (StReg stgSp))
             ])
 
  gentopcode absC
@@ -294,6 +299,14 @@ resulting StixTreeLists are joined together.
     gencode c2                         `thenUs` \ b2 ->
     returnUs (b1 . b2)
 
+ gencode (CSequential stuff)
+  = foo stuff
+    where
+       foo [] = returnUs id
+       foo (s:ss) = gencode s  `thenUs` \ stix ->
+                    foo ss     `thenUs` \ stixes ->
+                    returnUs (stix . stixes)
+
 \end{code}
 
 Initialising closure headers in the heap...a fairly complex ordeal if
@@ -309,7 +322,7 @@ addresses, etc.)
        lhs = a2stix reg_rel
        lbl = infoTableLabelFromCI cl_info
     in
-       returnUs (\xs -> StAssign PtrRep (StInd PtrRep lhs) (StCLbl lbl) : xs)
+       returnUs (\xs -> StAssignMem PtrRep lhs (StCLbl lbl) : xs)
 
 \end{code}
 
@@ -340,7 +353,7 @@ of the source?  Be careful about floats/doubles.
        lhs' = a2stix lhs
        rhs' = a2stix' rhs
     in
-       returnUs (\xs -> StAssign pk' lhs' rhs' : xs)
+       returnUs (\xs -> mkStAssign pk' lhs' rhs' : xs)
 
 \end{code}
 
@@ -373,8 +386,8 @@ which varies depending on whether we're profiling etc.
   = returnUs (\xs -> StJump NoDestInfo dest : xs)
   where
     dest = StInd PtrRep (StIndex PtrRep (a2stix table) dyn_off)
-    dyn_off = StPrim IntSubOp [StPrim IntNegOp [a2stix am], 
-                              StInt (toInteger (fixedItblSize+1))]
+    dyn_off = StMachOp MO_Nat_Sub [StMachOp MO_NatS_Neg [a2stix am], 
+                                  StInt (toInteger (fixedItblSize+1))]
 
 \end{code}
 
@@ -386,17 +399,60 @@ Now the PrimOps, some of which may need caller-saves register wrappers.
     foreignCallCode (nonVoid results) fcall (nonVoid args)
 
  gencode (COpStmt results (StgPrimOp op) args vols)
-  -- ToDo (ADR?): use that liveness mask
-  | primOpNeedsWrapper op
-  = let
-       saves    = volsaves vols
-       restores = volrestores vols
+  = panic "AbsCStixGen.gencode: un-translated PrimOp"
+
+ -- Translate out array indexing primops right here, so that
+ -- individual targets don't have to deal with them
+
+ gencode (CMachOpStmt (Just1 r1) (MO_ReadOSBI off_w rep) [base,index] vols) 
+  = returnUs (\xs ->
+       mkStAssign 
+          rep 
+          (a2stix r1) 
+          (StInd rep (StMachOp MO_Nat_Add 
+                               [StIndex rep (a2stix base) (a2stix index), 
+                                StInt (toInteger (off_w * wORD_SIZE))]))
+       : xs
+    )
+
+ gencode (CMachOpStmt Just0 (MO_WriteOSBI off_w rep) [base,index,val] vols) 
+  = returnUs (\xs ->
+       StAssignMem 
+          rep 
+          (StMachOp MO_Nat_Add 
+                    [StIndex rep (a2stix base) (a2stix index), 
+                     StInt (toInteger (off_w * wORD_SIZE))])
+          (a2stix val)
+       : xs
+    )
+
+ -- Gruesome cases for multiple-result primops
+ gencode (CMachOpStmt (Just2 r1 r2) mop [arg1, arg2] vols)
+  | mop `elem` [MO_NatS_AddC, MO_NatS_SubC, MO_NatS_MulC]
+  = getUniqueUs `thenUs`               \ u1 ->
+    getUniqueUs `thenUs`               \ u2 ->
+    let vr1 = StixVReg u1 IntRep
+        vr2 = StixVReg u2 IntRep
+        r1s = a2stix r1
+        r2s = a2stix r2
     in
-       p2stix (nonVoid results) op (nonVoid args)
-                                                       `thenUs` \ code ->
-       returnUs (\xs -> saves ++ code (restores ++ xs))
+    returnUs (\xs ->
+       StAssignMachOp (Just2 vr1 vr2) mop [a2stix arg1, a2stix arg2]
+       : mkStAssign IntRep r1s (StReg (StixTemp vr1))
+       : mkStAssign IntRep r2s (StReg (StixTemp vr2))
+       : xs
+    )
+
+ -- Ordinary MachOps are passed through unchanged.
 
-  | otherwise = p2stix (nonVoid results) op (nonVoid args)
+ gencode (CMachOpStmt (Just1 r1) mop args vols)
+  = let (Just1 rep) = resultRepsOfMachOp mop
+    in 
+    returnUs (\xs ->
+       mkStAssign rep (a2stix r1) 
+                  (StMachOp mop (map a2stix args))
+       : xs
+    )
 \end{code}
 
 Now the dreaded conditional jump.
@@ -564,10 +620,10 @@ already finish with a jump to the join point.
  mkJumpTable am alts lowTag highTag dflt
   = getUniqLabelNCG                                    `thenUs` \ utlbl ->
     mapUs genLabel alts                                `thenUs` \ branches ->
-    let        cjmpLo = StCondJump dflt (StPrim IntLtOp [am, StInt (toInteger lowTag)])
-       cjmpHi = StCondJump dflt (StPrim IntGtOp [am, StInt (toInteger highTag)])
+    let        cjmpLo = StCondJump dflt (StMachOp MO_NatS_Lt [am, StInt (toInteger lowTag)])
+       cjmpHi = StCondJump dflt (StMachOp MO_NatS_Gt [am, StInt (toInteger highTag)])
 
-       offset = StPrim IntSubOp [am, StInt lowTag]
+       offset = StMachOp MO_Nat_Sub [am, StInt lowTag]
         dsts   = DestInfo (dflt : map fst branches)
 
        jump = StJump dsts (StInd PtrRep (StIndex PtrRep (StCLbl utlbl) offset))
@@ -624,8 +680,8 @@ alternatives should already finish with a jump to the join point.
   | rangeOfOne = gencode alt
   | otherwise
   = let        tag' = a2stix (CLit tag)
-       cmpOp = if floating then DoubleNeOp else IntNeOp
-       test = StPrim cmpOp [am, tag']
+       cmpOp = if floating then MO_Dbl_Ne else MO_Nat_Ne
+       test = StMachOp cmpOp [am, tag']
        cjmp = StCondJump udlbl test
     in
        gencode alt                             `thenUs` \ alt_code ->
@@ -638,8 +694,8 @@ alternatives should already finish with a jump to the join point.
  mkBinaryTree am floating alts choices lowTag highTag udlbl
   = getUniqLabelNCG                                    `thenUs` \ uhlbl ->
     let tag' = a2stix (CLit splitTag)
-       cmpOp = if floating then DoubleGeOp else IntGeOp
-       test = StPrim cmpOp [am, tag']
+       cmpOp = if floating then MO_Dbl_Ge else MO_NatS_Ge
+       test = StMachOp cmpOp [am, tag']
        cjmp = StCondJump uhlbl test
     in
        mkBinaryTree am floating alts_lo half lowTag splitTag udlbl
@@ -671,8 +727,8 @@ alternatives should already finish with a jump to the join point.
     getUniqLabelNCG                                    `thenUs` \ utlbl ->
     let discrim' = a2stix discrim
        tag' = a2stix (CLit tag)
-       cmpOp = if (isFloatingRep (getAmodeRep discrim)) then DoubleNeOp else IntNeOp
-       test = StPrim cmpOp [discrim', tag']
+       cmpOp = if (isFloatingRep (getAmodeRep discrim)) then MO_Dbl_Ne else MO_Nat_Ne
+       test = StMachOp cmpOp [discrim', tag']
        cjmp = StCondJump utlbl test
        dest = StLabel utlbl
        join = StLabel ujlbl
@@ -681,8 +737,8 @@ alternatives should already finish with a jump to the join point.
        gencode deflt                           `thenUs` \ dflt_code ->
        returnUs (\xs -> cjmp : alt_code (dest : dflt_code (join : xs)))
 
-mkJoin :: AbstractC -> CLabel -> AbstractC
 
+mkJoin :: AbstractC -> CLabel -> AbstractC
 mkJoin code lbl
   | mightFallThrough code = mkAbsCStmts code (CJump (CLbl lbl PtrRep))
   | otherwise = code
index 22b95a5..95a1895 100644 (file)
@@ -17,13 +17,14 @@ import PprMach
 
 import AbsCStixGen     ( genCodeAbstractC )
 import AbsCSyn         ( AbstractC )
-import AbsCUtils       ( mkAbsCStmtList )
+import AbsCUtils       ( mkAbsCStmtList, magicIdPrimRep )
 import AsmRegAlloc     ( runRegAllocate )
-import PrimOp          ( commutableOp, PrimOp(..) )
+import MachOp          ( MachOp(..), isCommutableMachOp, isComparisonMachOp )
 import RegAllocInfo    ( findReservedRegs )
-import Stix            ( StixTree(..), StixReg(..), 
-                          pprStixTrees, pprStixTree, 
-                          stixCountTempUses, stixSubst,
+import Stix            ( StixReg(..), StixStmt(..), StixExpr(..), StixVReg(..),
+                          pprStixStmts, pprStixStmt, 
+                          stixStmt_CountTempUses, stixStmt_Subst,
+                          liftStrings,
                           initNat, mapNat,
                           mkNatM_State,
                           uniqOfNatM_State, deltaOfNatM_State )
@@ -95,12 +96,16 @@ nativeCodeGen absC us
          insn_sdoc         = my_vcat insn_sdocs
          stix_sdoc         = vcat stix_sdocs
 
-#        ifdef NCG_DEBUG
+#        ifdef NCG_DEBUG */
          my_trace m x = trace m x
-         my_vcat sds = vcat (intersperse (char ' ' 
-                                          $$ ptext SLIT("# ___ncg_debug_marker")
-                                          $$ char ' ') 
-                                          sds)
+         my_vcat sds = Pretty.vcat (
+                          intersperse (
+                             Pretty.char ' ' 
+                                Pretty.$$ Pretty.ptext SLIT("# ___ncg_debug_marker")
+                                Pretty.$$ Pretty.char ' '
+                          ) 
+                          sds
+                       )
 #        else
          my_vcat sds = Pretty.vcat sds
          my_trace m x = x
@@ -114,11 +119,12 @@ absCtoNat :: AbstractC -> UniqSM (SDoc, Pretty.Doc)
 absCtoNat absC
    = _scc_ "genCodeAbstractC" genCodeAbstractC absC        `thenUs` \ stixRaw ->
      _scc_ "genericOpt"       genericOpt stixRaw           `bind`   \ stixOpt ->
-     _scc_ "genMachCode"      genMachCode stixOpt          `thenUs` \ pre_regalloc ->
+     _scc_ "liftStrings"      liftStrings stixOpt          `thenUs` \ stixLifted ->
+     _scc_ "genMachCode"      genMachCode stixLifted       `thenUs` \ pre_regalloc ->
      _scc_ "regAlloc"         regAlloc pre_regalloc        `bind`   \ almost_final ->
      _scc_ "x86fp_kludge"     x86fp_kludge almost_final    `bind`   \ final_mach_code ->
      _scc_ "vcat"     Pretty.vcat (map pprInstr final_mach_code)  `bind`   \ final_sdoc ->
-     _scc_ "pprStixTrees"    pprStixTrees stixOpt          `bind`   \ stix_sdoc ->
+     _scc_ "pprStixTrees"     pprStixStmts stixOpt         `bind`   \ stix_sdoc ->
      returnUs (stix_sdoc, final_sdoc)
      where
         bind f x = x f
@@ -147,7 +153,7 @@ Switching between the two monads whilst carrying along the same Unique
 supply breaks abstraction.  Is that bad?
 
 \begin{code}
-genMachCode :: [StixTree] -> UniqSM InstrBlock
+genMachCode :: [StixStmt] -> UniqSM InstrBlock
 
 genMachCode stmts initial_us
   = let initial_st             = mkNatM_State initial_us 0
@@ -178,12 +184,12 @@ have introduced some new opportunities for constant-folding wrt
 address manipulations.
 
 \begin{code}
-genericOpt :: [StixTree] -> [StixTree]
-genericOpt = map stixConFold . stixPeep
+genericOpt :: [StixStmt] -> [StixStmt]
+genericOpt = map stixStmt_ConFold . stixPeep
 
 
 
-stixPeep :: [StixTree] -> [StixTree]
+stixPeep :: [StixStmt] -> [StixStmt]
 
 -- This transformation assumes that the temp assigned to in t1
 -- is not assigned to in t2; for otherwise the target of the
@@ -191,111 +197,120 @@ stixPeep :: [StixTree] -> [StixTree]
 -- code.  As far as I can see, StixTemps are only ever assigned
 -- to once.  It would be nice to be sure!
 
-stixPeep ( t1@(StAssign pka (StReg (StixTemp u pk)) rhs)
+stixPeep ( t1@(StAssignReg pka (StixTemp (StixVReg u pk)) rhs)
          : t2
          : ts )
-   | stixCountTempUses u t2 == 1
-     && sum (map (stixCountTempUses u) ts) == 0
+   | stixStmt_CountTempUses u t2 == 1
+     && sum (map (stixStmt_CountTempUses u) ts) == 0
    = 
 #    ifdef NCG_DEBUG
-     trace ("nativeGen: inlining " ++ showSDoc (pprStixTree rhs))
+     trace ("nativeGen: inlining " ++ showSDoc (pprStixExpr rhs))
 #    endif
-           (stixPeep (stixSubst u rhs t2 : ts))
+           (stixPeep (stixStmt_Subst u rhs t2 : ts))
 
 stixPeep (t1:t2:ts) = t1 : stixPeep (t2:ts)
 stixPeep [t1]       = [t1]
 stixPeep []         = []
-
--- disable stix inlining until we figure out how to fix the
--- latent bugs in the register allocator which are exposed by
--- the inliner.
---stixPeep = id
 \end{code}
 
 For most nodes, just optimize the children.
 
 \begin{code}
-stixConFold :: StixTree -> StixTree
-
-stixConFold (StInd pk addr) = StInd pk (stixConFold addr)
-
-stixConFold (StAssign pk dst src)
-  = StAssign pk (stixConFold dst) (stixConFold src)
-
-stixConFold (StJump dsts addr) = StJump dsts (stixConFold addr)
-
-stixConFold (StCondJump addr test)
-  = StCondJump addr (stixConFold test)
-
-stixConFold (StCall fn cconv pk args)
-  = StCall fn cconv pk (map stixConFold args)
-\end{code}
-
-Fold indices together when the types match:
-\begin{code}
-stixConFold (StIndex pk (StIndex pk' base off) off')
-  | pk == pk'
-  = StIndex pk (stixConFold base)
-              (stixConFold (StPrim IntAddOp [off, off']))
-
-stixConFold (StIndex pk base off)
-  = StIndex pk (stixConFold base) (stixConFold off)
-\end{code}
-
-For PrimOps, we first optimize the children, and then we try our hand
-at some constant-folding.
-
-\begin{code}
-stixConFold (StPrim op args) = stixPrimFold op (map stixConFold args)
-\end{code}
-
-Replace register leaves with appropriate StixTrees for the given
-target.
-
-\begin{code}
-stixConFold leaf@(StReg (StixMagicId id))
-  = case (stgReg id) of
-       Always tree -> stixConFold tree
-       Save _      -> leaf
-
-stixConFold other = other
+stixExpr_ConFold :: StixExpr -> StixExpr
+stixStmt_ConFold :: StixStmt -> StixStmt
+
+stixStmt_ConFold stmt
+   = case stmt of
+        StAssignReg pk reg@(StixTemp _) src
+           -> StAssignReg pk reg (stixExpr_ConFold src)
+        StAssignReg pk reg@(StixMagicId mid) src
+           -- Replace register leaves with appropriate StixTrees for 
+           -- the given target.
+           -> case get_MagicId_reg_or_addr mid of
+                 Left  realreg 
+                    -> StAssignReg pk reg (stixExpr_ConFold src)
+                 Right baseRegAddr 
+                    -> stixStmt_ConFold
+                          (StAssignMem pk baseRegAddr src)
+        StAssignMem pk addr src
+           -> StAssignMem pk (stixExpr_ConFold addr) (stixExpr_ConFold src)
+        StAssignMachOp lhss mop args
+           -> StAssignMachOp lhss mop (map stixExpr_ConFold args)
+        StVoidable expr
+           -> StVoidable (stixExpr_ConFold expr)
+        StJump dsts addr
+           -> StJump dsts (stixExpr_ConFold addr)
+        StCondJump addr test
+           -> StCondJump addr (stixExpr_ConFold test)
+        StData pk datas
+           -> StData pk (map stixExpr_ConFold datas)
+        other
+           -> other
+
+
+stixExpr_ConFold expr
+   = case expr of
+        StInd pk addr
+           -> StInd pk (stixExpr_ConFold addr)
+        StCall fn cconv pk args
+           -> StCall fn cconv pk (map stixExpr_ConFold args)
+        StIndex pk (StIndex pk' base off) off'
+           -- Fold indices together when the types match:
+           |  pk == pk'
+           -> StIndex pk (stixExpr_ConFold base)
+                         (stixExpr_ConFold (StMachOp MO_Nat_Add [off, off']))
+        StIndex pk base off
+           -> StIndex pk (stixExpr_ConFold base) (stixExpr_ConFold off)
+
+        StMachOp mop args
+           -- For PrimOps, we first optimize the children, and then we try 
+           -- our hand at some constant-folding.
+           -> stixMachOpFold mop (map stixExpr_ConFold args)
+        StReg (StixMagicId mid)
+           -- Replace register leaves with appropriate StixTrees for 
+           -- the given target.
+           -> case get_MagicId_reg_or_addr mid of
+                 Left  realreg -> expr
+                 Right baseRegAddr 
+                    -> stixExpr_ConFold (StInd (magicIdPrimRep mid) baseRegAddr)
+        other
+           -> other
 \end{code}
 
 Now, try to constant-fold the PrimOps.  The arguments have already
 been optimized and folded.
 
 \begin{code}
-stixPrimFold
-    :: PrimOp          -- The operation from an StPrim
-    -> [StixTree]      -- The optimized arguments
-    -> StixTree
-
-stixPrimFold op arg@[StInt x]
-  = case op of
-       IntNegOp -> StInt (-x)
-       _ -> StPrim op arg
-
-stixPrimFold op args@[StInt x, StInt y]
-  = case op of
-       CharGtOp -> StInt (if x > y  then 1 else 0)
-       CharGeOp -> StInt (if x >= y then 1 else 0)
-       CharEqOp -> StInt (if x == y then 1 else 0)
-       CharNeOp -> StInt (if x /= y then 1 else 0)
-       CharLtOp -> StInt (if x < y  then 1 else 0)
-       CharLeOp -> StInt (if x <= y then 1 else 0)
-       IntAddOp -> StInt (x + y)
-       IntSubOp -> StInt (x - y)
-       IntMulOp -> StInt (x * y)
-       IntQuotOp -> StInt (x `quot` y)
-       IntRemOp -> StInt (x `rem` y)
-       IntGtOp -> StInt (if x > y  then 1 else 0)
-       IntGeOp -> StInt (if x >= y then 1 else 0)
-       IntEqOp -> StInt (if x == y then 1 else 0)
-       IntNeOp -> StInt (if x /= y then 1 else 0)
-       IntLtOp -> StInt (if x < y  then 1 else 0)
-       IntLeOp -> StInt (if x <= y then 1 else 0)
-       -- ToDo: WordQuotOp, WordRemOp.
-       _ -> StPrim op args
+stixMachOpFold
+    :: MachOp          -- The operation from an StMachOp
+    -> [StixExpr]      -- The optimized arguments
+    -> StixExpr
+
+stixMachOpFold mop arg@[StInt x]
+  = case mop of
+       MO_NatS_Neg -> StInt (-x)
+       other       -> StMachOp mop arg
+
+stixMachOpFold mop args@[StInt x, StInt y]
+  = case mop of
+       MO_32U_Gt   -> StInt (if x > y  then 1 else 0)
+       MO_32U_Ge   -> StInt (if x >= y then 1 else 0)
+       MO_32U_Eq   -> StInt (if x == y then 1 else 0)
+       MO_32U_Ne   -> StInt (if x /= y then 1 else 0)
+       MO_32U_Lt   -> StInt (if x < y  then 1 else 0)
+       MO_32U_Le   -> StInt (if x <= y then 1 else 0)
+       MO_Nat_Add  -> StInt (x + y)
+       MO_Nat_Sub  -> StInt (x - y)
+       MO_NatS_Mul -> StInt (x * y)
+       MO_NatS_Quot | y /= 0 -> StInt (x `quot` y)
+       MO_NatS_Rem  | y /= 0 -> StInt (x `rem` y)
+       MO_NatS_Gt  -> StInt (if x > y  then 1 else 0)
+       MO_NatS_Ge  -> StInt (if x >= y then 1 else 0)
+       MO_Nat_Eq   -> StInt (if x == y then 1 else 0)
+       MO_Nat_Ne   -> StInt (if x /= y then 1 else 0)
+       MO_NatS_Lt  -> StInt (if x < y  then 1 else 0)
+       MO_NatS_Le  -> StInt (if x <= y then 1 else 0)
+       other       -> StMachOp mop args
 \end{code}
 
 When possible, shift the constants to the right-hand side, so that we
@@ -304,68 +319,65 @@ also assume that constants have been shifted to the right when
 possible.
 
 \begin{code}
-stixPrimFold op [x@(StInt _), y] | commutableOp op = stixPrimFold op [y, x]
+stixMachOpFold op [x@(StInt _), y] | isCommutableMachOp op 
+   = stixMachOpFold op [y, x]
 \end{code}
 
 We can often do something with constants of 0 and 1 ...
 
 \begin{code}
-stixPrimFold op args@[x, y@(StInt 0)]
-  = case op of
-       IntAddOp -> x
-       IntSubOp -> x
-       IntMulOp -> y
-       AndOp    -> y
-       OrOp     -> x
-       XorOp    -> x
-       SllOp    -> x
-       SrlOp    -> x
-       ISllOp   -> x
-       ISraOp   -> x
-       ISrlOp   -> x
-        IntNeOp  | is_comparison -> x
-       _        -> StPrim op args
+stixMachOpFold mop args@[x, y@(StInt 0)]
+  = case mop of
+       MO_Nat_Add  -> x
+       MO_Nat_Sub  -> x
+       MO_NatS_Mul -> y
+       MO_NatU_Mul -> y
+       MO_Nat_And  -> y
+       MO_Nat_Or   -> x
+       MO_Nat_Xor  -> x
+       MO_Nat_Shl  -> x
+       MO_Nat_Shr  -> x
+       MO_Nat_Sar  -> x
+        MO_Nat_Ne | x_is_comparison -> x
+       other       -> StMachOp mop args
     where
-       is_comparison
+       x_is_comparison
           = case x of
-               StPrim opp [_, _] -> opp `elem` comparison_ops
-               _                 -> False
-
-stixPrimFold op args@[x, y@(StInt 1)]
-  = case op of
-       IntMulOp  -> x
-       IntQuotOp -> x
-       IntRemOp  -> StInt 0
-       _         -> StPrim op args
+               StMachOp mopp [_, _] -> isComparisonMachOp mopp
+               _                    -> False
+
+stixMachOpFold mop args@[x, y@(StInt 1)]
+  = case mop of
+       MO_NatS_Mul  -> x
+       MO_NatU_Mul  -> x
+       MO_NatS_Quot -> x
+       MO_NatU_Quot -> x
+       MO_NatS_Rem  -> StInt 0
+       MO_NatU_Rem  -> StInt 0
+       other        -> StMachOp mop args
 \end{code}
 
 Now look for multiplication/division by powers of 2 (integers).
 
 \begin{code}
-stixPrimFold op args@[x, y@(StInt n)]
-  = case op of
-       IntMulOp -> case exactLog2 n of
-           Nothing -> StPrim op args
-           Just p  -> StPrim ISllOp [x, StInt p]
-       IntQuotOp -> case exactLog2 n of
-           Nothing -> StPrim op args
-           Just p  -> StPrim ISrlOp [x, StInt p]
-       _ -> StPrim op args
+stixMachOpFold mop args@[x, y@(StInt n)]
+  = case mop of
+       MO_NatS_Mul 
+           -> case exactLog2 n of
+                 Nothing -> unchanged
+                 Just p  -> StMachOp MO_Nat_Shl [x, StInt p]
+       MO_NatS_Quot 
+           -> case exactLog2 n of
+                 Nothing -> unchanged
+                 Just p  -> StMachOp MO_Nat_Shr [x, StInt p]
+       other 
+           -> unchanged
+    where
+       unchanged = StMachOp mop args
 \end{code}
 
 Anything else is just too hard.
 
 \begin{code}
-stixPrimFold op args = StPrim op args
-\end{code}
-
-\begin{code}
-comparison_ops
-   = [ CharGtOp  , CharGeOp  , CharEqOp  , CharNeOp  , CharLtOp  , CharLeOp,
-       IntGtOp   , IntGeOp   , IntEqOp   , IntNeOp   , IntLtOp   , IntLeOp,
-       WordGtOp  , WordGeOp  , WordEqOp  , WordNeOp  , WordLtOp  , WordLeOp,
-       AddrGtOp  , AddrGeOp  , AddrEqOp  , AddrNeOp  , AddrLtOp  , AddrLeOp,
-       FloatGtOp , FloatGeOp , FloatEqOp , FloatNeOp , FloatLtOp , FloatLeOp,
-       DoubleGtOp, DoubleGeOp, DoubleEqOp, DoubleNeOp, DoubleLtOp, DoubleLeOp
-     ]
+stixMachOpFold mop args = StMachOp mop args
 \end{code}
index b2a4e82..35c86b7 100644 (file)
@@ -18,29 +18,35 @@ import MachMisc             -- may differ per-platform
 import MachRegs
 import OrdList         ( OrdList, nilOL, isNilOL, unitOL, appOL, toOL,
                          snocOL, consOL, concatOL )
+import MachOp          ( MachOp(..), pprMachOp )
 import AbsCUtils       ( magicIdPrimRep )
+import PprAbsC         ( pprMagicId )
 import ForeignCall     ( CCallConv(..) )
 import CLabel          ( CLabel, labelDynamic )
 #if sparc_TARGET_ARCH || alpha_TARGET_ARCH
 import CLabel          ( isAsmTemp )
 #endif
-import Maybes          ( maybeToBool )
+import Maybes          ( maybeToBool, Maybe012(..) )
 import PrimRep         ( isFloatingRep, PrimRep(..) )
-import PrimOp          ( PrimOp(..) )
-import Stix            ( getNatLabelNCG, StixTree(..),
-                         StixReg(..), CodeSegment(..), 
+import Stix            ( getNatLabelNCG, StixStmt(..), StixExpr(..),
+                         StixReg(..), StixVReg(..), CodeSegment(..), 
                           DestInfo, hasDestInfo,
-                          pprStixTree, 
+                          pprStixExpr, 
+                          liftStrings,
                           NatM, thenNat, returnNat, mapNat, 
                           mapAndUnzipNat, mapAccumLNat,
                           getDeltaNat, setDeltaNat,
                           ncgPrimopMoan
                        )
 import Pretty
-import Outputable      ( panic, pprPanic )
+import Outputable      ( panic, pprPanic, showSDoc )
 import qualified Outputable
 import CmdLineOpts     ( opt_Static )
 
+-- DEBUGGING ONLY
+import IOExts          ( trace )
+import Stix            ( pprStixStmt )
+
 infixr 3 `bind`
 \end{code}
 
@@ -58,84 +64,13 @@ x `bind` f = f x
 Code extractor for an entire stix tree---stix statement level.
 
 \begin{code}
-stmtsToInstrs :: [StixTree] -> NatM InstrBlock
+stmtsToInstrs :: [StixStmt] -> NatM InstrBlock
 stmtsToInstrs stmts
-   = liftStrings stmts [] []           `thenNat` \ lifted ->
-     mapNat stmtToInstrs lifted                `thenNat` \ instrss ->
+   = mapNat stmtToInstrs stmts         `thenNat` \ instrss ->
      returnNat (concatOL instrss)
 
 
--- Lift StStrings out of top-level StDatas, putting them at the end of
--- the block, and replacing them with StCLbls which refer to the lifted-out strings. 
-{- Motivation for this hackery provided by the following bug:
-   Stix:
-      (DataSegment)
-      Bogon.ping_closure :
-      (Data P_ Addr.A#_static_info)
-      (Data StgAddr (Str `alalal'))
-      (Data P_ (0))
-   results in:
-      .data
-              .align 8
-      .global Bogon_ping_closure
-      Bogon_ping_closure:
-              .long   Addr_Azh_static_info
-              .long   .Ln1a8
-      .Ln1a8:
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x61
-              .byte   0x6C
-              .byte   0x00
-              .long   0
-   ie, the Str is planted in-line, when what we really meant was to place
-   a _reference_ to the string there.  liftStrings will lift out all such
-   strings in top-level data and place them at the end of the block.
-
-   This is still a rather half-baked solution -- to do the job entirely right
-   would mean a complete traversal of all the Stixes, but there's currently no
-   real need for it, and it would be slow.  Also, potentially there could be
-   literal types other than strings which need lifting out?
--}
-
-liftStrings :: [StixTree]    -- originals
-            -> [StixTree]    -- (reverse) originals with strings lifted out
-            -> [(CLabel, FAST_STRING)]   -- lifted strs, and their new labels
-            -> NatM [StixTree]
-
--- First, examine the original trees and lift out strings in top-level StDatas.
-liftStrings (st:sts) acc_stix acc_strs
-   = case st of
-        StData sz datas
-           -> lift datas acc_strs      `thenNat` \ (datas_done, acc_strs1) ->
-              liftStrings sts ((StData sz datas_done):acc_stix) acc_strs1
-        other 
-           -> liftStrings sts (other:acc_stix) acc_strs
-     where
-        -- Handle a top-level StData
-        lift []     acc_strs = returnNat ([], acc_strs)
-        lift (d:ds) acc_strs
-           = lift ds acc_strs          `thenNat` \ (ds_done, acc_strs1) ->
-             case d of
-                StString s 
-                   -> getNatLabelNCG   `thenNat` \ lbl ->
-                      returnNat ((StCLbl lbl):ds_done, ((lbl,s):acc_strs1))
-                other
-                   -> returnNat (other:ds_done, acc_strs1)
-
--- When we've run out of original trees, emit the lifted strings.
-liftStrings [] acc_stix acc_strs
-   = returnNat (reverse acc_stix ++ concatMap f acc_strs)
-     where
-        f (lbl,str) = [StSegment RoDataSegment, 
-                       StLabel lbl, 
-                       StString str, 
-                       StSegment TextSegment]
-
-
-stmtToInstrs :: StixTree {- a stix statement -} -> NatM InstrBlock
+stmtToInstrs :: StixStmt -> NatM InstrBlock
 stmtToInstrs stmt = case stmt of
     StComment s    -> returnNat (unitOL (COMMENT s))
     StSegment seg  -> returnNat (unitOL (SEGMENT seg))
@@ -150,13 +85,19 @@ stmtToInstrs stmt = case stmt of
     StJump dsts arg       -> genJump dsts (derefDLL arg)
     StCondJump lab arg    -> genCondJump lab (derefDLL arg)
 
-    -- A call returning void, ie one done for its side-effects
-    StCall fn cconv VoidRep args -> genCCall fn
-                                             cconv VoidRep (map derefDLL args)
+    -- A call returning void, ie one done for its side-effects.  Note
+    -- that this is the only StVoidable we handle.
+    StVoidable (StCall fn cconv VoidRep args) 
+       -> genCCall fn cconv VoidRep (map derefDLL args)
 
-    StAssign pk dst src
-      | isFloatingRep pk -> assignFltCode pk (derefDLL dst) (derefDLL src)
-      | otherwise       -> assignIntCode pk (derefDLL dst) (derefDLL src)
+    StAssignMem pk addr src
+      | isFloatingRep pk -> assignMem_FltCode pk (derefDLL addr) (derefDLL src)
+      | otherwise       -> assignMem_IntCode pk (derefDLL addr) (derefDLL src)
+    StAssignReg pk reg src
+      | isFloatingRep pk -> assignReg_FltCode pk reg (derefDLL src)
+      | otherwise       -> assignReg_IntCode pk reg (derefDLL src)
+    StAssignMachOp lhss mop rhss
+      -> assignMachOp lhss mop rhss
 
     StFallThrough lbl
        -- When falling through on the Alpha, we still have to load pv
@@ -169,7 +110,7 @@ stmtToInstrs stmt = case stmt of
         returnNat (DATA (primRepToSize kind) imms  
                     `consOL`  concatOL codes)
       where
-       getData :: StixTree -> NatM (InstrBlock, Imm)
+       getData :: StixExpr -> NatM (InstrBlock, Imm)
        getData (StInt i)        = returnNat (nilOL, ImmInteger i)
        getData (StDouble d)     = returnNat (nilOL, ImmDouble d)
        getData (StFloat d)      = returnNat (nilOL, ImmFloat d)
@@ -181,8 +122,8 @@ stmtToInstrs stmt = case stmt of
                            ImmIndex lbl (fromInteger off * sizeOf rep))
 
     -- Top-level lifted-out string.  The segment will already have been set
-    -- (see liftStrings above).
-    StString str
+    -- (see Stix.liftStrings).
+    StDataString str
       -> returnNat (unitOL (ASCII True (_UNPK_ str)))
 
 #ifdef DEBUG
@@ -193,7 +134,7 @@ stmtToInstrs stmt = case stmt of
 -- as labelDynamic.  stmt2Instrs calls derefDLL selectively, because
 -- not all such CLabel occurrences need this dereferencing -- SRTs don't
 -- for one.
-derefDLL :: StixTree -> StixTree
+derefDLL :: StixExpr -> StixExpr
 derefDLL tree
    | opt_Static   -- short out the entire deal if not doing DLLs
    = tree
@@ -207,7 +148,7 @@ derefDLL tree
                               else t
                 -- all the rest are boring
                 StIndex pk base offset -> StIndex pk (qq base) (qq offset)
-                StPrim pk args         -> StPrim pk (map qq args)
+                StMachOp mop args      -> StMachOp mop (map qq args)
                 StInd pk addr          -> StInd pk (qq addr)
                 StCall who cc pk args  -> StCall who cc pk (map qq args)
                 StInt    _             -> t
@@ -215,9 +156,8 @@ derefDLL tree
                 StDouble _             -> t
                 StString _             -> t
                 StReg    _             -> t
-                StScratchWord _        -> t
                 _                      -> pprPanic "derefDLL: unhandled case" 
-                                                   (pprStixTree t)
+                                                   (pprStixExpr t)
 \end{code}
 
 %************************************************************************
@@ -227,19 +167,19 @@ derefDLL tree
 %************************************************************************
 
 \begin{code}
-mangleIndexTree :: StixTree -> StixTree
+mangleIndexTree :: StixExpr -> StixExpr
 
 mangleIndexTree (StIndex pk base (StInt i))
-  = StPrim IntAddOp [base, off]
+  = StMachOp MO_Nat_Add [base, off]
   where
     off = StInt (i * toInteger (sizeOf pk))
 
 mangleIndexTree (StIndex pk base off)
-  = StPrim IntAddOp [
+  = StMachOp MO_Nat_Add [
        base,
        let s = shift pk
-       in  if s == 0 then off else StPrim SllOp [off, StInt (toInteger s)]
-      ]
+       in  if s == 0 then off else StMachOp MO_Nat_Shl [off, StInt (toInteger s)]
+    ]
   where
     shift :: PrimRep -> Int
     shift rep = case sizeOf rep of
@@ -252,7 +192,7 @@ mangleIndexTree (StIndex pk base off)
 \end{code}
 
 \begin{code}
-maybeImm :: StixTree -> Maybe Imm
+maybeImm :: StixExpr -> Maybe Imm
 
 maybeImm (StCLbl l)       
    = Just (ImmCLbl l)
@@ -304,6 +244,10 @@ registerRep :: Register -> PrimRep
 registerRep (Fixed pk _ _) = pk
 registerRep (Any   pk _) = pk
 
+swizzleRegisterRep :: Register -> PrimRep -> Register
+swizzleRegisterRep (Fixed _ reg code) rep = Fixed rep reg code
+swizzleRegisterRep (Any _ codefn)     rep = Any rep codefn
+
 {-# INLINE registerCode  #-}
 {-# INLINE registerCodeF #-}
 {-# INLINE registerName  #-}
@@ -321,17 +265,31 @@ isAny = not . isFixed
 
 Generate code to get a subtree into a @Register@:
 \begin{code}
-getRegister :: StixTree -> NatM Register
 
-getRegister (StReg (StixMagicId stgreg))
-  = case (magicIdRegMaybe stgreg) of
-      Just reg -> returnNat (Fixed (magicIdPrimRep stgreg) reg nilOL)
-                  -- cannae be Nothing
+getRegisterReg :: StixReg -> NatM Register
 
-getRegister (StReg (StixTemp u pk))
+getRegisterReg (StixMagicId mid)
+  = case get_MagicId_reg_or_addr mid of
+       Left (RealReg rrno) 
+          -> let pk = magicIdPrimRep mid
+             in  returnNat (Fixed pk (RealReg rrno) nilOL)
+       Right baseRegAddr 
+          -- By this stage, the only MagicIds remaining should be the
+          -- ones which map to a real machine register on this platform.  Hence ...
+          -> pprPanic "getRegisterReg-memory" (pprMagicId mid)
+
+getRegisterReg (StixTemp (StixVReg u pk))
   = returnNat (Fixed pk (mkVReg u pk) nilOL)
 
-getRegister tree@(StIndex _ _ _) = getRegister (mangleIndexTree tree)
+-------------
+
+getRegister :: StixExpr -> NatM Register
+
+getRegister (StReg reg) 
+  = getRegisterReg reg
+
+getRegister tree@(StIndex _ _ _) 
+  = getRegister (mangleIndexTree tree)
 
 getRegister (StCall fn cconv kind args)
   = genCCall fn cconv kind args            `thenNat` \ call ->
@@ -638,176 +596,180 @@ getRegister (StDouble d)
     in
     returnNat (Any DoubleRep code)
 
--- Calculate the offset for (i+1) words above the _initial_
--- %esp value by first determining the current offset of it.
-getRegister (StScratchWord i)
-   | i >= 0 && i < 6
-   = getDeltaNat `thenNat` \ current_stack_offset ->
-     let j = i+1   - (current_stack_offset `div` 4)
-         code dst
-           = unitOL (LEA L (OpAddr (spRel j)) (OpReg dst))
-     in 
-     returnNat (Any PtrRep code)
 
-getRegister (StPrim primop [x]) -- unary PrimOps
-  = case primop of
-      IntNegOp  -> trivialUCode (NEGI L) x
-      NotOp    -> trivialUCode (NOT L) x
+getRegister (StMachOp mop [x]) -- unary MachOps
+  = case mop of
+      MO_NatS_Neg  -> trivialUCode (NEGI L) x
+      MO_Nat_Not   -> trivialUCode (NOT L) x
 
-      FloatNegOp  -> trivialUFCode FloatRep  (GNEG F) x
-      DoubleNegOp -> trivialUFCode DoubleRep (GNEG DF) x
+      MO_Flt_Neg  -> trivialUFCode FloatRep  (GNEG F) x
+      MO_Dbl_Neg  -> trivialUFCode DoubleRep (GNEG DF) x
 
-      FloatSqrtOp  -> trivialUFCode FloatRep  (GSQRT F) x
-      DoubleSqrtOp -> trivialUFCode DoubleRep (GSQRT DF) x
+      MO_Flt_Sqrt -> trivialUFCode FloatRep  (GSQRT F) x
+      MO_Dbl_Sqrt -> trivialUFCode DoubleRep (GSQRT DF) x
 
-      FloatSinOp  -> trivialUFCode FloatRep  (GSIN F) x
-      DoubleSinOp -> trivialUFCode DoubleRep (GSIN DF) x
+      MO_Flt_Sin  -> trivialUFCode FloatRep  (GSIN F) x
+      MO_Dbl_Sin  -> trivialUFCode DoubleRep (GSIN DF) x
 
-      FloatCosOp  -> trivialUFCode FloatRep  (GCOS F) x
-      DoubleCosOp -> trivialUFCode DoubleRep (GCOS DF) x
+      MO_Flt_Cos  -> trivialUFCode FloatRep  (GCOS F) x
+      MO_Dbl_Cos  -> trivialUFCode DoubleRep (GCOS DF) x
 
-      FloatTanOp  -> trivialUFCode FloatRep  (GTAN F) x
-      DoubleTanOp -> trivialUFCode DoubleRep (GTAN DF) x
+      MO_Flt_Tan  -> trivialUFCode FloatRep  (GTAN F) x
+      MO_Dbl_Tan  -> trivialUFCode DoubleRep (GTAN DF) x
 
-      Double2FloatOp -> trivialUFCode FloatRep  GDTOF x
-      Float2DoubleOp -> trivialUFCode DoubleRep GFTOD x
+      MO_Flt_to_NatS -> coerceFP2Int x
+      MO_NatS_to_Flt -> coerceInt2FP FloatRep x
+      MO_Dbl_to_NatS -> coerceFP2Int x
+      MO_NatS_to_Dbl -> coerceInt2FP DoubleRep x
 
-      OrdOp -> coerceIntCode IntRep x
-      ChrOp -> chrCode x
+      -- Conversions which are a nop on x86
+      MO_NatS_to_32U  -> conversionNop WordRep   x
+      MO_32U_to_NatS  -> conversionNop IntRep    x
 
-      Float2IntOp  -> coerceFP2Int x
-      Int2FloatOp  -> coerceInt2FP FloatRep x
-      Double2IntOp -> coerceFP2Int x
-      Int2DoubleOp -> coerceInt2FP DoubleRep x
+      MO_NatU_to_NatS -> conversionNop IntRep    x
+      MO_NatS_to_NatU -> conversionNop WordRep   x
+      MO_NatP_to_NatU -> conversionNop WordRep   x
+      MO_NatU_to_NatP -> conversionNop PtrRep    x
+      MO_NatS_to_NatP -> conversionNop PtrRep    x
+      MO_NatP_to_NatS -> conversionNop IntRep    x
 
-      other_op ->
-       getRegister (StCall fn CCallConv DoubleRep [x])
-       where
-       (is_float_op, fn)
-         = case primop of
-             FloatExpOp    -> (True,  SLIT("exp"))
-             FloatLogOp    -> (True,  SLIT("log"))
+      MO_Dbl_to_Flt   -> conversionNop FloatRep  x
+      MO_Flt_to_Dbl   -> conversionNop DoubleRep x
 
-             FloatAsinOp   -> (True,  SLIT("asin"))
-             FloatAcosOp   -> (True,  SLIT("acos"))
-             FloatAtanOp   -> (True,  SLIT("atan"))
+      MO_8U_to_NatU   -> integerExtend False 24 x
+      MO_8S_to_NatS   -> integerExtend True  24 x
+      MO_16U_to_NatU  -> integerExtend False 16 x
+      MO_16S_to_NatS  -> integerExtend True  16 x
 
-             FloatSinhOp   -> (True,  SLIT("sinh"))
-             FloatCoshOp   -> (True,  SLIT("cosh"))
-             FloatTanhOp   -> (True,  SLIT("tanh"))
-
-             DoubleExpOp   -> (False, SLIT("exp"))
-             DoubleLogOp   -> (False, SLIT("log"))
-
-             DoubleAsinOp  -> (False, SLIT("asin"))
-             DoubleAcosOp  -> (False, SLIT("acos"))
-             DoubleAtanOp  -> (False, SLIT("atan"))
-
-             DoubleSinhOp  -> (False, SLIT("sinh"))
-             DoubleCoshOp  -> (False, SLIT("cosh"))
-             DoubleTanhOp  -> (False, SLIT("tanh"))
-
-              other
-                 -> ncgPrimopMoan "getRegister(x86,unary primop)" 
-                                  (pprStixTree (StPrim primop [x]))
-
-getRegister (StPrim primop [x, y]) -- dyadic PrimOps
-  = case primop of
-      CharGtOp -> condIntReg GTT x y
-      CharGeOp -> condIntReg GE x y
-      CharEqOp -> condIntReg EQQ x y
-      CharNeOp -> condIntReg NE x y
-      CharLtOp -> condIntReg LTT x y
-      CharLeOp -> condIntReg LE x y
-
-      IntGtOp  -> condIntReg GTT x y
-      IntGeOp  -> condIntReg GE x y
-      IntEqOp  -> condIntReg EQQ x y
-      IntNeOp  -> condIntReg NE x y
-      IntLtOp  -> condIntReg LTT x y
-      IntLeOp  -> condIntReg LE x y
-
-      WordGtOp -> condIntReg GU  x y
-      WordGeOp -> condIntReg GEU x y
-      WordEqOp -> condIntReg EQQ  x y
-      WordNeOp -> condIntReg NE  x y
-      WordLtOp -> condIntReg LU  x y
-      WordLeOp -> condIntReg LEU x y
-
-      AddrGtOp -> condIntReg GU  x y
-      AddrGeOp -> condIntReg GEU x y
-      AddrEqOp -> condIntReg EQQ  x y
-      AddrNeOp -> condIntReg NE  x y
-      AddrLtOp -> condIntReg LU  x y
-      AddrLeOp -> condIntReg LEU x y
-
-      FloatGtOp -> condFltReg GTT x y
-      FloatGeOp -> condFltReg GE x y
-      FloatEqOp -> condFltReg EQQ x y
-      FloatNeOp -> condFltReg NE x y
-      FloatLtOp -> condFltReg LTT x y
-      FloatLeOp -> condFltReg LE x y
-
-      DoubleGtOp -> condFltReg GTT x y
-      DoubleGeOp -> condFltReg GE x y
-      DoubleEqOp -> condFltReg EQQ x y
-      DoubleNeOp -> condFltReg NE x y
-      DoubleLtOp -> condFltReg LTT x y
-      DoubleLeOp -> condFltReg LE x y
-
-      IntAddOp  -> add_code L x y
-      IntSubOp  -> sub_code L x y
-      IntQuotOp -> trivialCode (IQUOT L) Nothing x y
-      IntRemOp  -> trivialCode (IREM L) Nothing x y
-      IntMulOp  -> let op = IMUL L in trivialCode op (Just op) x y
-
-      WordAddOp  -> add_code L x y
-      WordSubOp  -> sub_code L x y
-      WordMulOp  -> let op = IMUL L in trivialCode op (Just op) x y
-
-      FloatAddOp -> trivialFCode  FloatRep  GADD x y
-      FloatSubOp -> trivialFCode  FloatRep  GSUB x y
-      FloatMulOp -> trivialFCode  FloatRep  GMUL x y
-      FloatDivOp -> trivialFCode  FloatRep  GDIV x y
-
-      DoubleAddOp -> trivialFCode DoubleRep GADD x y
-      DoubleSubOp -> trivialFCode DoubleRep GSUB x y
-      DoubleMulOp -> trivialFCode DoubleRep GMUL x y
-      DoubleDivOp -> trivialFCode DoubleRep GDIV x y
-
-      AddrAddOp -> add_code L x y
-      AddrSubOp -> sub_code L x y
-      AddrRemOp -> trivialCode (IREM L) Nothing x y
-
-      AndOp -> let op = AND L in trivialCode op (Just op) x y
-      OrOp  -> let op = OR  L in trivialCode op (Just op) x y
-      XorOp -> let op = XOR L in trivialCode op (Just op) x y
+      other_op 
+         -> getRegister (
+               (if is_float_op then demote else id)
+               (StCall fn CCallConv DoubleRep 
+                          [(if is_float_op then promote else id) x])
+            )
+      where
+        integerExtend signed nBits x
+           = getRegister (
+                StMachOp (if signed then MO_Nat_Sar else MO_Nat_Shr) 
+                         [StInt nBits, StMachOp MO_Nat_Shl [StInt nBits, x]]
+             )
+
+        conversionNop new_rep expr
+            = getRegister expr         `thenNat` \ e_code ->
+              returnNat (swizzleRegisterRep e_code new_rep)
+
+        promote x = StMachOp MO_Flt_to_Dbl [x]
+        demote  x = StMachOp MO_Dbl_to_Flt [x]
+       (is_float_op, fn)
+         = case mop of
+             MO_Flt_Exp   -> (True,  SLIT("exp"))
+             MO_Flt_Log   -> (True,  SLIT("log"))
+
+             MO_Flt_Asin  -> (True,  SLIT("asin"))
+             MO_Flt_Acos  -> (True,  SLIT("acos"))
+             MO_Flt_Atan  -> (True,  SLIT("atan"))
+
+             MO_Flt_Sinh  -> (True,  SLIT("sinh"))
+             MO_Flt_Cosh  -> (True,  SLIT("cosh"))
+             MO_Flt_Tanh  -> (True,  SLIT("tanh"))
+
+             MO_Dbl_Exp   -> (False, SLIT("exp"))
+             MO_Dbl_Log   -> (False, SLIT("log"))
+
+             MO_Dbl_Asin  -> (False, SLIT("asin"))
+             MO_Dbl_Acos  -> (False, SLIT("acos"))
+             MO_Dbl_Atan  -> (False, SLIT("atan"))
+
+             MO_Dbl_Sinh  -> (False, SLIT("sinh"))
+             MO_Dbl_Cosh  -> (False, SLIT("cosh"))
+             MO_Dbl_Tanh  -> (False, SLIT("tanh"))
+
+              other -> pprPanic "getRegister(x86) - binary StMachOp (2)" 
+                                (pprMachOp mop)
+
+
+getRegister (StMachOp mop [x, y]) -- dyadic MachOps
+  = case mop of
+      MO_32U_Gt  -> condIntReg GTT x y
+      MO_32U_Ge  -> condIntReg GE x y
+      MO_32U_Eq  -> condIntReg EQQ x y
+      MO_32U_Ne  -> condIntReg NE x y
+      MO_32U_Lt  -> condIntReg LTT x y
+      MO_32U_Le  -> condIntReg LE x y
+
+      MO_Nat_Eq   -> condIntReg EQQ x y
+      MO_Nat_Ne   -> condIntReg NE x y
+
+      MO_NatS_Gt  -> condIntReg GTT x y
+      MO_NatS_Ge  -> condIntReg GE x y
+      MO_NatS_Lt  -> condIntReg LTT x y
+      MO_NatS_Le  -> condIntReg LE x y
+
+      MO_NatU_Gt  -> condIntReg GU  x y
+      MO_NatU_Ge  -> condIntReg GEU x y
+      MO_NatU_Lt  -> condIntReg LU  x y
+      MO_NatU_Le  -> condIntReg LEU x y
+
+      MO_Flt_Gt -> condFltReg GTT x y
+      MO_Flt_Ge -> condFltReg GE x y
+      MO_Flt_Eq -> condFltReg EQQ x y
+      MO_Flt_Ne -> condFltReg NE x y
+      MO_Flt_Lt -> condFltReg LTT x y
+      MO_Flt_Le -> condFltReg LE x y
+
+      MO_Dbl_Gt -> condFltReg GTT x y
+      MO_Dbl_Ge -> condFltReg GE x y
+      MO_Dbl_Eq -> condFltReg EQQ x y
+      MO_Dbl_Ne -> condFltReg NE x y
+      MO_Dbl_Lt -> condFltReg LTT x y
+      MO_Dbl_Le -> condFltReg LE x y
+
+      MO_Nat_Add   -> add_code L x y
+      MO_Nat_Sub   -> sub_code L x y
+      MO_NatS_Quot -> trivialCode (IQUOT L) Nothing x y
+      MO_NatS_Rem  -> trivialCode (IREM L) Nothing x y
+      MO_NatU_Quot -> trivialCode (QUOT L) Nothing x y
+      MO_NatU_Rem  -> trivialCode (REM L) Nothing x y
+      MO_NatS_Mul  -> let op = IMUL L in trivialCode op (Just op) x y
+      MO_NatU_Mul  -> let op = MUL L in trivialCode op (Just op) x y
+
+      MO_Flt_Add -> trivialFCode  FloatRep  GADD x y
+      MO_Flt_Sub -> trivialFCode  FloatRep  GSUB x y
+      MO_Flt_Mul -> trivialFCode  FloatRep  GMUL x y
+      MO_Flt_Div -> trivialFCode  FloatRep  GDIV x y
+
+      MO_Dbl_Add -> trivialFCode DoubleRep GADD x y
+      MO_Dbl_Sub -> trivialFCode DoubleRep GSUB x y
+      MO_Dbl_Mul -> trivialFCode DoubleRep GMUL x y
+      MO_Dbl_Div -> trivialFCode DoubleRep GDIV x y
+
+      MO_Nat_And -> let op = AND L in trivialCode op (Just op) x y
+      MO_Nat_Or  -> let op = OR  L in trivialCode op (Just op) x y
+      MO_Nat_Xor -> let op = XOR L in trivialCode op (Just op) x y
 
        {- Shift ops on x86s have constraints on their source, it
           either has to be Imm, CL or 1
            => trivialCode's is not restrictive enough (sigh.)
-       -}
-          
-      SllOp  -> shift_code (SHL L) x y {-False-}
-      SrlOp  -> shift_code (SHR L) x y {-False-}
-      ISllOp -> shift_code (SHL L) x y {-False-}
-      ISraOp -> shift_code (SAR L) x y {-False-}
-      ISrlOp -> shift_code (SHR L) x y {-False-}
+       -}         
+      MO_Nat_Shl  -> shift_code (SHL L) x y {-False-}
+      MO_Nat_Shr  -> shift_code (SHR L) x y {-False-}
+      MO_Nat_Sar  -> shift_code (SAR L) x y {-False-}
 
-      FloatPowerOp  -> getRegister (StCall SLIT("pow") CCallConv DoubleRep 
+      MO_Flt_Pwr  -> getRegister (demote 
+                                 (StCall SLIT("pow") CCallConv DoubleRep 
                                            [promote x, promote y])
-                      where promote x = StPrim Float2DoubleOp [x]
-      DoublePowerOp -> getRegister (StCall SLIT("pow") CCallConv DoubleRep 
+                                 )
+      MO_Dbl_Pwr -> getRegister (StCall SLIT("pow") CCallConv DoubleRep 
                                            [x, y])
-      other
-         -> ncgPrimopMoan "getRegister(x86,dyadic primop)" 
-                          (pprStixTree (StPrim primop [x, y]))
+      other -> pprPanic "getRegister(x86) - binary StMachOp (1)" (pprMachOp mop)
   where
+    promote x = StMachOp MO_Flt_to_Dbl [x]
+    demote x  = StMachOp MO_Dbl_to_Flt [x]
 
     --------------------
     shift_code :: (Imm -> Operand -> Instr)
-              -> StixTree
-              -> StixTree
+              -> StixExpr
+              -> StixExpr
               -> NatM Register
 
       {- Case1: shift length as immediate -}
@@ -895,7 +857,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
        returnNat (Any IntRep code__2)
 
     --------------------
-    add_code :: Size -> StixTree -> StixTree -> NatM Register
+    add_code :: Size -> StixExpr -> StixExpr -> NatM Register
 
     add_code sz x (StInt y)
       = getRegister x          `thenNat` \ register ->
@@ -914,7 +876,7 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
     add_code sz x y = trivialCode (ADD sz) (Just (ADD sz)) x y
 
     --------------------
-    sub_code :: Size -> StixTree -> StixTree -> NatM Register
+    sub_code :: Size -> StixExpr -> StixExpr -> NatM Register
 
     sub_code sz x (StInt y)
       = getRegister x          `thenNat` \ register ->
@@ -932,7 +894,6 @@ getRegister (StPrim primop [x, y]) -- dyadic PrimOps
 
     sub_code sz x y = trivialCode (SUB sz) Nothing x y
 
-
 getRegister (StInd pk mem)
   = getAmode mem                   `thenNat` \ amode ->
     let
@@ -970,11 +931,49 @@ getRegister leaf
     in
        returnNat (Any PtrRep code)
   | otherwise
-  = ncgPrimopMoan "getRegister(x86)" (pprStixTree leaf)
+  = ncgPrimopMoan "getRegister(x86)" (pprStixExpr leaf)
   where
     imm = maybeImm leaf
     imm__2 = case imm of Just x -> x
 
+
+assignMachOp :: Maybe012 StixVReg -> MachOp -> [StixExpr] 
+             -> NatM InstrBlock
+
+assignMachOp (Just2 sv_rr sv_cc) mop [aa,bb]
+  | mop `elem` [MO_NatS_AddC, MO_NatS_SubC, MO_NatS_MulC] 
+  = getRegister aa                     `thenNat` \ registeraa ->
+    getRegister bb                     `thenNat` \ registerbb ->
+    getNewRegNCG IntRep                        `thenNat` \ tmp ->
+    getNewRegNCG IntRep                        `thenNat` \ tmpaa ->
+    getNewRegNCG IntRep                        `thenNat` \ tmpbb ->
+    let stixVReg_to_VReg (StixVReg u rep) = mkVReg u rep
+        rr = stixVReg_to_VReg sv_rr
+        cc = stixVReg_to_VReg sv_cc
+        codeaa = registerCode registeraa tmpaa
+        srcaa  = registerName registeraa tmpaa
+        codebb = registerCode registerbb tmpbb
+        srcbb  = registerName registerbb tmpbb
+
+        insn = case mop of MO_NatS_AddC -> ADD; MO_NatS_SubC -> SUB
+                           MO_NatS_MulC -> IMUL
+        cond = if mop == MO_NatS_MulC then OFLO else CARRY
+        str  = showSDoc (pprMachOp mop)
+
+        code = toOL [
+                 COMMENT (_PK_ ("begin " ++ str)),
+                 MOV L (OpReg srcbb) (OpReg tmp),
+                 insn L (OpReg srcaa) (OpReg tmp),
+                 MOV L (OpReg tmp) (OpReg rr),
+                 MOV L (OpImm (ImmInt 0)) (OpReg eax),
+                 SETCC cond (OpReg eax),
+                 MOV L (OpReg eax) (OpReg cc),
+                 COMMENT (_PK_ ("end " ++ str))
+               ]
+    in
+       returnNat (codeaa `appOL` codebb `appOL` code)
+
+
 #endif {- i386_TARGET_ARCH -}
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if sparc_TARGET_ARCH
@@ -1239,7 +1238,7 @@ temporary, then do the other computation, and then use the temporary:
     ... (tmp) ...
 
 \begin{code}
-getAmode :: StixTree -> NatM Amode
+getAmode :: StixExpr -> NatM Amode
 
 getAmode tree@(StIndex _ _ _) = getAmode (mangleIndexTree tree)
 
@@ -1285,7 +1284,9 @@ getAmode other
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
-getAmode (StPrim IntSubOp [x, StInt i])
+-- This is all just ridiculous, since it carefully undoes 
+-- what mangleIndexTree has just done.
+getAmode (StMachOp MO_Nat_Sub [x, StInt i])
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
     let
@@ -1295,14 +1296,14 @@ getAmode (StPrim IntSubOp [x, StInt i])
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
-getAmode (StPrim IntAddOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
   | maybeToBool imm
   = returnNat (Amode (ImmAddr imm__2 (fromInteger i)) nilOL)
   where
     imm    = maybeImm x
     imm__2 = case imm of Just x -> x
 
-getAmode (StPrim IntAddOp [x, StInt i])
+getAmode (StMachOp MO_Nat_Add [x, StInt i])
   = getNewRegNCG PtrRep                `thenNat` \ tmp ->
     getRegister x              `thenNat` \ register ->
     let
@@ -1312,7 +1313,7 @@ getAmode (StPrim IntAddOp [x, StInt i])
     in
     returnNat (Amode (AddrBaseIndex (Just reg) Nothing off) code)
 
-getAmode (StPrim IntAddOp [x, StPrim SllOp [y, StInt shift]])
+getAmode (StMachOp MO_Nat_Add [x, StMachOp MO_Nat_Shl [y, StInt shift]])
   | shift == 0 || shift == 1 || shift == 2 || shift == 3
   = getNewRegNCG PtrRep                `thenNat` \ tmp1 ->
     getNewRegNCG IntRep        `thenNat` \ tmp2 ->
@@ -1428,7 +1429,7 @@ condCode  (CondCode _ _ code)        = code
 Set up a condition code for a conditional branch.
 
 \begin{code}
-getCondCode :: StixTree -> NatM CondCode
+getCondCode :: StixExpr -> NatM CondCode
 
 #if alpha_TARGET_ARCH
 getCondCode = panic "MachCode.getCondCode: not on Alphas"
@@ -1438,49 +1439,43 @@ getCondCode = panic "MachCode.getCondCode: not on Alphas"
 #if i386_TARGET_ARCH || sparc_TARGET_ARCH
 -- yes, they really do seem to want exactly the same!
 
-getCondCode (StPrim primop [x, y])
-  = case primop of
-      CharGtOp -> condIntCode GTT  x y
-      CharGeOp -> condIntCode GE   x y
-      CharEqOp -> condIntCode EQQ  x y
-      CharNeOp -> condIntCode NE   x y
-      CharLtOp -> condIntCode LTT  x y
-      CharLeOp -> condIntCode LE   x y
+getCondCode (StMachOp mop [x, y])
+  = case mop of
+      MO_32U_Gt -> condIntCode GTT  x y
+      MO_32U_Ge -> condIntCode GE   x y
+      MO_32U_Eq -> condIntCode EQQ  x y
+      MO_32U_Ne -> condIntCode NE   x y
+      MO_32U_Lt -> condIntCode LTT  x y
+      MO_32U_Le -> condIntCode LE   x y
  
-      IntGtOp  -> condIntCode GTT  x y
-      IntGeOp  -> condIntCode GE   x y
-      IntEqOp  -> condIntCode EQQ  x y
-      IntNeOp  -> condIntCode NE   x y
-      IntLtOp  -> condIntCode LTT  x y
-      IntLeOp  -> condIntCode LE   x y
-
-      WordGtOp -> condIntCode GU   x y
-      WordGeOp -> condIntCode GEU  x y
-      WordEqOp -> condIntCode EQQ  x y
-      WordNeOp -> condIntCode NE   x y
-      WordLtOp -> condIntCode LU   x y
-      WordLeOp -> condIntCode LEU  x y
-
-      AddrGtOp -> condIntCode GU   x y
-      AddrGeOp -> condIntCode GEU  x y
-      AddrEqOp -> condIntCode EQQ  x y
-      AddrNeOp -> condIntCode NE   x y
-      AddrLtOp -> condIntCode LU   x y
-      AddrLeOp -> condIntCode LEU  x y
-
-      FloatGtOp -> condFltCode GTT x y
-      FloatGeOp -> condFltCode GE  x y
-      FloatEqOp -> condFltCode EQQ x y
-      FloatNeOp -> condFltCode NE  x y
-      FloatLtOp -> condFltCode LTT x y
-      FloatLeOp -> condFltCode LE  x y
-
-      DoubleGtOp -> condFltCode GTT x y
-      DoubleGeOp -> condFltCode GE  x y
-      DoubleEqOp -> condFltCode EQQ x y
-      DoubleNeOp -> condFltCode NE  x y
-      DoubleLtOp -> condFltCode LTT x y
-      DoubleLeOp -> condFltCode LE  x y
+      MO_Nat_Eq  -> condIntCode EQQ  x y
+      MO_Nat_Ne  -> condIntCode NE   x y
+
+      MO_NatS_Gt -> condIntCode GTT  x y
+      MO_NatS_Ge -> condIntCode GE   x y
+      MO_NatS_Lt -> condIntCode LTT  x y
+      MO_NatS_Le -> condIntCode LE   x y
+
+      MO_NatU_Gt -> condIntCode GU   x y
+      MO_NatU_Ge -> condIntCode GEU  x y
+      MO_NatU_Lt -> condIntCode LU   x y
+      MO_NatU_Le -> condIntCode LEU  x y
+
+      MO_Flt_Gt -> condFltCode GTT x y
+      MO_Flt_Ge -> condFltCode GE  x y
+      MO_Flt_Eq -> condFltCode EQQ x y
+      MO_Flt_Ne -> condFltCode NE  x y
+      MO_Flt_Lt -> condFltCode LTT x y
+      MO_Flt_Le -> condFltCode LE  x y
+
+      MO_Dbl_Gt -> condFltCode GTT x y
+      MO_Dbl_Ge -> condFltCode GE  x y
+      MO_Dbl_Eq -> condFltCode EQQ x y
+      MO_Dbl_Ne -> condFltCode NE  x y
+      MO_Dbl_Lt -> condFltCode LTT x y
+      MO_Dbl_Le -> condFltCode LE  x y
+
+      other -> pprPanic "getCondCode(x86,sparc)" (pprMachOp mop)
 
 #endif {- i386_TARGET_ARCH || sparc_TARGET_ARCH -}
 \end{code}
@@ -1491,7 +1486,7 @@ getCondCode (StPrim primop [x, y])
 passed back up the tree.
 
 \begin{code}
-condIntCode, condFltCode :: Cond -> StixTree -> StixTree -> NatM CondCode
+condIntCode, condFltCode :: Cond -> StixExpr -> StixExpr -> NatM CondCode
 
 #if alpha_TARGET_ARCH
 condIntCode = panic "MachCode.condIntCode: not on Alphas"
@@ -1735,8 +1730,11 @@ generation for the right hand side.  This only fails when the right
 hand side is forced into a fixed register (e.g. the result of a call).
 
 \begin{code}
-assignIntCode, assignFltCode
-       :: PrimRep -> StixTree -> StixTree -> NatM InstrBlock
+assignMem_IntCode :: PrimRep -> StixExpr -> StixExpr -> NatM InstrBlock
+assignReg_IntCode :: PrimRep -> StixReg  -> StixExpr -> NatM InstrBlock
+
+assignMem_FltCode :: PrimRep -> StixExpr -> StixExpr -> NatM InstrBlock
+assignReg_FltCode :: PrimRep -> StixReg  -> StixExpr -> NatM InstrBlock
 
 #if alpha_TARGET_ARCH
 
@@ -1771,10 +1769,9 @@ assignIntCode pk dst src
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
--- Destination of an assignment can only be reg or mem.
--- This is the mem case.
-assignIntCode pk (StInd _ dst) src
-  = getAmode dst               `thenNat` \ amode ->
+-- non-FP assignment to memory
+assignMem_IntCode pk addr src
+  = getAmode addr              `thenNat` \ amode ->
     get_op_RI src              `thenNat` \ (codesrc, opsrc) ->
     getNewRegNCG PtrRep         `thenNat` \ tmp ->
     let
@@ -1801,7 +1798,7 @@ assignIntCode pk (StInd _ dst) src
     returnNat code
   where
     get_op_RI
-       :: StixTree
+       :: StixExpr
        -> NatM (InstrBlock,Operand)    -- code, operator
 
     get_op_RI op
@@ -1818,15 +1815,13 @@ assignIntCode pk (StInd _ dst) src
        returnNat (code, OpReg reg)
 
 -- Assign; dst is a reg, rhs is mem
-assignIntCode pk dst (StInd pks src)
+assignReg_IntCode pk reg (StInd pks src)
   = getNewRegNCG PtrRep            `thenNat` \ tmp ->
     getAmode src                   `thenNat` \ amode ->
-    getRegister dst                `thenNat` \ reg_dst ->
+    getRegisterReg reg             `thenNat` \ reg_dst ->
     let
        c_addr  = amodeCode amode
        am_addr = amodeAddr amode
-
-       c_dst = registerCode reg_dst tmp  -- should be empty
        r_dst = registerName reg_dst tmp
        szs   = primRepToSize pks
         opc   = case szs of
@@ -1837,30 +1832,23 @@ assignIntCode pk dst (StInd pks src)
             L  -> MOV L
             Lu -> MOV L
 
-       code  | isNilOL c_dst
-              = c_addr `snocOL`
+       code  = c_addr `snocOL`
                 opc (OpAddr am_addr) (OpReg r_dst)
-              | otherwise
-              = panic "assignIntCode(x86): bad dst(2)"
     in
     returnNat code
 
 -- dst is a reg, but src could be anything
-assignIntCode pk dst src
-  = getRegister dst                `thenNat` \ registerd ->
+assignReg_IntCode pk reg src
+  = getRegisterReg reg             `thenNat` \ registerd ->
     getRegister src                `thenNat` \ registers ->
     getNewRegNCG IntRep            `thenNat` \ tmp ->
     let 
         r_dst = registerName registerd tmp
-        c_dst = registerCode registerd tmp -- should be empty
         r_src = registerName registers r_dst
         c_src = registerCode registers r_dst
         
-        code | isNilOL c_dst
-             = c_src `snocOL` 
+        code = c_src `snocOL` 
                MOV L (OpReg r_src) (OpReg r_dst)
-             | otherwise
-             = panic "assignIntCode(x86): bad dst(3)"
     in
     returnNat code
 
@@ -1935,11 +1923,8 @@ assignFltCode pk dst src
 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 #if i386_TARGET_ARCH
 
--- dst is memory
-assignFltCode pk (StInd pk_dst addr) src
-   | pk /= pk_dst
-   = panic "assignFltCode(x86): src/ind sz mismatch"
-   | otherwise
+-- Floating point assignment to memory
+assignMem_FltCode pk addr src
    = getRegister src      `thenNat`  \ reg_src  ->
      getRegister addr     `thenNat`  \ reg_addr ->
      getNewRegNCG pk      `thenNat`  \ tmp_src  ->
@@ -1960,24 +1945,19 @@ assignFltCode pk (StInd pk_dst addr) src
      in
      returnNat code
 
--- dst must be a (FP) register
-assignFltCode pk dst src
-  = getRegister dst                `thenNat` \ reg_dst ->
+-- Floating point assignment to a register/temporary
+assignReg_FltCode pk reg src
+  = getRegisterReg reg             `thenNat` \ reg_dst ->
     getRegister src                `thenNat` \ reg_src ->
     getNewRegNCG pk                 `thenNat` \ tmp ->
     let
        r_dst = registerName reg_dst tmp
-        c_dst = registerCode reg_dst tmp -- should be empty
-
        r_src = registerName reg_src r_dst
        c_src = registerCode reg_src r_dst
 
-       code | isNilOL c_dst
-             = if   isFixed reg_src
+       code = if   isFixed reg_src
                then c_src `snocOL` GMOV r_src r_dst
                else c_src
-             | otherwise
-             = panic "assignFltCode(x86): lhs is not mem or reg" 
     in
     returnNat code
 
@@ -2055,7 +2035,7 @@ branch instruction.  Other CLabels are assumed to be far away.
 register allocator.
 
 \begin{code}
-genJump :: DestInfo -> StixTree{-the branch target-} -> NatM InstrBlock
+genJump :: DestInfo -> StixExpr{-the branch target-} -> NatM InstrBlock
 
 #if alpha_TARGET_ARCH
 
@@ -2157,7 +2137,7 @@ allocator.
 \begin{code}
 genCondJump
     :: CLabel      -- the branch target
-    -> StixTree     -- the condition on which to branch
+    -> StixExpr     -- the condition on which to branch
     -> NatM InstrBlock
 
 #if alpha_TARGET_ARCH
@@ -2354,7 +2334,7 @@ genCCall
     :: FAST_STRING     -- function to call
     -> CCallConv
     -> PrimRep         -- type of the result
-    -> [StixTree]      -- arguments (of mixed type)
+    -> [StixExpr]      -- arguments (of mixed type)
     -> NatM InstrBlock
 
 #if alpha_TARGET_ARCH
@@ -2482,7 +2462,7 @@ genCCall fn cconv kind args
     arg_size _  = 4
 
     ------------
-    get_call_arg :: StixTree{-current argument-}
+    get_call_arg :: StixExpr{-current argument-}
                     -> NatM (Int, InstrBlock)  -- argsz, code
 
     get_call_arg arg
@@ -2506,7 +2486,7 @@ genCCall fn cconv kind args
                        )
     ------------
     get_op
-       :: StixTree
+       :: StixExpr
        -> NatM (InstrBlock, Reg, Size) -- code, reg, size
 
     get_op op
@@ -2665,7 +2645,7 @@ the right hand side of an assignment).
 register allocator.
 
 \begin{code}
-condIntReg, condFltReg :: Cond -> StixTree -> StixTree -> NatM Register
+condIntReg, condFltReg :: Cond -> StixExpr -> StixExpr -> NatM Register
 
 #if alpha_TARGET_ARCH
 condIntReg = panic "MachCode.condIntReg (not on Alpha)"
@@ -2827,7 +2807,7 @@ trivialCode
                      -> Maybe (Operand -> Operand -> Instr)
       ,IF_ARCH_sparc((Reg -> RI -> Reg -> Instr)
       ,)))
-    -> StixTree -> StixTree -- the two arguments
+    -> StixExpr -> StixExpr -- the two arguments
     -> NatM Register
 
 trivialFCode
@@ -2836,7 +2816,7 @@ trivialFCode
       ,IF_ARCH_sparc((Size -> Reg -> Reg -> Reg -> Instr)
       ,IF_ARCH_i386 ((Size -> Reg -> Reg -> Reg -> Instr)
       ,)))
-    -> StixTree -> StixTree -- the two arguments
+    -> StixExpr -> StixExpr -- the two arguments
     -> NatM Register
 
 trivialUCode
@@ -2844,7 +2824,7 @@ trivialUCode
       ,IF_ARCH_i386 ((Operand -> Instr)
       ,IF_ARCH_sparc((RI -> Reg -> Instr)
       ,)))
-    -> StixTree        -- the one argument
+    -> StixExpr        -- the one argument
     -> NatM Register
 
 trivialUFCode
@@ -2853,7 +2833,7 @@ trivialUFCode
       ,IF_ARCH_i386 ((Reg -> Reg -> Instr)
       ,IF_ARCH_sparc((Reg -> Reg -> Instr)
       ,)))
-    -> StixTree -- the one argument
+    -> StixExpr -- the one argument
     -> NatM Register
 
 #if alpha_TARGET_ARCH
@@ -3207,11 +3187,11 @@ conversions.  We have to store temporaries in memory to move
 between the integer and the floating point register sets.
 
 \begin{code}
-coerceIntCode :: PrimRep -> StixTree -> NatM Register
-coerceFltCode ::           StixTree -> NatM Register
+coerceIntCode :: PrimRep -> StixExpr -> NatM Register
+coerceFltCode ::           StixExpr -> NatM Register
 
-coerceInt2FP :: PrimRep -> StixTree -> NatM Register
-coerceFP2Int ::           StixTree -> NatM Register
+coerceInt2FP :: PrimRep -> StixExpr -> NatM Register
+coerceFP2Int ::           StixExpr -> NatM Register
 
 coerceIntCode pk x
   = getRegister x              `thenNat` \ register ->
@@ -3339,7 +3319,7 @@ coerceFP2Int x
 Integer to character conversion.
 
 \begin{code}
-chrCode :: StixTree -> NatM Register
+chrCode :: StixExpr -> NatM Register
 
 #if alpha_TARGET_ARCH
 
index b72706e..ce88dd3 100644 (file)
@@ -42,21 +42,24 @@ import AbsCSyn              ( MagicId(..) )
 import AbsCUtils       ( magicIdPrimRep )
 import CLabel           ( CLabel, isAsmTemp )
 import Literal         ( mkMachInt, Literal(..) )
-import MachRegs                ( stgReg, callerSaves, RegLoc(..),
-                         Imm(..), Reg(..), 
-                         MachRegsAddr(..)
+import MachRegs                ( callerSaves,
+                          get_MagicId_addr, get_MagicId_reg_or_addr,
+                         Imm(..), Reg(..), MachRegsAddr(..)
 #                         if sparc_TARGET_ARCH
                           ,fp, sp
 #                         endif
                        )
 import PrimRep         ( PrimRep(..) )
-import Stix            ( StixTree(..), StixReg(..), CodeSegment, DestInfo(..) )
+import Stix            ( StixStmt(..), StixExpr(..), StixReg(..), 
+                          CodeSegment, DestInfo(..) )
 import Panic           ( panic )
 import GlaExts         ( word2Int#, int2Word#, shiftRL#, and#, (/=#) )
 import Outputable      ( pprPanic, ppr, showSDoc )
 import IOExts          ( trace )
 import Config           ( cLeadingUnderscore )
 import FastTypes
+
+import Maybe           ( catMaybes )
 \end{code}
 
 \begin{code}
@@ -110,30 +113,45 @@ constants.
 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
 
 \begin{code}
-volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
+volatileSaves, volatileRestores :: [MagicId] -> [StixStmt]
+
+volatileSaves    = volatileSavesOrRestores True
+volatileRestores = volatileSavesOrRestores False
 
 save_cands    = [BaseReg,Sp,Su,SpLim,Hp,HpLim]
 restore_cands = save_cands
 
-volatileSaves vols
-  = map save ((filter callerSaves) (save_cands ++ vols))
-  where
-    save x = StAssign (magicIdPrimRep x) loc reg
-      where
-       reg = StReg (StixMagicId x)
-       loc = case stgReg x of
-               Save loc -> loc
-               Always _ -> panic "volatileSaves"
-
-volatileRestores vols
-  = map restore ((filter callerSaves) (restore_cands ++ vols))
-  where
-    restore x = StAssign (magicIdPrimRep x) reg loc
-      where
-       reg = StReg (StixMagicId x)
-       loc = case stgReg x of
-               Save loc -> loc
-               Always _ -> panic "volatileRestores"
+volatileSavesOrRestores do_saves vols
+   = catMaybes (map mkCode vols)
+     where
+        mkCode mid
+           | not (callerSaves mid)
+           = Nothing
+           | otherwise -- must be callee-saves ...
+           = case get_MagicId_reg_or_addr mid of
+                -- If stored in BaseReg, we ain't interested
+                Right baseRegAddr 
+                   -> Nothing
+                Left (RealReg rrno)
+                   -- OK, it's callee-saves, and in a real reg (rrno).
+                   -- We have to cook up some transfer code.
+                   {- Note that the use of (StixMagicId mid) here is a bit subtle.  
+                      Here, we only create those for MagicIds which are stored in 
+                      a real reg on this arch -- the preceding case on the result 
+                      of get_MagicId_reg_or_addr guarantees this.  Later, when 
+                      selecting insns, that means these assignments are sure to turn 
+                      into real reg-to-mem or mem-to-reg moves, rather than being 
+                      pointless moves from some address in the reg-table 
+                      back to itself.-}
+                   |  do_saves
+                   -> Just (StAssignMem rep addr 
+                                            (StReg (StixMagicId mid)))
+                   |  otherwise
+                   -> Just (StAssignReg rep (StixMagicId mid)
+                                            (StInd rep addr))
+                      where
+                         rep  = magicIdPrimRep mid
+                         addr = get_MagicId_addr mid
 \end{code}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -206,6 +224,8 @@ data Cond
   | NE
   | NEG
   | POS
+  | CARRY
+  | OFLO
 #endif
 #if sparc_TARGET_ARCH
   = ALWAYS     -- What's really used? ToDo
@@ -291,6 +311,7 @@ primRepToSize WeakPtrRep    = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W
 primRepToSize ForeignObjRep = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W,  )))
 primRepToSize BCORep        = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W,  )))
 primRepToSize StablePtrRep  = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W,  )))
+primRepToSize StableNameRep = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W,  )))
 primRepToSize ThreadIdRep   = IF_ARCH_alpha(Q,  IF_ARCH_i386(L,  IF_ARCH_sparc(W,  )))
 
 primRepToSize Word64Rep     = primRepToSize_fail "Word64Rep"
@@ -476,14 +497,17 @@ but we don't care, since it doesn't get used much.  We hope.
 
              | ADD           Size Operand Operand
              | SUB           Size Operand Operand
-             | IMUL          Size Operand Operand
+             | IMUL          Size Operand Operand      -- signed int mul
+             | MUL           Size Operand Operand      -- unsigned int mul
 
 -- Quotient and remainder.  SEE comment above -- these are not
 -- real x86 insns; instead they are expanded when printed
 -- into a sequence of real insns.
 
-              | IQUOT         Size Operand Operand
-              | IREM          Size Operand Operand
+              | IQUOT         Size Operand Operand     -- signed quotient
+              | IREM          Size Operand Operand     -- signed remainder
+              | QUOT          Size Operand Operand     -- unsigned quotient
+              | REM           Size Operand Operand     -- unsigned remainder
 
 -- Simple bit-twiddling.
 
@@ -513,10 +537,7 @@ but we don't care, since it doesn't get used much.  We hope.
               | GLDZ          Reg -- dst(fpreg)
               | GLD1          Reg -- dst(fpreg)
 
-             | GFTOD         Reg Reg -- src(fpreg), dst(fpreg)
               | GFTOI         Reg Reg -- src(fpreg), dst(intreg)
-
-             | GDTOF         Reg Reg -- src(fpreg), dst(fpreg)
               | GDTOI         Reg Reg -- src(fpreg), dst(intreg)
 
               | GITOF         Reg Reg -- src(intreg), dst(fpreg)
@@ -592,8 +613,7 @@ is_G_instr instr
    = case instr of
         GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True;
         GLDZ _ -> True; GLD1 _ -> True;
-        GFTOD _ _ -> True; GFTOI _ _ -> True;
-        GDTOF _ _ -> True; GDTOI _ _ -> True;
+        GFTOI _ _ -> True; GDTOI _ _ -> True;
         GITOF _ _ -> True; GITOD _ _ -> True;
        GADD _ _ _ _ -> True; GDIV _ _ _ _ -> True
        GSUB _ _ _ _ -> True; GMUL _ _ _ _ -> True
index 0dce2fe..1e6d0b5 100644 (file)
@@ -20,7 +20,6 @@ module MachRegs (
 
        Imm(..),
        MachRegsAddr(..),
-       RegLoc(..),
 
        addrOffset,
        baseRegOffset,
@@ -28,11 +27,10 @@ module MachRegs (
        freeReg,
        getNewRegNCG,
        mkVReg,
-       magicIdRegMaybe,
-       saveLoc,
+        get_MagicId_reg_or_addr,
+        get_MagicId_addr,
+        get_Regtable_addr_from_offset,
        spRel,
-       stgReg,
-       regTableEntry,
        strImmLit
 
 #if alpha_TARGET_ARCH
@@ -56,11 +54,10 @@ module MachRegs (
 #include "HsVersions.h"
 
 import AbsCSyn         ( MagicId(..) )
-import AbsCUtils       ( magicIdPrimRep )
 import CLabel           ( CLabel, mkMainRegTableLabel )
-import PrimOp          ( PrimOp(..) )
+import MachOp          ( MachOp(..) )
 import PrimRep         ( PrimRep(..), isFloatingRep )
-import Stix            ( StixTree(..), StixReg(..),
+import Stix            ( StixExpr(..), StixReg(..),
                           getUniqueNat, returnNat, thenNat, NatM )
 import Unique          ( mkPseudoUnique2, Uniquable(..), Unique )
 import Pretty
@@ -171,42 +168,34 @@ largeOffsetError i
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
-@stgReg@: we map STG registers onto appropriate Stix Trees.  First, we
-handle the two constants, @STK_STUB_closure@ and @vtbl_StdUpdFrame@.
-The rest are either in real machine registers or stored as offsets
-from BaseReg.
+@stgReg@: we map STG registers onto appropriate Stix Trees.  Either
+they map to real machine registers or stored as offsets from BaseReg.
+Given a MagicId, get_MagicId_reg_or_addr produces either the real
+register it is in, on this platform, or a StixExpr denoting the
+address in the register table holding it.  get_MagicId_addr always
+produces the register table address for it.
 
 \begin{code}
-data RegLoc = Save StixTree | Always StixTree
-\end{code}
-
-Trees for register save locations:
-\begin{code}
-saveLoc :: MagicId -> StixTree
-saveLoc reg = case (stgReg reg) of {Always loc -> loc; Save loc -> loc}
-\end{code}
-
-\begin{code}
-stgReg :: MagicId -> RegLoc
-stgReg BaseReg
- = case magicIdRegMaybe BaseReg of
-       Nothing -> Always (StCLbl mkMainRegTableLabel)
-       Just _  -> Save   (StCLbl mkMainRegTableLabel)
-stgReg x
-  = case magicIdRegMaybe x of
-       Just _  -> Save   stix
-       Nothing -> Always stix
-  where
-    stix   = regTableEntry (magicIdPrimRep x) (baseRegOffset x)
-
-regTableEntry :: PrimRep -> Int -> StixTree
-regTableEntry rep offset 
-  = StInd rep (StPrim IntAddOp 
-                  [baseLoc, StInt (toInteger (offset*BYTES_PER_WORD))])
-  where
-    baseLoc = case (magicIdRegMaybe BaseReg) of
-      Just _  -> StReg (StixMagicId BaseReg)
-      Nothing -> StCLbl mkMainRegTableLabel
+get_MagicId_reg_or_addr       :: MagicId -> Either Reg StixExpr
+get_MagicId_addr              :: MagicId -> StixExpr
+get_Regtable_addr_from_offset :: Int -> StixExpr
+
+get_MagicId_reg_or_addr mid
+   = case magicIdRegMaybe mid of
+        Just rr -> Left rr
+        Nothing -> Right (get_MagicId_addr mid)
+
+get_MagicId_addr BaseReg
+   = panic "MachRegs.get_MagicId_addr of BaseReg"
+get_MagicId_addr mid
+   = get_Regtable_addr_from_offset (baseRegOffset mid)
+
+get_Regtable_addr_from_offset offset_in_words
+   = case magicIdRegMaybe BaseReg of
+        Nothing -> panic "MachRegs.get_Regtable_addr_from_offset: BaseReg not in a reg"
+        Just rr -> StMachOp MO_Nat_Add 
+                            [StReg (StixMagicId BaseReg),
+                             StInt (toInteger (offset_in_words*BYTES_PER_WORD))]
 \end{code}
 
 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
index 273a679..b873dcd 100644 (file)
@@ -249,6 +249,7 @@ pprCond c = ptext (case c of {
        LTT     -> SLIT("l");   LE    -> SLIT("le");
        LEU     -> SLIT("be");  NE    -> SLIT("ne");
        NEG     -> SLIT("s");   POS   -> SLIT("ns");
+        CARRY   -> SLIT("c");   OFLO  -> SLIT("o");
        ALWAYS  -> SLIT("mp")   -- hack
 #endif
 #if sparc_TARGET_ARCH
@@ -939,6 +940,15 @@ pprInstr (ADD size src dst)
 pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst
 pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
 
+{- A hack.  The Intel documentation says that "The two and three
+   operand forms [of IMUL] may also be used with unsigned operands
+   because the lower half of the product is the same regardless if
+   (sic) the operands are signed or unsigned.  The CF and OF flags,
+   however, cannot be used to determine if the upper half of the
+   result is non-zero."  So there.  
+-} 
+pprInstr (MUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
+
 pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst
 pprInstr (OR  size src dst) = pprSizeOpOp SLIT("or")  size src dst
 pprInstr (XOR size src dst) = pprSizeOpOp SLIT("xor")  size src dst
@@ -968,8 +978,12 @@ pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
 pprInstr (JMP dsts op)          = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
 pprInstr (CALL imm)             = (<>) (ptext SLIT("\tcall ")) (pprImm imm)
 
-pprInstr (IQUOT sz src dst) = pprInstr_quotRem True sz src dst
-pprInstr (IREM  sz src dst) = pprInstr_quotRem False sz src dst
+-- First bool indicates signedness; second whether quot or rem
+pprInstr (IQUOT sz src dst) = pprInstr_quotRem True True sz src dst
+pprInstr (IREM  sz src dst) = pprInstr_quotRem True False sz src dst
+
+pprInstr (QUOT sz src dst) = pprInstr_quotRem False True sz src dst
+pprInstr (REM  sz src dst) = pprInstr_quotRem False False sz src dst
 
 -- Simulating a flat register set on the x86 FP stack is tricky.
 -- you have to free %st(7) before pushing anything on the FP reg stack
@@ -995,15 +1009,12 @@ pprInstr g@(GLDZ dst)
 pprInstr g@(GLD1 dst)
  = pprG g (hcat [gtab, text "ffree %st(7) ; fld1 ; ", gpop dst 1])
 
-pprInstr g@(GFTOD src dst) 
-   = pprG g bogus
 pprInstr g@(GFTOI src dst) 
-   = pprG g bogus
-
-pprInstr g@(GDTOF src dst) 
-   = pprG g bogus
+   = pprInstr (GDTOI src dst)
 pprInstr g@(GDTOI src dst) 
-   = pprG g bogus
+   = pprG g (hcat [gtab, text "subl $4, %esp ; ", 
+                   gpush src 0, gsemi, text "fistpl 0(%esp) ; popl ", 
+                   pprReg L dst])
 
 pprInstr g@(GITOF src dst) 
    = pprInstr (GITOD src dst)
@@ -1108,7 +1119,7 @@ pprInstr GFREE
           ]
 
 
-pprInstr_quotRem isQuot sz src dst
+pprInstr_quotRem signed isQuot sz src dst
    | case sz of L -> False; _ -> True
    = panic "pprInstr_quotRem: dunno how to do non-32bit operands"
    | otherwise
@@ -1116,20 +1127,23 @@ pprInstr_quotRem isQuot sz src dst
      (text "\t# BEGIN " <> fakeInsn),
      (text "\tpushl $0;  pushl %eax;  pushl %edx;  pushl " <> pprOperand sz src),
      (text "\tmovl " <> pprOperand sz dst <> text ",%eax;  xorl %edx,%edx;  cltd"),
-     (text "\tdivl 0(%esp);  movl " <> text resReg <> text ",12(%esp)"),
+     (x86op <> text " 0(%esp);  movl " <> text resReg <> text ",12(%esp)"),
      (text "\tpopl %edx;  popl %edx;  popl %eax;  popl " <> pprOperand sz dst),
      (text "\t# END   " <> fakeInsn)
      ]
      where
+        x86op = if signed then text "\tidivl" else text "\tdivl"
         resReg = if isQuot then "%eax" else "%edx"
-        opStr  = if isQuot then "IQUOT" else "IREM"
-        fakeInsn = text opStr <+> pprOperand sz src <> char ',' <+> pprOperand sz dst
+        opStr  | signed     = if isQuot then "IQUOT" else "IREM"
+               | not signed = if isQuot then "QUOT"  else "REM"
+        fakeInsn = text opStr <+> pprOperand sz src 
+                              <> char ',' <+> pprOperand sz dst
 
 --------------------------
 
 -- coerce %st(0) to the specified size
 gcoerceto DF = empty
-gcoerceto  F = text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
+gcoerceto  F = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
 
 gpush reg offset
    = hcat [text "ffree %st(7) ; fld ", greg reg offset]
@@ -1157,10 +1171,7 @@ pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst
 pprGInstr (GLDZ dst) = pprSizeReg SLIT("gldz") DF dst
 pprGInstr (GLD1 dst) = pprSizeReg SLIT("gld1") DF dst
 
-pprGInstr (GFTOD src dst) = pprSizeSizeRegReg SLIT("gftod") F DF src dst
 pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L  src dst
-
-pprGInstr (GDTOF src dst) = pprSizeSizeRegReg SLIT("gdtof") DF F src dst
 pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst
 
 pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F  src dst
index 7fd7e91..f64ba40 100644 (file)
@@ -236,8 +236,11 @@ regUsage instr = case instr of
     ADD    sz src dst  -> usageRM src dst
     SUB    sz src dst  -> usageRM src dst
     IMUL   sz src dst  -> usageRM src dst
+    MUL    sz src dst  -> usageRM src dst
     IQUOT  sz src dst  -> usageRM src dst
     IREM   sz src dst  -> usageRM src dst
+    QUOT   sz src dst  -> usageRM src dst
+    REM    sz src dst  -> usageRM src dst
     AND    sz src dst  -> usageRM src dst
     OR     sz src dst  -> usageRM src dst
     XOR    sz src dst  -> usageRM src dst
@@ -266,10 +269,7 @@ regUsage instr = case instr of
     GLDZ   dst         -> mkRU [] [dst]
     GLD1   dst         -> mkRU [] [dst]
 
-    GFTOD  src dst     -> mkRU [src] [dst]
     GFTOI  src dst     -> mkRU [src] [dst]
-
-    GDTOF  src dst     -> mkRU [src] [dst]
     GDTOI  src dst     -> mkRU [src] [dst]
 
     GITOF  src dst     -> mkRU [src] [dst]
@@ -627,8 +627,11 @@ patchRegs instr env = case instr of
     ADD  sz src dst    -> patch2 (ADD  sz) src dst
     SUB  sz src dst    -> patch2 (SUB  sz) src dst
     IMUL sz src dst    -> patch2 (IMUL sz) src dst
+    MUL sz src dst     -> patch2 (MUL sz) src dst
     IQUOT sz src dst   -> patch2 (IQUOT sz) src dst
     IREM sz src dst    -> patch2 (IREM sz) src dst
+    QUOT sz src dst    -> patch2 (QUOT sz) src dst
+    REM sz src dst     -> patch2 (REM sz) src dst
     AND  sz src dst    -> patch2 (AND  sz) src dst
     OR   sz src dst    -> patch2 (OR   sz) src dst
     XOR  sz src dst    -> patch2 (XOR  sz) src dst
@@ -652,10 +655,7 @@ patchRegs instr env = case instr of
     GLDZ dst           -> GLDZ (env dst)
     GLD1 dst           -> GLD1 (env dst)
 
-    GFTOD src dst      -> GFTOD (env src) (env dst)
     GFTOI src dst      -> GFTOI (env src) (env dst)
-
-    GDTOF src dst      -> GDTOF (env src) (env dst)
     GDTOI src dst      -> GDTOI (env src) (env dst)
 
     GITOF src dst      -> GITOF (env src) (env dst)
index e8c27d1..951cfb6 100644 (file)
@@ -4,9 +4,11 @@
 
 \begin{code}
 module Stix (
-       CodeSegment(..), StixReg(..), StixTree(..), StixTreeList,
-       pprStixTrees, pprStixTree, ppStixReg,
-        stixCountTempUses, stixSubst,
+       CodeSegment(..), StixReg(..), StixExpr(..), StixVReg(..),
+        StixStmt(..), mkStAssign, StixStmtList,
+       pprStixStmts, pprStixStmt, pprStixExpr, pprStixReg,
+        stixStmt_CountTempUses, stixStmt_Subst,
+        liftStrings,
        DestInfo(..), hasDestInfo,
 
        stgBaseReg, stgNode, stgSp, stgSu, stgSpLim, 
@@ -35,54 +37,45 @@ import AbsCSyn              ( node, tagreg, MagicId(..) )
 import ForeignCall     ( CCallConv )
 import CLabel          ( mkAsmTempLabel, CLabel, pprCLabel )
 import PrimRep          ( PrimRep(..) )
-import PrimOp           ( PrimOp )
+import MachOp          ( MachOp(..), pprMachOp )
 import Unique           ( Unique )
 import SMRep           ( fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize )
 import UniqSupply      ( UniqSupply, splitUniqSupply, uniqFromSupply,
                           UniqSM, thenUs, returnUs, getUniqueUs )
+import Maybes          ( Maybe012(..), maybe012ToList )
 import Outputable
 import FastTypes
 \end{code}
 
-Here is the tag at the nodes of our @StixTree@.         Notice its
-relationship with @PrimOp@ in prelude/PrimOp.
+Two types, StixStmt and StixValue, define Stix.
 
 \begin{code}
-data StixTree
-  = -- Segment (text or data)
 
-    StSegment CodeSegment
-
-    -- We can tag the leaves with constants/immediates.
-
-  | StInt      Integer     -- ** add Kind at some point
-  | StFloat    Rational
-  | StDouble   Rational
-  | StString   FAST_STRING
-  | StCLbl     CLabel      -- labels that we might index into
-
-    -- Abstract registers of various kinds
-
-  | StReg StixReg
+-- Non-value trees; ones executed for their side-effect.
+data StixStmt
 
-    -- A typed offset from a base location
-
-  | StIndex PrimRep StixTree StixTree -- kind, base, offset
+  = -- Directive for the assembler to change segment
+    StSegment CodeSegment
 
-    -- An indirection from an address to its contents.
+    -- Assembly-language comments
+  | StComment FAST_STRING
 
-  | StInd PrimRep StixTree
+    -- Assignments are typed to determine size and register placement.
+    -- Assign a value to a StixReg
+  | StAssignReg PrimRep StixReg StixExpr
 
-    -- Assignment is typed to determine size and register placement
+    -- Assign a value to memory.  First tree indicates the address to be
+    -- assigned to, so there is an implicit dereference here.
+  | StAssignMem PrimRep StixExpr StixExpr -- dst, src
 
-  | StAssign PrimRep StixTree StixTree -- dst, src
+    -- Do a machine op which generates multiple values, and assign
+    -- the results to the lvalues stated here.
+  | StAssignMachOp (Maybe012 StixVReg) MachOp [StixExpr]
 
     -- A simple assembly label that we might jump to.
-
   | StLabel CLabel
 
     -- A function header and footer
-
   | StFunBegin CLabel
   | StFunEnd CLabel
 
@@ -93,41 +86,71 @@ data StixTree
     -- the exact targets to be attached, so that the allocator can
     -- easily construct the exact flow edges leaving this insn.
     -- Dynamic targets are allowed.
-
-  | StJump DestInfo StixTree
+  | StJump DestInfo StixExpr
 
     -- A fall-through, from slow to fast
-
   | StFallThrough CLabel
 
     -- A conditional jump. This instruction can be non-terminal :-)
     -- Only static, local, forward labels are allowed
-
-  | StCondJump CLabel StixTree
+  | StCondJump CLabel StixExpr
 
     -- Raw data (as in an info table).
+  | StData PrimRep [StixExpr]
+    -- String which has been lifted to the top level (sigh).
+  | StDataString FAST_STRING
+
+    -- A value computed only for its side effects; result is discarded
+    -- (A handy trapdoor to allow CCalls with no results to appear as
+    -- statements).
+  | StVoidable StixExpr
+
+
+-- Helper fn to make Stix assignment statements where the 
+-- lvalue masquerades as a StixExpr.  A kludge that should
+-- be done away with.
+mkStAssign :: PrimRep -> StixExpr -> StixExpr -> StixStmt
+mkStAssign rep (StReg reg) rhs  
+   = StAssignReg rep reg rhs
+mkStAssign rep (StInd rep' addr) rhs 
+   | rep `isCloseEnoughTo` rep'
+   = StAssignMem rep addr rhs
+   | otherwise
+   = --pprPanic "Stix.mkStAssign: mismatched reps" (ppr rep <+> ppr rep')
+     --trace ("Stix.mkStAssign: mismatched reps: " ++ showSDoc (ppr rep <+> ppr rep')) (
+     StAssignMem rep addr rhs
+     --)
+     where
+        isCloseEnoughTo r1 r2
+           = r1 == r2 || (wordIsh r1 && wordIsh r2)
+        wordIsh rep
+           = rep `elem` [IntRep, WordRep, PtrRep, AddrRep, CodePtrRep, 
+                         RetRep, ArrayRep, PrimPtrRep, StableNameRep, BCORep]
+                        -- determined by looking at PrimRep.showPrimRep
+
+-- Stix trees which denote a value.
+data StixExpr
+  = -- Literals
+    StInt      Integer     -- ** add Kind at some point
+  | StFloat    Rational
+  | StDouble   Rational
+  | StString   FAST_STRING
+  | StCLbl     CLabel      -- labels that we might index into
 
-  | StData PrimRep [StixTree]
-
-    -- Primitive Operations
-
-  | StPrim PrimOp [StixTree]
-
-    -- Calls to C functions
-
-  | StCall FAST_STRING CCallConv PrimRep [StixTree]
+    -- Abstract registers of various kinds
+  | StReg StixReg
 
-    -- A volatile memory scratch array, which is allocated
-    -- relative to the stack pointer.  It is an array of
-    -- ptr/word/int sized things.  Do not expect to be preserved
-    -- beyond basic blocks or over a ccall.  Current max size
-    -- is 6, used in StixInteger.
+    -- A typed offset from a base location
+  | StIndex PrimRep StixExpr StixExpr -- kind, base, offset
 
-  | StScratchWord Int
+    -- An indirection from an address to its contents.
+  | StInd PrimRep StixExpr
 
-    -- Assembly-language comments
+    -- Primitive Operations
+  | StMachOp MachOp [StixExpr]
 
-  | StComment FAST_STRING
+    -- Calls to C functions
+  | StCall FAST_STRING CCallConv PrimRep [StixExpr]
 
 
 -- used by insnFuture in RegAllocInfo.lhs
@@ -143,46 +166,64 @@ pprDests NoDestInfo      = text "NoDestInfo"
 pprDests (DestInfo dsts) = brackets (hsep (map pprCLabel dsts))
 
 
-pprStixTrees :: [StixTree] -> SDoc
-pprStixTrees ts 
+pprStixStmts :: [StixStmt] -> SDoc
+pprStixStmts ts 
   = vcat [
-       vcat (map pprStixTree ts),
+       vcat (map pprStixStmt ts),
        char ' ',
        char ' '
     ]
 
-pprStixTree :: StixTree -> SDoc
-pprStixTree t 
+
+pprStixExpr :: StixExpr -> SDoc
+pprStixExpr t 
    = case t of
-       StSegment cseg   -> parens (ppCodeSegment cseg)
-       StInt i          -> parens (integer i)
+       StCLbl lbl       -> pprCLabel lbl
+       StInt i          -> (if i < 0 then parens else id) (integer i)
        StFloat rat      -> parens (text "Float" <+> rational rat)
        StDouble        rat     -> parens (text "Double" <+> rational rat)
        StString str     -> parens (text "Str `" <> ptext str <> char '\'')
+       StIndex k b o    -> parens (pprStixExpr b <+> char '+' <> 
+                                   ppr k <+> pprStixExpr o)
+       StInd k t        -> ppr k <> char '[' <> pprStixExpr t <> char ']'
+       StReg reg        -> pprStixReg reg
+       StMachOp op args -> pprMachOp op 
+                           <> parens (hsep (punctuate comma (map pprStixExpr args)))
+       StCall nm cc k args
+                        -> parens (text "Call" <+> ptext nm <+>
+                                   ppr cc <+> ppr k <+> 
+                                   hsep (map pprStixExpr args))
+
+pprStixStmt :: StixStmt -> SDoc
+pprStixStmt t 
+   = case t of
+       StSegment cseg   -> parens (ppCodeSegment cseg)
        StComment str    -> parens (text "Comment" <+> ptext str)
-       StCLbl lbl       -> pprCLabel lbl
-       StReg reg        -> ppStixReg reg
-       StIndex k b o    -> parens (pprStixTree b <+> char '+' <> 
-                                   ppr k <+> pprStixTree o)
-       StInd k t        -> ppr k <> char '[' <> pprStixTree t <> char ']'
-       StAssign k d s   -> pprStixTree d <> text "  :=" <> ppr k 
-                                         <> text "  " <> pprStixTree s
+       StAssignReg pr reg rhs
+                        -> pprStixReg reg <> text "  :=" <> ppr pr
+                                          <> text "  " <> pprStixExpr rhs
+       StAssignMem pr addr rhs
+                        -> ppr pr <> char '[' <> pprStixExpr addr <> char ']'
+                                  <> text "  :=" <> ppr pr
+                                  <> text "  " <> pprStixExpr rhs
+       StAssignMachOp lhss mop args
+                        -> parens (hcat (punctuate comma (
+                              map pprStixVReg (maybe012ToList lhss)
+                           )))
+                           <> text "  :=  "
+                           <> pprMachOp mop
+                           <> parens (hsep (punctuate comma (map pprStixExpr args)))
        StLabel ll       -> pprCLabel ll <+> char ':'
        StFunBegin ll    -> char ' ' $$ parens (text "FunBegin" <+> pprCLabel ll)
        StFunEnd ll      -> parens (text "FunEnd" <+> pprCLabel ll)
-       StJump dsts t    -> parens (text "Jump" <+> pprDests dsts <+> pprStixTree t)
+       StJump dsts t    -> parens (text "Jump" <+> pprDests dsts <+> pprStixExpr t)
        StFallThrough ll -> parens (text "FallThru" <+> pprCLabel ll)
        StCondJump l t   -> parens (text "JumpC" <+> pprCLabel l 
-                                                <+> pprStixTree t)
+                                                <+> pprStixExpr t)
        StData k ds      -> parens (text "Data" <+> ppr k <+>
-                                   hsep (map pprStixTree ds))
-       StPrim op ts     -> parens (text "Prim" <+> ppr op <+> 
-                                   hsep (map pprStixTree ts))
-       StCall nm cc k args
-                        -> parens (text "Call" <+> ptext nm <+>
-                                   ppr cc <+> ppr k <+> 
-                                   hsep (map pprStixTree args))
-       StScratchWord i  -> text "ScratchWord" <> parens (int i)
+                                   hsep (map pprStixExpr ds))
+       StDataString str -> parens (text "DataString" <+> ppr str)
+       StVoidable expr  -> text "(void)" <+> pprStixExpr expr
 \end{code}
 
 Stix registers can have two forms.  They {\em may} or {\em may not}
@@ -192,13 +233,17 @@ map to real, machine-level registers.
 data StixReg
   = StixMagicId MagicId        -- Regs which are part of the abstract machine model
 
-  | StixTemp Unique PrimRep -- "Regs" which model local variables (CTemps) in
-                                       -- the abstract C.
+  | StixTemp StixVReg   -- "Regs" which model local variables (CTemps) in
+                       -- the abstract C.
+
+pprStixReg (StixMagicId mid)  = ppMId mid
+pprStixReg (StixTemp temp)    = pprStixVReg temp
+
+data StixVReg
+   = StixVReg Unique PrimRep
+
+pprStixVReg (StixVReg u pr) = hcat [text "VReg(", ppr u, ppr pr, char ')']
 
-ppStixReg (StixMagicId mid)
-   = ppMId mid
-ppStixReg (StixTemp u pr)
-   = hcat [text "Temp(", ppr u, ppr pr, char ')']
 
 
 ppMId BaseReg              = text "BaseReg"
@@ -222,30 +267,35 @@ segment (or that it has no segments at all, and we can lump these
 together).
 
 \begin{code}
-data CodeSegment = DataSegment | TextSegment | RoDataSegment deriving (Eq, Show)
+data CodeSegment 
+   = DataSegment 
+   | TextSegment 
+   | RoDataSegment 
+     deriving (Eq, Show)
+
 ppCodeSegment = text . show
 
-type StixTreeList = [StixTree] -> [StixTree]
+type StixStmtList = [StixStmt] -> [StixStmt]
 \end{code}
 
 Stix Trees for STG registers:
 \begin{code}
 stgBaseReg, stgNode, stgSp, stgSu, stgSpLim, stgHp, stgHpLim 
-       :: StixTree
-
-stgBaseReg         = StReg (StixMagicId BaseReg)
-stgNode            = StReg (StixMagicId node)
-stgTagReg          = StReg (StixMagicId tagreg)
-stgSp              = StReg (StixMagicId Sp)
-stgSu              = StReg (StixMagicId Su)
-stgSpLim           = StReg (StixMagicId SpLim)
-stgHp              = StReg (StixMagicId Hp)
-stgHpLim           = StReg (StixMagicId HpLim)
-stgHpAlloc         = StReg (StixMagicId HpAlloc)
-stgCurrentTSO      = StReg (StixMagicId CurrentTSO)
-stgCurrentNursery   = StReg (StixMagicId CurrentNursery)
-stgR9               = StReg (StixMagicId (VanillaReg WordRep (_ILIT 9)))
-stgR10              = StReg (StixMagicId (VanillaReg WordRep (_ILIT 10)))
+       :: StixReg
+
+stgBaseReg         = StixMagicId BaseReg
+stgNode            = StixMagicId node
+stgTagReg          = StixMagicId tagreg
+stgSp              = StixMagicId Sp
+stgSu              = StixMagicId Su
+stgSpLim           = StixMagicId SpLim
+stgHp              = StixMagicId Hp
+stgHpLim           = StixMagicId HpLim
+stgHpAlloc         = StixMagicId HpAlloc
+stgCurrentTSO      = StixMagicId CurrentTSO
+stgCurrentNursery   = StixMagicId CurrentNursery
+stgR9               = StixMagicId (VanillaReg WordRep (_ILIT 9))
+stgR10              = StixMagicId (VanillaReg WordRep (_ILIT 10))
 
 getNatLabelNCG :: NatM CLabel
 getNatLabelNCG
@@ -267,83 +317,220 @@ given temporary appears in a tree, so as to be able to decide
 whether or not to inline the assignment's RHS at usage site(s).
 
 \begin{code}
-stixCountTempUses :: Unique -> StixTree -> Int
-stixCountTempUses u t 
-   = let qq = stixCountTempUses u
+stixExpr_CountTempUses :: Unique -> StixExpr -> Int
+stixExpr_CountTempUses u t 
+   = let qs = stixStmt_CountTempUses u
+         qe = stixExpr_CountTempUses u
+         qr = stixReg_CountTempUses u
      in
      case t of
-        StReg reg
-           -> case reg of 
-                 StixTemp uu pr  -> if u == uu then 1 else 0
-                 StixMagicId mid -> 0
-
-        StIndex    pk t1 t2       -> qq t1 + qq t2
-        StInd      pk t1          -> qq t1
-        StAssign   pk t1 t2       -> qq t1 + qq t2
-        StJump     dsts t1        -> qq t1
-        StCondJump lbl t1         -> qq t1
-        StData     pk ts          -> sum (map qq ts)
-        StPrim     op ts          -> sum (map qq ts)
-        StCall     nm cconv pk ts -> sum (map qq ts)
-
-        StSegment _      -> 0
+        StReg      reg            -> qr reg
+        StIndex    pk t1 t2       -> qe t1 + qe t2
+        StInd      pk t1          -> qe t1
+        StMachOp   mop ts         -> sum (map qe ts)
+        StCall     nm cconv pk ts -> sum (map qe ts)
         StInt _          -> 0
         StFloat _        -> 0
         StDouble _       -> 0
         StString _       -> 0
         StCLbl _         -> 0
-        StLabel _        -> 0
+
+stixStmt_CountTempUses :: Unique -> StixStmt -> Int
+stixStmt_CountTempUses u t 
+   = let qe = stixExpr_CountTempUses u
+         qr = stixReg_CountTempUses u
+         qv = stixVReg_CountTempUses u
+     in
+     case t of
+        StAssignReg pk reg rhs  -> qr reg + qe rhs
+        StAssignMem pk addr rhs -> qe addr + qe rhs
+        StJump     dsts t1      -> qe t1
+        StCondJump lbl t1       -> qe t1
+        StData     pk ts        -> sum (map qe ts)
+        StAssignMachOp lhss mop args
+           -> sum (map qv (maybe012ToList lhss)) + sum (map qe args)
+        StVoidable expr  -> qe expr
+        StSegment _      -> 0
         StFunBegin _     -> 0
         StFunEnd _       -> 0
         StFallThrough _  -> 0
-        StScratchWord _  -> 0
         StComment _      -> 0
+        StLabel _        -> 0
+        StDataString _   -> 0
+
+stixReg_CountTempUses u reg
+   = case reg of 
+        StixTemp vreg    -> stixVReg_CountTempUses u vreg
+        StixMagicId mid  -> 0
 
+stixVReg_CountTempUses u (StixVReg uu pr)
+   = if u == uu then 1 else 0
+\end{code}
+
+If we do decide to inline a temporary binding, the following functions
+do the biz.
 
-stixSubst :: Unique -> StixTree -> StixTree -> StixTree
-stixSubst u new_u in_this_tree
-   = stixMapUniques f in_this_tree
+\begin{code}
+stixStmt_Subst :: Unique -> StixExpr -> StixStmt -> StixStmt
+stixStmt_Subst u new_u in_this_tree
+   = stixStmt_MapUniques f in_this_tree
      where
-        f :: Unique -> Maybe StixTree
+        f :: Unique -> Maybe StixExpr
         f uu = if uu == u then Just new_u else Nothing
 
 
-stixMapUniques :: (Unique -> Maybe StixTree) -> StixTree -> StixTree
-stixMapUniques f t
-   = let qq = stixMapUniques f
+stixExpr_MapUniques :: (Unique -> Maybe StixExpr) -> StixExpr -> StixExpr
+stixExpr_MapUniques f t
+   = let qe = stixExpr_MapUniques f
+         qs = stixStmt_MapUniques f
+         qr = stixReg_MapUniques f
      in
      case t of
-        StReg reg
-           -> case reg of 
-                 StixMagicId mid -> t
-                 StixTemp uu pr  
-                    -> case f uu of
-                          Just xx -> xx
-                          Nothing -> t
-
-        StIndex    pk t1 t2       -> StIndex    pk (qq t1) (qq t2)
-        StInd      pk t1          -> StInd      pk (qq t1)
-        StAssign   pk t1 t2       -> StAssign   pk (qq t1) (qq t2)
-        StJump     dsts t1        -> StJump     dsts (qq t1)
-        StCondJump lbl t1         -> StCondJump lbl (qq t1)
-        StData     pk ts          -> StData     pk (map qq ts)
-        StPrim     op ts          -> StPrim     op (map qq ts)
-        StCall     nm cconv pk ts -> StCall     nm cconv pk (map qq ts)
-
-        StSegment _      -> t
+        StReg reg -> case qr reg of
+                     Nothing -> StReg reg
+                     Just xx -> xx
+        StIndex    pk t1 t2       -> StIndex    pk (qe t1) (qe t2)
+        StInd      pk t1          -> StInd      pk (qe t1)
+        StMachOp   mop args       -> StMachOp   mop (map qe args)
+        StCall     nm cconv pk ts -> StCall     nm cconv pk (map qe ts)
         StInt _          -> t
         StFloat _        -> t
         StDouble _       -> t
         StString _       -> t
         StCLbl _         -> t
+
+stixStmt_MapUniques :: (Unique -> Maybe StixExpr) -> StixStmt -> StixStmt
+stixStmt_MapUniques f t
+   = let qe = stixExpr_MapUniques f
+         qs = stixStmt_MapUniques f
+         qr = stixReg_MapUniques f
+         qv = stixVReg_MapUniques f
+
+         doMopLhss Just0 = Just0
+         doMopLhss (Just1 r1)
+            = case qv r1 of
+                 Nothing -> Just1 r1
+                 other   -> doMopLhss_panic
+         doMopLhss (Just2 r1 r2)
+            = case (qv r1, qv r2) of
+                 (Nothing, Nothing) -> Just2 r1 r2
+                 other              -> doMopLhss_panic
+         -- Because the StixRegs processed by doMopLhss are lvalues, they
+         -- absolutely shouldn't be mapped to a StixExpr; 
+         -- hence we panic if they do.  Same deal for StAssignReg below.
+         doMopLhss_panic
+            = panic "stixStmt_MapUniques:doMopLhss"
+     in
+     case t of
+        StAssignReg pk reg rhs
+           -> case qr reg of
+                 Nothing -> StAssignReg pk reg (qe rhs)
+                 Just xx -> panic "stixStmt_MapUniques:StAssignReg"
+        StAssignMem pk addr rhs   -> StAssignMem pk (qe addr) (qe rhs)
+        StJump     dsts t1        -> StJump     dsts (qe t1)
+        StCondJump lbl t1         -> StCondJump lbl (qe t1)
+        StData     pk ts          -> StData     pk (map qe ts)
+        StVoidable expr           ->  StVoidable (qe expr)
+        StAssignMachOp lhss mop args
+           -> StAssignMachOp (doMopLhss lhss) mop (map qe args)
+        StSegment _      -> t
         StLabel _        -> t
         StFunBegin _     -> t
         StFunEnd _       -> t
         StFallThrough _  -> t
-        StScratchWord _  -> t
         StComment _      -> t
+        StDataString _   -> t
+
+
+stixReg_MapUniques :: (Unique -> Maybe StixExpr) -> StixReg -> Maybe StixExpr
+stixReg_MapUniques f reg
+   = case reg of
+        StixMagicId mid -> Nothing
+        StixTemp vreg   -> stixVReg_MapUniques f vreg
+
+stixVReg_MapUniques :: (Unique -> Maybe StixExpr) -> StixVReg -> Maybe StixExpr
+stixVReg_MapUniques f (StixVReg uu pr)
+   = f uu
+\end{code}
+
+\begin{code}
+-- Lift StStrings out of top-level StDatas, putting them at the end of
+-- the block, and replacing them with StCLbls which refer to the lifted-out strings. 
+{- Motivation for this hackery provided by the following bug:
+   Stix:
+      (DataSegment)
+      Bogon.ping_closure :
+      (Data P_ Addr.A#_static_info)
+      (Data StgAddr (Str `alalal'))
+      (Data P_ (0))
+   results in:
+      .data
+              .align 8
+      .global Bogon_ping_closure
+      Bogon_ping_closure:
+              .long   Addr_Azh_static_info
+              .long   .Ln1a8
+      .Ln1a8:
+              .byte   0x61
+              .byte   0x6C
+              .byte   0x61
+              .byte   0x6C
+              .byte   0x61
+              .byte   0x6C
+              .byte   0x00
+              .long   0
+   ie, the Str is planted in-line, when what we really meant was to place
+   a _reference_ to the string there.  liftStrings will lift out all such
+   strings in top-level data and place them at the end of the block.
+
+   This is still a rather half-baked solution -- to do the job entirely right
+   would mean a complete traversal of all the Stixes, but there's currently no
+   real need for it, and it would be slow.  Also, potentially there could be
+   literal types other than strings which need lifting out?
+-}
+
+liftStrings :: [StixStmt] -> UniqSM [StixStmt]
+liftStrings stmts
+   = liftStrings_wrk stmts [] []
+
+liftStrings_wrk :: [StixStmt]    -- originals
+                -> [StixStmt]    -- (reverse) originals with strings lifted out
+                -> [(CLabel, FAST_STRING)]   -- lifted strs, and their new labels
+                -> UniqSM [StixStmt]
+
+-- First, examine the original trees and lift out strings in top-level StDatas.
+liftStrings_wrk (st:sts) acc_stix acc_strs
+   = case st of
+        StData sz datas
+           -> lift datas acc_strs      `thenUs` \ (datas_done, acc_strs1) ->
+              liftStrings_wrk sts ((StData sz datas_done):acc_stix) acc_strs1
+        other 
+           -> liftStrings_wrk sts (other:acc_stix) acc_strs
+     where
+        -- Handle a top-level StData
+        lift []     acc_strs = returnUs ([], acc_strs)
+        lift (d:ds) acc_strs
+           = lift ds acc_strs          `thenUs` \ (ds_done, acc_strs1) ->
+             case d of
+                StString s 
+                   -> getUniqueUs      `thenUs` \ unq ->
+                      let lbl = mkAsmTempLabel unq in
+                      returnUs ((StCLbl lbl):ds_done, ((lbl,s):acc_strs1))
+                other
+                   -> returnUs (other:ds_done, acc_strs1)
+
+-- When we've run out of original trees, emit the lifted strings.
+liftStrings_wrk [] acc_stix acc_strs
+   = returnUs (reverse acc_stix ++ concatMap f acc_strs)
+     where
+        f (lbl,str) = [StSegment RoDataSegment, 
+                       StLabel lbl, 
+                       StDataString str, 
+                       StSegment TextSegment]
 \end{code}
 
+The NCG's monad.
+
 \begin{code}
 data NatM_State = NatM_State UniqSupply Int
 type NatM result = NatM_State -> (result, NatM_State)
index af6fa72..bf822e2 100644 (file)
@@ -42,7 +42,7 @@ Generating code for info tables (arrays of data).
 \begin{code}
 genCodeInfoTable
     :: AbstractC
-    -> UniqSM StixTreeList
+    -> UniqSM StixStmtList
 
 genCodeInfoTable (CClosureInfoAndCode cl_info _ _ cl_descr)
   = returnUs (\xs -> StData PtrRep table : StLabel info_lbl : xs)
@@ -106,7 +106,7 @@ genBitmapInfoTable
        -> C_SRT
        -> Int
        -> Bool                 -- must include SRT field (i.e. it's a vector)
-       -> UniqSM StixTreeList
+       -> UniqSM StixStmtList
 
 genBitmapInfoTable liveness srt closure_type include_srt
   = returnUs (\xs -> StData PtrRep table : xs)
diff --git a/ghc/compiler/nativeGen/StixInteger.lhs b/ghc/compiler/nativeGen/StixInteger.lhs
deleted file mode 100644 (file)
index cd642e8..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-%
-% (c) The AQUA Project, Glasgow University, 1993-1998
-%
-
-\begin{code}
-module StixInteger ( 
-       gmpCompare, 
-        gmpCompareInt,
-       gmpInteger2Int, 
-       gmpInteger2Word,
-       gmpNegate
-       ) where
-
-#include "HsVersions.h"
-
-import {-# SOURCE #-} StixPrim ( amodeToStix )
-
-import AbsCSyn         hiding (spRel) -- bits and bobs..
-import ForeignCall     ( CCallConv(..) )
-import PrimOp          ( PrimOp(..) )
-import PrimRep         ( PrimRep(..) )
-import Stix            ( StixTree(..), StixTreeList, arrWordsHS )
-import UniqSupply      ( returnUs, UniqSM )
-\end{code}
-
-Although gmpCompare doesn't allocate space, it does temporarily use
-some space just beyond the heap pointer.  This is safe, because the
-enclosing routine has already guaranteed that this space will be
-available.  (See ``primOpHeapRequired.'')
-
-\begin{code}
-stgArrWords__words        :: StixTree -> StixTree
-stgArrWords__BYTE_ARR_CTS :: StixTree -> StixTree
-
-stgArrWords__BYTE_ARR_CTS arr 
-   = StIndex WordRep arr arrWordsHS
-stgArrWords__words        arr 
-   = case arrWordsHS of 
-        StInt i -> StInd WordRep (StIndex PtrRep arr (StInt (i-1)))
-
-gmpCompare
-    :: CAddrMode           -- result (boolean)
-    -> (CAddrMode,CAddrMode,CAddrMode,CAddrMode)
-                           -- alloc hp + 2 arguments (2 parts each)
-    -> UniqSM StixTreeList
-
-gmpCompare res args@(csa1,cda1, csa2,cda2)
-  = let
-       result  = amodeToStix res
-       sa1     = amodeToStix csa1
-       sa2     = amodeToStix csa2
-       aa1     = stgArrWords__words (amodeToStix cda1)
-       aa2     = stgArrWords__words (amodeToStix cda2)
-       da1     = stgArrWords__BYTE_ARR_CTS (amodeToStix cda1)
-       da2     = stgArrWords__BYTE_ARR_CTS (amodeToStix cda2)
-
-       (a1,a2,a3) = toStruct scratch1 (aa1,sa1,da1)
-       (a4,a5,a6) = toStruct scratch2 (aa2,sa2,da2)
-       mpz_cmp = StCall SLIT("__gmpz_cmp") CCallConv IntRep [scratch1, scratch2]
-       r1 = StAssign IntRep result mpz_cmp
-    in
-    returnUs (\xs -> a1 : a2 : a3 : a4 : a5 : a6 : r1 : xs)
-
-
-gmpCompareInt
-    :: CAddrMode           -- result (boolean)
-    -> (CAddrMode,CAddrMode,CAddrMode)
-    -> UniqSM StixTreeList  -- alloc hp + 1 arg (??)
-
-gmpCompareInt res args@(csa1,cda1, cai)
-  = let
-       result   = amodeToStix res
-       sa1      = amodeToStix csa1
-       aa1      = stgArrWords__words (amodeToStix cda1)
-       da1      = stgArrWords__BYTE_ARR_CTS (amodeToStix cda1)
-        ai       = amodeToStix cai
-       (a1,a2,a3) = toStruct scratch1 (aa1,sa1,da1)
-       mpz_cmp_si = StCall SLIT("__gmpz_cmp_si") CCallConv IntRep [scratch1, ai]
-       r1 = StAssign IntRep result mpz_cmp_si
-    in
-    returnUs (\xs -> a1 : a2 : a3 : r1 : xs)
-\end{code}
-
-\begin{code}
-gmpInteger2Int
-    :: CAddrMode           -- result
-    -> (CAddrMode,CAddrMode) -- alloc hp + argument (2 parts)
-    -> UniqSM StixTreeList
-
-gmpInteger2Int res args@(csa,cda)
-  = let
-       result  = amodeToStix res
-       sa      = amodeToStix csa
-       aa      = stgArrWords__words (amodeToStix cda)
-       da      = stgArrWords__BYTE_ARR_CTS (amodeToStix cda)
-
-       (a1,a2,a3) = toStruct scratch1 (aa,sa,da)
-       mpz_get_si = StCall SLIT("__gmpz_get_si") CCallConv IntRep [scratch1]
-       r1 = StAssign IntRep result mpz_get_si
-    in
-    returnUs (\xs -> a1 : a2 : a3 : r1 : xs)
-
-gmpInteger2Word
-    :: CAddrMode           -- result
-    -> (CAddrMode,CAddrMode) -- alloc hp + argument (2 parts)
-    -> UniqSM StixTreeList
-
-gmpInteger2Word res args@(csa,cda)
-  = let
-       result  = amodeToStix res
-       sa      = amodeToStix csa
-       aa      = stgArrWords__words (amodeToStix cda)
-       da      = stgArrWords__BYTE_ARR_CTS (amodeToStix cda)
-
-       (a1,a2,a3) = toStruct scratch1 (aa,sa,da)
-       mpz_get_ui = StCall SLIT("__gmpz_get_ui") CCallConv IntRep [scratch1]
-       r1 = StAssign WordRep result mpz_get_ui
-    in
-    returnUs (\xs -> a1 : a2 : a3 : r1 : xs)
-
-gmpNegate
-    :: (CAddrMode,CAddrMode) -- result
-    -> (CAddrMode,CAddrMode) -- argument (2 parts)
-    -> UniqSM StixTreeList
-
-gmpNegate (rcs, rcd) args@(cs, cd)
-  = let
-       s       = amodeToStix cs
-       a       = stgArrWords__words (amodeToStix cd)
-       d       = stgArrWords__BYTE_ARR_CTS (amodeToStix cd)
-       rs      = amodeToStix rcs
-       ra      = stgArrWords__words (amodeToStix rcd)
-       rd      = stgArrWords__BYTE_ARR_CTS (amodeToStix rcd)
-       a1      = StAssign IntRep ra a
-       a2      = StAssign IntRep rs (StPrim IntNegOp [s])
-       a3      = StAssign PtrRep rd d
-    in
-    returnUs (\xs -> a1 : a2 : a3 : xs)
-\end{code}
-
-Support for the Gnu GMP multi-precision package.
-
-\begin{code}
--- size (in words) of __MP_INT
-mpIntSize = 3 :: Int
-
-mpAlloc, mpSize, mpData :: StixTree -> StixTree
-mpAlloc base = StInd IntRep base
-mpSize base = StInd IntRep (StIndex IntRep base (StInt 1))
-mpData base = StInd PtrRep (StIndex IntRep base (StInt 2))
-\end{code}
-
-\begin{code}
-toStruct
-    :: StixTree
-    -> (StixTree, StixTree, StixTree)
-    -> (StixTree, StixTree, StixTree)
-
-toStruct str (alloc,size,arr)
-  = let
-       f1 = StAssign IntRep (mpAlloc str) alloc
-       f2 = StAssign IntRep (mpSize str) size
-       f3 = StAssign PtrRep (mpData str) arr
-    in
-    (f1, f2, f3)
-
-scratch1 = StScratchWord 0
-scratch2 = StScratchWord mpIntSize
-\end{code}
-
index bcb2ba6..170cc39 100644 (file)
@@ -11,13 +11,13 @@ module StixMacro ( macroCode, checkCode ) where
 import {-# SOURCE #-} StixPrim ( amodeToStix )
 
 import MachRegs
-import AbsCSyn         ( CStmtMacro(..), CAddrMode, tagreg,
-                         CCheckMacro(..) )
+import AbsCSyn         ( CStmtMacro(..), CAddrMode, tagreg, CCheckMacro(..) )
 import Constants       ( uF_RET, uF_SU, uF_UPDATEE, uF_SIZE )
 import ForeignCall     ( CCallConv(..) )
-import PrimOp          ( PrimOp(..) )
+import MachOp          ( MachOp(..) )
 import PrimRep         ( PrimRep(..) )
 import Stix
+import Panic           ( panic )
 import UniqSupply      ( returnUs, thenUs, UniqSM )
 import CLabel          ( mkBlackHoleInfoTableLabel, mkIndStaticInfoLabel,
                          mkIndInfoLabel, mkUpdInfoLabel, mkSeqInfoLabel,
@@ -33,7 +33,7 @@ closure address.
 macroCode
     :: CStmtMacro          -- statement macro
     -> [CAddrMode]         -- args
-    -> UniqSM StixTreeList
+    -> UniqSM StixStmtList
 \end{code}
 
 -----------------------------------------------------------------------------
@@ -44,18 +44,18 @@ macroCode ARGS_CHK_LOAD_NODE args
   = getUniqLabelNCG                                    `thenUs` \ ulbl ->
     let
          [words, lbl] = map amodeToStix args
-         temp = StIndex PtrRep stgSp words
-         test = StPrim AddrGeOp [stgSu, temp]
+         temp = StIndex PtrRep (StReg stgSp) words
+         test = StMachOp MO_NatU_Ge [StReg stgSu, temp]
          cjmp = StCondJump ulbl test
-         assign = StAssign PtrRep stgNode lbl
+         assign = StAssignReg PtrRep stgNode lbl
          join = StLabel ulbl
     in
     returnUs (\xs -> cjmp : assign : updatePAP : join : xs)
 
 macroCode ARGS_CHK [words]
   = getUniqLabelNCG                                    `thenUs` \ ulbl ->
-    let temp = StIndex PtrRep stgSp (amodeToStix words)
-       test = StPrim AddrGeOp [stgSu, temp]
+    let temp = StIndex PtrRep (StReg stgSp) (amodeToStix words)
+       test = StMachOp MO_NatU_Ge [StReg stgSu, temp]
        cjmp = StCondJump ulbl test
        join = StLabel ulbl
     in
@@ -72,11 +72,9 @@ adding an indirection.
 macroCode UPD_CAF args
   = let
        [cafptr,bhptr] = map amodeToStix args
-       new_caf = StCall SLIT("newCAF") CCallConv VoidRep [cafptr]
-       w0 = StInd PtrRep cafptr
-       w1 = StInd PtrRep (StIndex PtrRep cafptr fixedHS)
-       a1 = StAssign PtrRep w1 bhptr
-       a2 = StAssign PtrRep w0 ind_static_info
+       new_caf = StVoidable (StCall SLIT("newCAF") CCallConv VoidRep [cafptr])
+       a1 = StAssignMem PtrRep (StIndex PtrRep cafptr fixedHS) bhptr
+       a2 = StAssignMem PtrRep cafptr ind_static_info
     in
     returnUs (\xs -> new_caf : a1 : a2 : xs)
 \end{code}
@@ -119,37 +117,35 @@ to the current Sp location.
 macroCode PUSH_UPD_FRAME args
   = let
        [bhptr, _{-0-}] = map amodeToStix args
-       frame n = StInd PtrRep
-           (StIndex PtrRep stgSp (StInt (toInteger (n-uF_SIZE))))
+       frame n = StIndex PtrRep (StReg stgSp) (StInt (toInteger (n-uF_SIZE)))
 
         -- HWL: these values are *wrong* in a GranSim setup; ToDo: fix
-       a1 = StAssign PtrRep (frame uF_RET)     upd_frame_info
-       a3 = StAssign PtrRep (frame uF_SU)      stgSu
-       a4 = StAssign PtrRep (frame uF_UPDATEE) bhptr
-
-       updSu = StAssign PtrRep stgSu
-               (StIndex PtrRep stgSp (StInt (toInteger (-uF_SIZE))))
+       a1 = StAssignMem PtrRep (frame uF_RET)     upd_frame_info
+       a3 = StAssignMem PtrRep (frame uF_SU)      (StReg stgSu)
+       a4 = StAssignMem PtrRep (frame uF_UPDATEE) bhptr
+
+       updSu = StAssignReg 
+                   PtrRep 
+                   stgSu
+                  (StIndex PtrRep (StReg stgSp) (StInt (toInteger (-uF_SIZE))))
     in
     returnUs (\xs -> a1 : a3 : a4 : updSu : xs)
 
 
 macroCode PUSH_SEQ_FRAME args
    = let [arg_frame] = map amodeToStix args
-         frame n = StInd PtrRep
-                     (StIndex PtrRep arg_frame (StInt (toInteger n)))
-         a1 = StAssign PtrRep (frame 0) seq_frame_info
-         a2 = StAssign PtrRep (frame 1) stgSu
-         updSu = StAssign PtrRep stgSu arg_frame 
+         frame n = StIndex PtrRep arg_frame (StInt (toInteger n))
+         a1 = StAssignMem PtrRep (frame 0) seq_frame_info
+         a2 = StAssignMem PtrRep (frame 1) (StReg stgSu)
+         updSu = StAssignReg PtrRep stgSu arg_frame 
      in
      returnUs (\xs -> a1 : a2 : updSu : xs)
 
 
 macroCode UPDATE_SU_FROM_UPD_FRAME args
    = let [arg_frame] = map amodeToStix args
-         frame n = StInd PtrRep
-                      (StIndex PtrRep arg_frame (StInt (toInteger n)))
-         updSu
-            = StAssign PtrRep stgSu (frame uF_SU)
+         frame n = StIndex PtrRep arg_frame (StInt (toInteger n))
+         updSu = StAssignReg PtrRep stgSu (StInd PtrRep (frame uF_SU))
      in
      returnUs (\xs -> updSu : xs)
 \end{code}
@@ -161,11 +157,12 @@ This one only applies if we have a machine register devoted to TagReg.
 
 \begin{code}
 macroCode SET_TAG [tag]
-  = let set_tag = StAssign IntRep stgTagReg (amodeToStix tag)
-    in
-    case stgReg tagreg of
-      Always _ -> returnUs id
-      Save   _ -> returnUs (\ xs -> set_tag : xs)
+  = case get_MagicId_reg_or_addr tagreg of
+       Right baseRegAddr 
+          -> returnUs id
+       Left  realreg 
+          -> let a1 = StAssignReg IntRep (StixMagicId tagreg) (amodeToStix tag)
+             in returnUs ( \xs -> a1 : xs )
 \end{code}
 
 -----------------------------------------------------------------------------
@@ -173,24 +170,23 @@ macroCode SET_TAG [tag]
 \begin{code}
 macroCode REGISTER_IMPORT [arg]
    = returnUs (
-       \xs -> StAssign WordRep (StInd WordRep stgSp) (amodeToStix arg)
-            : StAssign PtrRep  stgSp (StPrim IntAddOp [stgSp, StInt 4])
+       \xs -> StAssignMem WordRep (StReg stgSp) (amodeToStix arg)
+            : StAssignReg PtrRep  stgSp (StMachOp MO_Nat_Add [StReg stgSp, StInt 4])
             : xs
      )
 
 macroCode REGISTER_FOREIGN_EXPORT [arg]
    = returnUs (
-       \xs -> StCall SLIT("getStablePtr") CCallConv VoidRep [amodeToStix arg]
+       \xs -> StVoidable (
+                  StCall SLIT("getStablePtr") CCallConv VoidRep [amodeToStix arg]
+               )
             : xs
      )
 
 macroCode other args
-   = case other of
-        SET_TAG -> error "foobarxyzzy8"
-       _       -> error "StixMacro.macroCode: unknown macro/args"
+   = panic "StixMacro.macroCode"
 \end{code}
 
-
 Do the business for a @HEAP_CHK@, having converted the args to Trees
 of StixOp.
 
@@ -200,7 +196,7 @@ Let's make sure that these CAFs are lifted out, shall we?
 \begin{code}
 -- Some common labels
 
-bh_info, ind_static_info, ind_info :: StixTree
+bh_info, ind_static_info, ind_info :: StixExpr
 
 bh_info        = StCLbl mkBlackHoleInfoTableLabel
 ind_static_info        = StCLbl mkIndStaticInfoLabel
@@ -208,37 +204,34 @@ ind_info          = StCLbl mkIndInfoLabel
 upd_frame_info = StCLbl mkUpdInfoLabel
 seq_frame_info = StCLbl mkSeqInfoLabel
 
-stg_update_PAP  = regTableEntry CodePtrRep OFFSET_stgUpdatePAP
-
 -- Some common call trees
 
-updatePAP :: StixTree
-updatePAP = StJump NoDestInfo stg_update_PAP
+updatePAP :: StixStmt
+updatePAP = mkStJump_to_RegTable_offw OFFSET_stgUpdatePAP
+
 \end{code}
 
 -----------------------------------------------------------------------------
 Heap/Stack checks
 
 \begin{code}
-checkCode :: CCheckMacro -> [CAddrMode] -> StixTreeList -> UniqSM StixTreeList
+checkCode :: CCheckMacro -> [CAddrMode] -> StixStmtList -> UniqSM StixStmtList
 checkCode macro args assts
   = getUniqLabelNCG            `thenUs` \ ulbl_fail ->
     getUniqLabelNCG            `thenUs` \ ulbl_pass ->
 
-    let args_stix = map amodeToStix args
-       newHp wds = StIndex PtrRep stgHp wds
-       assign_hp wds = StAssign PtrRep stgHp (newHp wds)
-       hp_alloc wds = StAssign IntRep stgHpAlloc wds
-       test_hp = StPrim AddrLeOp [stgHp, stgHpLim]
-       cjmp_hp = StCondJump ulbl_pass test_hp
-
-       newSp wds = StIndex PtrRep stgSp (StPrim IntNegOp [wds])
-       test_sp_pass wds = StPrim AddrGeOp [newSp wds, stgSpLim]
-       test_sp_fail wds = StPrim AddrLtOp [newSp wds, stgSpLim]
+    let args_stix        = map amodeToStix args
+       newHp wds        = StIndex PtrRep (StReg stgHp) wds
+       assign_hp wds    = StAssignReg PtrRep stgHp (newHp wds)
+       hp_alloc wds     = StAssignReg IntRep stgHpAlloc wds
+       test_hp          = StMachOp MO_NatU_Le [StReg stgHp, StReg stgHpLim]
+       cjmp_hp          = StCondJump ulbl_pass test_hp
+       newSp wds        = StIndex PtrRep (StReg stgSp) (StMachOp MO_NatS_Neg [wds])
+       test_sp_pass wds = StMachOp MO_NatU_Ge [newSp wds, StReg stgSpLim]
+       test_sp_fail wds = StMachOp MO_NatU_Lt [newSp wds, StReg stgSpLim]
        cjmp_sp_pass wds = StCondJump ulbl_pass (test_sp_pass wds)
        cjmp_sp_fail wds = StCondJump ulbl_fail (test_sp_fail wds)
-
-       assign_ret r ret = StAssign CodePtrRep r ret
+       assign_ret r ret = mkStAssign CodePtrRep r ret
 
        fail = StLabel ulbl_fail
        join = StLabel ulbl_pass
@@ -248,10 +241,10 @@ checkCode macro args assts
            = IF_ARCH_alpha(16383,65535)
 
         assign_liveness ptr_regs 
-           = StAssign WordRep stgR9
-                      (StPrim XorOp [StInt aLL_NON_PTRS, ptr_regs])
+           = StAssignReg WordRep stgR9
+                         (StMachOp MO_Nat_Xor [StInt aLL_NON_PTRS, ptr_regs])
         assign_reentry reentry 
-           = StAssign WordRep stgR10 reentry
+           = StAssignReg WordRep stgR10 reentry
     in 
 
     returnUs (
@@ -340,28 +333,34 @@ checkCode macro args assts
 
 -- Various canned heap-check routines
 
-mkStJump_to_GCentry :: String -> StixTree
-mkStJump_to_GCentry gcname
+mkStJump_to_GCentry_name :: String -> StixStmt
+mkStJump_to_GCentry_name gcname
 --   | opt_Static
    = StJump NoDestInfo (StCLbl (mkRtsGCEntryLabel gcname))
 --   | otherwise -- it's in a different DLL
 --   = StJump (StInd PtrRep (StLitLbl True sdoc))
 
-gc_chk (StInt 0)   = StJump NoDestInfo (regTableEntry CodePtrRep OFFSET_stgChk0)
-gc_chk (StInt 1)   = StJump NoDestInfo (regTableEntry CodePtrRep OFFSET_stgChk1)
-gc_chk (StInt n)   = mkStJump_to_GCentry ("stg_chk_" ++ show n)
-
-gc_enter (StInt 1) = StJump NoDestInfo (regTableEntry CodePtrRep OFFSET_stgGCEnter1)
-gc_enter (StInt n) = mkStJump_to_GCentry ("stg_gc_enter_" ++ show n)
-
-gc_seq (StInt n)   = mkStJump_to_GCentry ("stg_gc_seq_" ++ show n)
-gc_noregs          = mkStJump_to_GCentry "stg_gc_noregs"
-gc_unpt_r1         = mkStJump_to_GCentry "stg_gc_unpt_r1"
-gc_unbx_r1         = mkStJump_to_GCentry "stg_gc_unbx_r1"
-gc_f1              = mkStJump_to_GCentry "stg_gc_f1"
-gc_d1              = mkStJump_to_GCentry "stg_gc_d1"
-gc_gen             = mkStJump_to_GCentry "stg_gen_chk"
+mkStJump_to_RegTable_offw :: Int -> StixStmt
+mkStJump_to_RegTable_offw regtable_offw
+--   | opt_Static
+   = StJump NoDestInfo (StInd PtrRep (get_Regtable_addr_from_offset regtable_offw))
+--   | otherwise
+--   do something plausible for cross-DLL jump
+
+gc_chk (StInt 0)   = mkStJump_to_RegTable_offw OFFSET_stgChk0
+gc_chk (StInt 1)   = mkStJump_to_RegTable_offw OFFSET_stgChk1
+gc_chk (StInt n)   = mkStJump_to_GCentry_name ("stg_chk_" ++ show n)
+
+gc_enter (StInt 1) = mkStJump_to_RegTable_offw OFFSET_stgGCEnter1
+gc_enter (StInt n) = mkStJump_to_GCentry_name ("stg_gc_enter_" ++ show n)
+
+gc_seq (StInt n)   = mkStJump_to_GCentry_name ("stg_gc_seq_" ++ show n)
+gc_noregs          = mkStJump_to_GCentry_name "stg_gc_noregs"
+gc_unpt_r1         = mkStJump_to_GCentry_name "stg_gc_unpt_r1"
+gc_unbx_r1         = mkStJump_to_GCentry_name "stg_gc_unbx_r1"
+gc_f1              = mkStJump_to_GCentry_name "stg_gc_f1"
+gc_d1              = mkStJump_to_GCentry_name "stg_gc_d1"
+gc_gen             = mkStJump_to_GCentry_name "stg_gen_chk"
 gc_ut (StInt p) (StInt np)
-                   = mkStJump_to_GCentry ("stg_gc_ut_" ++ show p 
-                                          ++ "_" ++ show np)
+                   = mkStJump_to_GCentry_name ("stg_gc_ut_" ++ show p ++ "_" ++ show np)
 \end{code}
index 1df7a8c..7997542 100644 (file)
@@ -2,4 +2,4 @@ _interface_ StixPrim 1
 _exports_
 StixPrim amodeToStix;
 _declarations_
-1 amodeToStix _:_ AbsCSyn.CAddrMode -> Stix.StixTree ;;
+1 amodeToStix _:_ AbsCSyn.CAddrMode -> Stix.StixExpr ;;
index 6e86b28..f1b3b9e 100644 (file)
@@ -1,3 +1,3 @@
 __interface StixPrim 1 0 where
 __export StixPrim amodeToStix;
-1 amodeToStix :: AbsCSyn.CAddrMode -> Stix.StixTree ;
+1 amodeToStix :: AbsCSyn.CAddrMode -> Stix.StixExpr ;
index a7c04fe..a94209c 100644 (file)
@@ -3,20 +3,20 @@
 %
 
 \begin{code}
-module StixPrim ( primCode, amodeToStix, amodeToStix', foreignCallCode )
-  where
+module StixPrim ( amodeToStix, amodeToStix', foreignCallCode )
+where
 
 #include "HsVersions.h"
 
 import MachMisc
 import Stix
-import StixInteger
 
+import PprAbsC         ( pprAmode )
 import AbsCSyn                 hiding ( spRel )
 import AbsCUtils       ( getAmodeRep, mixedTypeLocn )
 import SMRep           ( fixedHdrSize )
 import Literal         ( Literal(..), word2IntLit )
-import PrimOp          ( PrimOp(..) )
+import MachOp          ( MachOp(..) )
 import PrimRep         ( PrimRep(..), getPrimRepSizeInBytes )
 import UniqSupply      ( returnUs, thenUs, getUniqueUs, UniqSM )
 import Constants       ( mIN_INTLIKE, mIN_CHARLIKE, uF_UPDATEE, bLOCK_SIZE,
@@ -32,20 +32,14 @@ import FastTypes
 #include "NCG.h"
 \end{code}
 
-The main honchos here are primCode anf foreignCallCode, which handle the guts of COpStmts.
+The main honchos here are primCode and foreignCallCode, which handle the guts of COpStmts.
 
 \begin{code}
 foreignCallCode
     :: [CAddrMode]     -- results
     -> ForeignCall     -- op
     -> [CAddrMode]     -- args
-    -> UniqSM StixTreeList
-
-primCode
-    :: [CAddrMode]     -- results
-    -> PrimOp          -- op
-    -> [CAddrMode]     -- args
-    -> UniqSM StixTreeList
+    -> UniqSM StixStmtList
 \end{code}
 
 %************************************************************************
@@ -70,20 +64,23 @@ calling.
 
 \begin{code}
 foreignCallCode lhs (CCall (CCallSpec (StaticTarget fn) cconv safety)) rhs
-  | not (playSafe safety) = returnUs (\xs -> ccall : xs)
+
+  | not (playSafe safety) 
+  = returnUs (\xs -> ccall : xs)
 
   | otherwise
   = save_thread_state  `thenUs` \ save ->
     load_thread_state  `thenUs` \ load -> 
     getUniqueUs                `thenUs` \ uniq -> 
     let
-       id  = StReg (StixTemp uniq IntRep)
+       id  = StixTemp (StixVReg uniq IntRep)
     
-       suspend = StAssign IntRep id 
-               (StCall SLIT("suspendThread") {-no:cconv-} CCallConv
-                            IntRep [stgBaseReg])
-       resume  = StCall SLIT("resumeThread") {-no:cconv-} CCallConv
-                        VoidRep [id]
+       suspend = StAssignReg IntRep id 
+                (StCall SLIT("suspendThread") {-no:cconv-} CCallConv
+                         IntRep [StReg stgBaseReg])
+       resume  = StVoidable 
+                 (StCall SLIT("resumeThread") {-no:cconv-} CCallConv
+                         VoidRep [StReg id])
     in
     returnUs (\xs -> save (suspend : ccall : resume : load xs))
 
@@ -99,8 +96,8 @@ foreignCallCode lhs (CCall (CCallSpec (StaticTarget fn) cconv safety)) rhs
              _ -> base
 
     ccall = case lhs of
-      []    -> StCall fn cconv VoidRep args
-      [lhs] -> StAssign pk lhs' (StCall fn cconv pk args)
+      []    -> StVoidable (StCall fn cconv VoidRep args)
+      [lhs] -> mkStAssign pk lhs' (StCall fn cconv pk args)
            where
               lhs' = amodeToStix lhs
               pk   = case getAmodeRep lhs of
@@ -112,510 +109,24 @@ foreignCallCode lhs call rhs
   = ncgPrimopMoan "Native code generator can't handle foreign call" (ppr call)
 \end{code}
 
-
 %************************************************************************
 %*                                                                     *
-\subsubsection{Code for primops}
+\subsubsection{Code for @CAddrMode@s}
 %*                                                                     *
 %************************************************************************
 
-The (MP) integer operations are a true nightmare.  Since we don't have
-a convenient abstract way of allocating temporary variables on the (C)
-stack, we use the space just below HpLim for the @MP_INT@ structures,
-and modify our heap check accordingly.
-
-\begin{code}
--- NB: ordering of clauses somewhere driven by
--- the desire to getting sane patt-matching behavior
-
-primCode [res] IntegerCmpOp args@[sa1,da1, sa2,da2]
-  = gmpCompare res (sa1,da1, sa2,da2)
-
-primCode [res] IntegerCmpIntOp args@[sa1,da1,ai]
-  = gmpCompareInt res (sa1,da1,ai)
-
-primCode [res] Integer2IntOp arg@[sa,da]
-  = gmpInteger2Int res (sa,da)
-
-primCode [res] Integer2WordOp arg@[sa,da]
-  = gmpInteger2Word res (sa,da)
-
-primCode [res] Int2WordOp [arg]
-  = simpleCoercion IntRep{-WordRep?-} res arg
-
-primCode [res] Word2IntOp [arg]
-  = simpleCoercion IntRep res arg
-
-primCode [res] AddrToHValueOp [arg]
-  = simpleCoercion PtrRep res arg
-
-#if (WORD_SIZE_IN_BITS == 32 || WORD_SIZE_IN_BITS == 64)
-primCode [res] Int2AddrOp [arg]
-  = simpleCoercion AddrRep res arg
-
-primCode [res] Addr2IntOp [arg]
-  = simpleCoercion IntRep res arg
-#endif
-
-primCode [res] Narrow8IntOp [arg]
-  = narrowingCoercion IntRep Int8Rep res arg
-primCode [res] Narrow16IntOp [arg]
-  = narrowingCoercion IntRep Int16Rep res arg
-primCode [res] Narrow32IntOp [arg]
-  = narrowingCoercion IntRep Int32Rep res arg
-
-primCode [res] Narrow8WordOp [arg]
-  = narrowingCoercion WordRep Word8Rep res arg
-primCode [res] Narrow16WordOp [arg]
-  = narrowingCoercion WordRep Word16Rep res arg
-primCode [res] Narrow32WordOp [arg]
-  = narrowingCoercion WordRep Word32Rep res arg
-\end{code}
-
-\begin{code}
-primCode [res] SameMutableArrayOp args
-  = let
-       compare = StPrim AddrEqOp (map amodeToStix args)
-       assign = StAssign IntRep (amodeToStix res) compare
-    in
-    returnUs (\xs -> assign : xs)
-
-primCode res@[_] SameMutableByteArrayOp args
-  = primCode res SameMutableArrayOp args
-
-primCode res@[_] SameMutVarOp args
-  = primCode res SameMutableArrayOp args
-\end{code}
-
-\begin{code}
-primCode res@[_] SameMVarOp args
-  = primCode res SameMutableArrayOp args
-
--- #define isEmptyMVarzh(r,a) \
---     r =(I_)((GET_INFO((StgMVar*)(a))) == &stg_EMPTY_MVAR_info )
-primCode [res] IsEmptyMVarOp [arg] 
-   = let res'     = amodeToStix res
-         arg'     = amodeToStix arg
-         arg_info = StInd PtrRep arg'
-         em_info  = StCLbl mkEMPTY_MVAR_infoLabel
-         same     = StPrim IntEqOp [arg_info, em_info]
-         assign   = StAssign IntRep res' same
-     in
-     returnUs (\xs -> assign : xs)
-
--- #define myThreadIdzh(t) (t = CurrentTSO)
-primCode [res] MyThreadIdOp [] 
-   = let res' = amodeToStix res
-     in  returnUs (\xs -> StAssign ThreadIdRep res' stgCurrentTSO : xs)
-
-\end{code}
-
-Freezing an array of pointers is a double assignment.  We fix the
-header of the ``new'' closure because the lhs is probably a better
-addressing mode for the indirection (most likely, it's a VanillaReg).
-
-\begin{code}
-
-primCode [lhs] UnsafeFreezeArrayOp [rhs]
-  = let
-       lhs' = amodeToStix lhs
-       rhs' = amodeToStix rhs
-       header = StInd PtrRep lhs'
-       assign = StAssign PtrRep lhs' rhs'
-       freeze = StAssign PtrRep header mutArrPtrsFrozen_info
-    in
-    returnUs (\xs -> assign : freeze : xs)
-
-primCode [lhs] UnsafeFreezeByteArrayOp [rhs]
-  = simpleCoercion PtrRep lhs rhs
-\end{code}
-
-Returning the size of (mutable) byte arrays is just
-an indexing operation.
-
-\begin{code}
-primCode [lhs] SizeofByteArrayOp [rhs]
-  = let
-       lhs' = amodeToStix lhs
-       rhs' = amodeToStix rhs
-       sz   = StIndex IntRep rhs' fixedHS
-       assign = StAssign IntRep lhs' (StInd IntRep sz)
-    in
-    returnUs (\xs -> assign : xs)
-
-primCode [lhs] SizeofMutableByteArrayOp [rhs]
-  = let
-       lhs' = amodeToStix lhs
-       rhs' = amodeToStix rhs
-       sz   = StIndex IntRep rhs' fixedHS
-       assign = StAssign IntRep lhs' (StInd IntRep sz)
-    in
-    returnUs (\xs -> assign : xs)
-
-\end{code}
-
-Most other array primitives translate to simple indexing.
-
-\begin{code}
-primCode lhs@[_] IndexArrayOp args
-  = primCode lhs ReadArrayOp args
-
-primCode [lhs] ReadArrayOp [obj, ix]
-  = let
-       lhs' = amodeToStix lhs
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       base = StIndex IntRep obj' arrPtrsHS
-       assign = StAssign PtrRep lhs' (StInd PtrRep (StIndex PtrRep base ix'))
-    in
-    returnUs (\xs -> assign : xs)
-
-primCode [] WriteArrayOp [obj, ix, v]
-  = let
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       v' = amodeToStix v
-       base = StIndex IntRep obj' arrPtrsHS
-       assign = StAssign PtrRep (StInd PtrRep (StIndex PtrRep base ix')) v'
-    in
-    returnUs (\xs -> assign : xs)
-
-primCode [] WriteForeignObjOp [obj, v]
-  = let
-       obj' = amodeToStix obj
-       v' = amodeToStix v
-       obj'' = StIndex AddrRep obj' (StInt 4711) -- fixedHS
-       assign = StAssign AddrRep (StInd AddrRep obj'') v'
-    in
-    returnUs (\xs -> assign : xs)
-
--- NB: indexing in "pk" units, *not* in bytes (WDP 95/09)
-primCode ls IndexByteArrayOp_Char      rs = primCode_ReadByteArrayOp Word8Rep     ls rs
-primCode ls IndexByteArrayOp_WideChar  rs = primCode_ReadByteArrayOp CharRep      ls rs
-primCode ls IndexByteArrayOp_Int       rs = primCode_ReadByteArrayOp IntRep       ls rs
-primCode ls IndexByteArrayOp_Word      rs = primCode_ReadByteArrayOp WordRep      ls rs
-primCode ls IndexByteArrayOp_Addr      rs = primCode_ReadByteArrayOp AddrRep      ls rs
-primCode ls IndexByteArrayOp_Float     rs = primCode_ReadByteArrayOp FloatRep     ls rs
-primCode ls IndexByteArrayOp_Double    rs = primCode_ReadByteArrayOp DoubleRep    ls rs
-primCode ls IndexByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
-primCode ls IndexByteArrayOp_Int8      rs = primCode_ReadByteArrayOp Int8Rep      ls rs
-primCode ls IndexByteArrayOp_Int16     rs = primCode_ReadByteArrayOp Int16Rep     ls rs
-primCode ls IndexByteArrayOp_Int32     rs = primCode_ReadByteArrayOp Int32Rep     ls rs
-primCode ls IndexByteArrayOp_Int64     rs = primCode_ReadByteArrayOp Int64Rep     ls rs
-primCode ls IndexByteArrayOp_Word8     rs = primCode_ReadByteArrayOp Word8Rep     ls rs
-primCode ls IndexByteArrayOp_Word16    rs = primCode_ReadByteArrayOp Word16Rep    ls rs
-primCode ls IndexByteArrayOp_Word32    rs = primCode_ReadByteArrayOp Word32Rep    ls rs
-primCode ls IndexByteArrayOp_Word64    rs = primCode_ReadByteArrayOp Word64Rep    ls rs
-
-primCode ls ReadByteArrayOp_Char      rs = primCode_ReadByteArrayOp Word8Rep     ls rs
-primCode ls ReadByteArrayOp_WideChar  rs = primCode_ReadByteArrayOp CharRep      ls rs
-primCode ls ReadByteArrayOp_Int       rs = primCode_ReadByteArrayOp IntRep       ls rs
-primCode ls ReadByteArrayOp_Word      rs = primCode_ReadByteArrayOp WordRep      ls rs
-primCode ls ReadByteArrayOp_Addr      rs = primCode_ReadByteArrayOp AddrRep      ls rs
-primCode ls ReadByteArrayOp_Float     rs = primCode_ReadByteArrayOp FloatRep     ls rs
-primCode ls ReadByteArrayOp_Double    rs = primCode_ReadByteArrayOp DoubleRep    ls rs
-primCode ls ReadByteArrayOp_StablePtr rs = primCode_ReadByteArrayOp StablePtrRep ls rs
-primCode ls ReadByteArrayOp_Int8      rs = primCode_ReadByteArrayOp Int8Rep      ls rs
-primCode ls ReadByteArrayOp_Int16     rs = primCode_ReadByteArrayOp Int16Rep     ls rs
-primCode ls ReadByteArrayOp_Int32     rs = primCode_ReadByteArrayOp Int32Rep     ls rs
-primCode ls ReadByteArrayOp_Int64     rs = primCode_ReadByteArrayOp Int64Rep     ls rs
-primCode ls ReadByteArrayOp_Word8     rs = primCode_ReadByteArrayOp Word8Rep     ls rs
-primCode ls ReadByteArrayOp_Word16    rs = primCode_ReadByteArrayOp Word16Rep    ls rs
-primCode ls ReadByteArrayOp_Word32    rs = primCode_ReadByteArrayOp Word32Rep    ls rs
-primCode ls ReadByteArrayOp_Word64    rs = primCode_ReadByteArrayOp Word64Rep    ls rs
-
-primCode ls WriteByteArrayOp_Char      rs = primCode_WriteByteArrayOp Word8Rep     ls rs
-primCode ls WriteByteArrayOp_WideChar  rs = primCode_WriteByteArrayOp CharRep      ls rs
-primCode ls WriteByteArrayOp_Int       rs = primCode_WriteByteArrayOp IntRep       ls rs
-primCode ls WriteByteArrayOp_Word      rs = primCode_WriteByteArrayOp WordRep      ls rs
-primCode ls WriteByteArrayOp_Addr      rs = primCode_WriteByteArrayOp AddrRep      ls rs
-primCode ls WriteByteArrayOp_Float     rs = primCode_WriteByteArrayOp FloatRep     ls rs
-primCode ls WriteByteArrayOp_Double    rs = primCode_WriteByteArrayOp DoubleRep    ls rs
-primCode ls WriteByteArrayOp_StablePtr rs = primCode_WriteByteArrayOp StablePtrRep ls rs
-primCode ls WriteByteArrayOp_Int8      rs = primCode_WriteByteArrayOp Int8Rep      ls rs
-primCode ls WriteByteArrayOp_Int16     rs = primCode_WriteByteArrayOp Int16Rep     ls rs
-primCode ls WriteByteArrayOp_Int32     rs = primCode_WriteByteArrayOp Int32Rep     ls rs
-primCode ls WriteByteArrayOp_Int64     rs = primCode_WriteByteArrayOp Int64Rep     ls rs
-primCode ls WriteByteArrayOp_Word8     rs = primCode_WriteByteArrayOp Word8Rep     ls rs
-primCode ls WriteByteArrayOp_Word16    rs = primCode_WriteByteArrayOp Word16Rep    ls rs
-primCode ls WriteByteArrayOp_Word32    rs = primCode_WriteByteArrayOp Word32Rep    ls rs
-primCode ls WriteByteArrayOp_Word64    rs = primCode_WriteByteArrayOp Word64Rep    ls rs
-
-primCode ls IndexOffAddrOp_Char      rs = primCode_IndexOffAddrOp Word8Rep     ls rs
-primCode ls IndexOffAddrOp_WideChar  rs = primCode_IndexOffAddrOp CharRep      ls rs
-primCode ls IndexOffAddrOp_Int       rs = primCode_IndexOffAddrOp IntRep       ls rs
-primCode ls IndexOffAddrOp_Word      rs = primCode_IndexOffAddrOp WordRep      ls rs
-primCode ls IndexOffAddrOp_Addr      rs = primCode_IndexOffAddrOp AddrRep      ls rs
-primCode ls IndexOffAddrOp_Float     rs = primCode_IndexOffAddrOp FloatRep     ls rs
-primCode ls IndexOffAddrOp_Double    rs = primCode_IndexOffAddrOp DoubleRep    ls rs
-primCode ls IndexOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
-primCode ls IndexOffAddrOp_Int8      rs = primCode_IndexOffAddrOp Int8Rep      ls rs
-primCode ls IndexOffAddrOp_Int16     rs = primCode_IndexOffAddrOp Int16Rep     ls rs
-primCode ls IndexOffAddrOp_Int32     rs = primCode_IndexOffAddrOp Int32Rep     ls rs
-primCode ls IndexOffAddrOp_Int64     rs = primCode_IndexOffAddrOp Int64Rep     ls rs
-primCode ls IndexOffAddrOp_Word8     rs = primCode_IndexOffAddrOp Word8Rep     ls rs
-primCode ls IndexOffAddrOp_Word16    rs = primCode_IndexOffAddrOp Word16Rep    ls rs
-primCode ls IndexOffAddrOp_Word32    rs = primCode_IndexOffAddrOp Word32Rep    ls rs
-primCode ls IndexOffAddrOp_Word64    rs = primCode_IndexOffAddrOp Word64Rep    ls rs
-
-primCode ls IndexOffForeignObjOp_Char      rs = primCode_IndexOffForeignObjOp Word8Rep     ls rs
-primCode ls IndexOffForeignObjOp_WideChar  rs = primCode_IndexOffForeignObjOp CharRep      ls rs
-primCode ls IndexOffForeignObjOp_Int       rs = primCode_IndexOffForeignObjOp IntRep       ls rs
-primCode ls IndexOffForeignObjOp_Word      rs = primCode_IndexOffForeignObjOp WordRep      ls rs
-primCode ls IndexOffForeignObjOp_Addr      rs = primCode_IndexOffForeignObjOp AddrRep      ls rs
-primCode ls IndexOffForeignObjOp_Float     rs = primCode_IndexOffForeignObjOp FloatRep     ls rs
-primCode ls IndexOffForeignObjOp_Double    rs = primCode_IndexOffForeignObjOp DoubleRep    ls rs
-primCode ls IndexOffForeignObjOp_StablePtr rs = primCode_IndexOffForeignObjOp StablePtrRep ls rs
-primCode ls IndexOffForeignObjOp_Int8      rs = primCode_IndexOffForeignObjOp Int8Rep      ls rs
-primCode ls IndexOffForeignObjOp_Int16     rs = primCode_IndexOffForeignObjOp Int16Rep     ls rs
-primCode ls IndexOffForeignObjOp_Int32     rs = primCode_IndexOffForeignObjOp Int32Rep     ls rs
-primCode ls IndexOffForeignObjOp_Int64     rs = primCode_IndexOffForeignObjOp Int64Rep     ls rs
-primCode ls IndexOffForeignObjOp_Word8     rs = primCode_IndexOffForeignObjOp Word8Rep     ls rs
-primCode ls IndexOffForeignObjOp_Word16    rs = primCode_IndexOffForeignObjOp Word16Rep    ls rs
-primCode ls IndexOffForeignObjOp_Word32    rs = primCode_IndexOffForeignObjOp Word32Rep    ls rs
-primCode ls IndexOffForeignObjOp_Word64    rs = primCode_IndexOffForeignObjOp Word64Rep    ls rs
-
-primCode ls ReadOffAddrOp_Char      rs = primCode_IndexOffAddrOp Word8Rep     ls rs
-primCode ls ReadOffAddrOp_WideChar  rs = primCode_IndexOffAddrOp CharRep      ls rs
-primCode ls ReadOffAddrOp_Int       rs = primCode_IndexOffAddrOp IntRep       ls rs
-primCode ls ReadOffAddrOp_Word      rs = primCode_IndexOffAddrOp WordRep      ls rs
-primCode ls ReadOffAddrOp_Addr      rs = primCode_IndexOffAddrOp AddrRep      ls rs
-primCode ls ReadOffAddrOp_Float     rs = primCode_IndexOffAddrOp FloatRep     ls rs
-primCode ls ReadOffAddrOp_Double    rs = primCode_IndexOffAddrOp DoubleRep    ls rs
-primCode ls ReadOffAddrOp_StablePtr rs = primCode_IndexOffAddrOp StablePtrRep ls rs
-primCode ls ReadOffAddrOp_Int8      rs = primCode_IndexOffAddrOp Int8Rep      ls rs
-primCode ls ReadOffAddrOp_Int16     rs = primCode_IndexOffAddrOp Int16Rep     ls rs
-primCode ls ReadOffAddrOp_Int32     rs = primCode_IndexOffAddrOp Int32Rep     ls rs
-primCode ls ReadOffAddrOp_Int64     rs = primCode_IndexOffAddrOp Int64Rep     ls rs
-primCode ls ReadOffAddrOp_Word8     rs = primCode_IndexOffAddrOp Word8Rep     ls rs
-primCode ls ReadOffAddrOp_Word16    rs = primCode_IndexOffAddrOp Word16Rep    ls rs
-primCode ls ReadOffAddrOp_Word32    rs = primCode_IndexOffAddrOp Word32Rep    ls rs
-primCode ls ReadOffAddrOp_Word64    rs = primCode_IndexOffAddrOp Word64Rep    ls rs
-
-primCode ls WriteOffAddrOp_Char      rs = primCode_WriteOffAddrOp Word8Rep     ls rs
-primCode ls WriteOffAddrOp_WideChar  rs = primCode_WriteOffAddrOp CharRep      ls rs
-primCode ls WriteOffAddrOp_Int       rs = primCode_WriteOffAddrOp IntRep       ls rs
-primCode ls WriteOffAddrOp_Word      rs = primCode_WriteOffAddrOp WordRep      ls rs
-primCode ls WriteOffAddrOp_Addr      rs = primCode_WriteOffAddrOp AddrRep      ls rs
-primCode ls WriteOffAddrOp_Float     rs = primCode_WriteOffAddrOp FloatRep     ls rs
-primCode ls WriteOffAddrOp_Double    rs = primCode_WriteOffAddrOp DoubleRep    ls rs
-primCode ls WriteOffAddrOp_StablePtr rs = primCode_WriteOffAddrOp StablePtrRep ls rs
-primCode ls WriteOffAddrOp_Int8      rs = primCode_WriteOffAddrOp Int8Rep      ls rs
-primCode ls WriteOffAddrOp_Int16     rs = primCode_WriteOffAddrOp Int16Rep     ls rs
-primCode ls WriteOffAddrOp_Int32     rs = primCode_WriteOffAddrOp Int32Rep     ls rs
-primCode ls WriteOffAddrOp_Int64     rs = primCode_WriteOffAddrOp Int64Rep     ls rs
-primCode ls WriteOffAddrOp_Word8     rs = primCode_WriteOffAddrOp Word8Rep     ls rs
-primCode ls WriteOffAddrOp_Word16    rs = primCode_WriteOffAddrOp Word16Rep    ls rs
-primCode ls WriteOffAddrOp_Word32    rs = primCode_WriteOffAddrOp Word32Rep    ls rs
-primCode ls WriteOffAddrOp_Word64    rs = primCode_WriteOffAddrOp Word64Rep    ls rs
-
-\end{code}
-
-
-DataToTagOp won't work for 64-bit archs, as it is.
-
-\begin{code}
-primCode [lhs] DataToTagOp [arg]
-  = let lhs'        = amodeToStix lhs
-        arg'        = amodeToStix arg
-        infoptr     = StInd PtrRep arg'
-        word_32     = StInd WordRep (StIndex PtrRep infoptr (StInt (-1)))
-        masked_le32 = StPrim SrlOp [word_32, StInt 16]
-        masked_be32 = StPrim AndOp [word_32, StInt 65535]
-#ifdef WORDS_BIGENDIAN
-        masked      = masked_be32
-#else
-        masked      = masked_le32
-#endif
-        assign      = StAssign IntRep lhs' masked
-    in
-    returnUs (\xs -> assign : xs)
-\end{code}
-
-MutVars are pretty simple.
-#define writeMutVarzh(a,v)       (P_)(((StgMutVar *)(a))->var)=(v)
-
-\begin{code}
-primCode [] WriteMutVarOp [aa,vv]
-   = let aa_s      = amodeToStix aa
-         vv_s      = amodeToStix vv
-         var_field = StIndex PtrRep aa_s fixedHS
-         assign    = StAssign PtrRep (StInd PtrRep var_field) vv_s
-     in
-     returnUs (\xs -> assign : xs)
-
-primCode [rr] ReadMutVarOp [aa]
-   = let aa_s      = amodeToStix aa
-         rr_s      = amodeToStix rr
-         var_field = StIndex PtrRep aa_s fixedHS
-         assign    = StAssign PtrRep rr_s (StInd PtrRep var_field)
-     in
-     returnUs (\xs -> assign : xs)
-\end{code}
-
-ForeignObj# primops.
-
-\begin{code}
-primCode [rr] ForeignObjToAddrOp [fo]
-  = let code =  StAssign AddrRep (amodeToStix rr)
-                  (StInd AddrRep 
-                       (StIndex PtrRep (amodeToStix fo) fixedHS))
-    in
-    returnUs (\xs -> code : xs)
-
-primCode [] TouchOp [_] = returnUs id
-\end{code}
-
-Now the more mundane operations.
-
-\begin{code}
-primCode lhs op rhs
-  = let
-       lhs' = map amodeToStix  lhs
-       rhs' = map amodeToStix' rhs
-       pk   = getAmodeRep (head lhs)
-    in
-    returnUs (\ xs -> simplePrim pk lhs' op rhs' : xs)
-\end{code}
-
-Helper fns for some array ops.
-
-\begin{code}
-primCode_ReadByteArrayOp pk [lhs] [obj, ix]
-  = let
-       lhs' = amodeToStix lhs
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       base = StIndex IntRep obj' arrWordsHS
-       assign = StAssign pk lhs' (StInd pk (StIndex pk base ix'))
-    in
-    returnUs (\xs -> assign : xs)
-
-
-primCode_IndexOffAddrOp pk [lhs] [obj, ix]
-  = let
-       lhs' = amodeToStix lhs
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       assign = StAssign pk lhs' (StInd pk (StIndex pk obj' ix'))
-    in
-    returnUs (\xs -> assign : xs)
-
-
-primCode_IndexOffForeignObjOp pk [lhs] [obj, ix]
-  = let
-       lhs' = amodeToStix lhs
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       obj'' = StIndex AddrRep obj' fixedHS
-       assign = StAssign pk lhs' (StInd pk (StIndex pk obj'' ix'))
-    in
-    returnUs (\xs -> assign : xs)
-
-
-primCode_WriteOffAddrOp pk [] [obj, ix, v]
-  = let
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       v' = amodeToStix v
-       assign = StAssign pk (StInd pk (StIndex pk obj' ix')) v'
-    in
-    returnUs (\xs -> assign : xs)
-
-
-primCode_WriteByteArrayOp pk [] [obj, ix, v]
-  = let
-       obj' = amodeToStix obj
-       ix' = amodeToStix ix
-       v' = amodeToStix v
-       base = StIndex IntRep obj' arrWordsHS
-       assign = StAssign pk (StInd pk (StIndex pk base ix')) v'
-    in
-    returnUs (\xs -> assign : xs)
-
-\end{code}
-
-\begin{code}
-simpleCoercion
-      :: PrimRep
-      -> CAddrMode
-      -> CAddrMode
-      -> UniqSM StixTreeList
-
-simpleCoercion pk lhs rhs
-  = returnUs (\xs -> StAssign pk (amodeToStix lhs) (amodeToStix rhs) : xs)
-
-
--- Rewrite a narrowing coercion into a pair of shifts.
-narrowingCoercion
-      :: PrimRep   -> PrimRep
-      -> CAddrMode -> CAddrMode
-      -> UniqSM StixTreeList
-
-narrowingCoercion pks pkd dst src
-  | szd > szs 
-  = panic "StixPrim.narrowingCoercion"
-  | szd == szs
-  = returnUs (\xs -> StAssign pkd dst' src' : xs)
-  | otherwise
-  = returnUs (\xs -> assign : xs)
-    where 
-          szs       = getPrimRepSizeInBytes pks
-          szd       = getPrimRepSizeInBytes pkd
-          src'      = amodeToStix src
-          dst'      = amodeToStix dst
-          shift_amt = fromIntegral (8 * (szs - szd))
-
-          assign
-             = StAssign pkd dst'
-                  (StPrim (if signed then ISraOp else SrlOp) 
-                     [StPrim SllOp [src', StInt shift_amt],
-                      StInt shift_amt])
-          signed 
-             = case pkd of 
-                  Int8Rep -> True; Int16Rep -> True
-                  Int32Rep -> True; Int64Rep -> True; IntRep -> True
-                  Word8Rep -> False; Word16Rep -> False
-                  Word32Rep -> False; Word64Rep -> False; WordRep -> False
-                  other -> pprPanic "StixPrim.narrowingCoercion" (ppr pkd)
-\end{code}
-
-Here we try to rewrite primitives into a form the code generator can
-understand.  Any primitives not handled here must be handled at the
-level of the specific code generator.
-
-\begin{code}
-simplePrim
-    :: PrimRep         -- Rep of first destination
-    -> [StixTree]      -- Destinations
-    -> PrimOp
-    -> [StixTree]
-    -> StixTree
-\end{code}
-
-Now look for something more conventional.
-
-\begin{code}
-simplePrim pk [lhs] op rest  = StAssign pk lhs (StPrim op rest)
-simplePrim pk as    op bs    = ncgPrimopMoan "simplPrim(all targets)" (ppr op)
-\end{code}
-
-%---------------------------------------------------------------------
-
-Here we generate the Stix code for CAddrModes.
-
 When a character is fetched from a mixed type location, we have to do
 an extra cast.  This is reflected in amodeCode', which is for rhs
 amodes that might possibly need the extra cast.
 
 \begin{code}
-amodeToStix, amodeToStix' :: CAddrMode -> StixTree
+amodeToStix, amodeToStix' :: CAddrMode -> StixExpr
 
 amodeToStix'{-'-} am@(CVal rr CharRep)
-    | mixedTypeLocn am = StPrim ChrOp [amodeToStix am]
-    | otherwise = amodeToStix am
-
-amodeToStix' am = amodeToStix am
+  | mixedTypeLocn am = StMachOp MO_NatS_to_32U [amodeToStix am]
+  | otherwise        = amodeToStix am
+amodeToStix' am 
+  = amodeToStix am
 
 -----------
 amodeToStix am@(CVal rr CharRep)
@@ -624,20 +135,22 @@ amodeToStix am@(CVal rr CharRep)
 
 amodeToStix (CVal rr pk) = StInd pk (amodeToStix (CAddr rr))
 
+amodeToStix (CMem pk addr) = StInd pk (amodeToStix addr)
+
 amodeToStix (CAddr (SpRel off))
-  = StIndex PtrRep stgSp (StInt (toInteger (iBox off)))
+  = StIndex PtrRep (StReg stgSp) (StInt (toInteger (iBox off)))
 
 amodeToStix (CAddr (HpRel off))
-  = StIndex IntRep stgHp (StInt (toInteger (- (iBox off))))
+  = StIndex IntRep (StReg stgHp) (StInt (toInteger (- (iBox off))))
 
 amodeToStix (CAddr (NodeRel off))
-  = StIndex IntRep stgNode (StInt (toInteger (iBox off)))
+  = StIndex IntRep (StReg stgNode) (StInt (toInteger (iBox off)))
 
 amodeToStix (CAddr (CIndex base off pk))
   = StIndex pk (amodeToStix base) (amodeToStix off)
 
 amodeToStix (CReg magic)    = StReg (StixMagicId magic)
-amodeToStix (CTemp uniq pk) = StReg (StixTemp uniq pk)
+amodeToStix (CTemp uniq pk) = StReg (StixTemp (StixVReg uniq pk))
 
 amodeToStix (CLbl      lbl _) = StCLbl lbl
 
@@ -649,7 +162,7 @@ amodeToStix (CCharLike (CLit (MachChar c)))
     off = charLikeSize * (c - mIN_CHARLIKE)
 
 amodeToStix (CCharLike x)
-  = panic "CCharLike"
+  = panic "amodeToStix.CCharLike"
 
 amodeToStix (CIntLike (CLit (MachInt i)))
   = StIndex Word8Rep iNTLIKE_closure (StInt (toInteger off))
@@ -657,7 +170,7 @@ amodeToStix (CIntLike (CLit (MachInt i)))
     off = intLikeSize * (fromInteger (i - mIN_INTLIKE))
 
 amodeToStix (CIntLike x)
-  = panic "CIntLike"
+  = panic "amodeToStix.CIntLike"
 
 amodeToStix (CLit core)
   = case core of
@@ -678,12 +191,12 @@ amodeToStix (CMacroExpr _ macro [arg])
       ARG_TAG    -> amodeToStix arg -- just an integer no. of words
       GET_TAG    -> 
 #ifdef WORDS_BIGENDIAN
-                    StPrim AndOp 
+                    StMachOp MO_Nat_And
                        [StInd WordRep (StIndex PtrRep (amodeToStix arg)
                                                 (StInt (toInteger (-1)))),
                         StInt 65535]
 #else
-                    StPrim SrlOp 
+                    StMachOp MO_Nat_Shr
                        [StInd WordRep (StIndex PtrRep (amodeToStix arg)
                                                 (StInt (toInteger (-1)))),
                         StInt 16]
@@ -692,8 +205,11 @@ amodeToStix (CMacroExpr _ macro [arg])
          -> StInd PtrRep (StIndex PtrRep (amodeToStix arg) 
                                          (StInt (toInteger uF_UPDATEE)))
 
-litLitErr = 
-  panic "native code generator can't compile lit-lits, use -fvia-C"
+amodeToStix other
+   = pprPanic "StixPrim.amodeToStix" (pprAmode other)
+
+litLitErr 
+   = ncgPrimopMoan "native code generator can't handle lit-lits" empty
 \end{code}
 
 Sizes of the CharLike and IntLike closures that are arranged as arrays
@@ -702,12 +218,12 @@ in the data segment.  (These are in bytes.)
 \begin{code}
 -- The INTLIKE base pointer
 
-iNTLIKE_closure :: StixTree
+iNTLIKE_closure :: StixExpr
 iNTLIKE_closure = StCLbl mkIntlikeClosureLabel
 
 -- The CHARLIKE base
 
-cHARLIKE_closure :: StixTree
+cHARLIKE_closure :: StixExpr
 cHARLIKE_closure = StCLbl mkCharlikeClosureLabel
 
 mutArrPtrsFrozen_info = StCLbl mkMAP_FROZEN_infoLabel
@@ -720,55 +236,66 @@ intLikeSize  = (fixedHdrSize + 1) * (sizeOf PtrRep)
 
 \begin{code}
 save_thread_state 
-   = getUniqueUs   `thenUs` \tso_uq -> 
-     let tso = StReg (StixTemp tso_uq ThreadIdRep) in
+   = getUniqueUs   `thenUs` \ tso_uq -> 
+     let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
      returnUs (\xs ->
-       StAssign ThreadIdRep tso stgCurrentTSO :
-       StAssign PtrRep
-          (StInd PtrRep (StPrim IntAddOp 
-               [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
-          stgSp :
-       StAssign PtrRep 
-          (StInd PtrRep (StPrim IntAddOp 
-               [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
-          stgSu :
-       StAssign PtrRep
-          (StInd PtrRep (StPrim IntAddOp
-               [stgCurrentNursery, 
-                StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]))
-          (StPrim IntAddOp [stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) :
-       xs
+       StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
+       : StAssignMem PtrRep
+             (StMachOp MO_Nat_Add
+                      [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])
+            (StReg stgSp)
+        : StAssignMem PtrRep 
+            (StMachOp MO_Nat_Add
+                      [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])
+            (StReg stgSu)
+        : StAssignMem PtrRep
+            (StMachOp MO_Nat_Add
+                      [StReg stgCurrentNursery, 
+                       StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))])
+             (StMachOp MO_Nat_Add 
+                       [StReg stgHp, StInt (toInteger (1 * BYTES_PER_WORD))]) 
+        : xs
      )
 
 load_thread_state 
-   = getUniqueUs   `thenUs` \tso_uq -> 
-     let tso = StReg (StixTemp tso_uq ThreadIdRep) in
+   = getUniqueUs   `thenUs` \ tso_uq -> 
+     let tso = StixTemp (StixVReg tso_uq ThreadIdRep) in
      returnUs (\xs ->
-       StAssign ThreadIdRep tso stgCurrentTSO :
-       StAssign PtrRep stgSp
-          (StInd PtrRep (StPrim IntAddOp 
-               [tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))])) :
-       StAssign PtrRep stgSu
-          (StInd PtrRep (StPrim IntAddOp 
-               [tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))])) :
-       StAssign PtrRep stgSpLim
-          (StPrim IntAddOp [tso, 
-                            StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
-                                              *BYTES_PER_WORD))]) :
-       StAssign PtrRep stgHp
-          (StPrim IntSubOp [
-             StInd PtrRep (StPrim IntAddOp
-               [stgCurrentNursery, 
-                StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
-             StInt (toInteger (1 * BYTES_PER_WORD))
-           ]) :
-       StAssign PtrRep stgHpLim
-          (StPrim IntAddOp [
-             StInd PtrRep (StPrim IntAddOp
-               [stgCurrentNursery, 
-                StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
-             StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))
-           ]) :
-       xs
+       StAssignReg ThreadIdRep tso (StReg stgCurrentTSO)
+       : StAssignReg PtrRep 
+             stgSp
+            (StInd PtrRep 
+                  (StMachOp MO_Nat_Add
+                            [StReg tso, StInt (toInteger (TSO_SP*BYTES_PER_WORD))]))
+       : StAssignReg PtrRep 
+             stgSu
+            (StInd PtrRep 
+                  (StMachOp MO_Nat_Add
+                           [StReg tso, StInt (toInteger (TSO_SU*BYTES_PER_WORD))]))
+       : StAssignReg PtrRep 
+             stgSpLim
+            (StMachOp MO_Nat_Add 
+                       [StReg tso, 
+                       StInt (toInteger ((TSO_STACK + rESERVED_STACK_WORDS)
+                                         *BYTES_PER_WORD))])
+       : StAssignReg PtrRep 
+             stgHp
+            (StMachOp MO_Nat_Sub 
+                       [StInd PtrRep 
+                              (StMachOp MO_Nat_Add
+                                       [StReg stgCurrentNursery, 
+                                        StInt (toInteger (BDESCR_FREE * BYTES_PER_WORD))]),
+                       StInt (toInteger (1 * BYTES_PER_WORD))
+                      ]) 
+        : StAssignReg PtrRep 
+             stgHpLim
+            (StMachOp MO_Nat_Add 
+                       [StInd PtrRep 
+                              (StMachOp MO_Nat_Add
+                                       [StReg stgCurrentNursery, 
+                                        StInt (toInteger (BDESCR_START * BYTES_PER_WORD))]),
+                       StInt (toInteger (bLOCK_SIZE - (1 * BYTES_PER_WORD)))
+                      ]) 
+        : xs
      )
 \end{code}
index 6b7c199..628e28a 100644 (file)
@@ -263,40 +263,6 @@ Invariants:
            stable name.
 
 
-[Alastair Reid is to blame for this!]
-
-These days, (Glasgow) Haskell seems to have a bit of everything from
-other languages: strict operations, mutable variables, sequencing,
-pointers, etc.  About the only thing left is LISP's ability to test
-for pointer equality.  So, let's add it in!
-
-\begin{verbatim}
-reallyUnsafePtrEquality :: a -> a -> Int#
-\end{verbatim}
-
-which tests any two closures (of the same type) to see if they're the
-same.  (Returns $0$ for @False@, $\neq 0$ for @True@ - to avoid
-difficulties of trying to box up the result.)
-
-NB This is {\em really unsafe\/} because even something as trivial as
-a garbage collection might change the answer by removing indirections.
-Still, no-one's forcing you to use it.  If you're worried about little
-things like loss of referential transparency, you might like to wrap
-it all up in a monad-like thing as John O'Donnell and John Hughes did
-for non-determinism (1989 (Fraserburgh) Glasgow FP Workshop
-Proceedings?)
-
-I'm thinking of using it to speed up a critical equality test in some
-graphics stuff in a context where the possibility of saying that
-denotationally equal things aren't isn't a problem (as long as it
-doesn't happen too often.)  ADR
-
-To Will: Jim said this was already in, but I can't see it so I'm
-adding it.  Up to you whether you add it.  (Note that this could have
-been readily implemented using a @veryDangerousCCall@ before they were
-removed...)
-
-
 -- HWL: The first 4 Int# in all par... annotations denote:
 --   name, granularity info, size of result, degree of parallelism
 --      Same  structure as _seq_ i.e. returns Int#
index 96a093c..8054366 100644 (file)
@@ -17,6 +17,7 @@ module PrimRep
       , is64BitRep
       , getPrimRepSize
       , getPrimRepSizeInBytes
+      , getPrimRepArrayElemSize
       , retPrimRepSize
       ) where
 
@@ -193,7 +194,32 @@ getPrimRepSizeInBytes StablePtrRep  = wORD_SIZE
 getPrimRepSizeInBytes StableNameRep = wORD_SIZE
 getPrimRepSizeInBytes ArrayRep      = wORD_SIZE
 getPrimRepSizeInBytes ByteArrayRep  = wORD_SIZE
-getPrimRepSizeInBytes _             = panic "getPrimRepSize: ouch - this wasn't supposed to happen!"
+getPrimRepSizeInBytes other         = pprPanic "getPrimRepSizeInBytes" (ppr other)
+
+
+-- Sizes in bytes of things when they are array elements,
+-- so that we can generate the correct indexing code
+-- inside the compiler.  This is not the same as the above
+-- getPrimRepSizeInBytes, the rationale behind which is
+-- unclear to me.
+getPrimRepArrayElemSize :: PrimRep -> Int
+getPrimRepArrayElemSize PtrRep        = wORD_SIZE
+getPrimRepArrayElemSize IntRep        = wORD_SIZE
+getPrimRepArrayElemSize WordRep       = wORD_SIZE
+getPrimRepArrayElemSize AddrRep       = wORD_SIZE
+getPrimRepArrayElemSize StablePtrRep  = wORD_SIZE
+getPrimRepArrayElemSize ForeignObjRep = wORD_SIZE
+getPrimRepArrayElemSize Word8Rep      = 1
+getPrimRepArrayElemSize Word16Rep     = 2
+getPrimRepArrayElemSize Word32Rep     = 4
+getPrimRepArrayElemSize Word64Rep     = 8
+getPrimRepArrayElemSize Int8Rep       = 1
+getPrimRepArrayElemSize Int16Rep      = 2
+getPrimRepArrayElemSize Int32Rep      = 4
+getPrimRepArrayElemSize Int64Rep      = 8
+getPrimRepArrayElemSize FloatRep      = 4
+getPrimRepArrayElemSize DoubleRep     = 8
+getPrimRepArrayElemSize other         = pprPanic "getPrimRepSizeArrayElemSize" (ppr other)
 
 \end{code}
 
index ee64b05..a8a80db 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------
--- $Id: primops.txt.pp,v 1.9 2001/10/31 17:03:12 rrt Exp $
+-- $Id: primops.txt.pp,v 1.10 2001/12/05 17:35:14 sewardj Exp $
 --
 -- Primitive Operations
 --
@@ -193,6 +193,8 @@ primop   IntRemOp    "remInt#"    Dyadic
    with can_fail = True
 
 primop   IntGcdOp    "gcdInt#"    Dyadic   Int# -> Int# -> Int#
+   with out_of_line = True
+
 primop   IntNegOp    "negateInt#"    Monadic   Int# -> Int#
 primop   IntAddCOp   "addIntC#"    GenPrimOp   Int# -> Int# -> (# Int#, Int# #)
         {Add with carry.  First member of result is (wrapped) sum; second member is 0 iff no overflow occured.}
@@ -383,7 +385,7 @@ primop   IntegerGcdOp   "gcdInteger#" GenPrimOp
 primop   IntegerIntGcdOp   "gcdIntegerInt#" GenPrimOp
    Int# -> ByteArr# -> Int# -> Int#
    {Greatest common divisor, where second argument is an ordinary Int\#.}
-   -- with commutable = True  (surely not? APT 8/01)
+   with out_of_line = True
 
 primop   IntegerDivExactOp   "divExactInteger#" GenPrimOp
    Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #)
@@ -404,12 +406,14 @@ primop   IntegerCmpOp   "cmpInteger#"   GenPrimOp
    Int# -> ByteArr# -> Int# -> ByteArr# -> Int#
    {Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument.}
    with needs_wrapper = True
+        out_of_line = True
 
 primop   IntegerCmpIntOp   "cmpIntegerInt#" GenPrimOp
    Int# -> ByteArr# -> Int# -> Int#
    {Returns -1,0,1 according as first argument is less than, equal to, or greater than second argument, which
    is an ordinary Int\#.}
    with needs_wrapper = True
+        out_of_line = True
 
 primop   IntegerQuotRemOp   "quotRemInteger#" GenPrimOp
    Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr#, Int#, ByteArr# #)
@@ -427,10 +431,12 @@ primop   IntegerDivModOp    "divModInteger#"  GenPrimOp
 primop   Integer2IntOp   "integer2Int#"    GenPrimOp
    Int# -> ByteArr# -> Int#
    with needs_wrapper = True
+        out_of_line = True
 
 primop   Integer2WordOp   "integer2Word#"   GenPrimOp
    Int# -> ByteArr# -> Word#
    with needs_wrapper = True
+        out_of_line = True
 
 #if WORD_SIZE_IN_BITS < 32
 primop   IntegerToInt32Op   "integerToInt32#" GenPrimOp
@@ -440,14 +446,6 @@ primop   IntegerToWord32Op   "integerToWord32#" GenPrimOp
    Int# -> ByteArr# -> Word32#
 #endif
 
-#if WORD_SIZE_IN_BITS < 64
-primop   IntegerToInt64Op   "integerToInt64#" GenPrimOp
-   Int# -> ByteArr# -> Int64#
-
-primop   IntegerToWord64Op   "integerToWord64#" GenPrimOp
-   Int# -> ByteArr# -> Word64#
-#endif
-
 primop   IntegerAndOp  "andInteger#" GenPrimOp
    Int# -> ByteArr# -> Int# -> ByteArr# -> (# Int#, ByteArr# #)
    with out_of_line = True
@@ -464,7 +462,7 @@ primop   IntegerComplementOp  "complementInteger#" GenPrimOp
    Int# -> ByteArr# -> (# Int#, ByteArr# #)
    with out_of_line = True
 
-#endif /* ILX */
+#endif /* ndef ILX */
 
 ------------------------------------------------------------------------
 section "Double#"
@@ -1355,7 +1353,7 @@ primop  IsEmptyMVarOp "isEmptyMVar#" GenPrimOp
    {Return 1 if mvar is empty; 0 otherwise.}
    with
    usage = { mangle IsEmptyMVarOp [mkP, mkP] mkM }
-
+   out_of_line = True
 
 ------------------------------------------------------------------------
 section "Delay/wait operations"
@@ -1414,7 +1412,9 @@ primop  YieldOp "yield#" GenPrimOp
    out_of_line      = True
 
 primop  MyThreadIdOp "myThreadId#" GenPrimOp
-    State# RealWorld -> (# State# RealWorld, ThreadId# #)
+   State# RealWorld -> (# State# RealWorld, ThreadId# #)
+   with
+   out_of_line = True
 
 ------------------------------------------------------------------------
 section "Weak pointers"
@@ -1435,6 +1435,7 @@ primop  DeRefWeakOp "deRefWeak#" GenPrimOp
    with
    usage            = { mangle DeRefWeakOp [mkM, mkP] mkM }
    has_side_effects = True
+   out_of_line      = True
 
 primop  FinalizeWeakOp "finalizeWeak#" GenPrimOp
    Weak# a -> State# RealWorld -> (# State# RealWorld, Int#, 
@@ -1456,6 +1457,7 @@ primop  MakeStablePtrOp "makeStablePtr#" GenPrimOp
    strictness       = { \ arity -> StrictnessInfo [wwLazy, wwPrim] False }
    usage            = { mangle MakeStablePtrOp [mkM, mkP] mkM }
    has_side_effects = True
+   out_of_line      = True
 
 primop  DeRefStablePtrOp "deRefStablePtr#" GenPrimOp
    StablePtr# a -> State# RealWorld -> (# State# RealWorld, a #)
@@ -1463,6 +1465,7 @@ primop  DeRefStablePtrOp "deRefStablePtr#" GenPrimOp
    usage            = { mangle DeRefStablePtrOp [mkM, mkP] mkM }
    needs_wrapper    = True
    has_side_effects = True
+   out_of_line      = True
 
 primop  EqStablePtrOp "eqStablePtr#" GenPrimOp
    StablePtr# a -> StablePtr# a -> Int#
@@ -1490,16 +1493,6 @@ primop  StableNameToIntOp "stableNameToInt#" GenPrimOp
    usage = { mangle StableNameToIntOp [mkP] mkR }
 
 ------------------------------------------------------------------------
-section "Unsafe pointer equality"
---  (#1 Bad Guy: Alistair Reid :)   
-------------------------------------------------------------------------
-
-primop  ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp
-   a -> a -> Int#
-   with
-   usage = { mangle ReallyUnsafePtrEqualityOp [mkZ, mkZ] mkR }
-
-------------------------------------------------------------------------
 section "Parallelism"
 ------------------------------------------------------------------------
 
index 3f94d34..1cb6aee 100644 (file)
@@ -5,7 +5,7 @@
 
 \begin{code}
 module Maybes (
-       Maybe2(..), Maybe3(..),
+       Maybe012(..), maybe012ToList,
        MaybeErr(..),
 
        orElse, 
@@ -32,13 +32,16 @@ infixr 4 `orElse`
 
 %************************************************************************
 %*                                                                     *
-\subsection[Maybe2,3 types]{The @Maybe2@ and @Maybe3@ types}
+\subsection[Maybe012 type]{The @Maybe012@ type}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-data Maybe2 a b   = Just2 a b   | Nothing2  deriving (Eq,Show)
-data Maybe3 a b c = Just3 a b c | Nothing3  deriving (Eq,Show)
+data Maybe012 a = Just0 | Just1 a | Just2 a a deriving (Eq,Show)
+
+maybe012ToList Just0       = []
+maybe012ToList (Just1 x)   = [x]
+maybe012ToList (Just2 x y) = [x, y]
 \end{code}
 
 
index c9b6697..e48f54b 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: PrimOps.h,v 1.85 2001/11/21 20:27:18 sof Exp $
+ * $Id: PrimOps.h,v 1.86 2001/12/05 17:35:14 sewardj Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -7,6 +7,13 @@
  *
  * ---------------------------------------------------------------------------*/
 
+/* As of 5 Dec 01, this file no longer implements the primops, since they are
+   translated into standard C in compiler/absCSyn/AbsCUtils during the absC
+   flattening pass.  Only {add,sub,mul}IntCzh remain untranslated.  Most of
+   what is here is now EXTFUN_RTS declarations for the out-of-line primop
+   implementations which live in compiler/rts/PrimOps.hc.
+*/
+
 #ifndef PRIMOPS_H
 #define PRIMOPS_H
 
 #error GHC C backend requires 32+-bit words
 #endif
 
-/* -----------------------------------------------------------------------------
-   Helpers for the bytecode linker.             
-   -------------------------------------------------------------------------- */
-
-#define addrToHValuezh(r,a) r=(P_)a
-
-
-/* -----------------------------------------------------------------------------
-   Comparison PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define gtCharzh(r,a,b)        r=((C_)(a))> ((C_)(b))
-#define geCharzh(r,a,b)        r=((C_)(a))>=((C_)(b))
-#define eqCharzh(r,a,b)        r=((C_)(a))==((C_)(b))
-#define neCharzh(r,a,b)        r=((C_)(a))!=((C_)(b))
-#define ltCharzh(r,a,b)        r=((C_)(a))< ((C_)(b))
-#define leCharzh(r,a,b)        r=((C_)(a))<=((C_)(b))
-
-/* Int comparisons: >#, >=# etc */
-#define zgzh(r,a,b)    r=((I_)(a))> ((I_)(b))
-#define zgzezh(r,a,b)  r=((I_)(a))>=((I_)(b))
-#define zezezh(r,a,b)  r=((I_)(a))==((I_)(b))
-#define zszezh(r,a,b)  r=((I_)(a))!=((I_)(b))
-#define zlzh(r,a,b)    r=((I_)(a))< ((I_)(b))
-#define zlzezh(r,a,b)  r=((I_)(a))<=((I_)(b))
-
-#define gtWordzh(r,a,b)        r=((W_)(a))> ((W_)(b))
-#define geWordzh(r,a,b)        r=((W_)(a))>=((W_)(b))
-#define eqWordzh(r,a,b)        r=((W_)(a))==((W_)(b))
-#define neWordzh(r,a,b)        r=((W_)(a))!=((W_)(b))
-#define ltWordzh(r,a,b)        r=((W_)(a))< ((W_)(b))
-#define leWordzh(r,a,b)        r=((W_)(a))<=((W_)(b))
-
-#define gtAddrzh(r,a,b)        r=((A_)(a))> ((A_)(b))
-#define geAddrzh(r,a,b)        r=((A_)(a))>=((A_)(b))
-#define eqAddrzh(r,a,b)        r=((A_)(a))==((A_)(b))
-#define neAddrzh(r,a,b)        r=((A_)(a))!=((A_)(b))
-#define ltAddrzh(r,a,b)        r=((A_)(a))< ((A_)(b))
-#define leAddrzh(r,a,b)        r=((A_)(a))<=((A_)(b))
-
-#define gtFloatzh(r,a,b)  r=((StgFloat)(a))> ((StgFloat)(b))
-#define geFloatzh(r,a,b)  r=((StgFloat)(a))>=((StgFloat)(b))
-#define eqFloatzh(r,a,b)  r=((StgFloat)(a))==((StgFloat)(b))
-#define neFloatzh(r,a,b)  r=((StgFloat)(a))!=((StgFloat)(b))
-#define ltFloatzh(r,a,b)  r=((StgFloat)(a))< ((StgFloat)(b))
-#define leFloatzh(r,a,b)  r=((StgFloat)(a))<=((StgFloat)(b))
-
-/* Double comparisons: >##, >=## etc */
-#define zgzhzh(r,a,b)  r=((StgDouble)(a))> ((StgDouble)(b))
-#define zgzezhzh(r,a,b)        r=((StgDouble)(a))>=((StgDouble)(b))
-#define zezezhzh(r,a,b)        r=((StgDouble)(a))==((StgDouble)(b))
-#define zszezhzh(r,a,b)        r=((StgDouble)(a))!=((StgDouble)(b))
-#define zlzhzh(r,a,b)  r=((StgDouble)(a))< ((StgDouble)(b))
-#define zlzezhzh(r,a,b)        r=((StgDouble)(a))<=((StgDouble)(b))
-
-/* -----------------------------------------------------------------------------
-   Char# PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define ordzh(r,a)     r=(I_)(a)
-#define chrzh(r,a)     r=(C_)(a)
-
-/* -----------------------------------------------------------------------------
-   Int# PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define zpzh(r,a,b)            r=((I_)(a))+((I_)(b))
-#define zmzh(r,a,b)            r=((I_)(a))-((I_)(b))
-#define ztzh(r,a,b)            r=((I_)(a))*((I_)(b))
-#define quotIntzh(r,a,b)       r=((I_)(a))/((I_)(b))
-#define remIntzh(r,a,b)                r=((I_)(a))%((I_)(b))
-#define negateIntzh(r,a)       r=-((I_)(a))
 
 /* -----------------------------------------------------------------------------
  * Int operations with carry.
@@ -193,260 +128,14 @@ typedef union {
 }
 #endif
 
-/* -----------------------------------------------------------------------------
-   Word# PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define plusWordzh(r,a,b)      r=((W_)(a))+((W_)(b))
-#define minusWordzh(r,a,b)     r=((W_)(a))-((W_)(b))
-#define timesWordzh(r,a,b)     r=((W_)(a))*((W_)(b))
-#define quotWordzh(r,a,b)      r=((W_)(a))/((W_)(b))
-#define remWordzh(r,a,b)       r=((W_)(a))%((W_)(b))
-
-#define andzh(r,a,b)           r=((W_)(a))&((W_)(b))
-#define orzh(r,a,b)            r=((W_)(a))|((W_)(b))
-#define xorzh(r,a,b)            r=((W_)(a))^((W_)(b))
-#define notzh(r,a)             r=~((W_)(a))
-
-/* The extra tests below properly define the behaviour when shifting
- * by offsets larger than the width of the value being shifted.  Doing
- * so is undefined in C (and in fact gives different answers depending
- * on whether the operation is constant folded or not with gcc on x86!)
- */
-
-#define shiftLzh(r,a,b)                r=(((I_)(b)) >= BITS_IN(W_)) ? 0 : ((W_)(a))<<((I_)(b))
-#define shiftRLzh(r,a,b)       r=(((I_)(b)) >= BITS_IN(W_)) ? 0 : ((W_)(a))>>((I_)(b))
-#define iShiftLzh(r,a,b)       r=(((I_)(b)) >= BITS_IN(W_)) ? 0 : ((W_)(a))<<((I_)(b))
-/* Right shifting of signed quantities is not portable in C, so
-   the behaviour you'll get from using these primops depends
-   on the whatever your C compiler is doing. ToDo: fix/document. -- sof 8/98
-*/
-#define iShiftRAzh(r,a,b)      r=(((I_)(b)) >= BITS_IN(I_)) ? ((((I_)(a)) < 0) ? -1 : 0) : ((I_)(a))>>((I_)(b))
-#define iShiftRLzh(r,a,b)      r=(((I_)(b)) >= BITS_IN(I_)) ? 0 : (I_)((W_)((I_)(a))>>((I_)(b)))
-
-#define int2Wordzh(r,a)        r=(W_)((I_)(a))
-#define word2Intzh(r,a)        r=(I_)((W_)(a))
-
-/* -----------------------------------------------------------------------------
-   Explicitly sized Int# and Word# PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define narrow8Intzh(r,a)      r=(StgInt8)((I_)(a))
-#define narrow16Intzh(r,a)     r=(StgInt16)((I_)(a))
-#define narrow32Intzh(r,a)     r=(StgInt32)((I_)(a))
-#define narrow8Wordzh(r,a)     r=(StgWord8)((W_)(a))
-#define narrow16Wordzh(r,a)    r=(StgWord16)((W_)(a))
-#define narrow32Wordzh(r,a)    r=(StgWord32)((W_)(a))
-
-/* -----------------------------------------------------------------------------
-   Addr# PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define nullAddrzh(r,i)         r=(A_)(0)
-#define plusAddrzh(r,a,i)       r=((char *)(a)) + (i)
-#define minusAddrzh(r,a,b)      r=((char *)(a)) - ((char *)(b))
-#define remAddrzh(r,a,i)        r=((W_)(a))%(i)
-#define int2Addrzh(r,a)        r=(A_)(a)
-#define addr2Intzh(r,a)        r=(I_)(a)
-
-#define readCharOffAddrzh(r,a,i)       r=((StgWord8 *)(a))[i]
-#define readWideCharOffAddrzh(r,a,i)   r=((C_ *)(a))[i]
-#define readIntOffAddrzh(r,a,i)                r=((I_ *)(a))[i]
-#define readWordOffAddrzh(r,a,i)       r=((W_ *)(a))[i]
-#define readAddrOffAddrzh(r,a,i)       r=((PP_)(a))[i]
-#define readFloatOffAddrzh(r,a,i)      r=PK_FLT((P_) (((StgFloat *)(a)) + i))
-#define readDoubleOffAddrzh(r,a,i)     r=PK_DBL((P_) (((StgDouble *)(a)) + i))
-#define readStablePtrOffAddrzh(r,a,i)  r=((StgStablePtr *)(a))[i]
-#define readInt8OffAddrzh(r,a,i)       r=((StgInt8 *)(a))[i]
-#define readInt16OffAddrzh(r,a,i)      r=((StgInt16 *)(a))[i]
-#define readWord8OffAddrzh(r,a,i)      r=((StgWord8 *)(a))[i]
-#define readWord16OffAddrzh(r,a,i)     r=((StgWord16 *)(a))[i]
-#define readInt32OffAddrzh(r,a,i)      r=((StgInt32 *)(a))[i]
-#define readWord32OffAddrzh(r,a,i)     r=((StgWord32 *)(a))[i]
-#ifdef SUPPORT_LONG_LONGS
-#define readInt64OffAddrzh(r,a,i)      r=((LI_ *)(a))[i]
-#define readWord64OffAddrzh(r,a,i)     r=((LW_ *)(a))[i]
-#else
-#define readInt64OffAddrzh(r,a,i)      r=((I_ *)(a))[i]
-#define readWord64OffAddrzh(r,a,i)     r=((W_ *)(a))[i]
-#endif
-
-#define writeCharOffAddrzh(a,i,v)      ((StgWord8 *)(a))[i] = (v)
-#define writeWideCharOffAddrzh(a,i,v)  ((C_ *)(a))[i] = (v)
-#define writeIntOffAddrzh(a,i,v)       ((I_ *)(a))[i] = (v)
-#define writeWordOffAddrzh(a,i,v)      ((W_ *)(a))[i] = (v)
-#define writeAddrOffAddrzh(a,i,v)      ((PP_)(a))[i] = (v)
-#define writeForeignObjOffAddrzh(a,i,v) ((PP_)(a))[i] = ForeignObj_CLOSURE_DATA(v)
-#define writeFloatOffAddrzh(a,i,v)     ASSIGN_FLT((P_) (((StgFloat *)(a)) + i),v)
-#define writeDoubleOffAddrzh(a,i,v)    ASSIGN_DBL((P_) (((StgDouble *)(a)) + i),v)
-#define writeStablePtrOffAddrzh(a,i,v) ((StgStablePtr *)(a))[i] = (v)
-#define writeInt8OffAddrzh(a,i,v)      ((StgInt8 *)(a))[i] = (v)
-#define writeInt16OffAddrzh(a,i,v)     ((StgInt16 *)(a))[i] = (v)
-#define writeInt32OffAddrzh(a,i,v)     ((StgInt32 *)(a))[i] = (v)
-#define writeWord8OffAddrzh(a,i,v)     ((StgWord8 *)(a))[i] = (v)
-#define writeWord16OffAddrzh(a,i,v)    ((StgWord16 *)(a))[i] = (v)
-#define writeWord32OffAddrzh(a,i,v)    ((StgWord32 *)(a))[i] = (v)
-#ifdef SUPPORT_LONG_LONGS
-#define writeInt64OffAddrzh(a,i,v)     ((LI_ *)(a))[i] = (v)
-#define writeWord64OffAddrzh(a,i,v)    ((LW_ *)(a))[i] = (v)
-#else
-#define writeInt64OffAddrzh(a,i,v)     ((I_ *)(a))[i] = (v)
-#define writeWord64OffAddrzh(a,i,v)    ((W_ *)(a))[i] = (v)
-#endif
-
-#define indexCharOffAddrzh(r,a,i)      r=((StgWord8 *)(a))[i]
-#define indexWideCharOffAddrzh(r,a,i)  r=((C_ *)(a))[i]
-#define indexIntOffAddrzh(r,a,i)       r=((I_ *)(a))[i]
-#define indexWordOffAddrzh(r,a,i)      r=((W_ *)(a))[i]
-#define indexAddrOffAddrzh(r,a,i)      r=((PP_)(a))[i]
-#define indexFloatOffAddrzh(r,a,i)     r=PK_FLT((P_) (((StgFloat *)(a)) + i))
-#define indexDoubleOffAddrzh(r,a,i)    r=PK_DBL((P_) (((StgDouble *)(a)) + i))
-#define indexStablePtrOffAddrzh(r,a,i)  r=((StgStablePtr *)(a))[i]
-#define indexInt8OffAddrzh(r,a,i)      r=((StgInt8 *)(a))[i]
-#define indexInt16OffAddrzh(r,a,i)     r=((StgInt16 *)(a))[i]
-#define indexInt32OffAddrzh(r,a,i)     r=((StgInt32 *)(a))[i]
-#define indexWord8OffAddrzh(r,a,i)     r=((StgWord8 *)(a))[i]
-#define indexWord16OffAddrzh(r,a,i)            r=((StgWord16 *)(a))[i]
-#define indexWord32OffAddrzh(r,a,i)            r=((StgWord32 *)(a))[i]
-#ifdef SUPPORT_LONG_LONGS
-#define indexInt64OffAddrzh(r,a,i)     r=((LI_ *)(a))[i]
-#define indexWord64OffAddrzh(r,a,i)    r=((LW_ *)(a))[i]
-#else
-#define indexInt64OffAddrzh(r,a,i)     r=((I_ *)(a))[i]
-#define indexWord64OffAddrzh(r,a,i)    r=((W_ *)(a))[i]
-#endif
-
-/* -----------------------------------------------------------------------------
-   Float PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define plusFloatzh(r,a,b)   r=((StgFloat)(a))+((StgFloat)(b))
-#define minusFloatzh(r,a,b)  r=((StgFloat)(a))-((StgFloat)(b))
-#define timesFloatzh(r,a,b)  r=((StgFloat)(a))*((StgFloat)(b))
-#define divideFloatzh(r,a,b) r=((StgFloat)(a))/((StgFloat)(b))
-#define negateFloatzh(r,a)   r=-((StgFloat)(a))
-                            
-#define int2Floatzh(r,a)     r=(StgFloat)((I_)(a))
-#define float2Intzh(r,a)     r=(I_)((StgFloat)(a))
-                            
-#define expFloatzh(r,a)             r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,exp,((StgFloat)(a)))
-#define logFloatzh(r,a)             r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,log,((StgFloat)(a)))
-#define sqrtFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sqrt,((StgFloat)(a)))
-#define sinFloatzh(r,a)             r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sin,((StgFloat)(a)))
-#define cosFloatzh(r,a)             r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cos,((StgFloat)(a)))
-#define tanFloatzh(r,a)             r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tan,((StgFloat)(a)))
-#define asinFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,asin,((StgFloat)(a)))
-#define acosFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,acos,((StgFloat)(a)))
-#define atanFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,atan,((StgFloat)(a)))
-#define sinhFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,sinh,((StgFloat)(a)))
-#define coshFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,cosh,((StgFloat)(a)))
-#define tanhFloatzh(r,a)     r=(StgFloat) RET_PRIM_STGCALL1(StgDouble,tanh,((StgFloat)(a)))
-#define powerFloatzh(r,a,b)  r=(StgFloat) RET_PRIM_STGCALL2(StgDouble,pow,((StgFloat)(a)),((StgFloat)(b)))
-
-/* -----------------------------------------------------------------------------
-   Double PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define zpzhzh(r,a,b)       r=((StgDouble)(a))+((StgDouble)(b))
-#define zmzhzh(r,a,b)       r=((StgDouble)(a))-((StgDouble)(b))
-#define ztzhzh(r,a,b)       r=((StgDouble)(a))*((StgDouble)(b))
-#define zszhzh(r,a,b)       r=((StgDouble)(a))/((StgDouble)(b))
-#define negateDoublezh(r,a)  r=-((StgDouble)(a))
-                            
-#define int2Doublezh(r,a)    r=(StgDouble)((I_)(a))
-#define double2Intzh(r,a)    r=(I_)((StgDouble)(a))
-                            
-#define float2Doublezh(r,a)  r=(StgDouble)((StgFloat)(a))
-#define double2Floatzh(r,a)  r=(StgFloat)((StgDouble)(a))
-                            
-#define expDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,exp,((StgDouble)(a)))
-#define logDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,log,((StgDouble)(a)))
-#define sqrtDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sqrt,((StgDouble)(a)))
-#define sinDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sin,((StgDouble)(a)))
-#define cosDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cos,((StgDouble)(a)))
-#define tanDoublezh(r,a)     r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tan,((StgDouble)(a)))
-#define asinDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,asin,((StgDouble)(a)))
-#define acosDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,acos,((StgDouble)(a)))
-#define atanDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,atan,((StgDouble)(a)))
-#define sinhDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,sinh,((StgDouble)(a)))
-#define coshDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,cosh,((StgDouble)(a)))
-#define tanhDoublezh(r,a)    r=(StgDouble) RET_PRIM_STGCALL1(StgDouble,tanh,((StgDouble)(a)))
-/* Power: **## */
-#define ztztzhzh(r,a,b)        r=(StgDouble) RET_PRIM_STGCALL2(StgDouble,pow,((StgDouble)(a)),((StgDouble)(b)))
 
 /* -----------------------------------------------------------------------------
    Integer PrimOps.
    -------------------------------------------------------------------------- */
 
-/* We can do integer2Int and cmpInteger inline, since they don't need
- * to allocate any memory.
- *
- * integer2Int# is now modular.
- */
-
-#define integer2Intzh(r, sa,da)                                \
-{ I_ s, res;                                           \
-                                                       \
-  s = (sa);                                            \
-  if (s == 0)                                          \
-    res = 0;                                           \
-  else {                                               \
-    res = ((mp_limb_t *) (BYTE_ARR_CTS(da)))[0];       \
-    if (s < 0) res = -res;                             \
-  }                                                    \
-  (r) = res;                                           \
-}
-
-#define integer2Wordzh(r, sa,da)                       \
-{ I_ s;                                                        \
-  W_ res;                                              \
-                                                       \
-  s = (sa);                                            \
-  if (s == 0)                                          \
-    res = 0;                                           \
-  else {                                               \
-    res = ((mp_limb_t *) (BYTE_ARR_CTS(da)))[0];       \
-    if (s < 0) res = -res;                             \
-  }                                                    \
-  (r) = res;                                           \
-}
-
-#define cmpIntegerzh(r, s1,d1, s2,d2)                          \
-{ MP_INT arg1;                                                 \
-  MP_INT arg2;                                                 \
-                                                               \
-  arg1._mp_size        = (s1);                                         \
-  arg1._mp_alloc= ((StgArrWords *)d1)->words;                  \
-  arg1._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(d1));             \
-  arg2._mp_size        = (s2);                                         \
-  arg2._mp_alloc= ((StgArrWords *)d2)->words;                  \
-  arg2._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(d2));             \
-                                                               \
-  (r) = RET_PRIM_STGCALL2(I_,mpz_cmp,&arg1,&arg2);             \
-}
-
-#define cmpIntegerIntzh(r, s,d, i)                             \
-{ MP_INT arg;                                                  \
-                                                               \
-  arg._mp_size = (s);                                          \
-  arg._mp_alloc = ((StgArrWords *)d)->words;                   \
-  arg._mp_d    = (mp_limb_t *) (BYTE_ARR_CTS(d));              \
-                                                               \
-  (r) = RET_PRIM_STGCALL2(I_,mpz_cmp_si,&arg,i);               \
-}
-
 /* NOTE: gcdIntzh and gcdIntegerIntzh work only for positive inputs! */
 
-/* mp_limb_t must be able to hold an StgInt for this to work properly */
-#define gcdIntzh(r,a,b) \
-{ mp_limb_t aa = (mp_limb_t)(a); \
-  r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(&aa), 1, (mp_limb_t)(b)); \
-}
-
-#define gcdIntegerIntzh(r,sa,a,b) \
-  r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(BYTE_ARR_CTS(a)), sa, b)
-
-/* The rest are all out-of-line: -------- */
+/* Some of these are out-of-line: -------- */
 
 /* Integer arithmetic */
 EXTFUN_RTS(plusIntegerzh_fast);
@@ -459,6 +148,13 @@ EXTFUN_RTS(remIntegerzh_fast);
 EXTFUN_RTS(divExactIntegerzh_fast);
 EXTFUN_RTS(divModIntegerzh_fast);
 
+EXTFUN_RTS(cmpIntegerIntzh_fast);
+EXTFUN_RTS(cmpIntegerzh_fast);
+EXTFUN_RTS(integer2Intzh_fast);
+EXTFUN_RTS(integer2Wordzh_fast);
+EXTFUN_RTS(gcdIntegerIntzh_fast);
+EXTFUN_RTS(gcdIntzh_fast);
+
 /* Conversions */
 EXTFUN_RTS(int2Integerzh_fast);
 EXTFUN_RTS(word2Integerzh_fast);
@@ -473,54 +169,18 @@ EXTFUN_RTS(orIntegerzh_fast);
 EXTFUN_RTS(xorIntegerzh_fast);
 EXTFUN_RTS(complementIntegerzh_fast);
 
+
 /* -----------------------------------------------------------------------------
    Word64 PrimOps.
    -------------------------------------------------------------------------- */
 
 #ifdef SUPPORT_LONG_LONGS
 
-#define integerToWord64zh(r,sa,da)                     \
-{ mp_limb_t* d;                                                \
-  I_ s;                                                        \
-  StgWord64 res;                                       \
-                                                       \
-  d = (mp_limb_t *) (BYTE_ARR_CTS(da));                        \
-  s = (sa);                                            \
-  switch (s) {                                         \
-    case  0: res = 0;     break;                       \
-    case  1: res = d[0];  break;                       \
-    case -1: res = -d[0]; break;                       \
-    default:                                           \
-      res = d[0] + ((StgWord64) d[1] << (BITS_IN (mp_limb_t))); \
-      if (s < 0) res = -res;                           \
-  }                                                    \
-  (r) = res;                                           \
-}
-
-#define integerToInt64zh(r,sa,da)                      \
-{ mp_limb_t* d;                                                \
-  I_ s;                                                        \
-  StgInt64 res;                                                \
-                                                       \
-  d = (mp_limb_t *) (BYTE_ARR_CTS(da));                        \
-  s = (sa);                                            \
-  switch (s) {                                         \
-    case  0: res = 0;     break;                       \
-    case  1: res = d[0];  break;                       \
-    case -1: res = -d[0]; break;                       \
-    default:                                           \
-      res = d[0] + ((StgWord64) d[1] << (BITS_IN (mp_limb_t))); \
-      if (s < 0) res = -res;                           \
-  }                                                    \
-  (r) = res;                                           \
-}
-
 /* Conversions */
 EXTFUN_RTS(int64ToIntegerzh_fast);
 EXTFUN_RTS(word64ToIntegerzh_fast);
 
-/* The rest are (way!) out of line, implemented via C entry points.
- */
+/* The rest are (way!) out of line, implemented in vanilla C. */
 I_ stg_gtWord64 (StgWord64, StgWord64);
 I_ stg_geWord64 (StgWord64, StgWord64);
 I_ stg_eqWord64 (StgWord64, StgWord64);
@@ -563,6 +223,10 @@ LW_ stg_int64ToWord64 (StgInt64);
 LW_ stg_wordToWord64  (StgWord);
 W_  stg_word64ToWord  (StgWord64);
 LI_ stg_word64ToInt64 (StgWord64);
+
+LI_ stg_integerToInt64 (I_ sa, StgByteArray /* Really: mp_limb_t* */ da);
+LW_ stg_integerToWord64 (I_ sa, StgByteArray /* Really: mp_limb_t* */ da);
+
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -588,115 +252,27 @@ LI_ stg_word64ToInt64 (StgWord64);
 #define PTRS_ARR_CTS(a)                REAL_PTRS_ARR_CTS(a)
 #endif
 
+
 extern I_ genSymZh(void);
 extern I_ resetGenSymZh(void);
 
-/*--- everything except new*Array is done inline: */
-
-#define sameMutableArrayzh(r,a,b)      r=(I_)((a)==(b))
-#define sameMutableByteArrayzh(r,a,b)  r=(I_)((a)==(b))
-
-#define readArrayzh(r,a,i)             r=((PP_) PTRS_ARR_CTS(a))[(i)]
-
-#define readCharArrayzh(r,a,i)         indexCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWideCharArrayzh(r,a,i)     indexWideCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readIntArrayzh(r,a,i)          indexIntOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWordArrayzh(r,a,i)         indexWordOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readAddrArrayzh(r,a,i)         indexAddrOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readFloatArrayzh(r,a,i)                indexFloatOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readDoubleArrayzh(r,a,i)       indexDoubleOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readStablePtrArrayzh(r,a,i)    indexStablePtrOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readInt8Arrayzh(r,a,i)         indexInt8OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readInt16Arrayzh(r,a,i)                indexInt16OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readInt32Arrayzh(r,a,i)                indexInt32OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWord8Arrayzh(r,a,i)                indexWord8OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWord16Arrayzh(r,a,i)       indexWord16OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWord32Arrayzh(r,a,i)       indexWord32OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readInt64Arrayzh(r,a,i)                indexInt64OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define readWord64Arrayzh(r,a,i)       indexWord64OffAddrzh(r,BYTE_ARR_CTS(a),i)
-
-/* result ("r") arg ignored in write macros! */
-#define writeArrayzh(a,i,v)            ((PP_) PTRS_ARR_CTS(a))[(i)]=(v)
-
-#define writeCharArrayzh(a,i,v)                writeCharOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWideCharArrayzh(a,i,v)    writeWideCharOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeIntArrayzh(a,i,v)         writeIntOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWordArrayzh(a,i,v)                writeWordOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeAddrArrayzh(a,i,v)                writeAddrOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeFloatArrayzh(a,i,v)       writeFloatOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeDoubleArrayzh(a,i,v)      writeDoubleOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeStablePtrArrayzh(a,i,v)   writeStablePtrOffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeInt8Arrayzh(a,i,v)                writeInt8OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeInt16Arrayzh(a,i,v)       writeInt16OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeInt32Arrayzh(a,i,v)       writeInt32OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWord8Arrayzh(a,i,v)       writeWord8OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWord16Arrayzh(a,i,v)      writeWord16OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWord32Arrayzh(a,i,v)      writeWord32OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeInt64Arrayzh(a,i,v)       writeInt64OffAddrzh(BYTE_ARR_CTS(a),i,v)
-#define writeWord64Arrayzh(a,i,v)      writeWord64OffAddrzh(BYTE_ARR_CTS(a),i,v)
-
-#define indexArrayzh(r,a,i)            r=((PP_) PTRS_ARR_CTS(a))[(i)]
-
-#define indexCharArrayzh(r,a,i)                indexCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWideCharArrayzh(r,a,i)    indexWideCharOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexIntArrayzh(r,a,i)         indexIntOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWordArrayzh(r,a,i)                indexWordOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexAddrArrayzh(r,a,i)                indexAddrOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexFloatArrayzh(r,a,i)       indexFloatOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexDoubleArrayzh(r,a,i)      indexDoubleOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexStablePtrArrayzh(r,a,i)   indexStablePtrOffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexInt8Arrayzh(r,a,i)                indexInt8OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexInt16Arrayzh(r,a,i)       indexInt16OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexInt32Arrayzh(r,a,i)       indexInt32OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWord8Arrayzh(r,a,i)       indexWord8OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWord16Arrayzh(r,a,i)      indexWord16OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWord32Arrayzh(r,a,i)      indexWord32OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexInt64Arrayzh(r,a,i)       indexInt64OffAddrzh(r,BYTE_ARR_CTS(a),i)
-#define indexWord64Arrayzh(r,a,i)      indexWord64OffAddrzh(r,BYTE_ARR_CTS(a),i)
-
-/* Freezing arrays-of-ptrs requires changing an info table, for the
-   benefit of the generational collector.  It needs to scavenge mutable
-   objects, even if they are in old space.  When they become immutable,
-   they can be removed from this scavenge list.         */
-
-#define unsafeFreezzeArrayzh(r,a)                                      \
-       {                                                               \
-        SET_INFO((StgClosure *)a,&stg_MUT_ARR_PTRS_FROZEN_info);        \
-       r = a;                                                          \
-       }
-
-#define unsafeFreezzeByteArrayzh(r,a)  r=(a)
+/*--- Almost everything in line. */
 
 EXTFUN_RTS(unsafeThawArrayzh_fast);
-
-#define sizzeofByteArrayzh(r,a) \
-     r = (((StgArrWords *)(a))->words * sizeof(W_))
-#define sizzeofMutableByteArrayzh(r,a) \
-     r = (((StgArrWords *)(a))->words * sizeof(W_))
-
-/* and the out-of-line ones... */
-
 EXTFUN_RTS(newByteArrayzh_fast);
 EXTFUN_RTS(newPinnedByteArrayzh_fast);
 EXTFUN_RTS(newArrayzh_fast);
 
-// Highly unsafe, for use with a pinned ByteArray 
-// being kept alive with touch# 
-#define byteArrayContentszh(r,a) r = BYTE_ARR_CTS(a)
-
-/* encoding and decoding of floats/doubles. */
-
-/* We only support IEEE floating point format */
-#include "ieee-flpt.h"
-
 /* The decode operations are out-of-line because they need to allocate
  * a byte array.
  */
+
+/* We only support IEEE floating point formats. */
+#include "ieee-flpt.h"
 EXTFUN_RTS(decodeFloatzh_fast);
 EXTFUN_RTS(decodeDoublezh_fast);
 
 /* grimy low-level support functions defined in StgPrimFloat.c */
-
 extern StgDouble __encodeDouble (I_ size, StgByteArray arr, I_ e);
 extern StgDouble __int_encodeDouble (I_ j, I_ e);
 extern StgFloat  __encodeFloat (I_ size, StgByteArray arr, I_ e);
@@ -712,6 +288,7 @@ extern StgInt    isFloatInfinite(StgFloat f);
 extern StgInt    isFloatDenormalized(StgFloat f);
 extern StgInt    isFloatNegativeZero(StgFloat f);
 
+
 /* -----------------------------------------------------------------------------
    Mutable variables
 
@@ -720,25 +297,21 @@ extern StgInt    isFloatNegativeZero(StgFloat f);
 
 EXTFUN_RTS(newMutVarzh_fast);
 
-#define readMutVarzh(r,a)       r=(P_)(((StgMutVar *)(a))->var)
-#define writeMutVarzh(a,v)       (P_)(((StgMutVar *)(a))->var)=(v)
-#define sameMutVarzh(r,a,b)      r=(I_)((a)==(b))
 
 /* -----------------------------------------------------------------------------
    MVar PrimOps.
 
    All out of line, because they either allocate or may block.
    -------------------------------------------------------------------------- */
-#define sameMVarzh(r,a,b)        r=(I_)((a)==(b))
 
-/* Assume external decl of EMPTY_MVAR_info is in scope by now */
-#define isEmptyMVarzh(r,a)       r=(I_)((GET_INFO((StgMVar*)(a))) == &stg_EMPTY_MVAR_info )
+EXTFUN_RTS(isEmptyMVarzh_fast);
 EXTFUN_RTS(newMVarzh_fast);
 EXTFUN_RTS(takeMVarzh_fast);
 EXTFUN_RTS(putMVarzh_fast);
 EXTFUN_RTS(tryTakeMVarzh_fast);
 EXTFUN_RTS(tryPutMVarzh_fast);
 
+
 /* -----------------------------------------------------------------------------
    Delay/Wait PrimOps
    -------------------------------------------------------------------------- */
@@ -747,6 +320,7 @@ EXTFUN_RTS(waitReadzh_fast);
 EXTFUN_RTS(waitWritezh_fast);
 EXTFUN_RTS(delayzh_fast);
 
+
 /* -----------------------------------------------------------------------------
    Primitive I/O, error-handling PrimOps
    -------------------------------------------------------------------------- */
@@ -756,27 +330,15 @@ EXTFUN_RTS(raisezh_fast);
 
 extern void stg_exit(I_ n)  __attribute__ ((noreturn));
 
+
 /* -----------------------------------------------------------------------------
    Stable Name / Stable Pointer  PrimOps
    -------------------------------------------------------------------------- */
 
 EXTFUN_RTS(makeStableNamezh_fast);
+EXTFUN_RTS(makeStablePtrzh_fast);
+EXTFUN_RTS(deRefStablePtrzh_fast);
 
-#define stableNameToIntzh(r,s)   (r = ((StgStableName *)s)->sn)
-
-#define eqStableNamezh(r,sn1,sn2)                                      \
-    (r = (((StgStableName *)sn1)->sn == ((StgStableName *)sn2)->sn))
-
-#define makeStablePtrzh(r,a) \
-   r = RET_STGCALL1(StgStablePtr,getStablePtr,a)
-
-#define deRefStablePtrzh(r,sp) do {            \
-  ASSERT(stable_ptr_table[(StgWord)sp].ref > 0);       \
-  r = stable_ptr_table[(StgWord)sp].addr; \
-} while (0);
-
-#define eqStablePtrzh(r,sp1,sp2) \
-    (r = ((StgWord)sp1 == (StgWord)sp2))
 
 /* -----------------------------------------------------------------------------
    Concurrency/Exception PrimOps.
@@ -788,12 +350,51 @@ EXTFUN_RTS(killThreadzh_fast);
 EXTFUN_RTS(seqzh_fast);
 EXTFUN_RTS(blockAsyncExceptionszh_fast);
 EXTFUN_RTS(unblockAsyncExceptionszh_fast);
-
-#define myThreadIdzh(t) (t = CurrentTSO)
+EXTFUN_RTS(myThreadIdzh_fast);
 
 extern int cmp_thread(const StgTSO *tso1, const StgTSO *tso2);
 extern int rts_getThreadId(const StgTSO *tso);
 
+
+/* -----------------------------------------------------------------------------
+   Weak Pointer PrimOps.
+   -------------------------------------------------------------------------- */
+
+EXTFUN_RTS(mkWeakzh_fast);
+EXTFUN_RTS(finalizzeWeakzh_fast);
+EXTFUN_RTS(deRefWeakzh_fast);
+
+
+/* -----------------------------------------------------------------------------
+   Foreign Object PrimOps.
+   -------------------------------------------------------------------------- */
+
+EXTFUN_RTS(mkForeignObjzh_fast);
+
+
+/* -----------------------------------------------------------------------------
+   BCOs and BCO linkery
+   -------------------------------------------------------------------------- */
+
+EXTFUN_RTS(newBCOzh_fast);
+EXTFUN_RTS(mkApUpd0zh_fast);
+
+
+/* -----------------------------------------------------------------------------
+   Signal handling.  Not really primops, but called directly from Haskell. 
+   -------------------------------------------------------------------------- */
+
+#define STG_SIG_DFL  (-1)
+#define STG_SIG_IGN  (-2)
+#define STG_SIG_ERR  (-3)
+#define STG_SIG_HAN  (-4)
+
+extern StgInt stg_sig_install (StgInt, StgInt, StgStablePtr, sigset_t *);
+#define stg_sig_default(sig,mask) stg_sig_install(sig,STG_SIG_DFL,0,(sigset_t *)mask)
+#define stg_sig_ignore(sig,mask) stg_sig_install(sig,STG_SIG_IGN,0,(sigset_t *)mask)
+#define stg_sig_catch(sig,ptr,mask) stg_sig_install(sig,STG_SIG_HAN,ptr,(sigset_t *)mask)
+
+
 /* ------------------------------------------------------------------------
    Parallel PrimOps
 
@@ -886,97 +487,4 @@ extern int rts_getThreadId(const StgTSO *tso);
 #define parzh(r,node) r = 1
 #endif
 
-/* -----------------------------------------------------------------------------
-   Pointer equality
-   -------------------------------------------------------------------------- */
-
-/* warning: extremely non-referentially transparent, need to hide in
-   an appropriate monad.
-
-   ToDo: follow indirections.  
-*/
-
-#define reallyUnsafePtrEqualityzh(r,a,b) r=((StgPtr)(a) == (StgPtr)(b))
-
-/* -----------------------------------------------------------------------------
-   Weak Pointer PrimOps.
-   -------------------------------------------------------------------------- */
-
-EXTFUN_RTS(mkWeakzh_fast);
-EXTFUN_RTS(finalizzeWeakzh_fast);
-
-#define deRefWeakzh(code,val,w)                                \
-  if (((StgWeak *)w)->header.info == &stg_WEAK_info) { \
-       code = 1;                                       \
-       val = (P_)((StgWeak *)w)->value;                \
-  } else {                                             \
-       code = 0;                                       \
-       val = (P_)w;                                    \
-  }
-
-#define sameWeakzh(w1,w2)  ((w1)==(w2))
-
-
-/* -----------------------------------------------------------------------------
-   Foreign Object PrimOps.
-   -------------------------------------------------------------------------- */
-
-#define ForeignObj_CLOSURE_DATA(c)  (((StgForeignObj *)c)->data)
-
-#define foreignObjToAddrzh(r,fo)    r=ForeignObj_CLOSURE_DATA(fo)
-#define touchzh(o)                  /* nothing */
-
-EXTFUN_RTS(mkForeignObjzh_fast);
-
-#define writeForeignObjzh(res,datum) \
-   (ForeignObj_CLOSURE_DATA(res) = (P_)(datum))
-
-#define eqForeignObjzh(r,f1,f2)                 r=(f1)==(f2)
-#define indexCharOffForeignObjzh(r,fo,i)       indexCharOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWideCharOffForeignObjzh(r,fo,i)   indexWideCharOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexIntOffForeignObjzh(r,fo,i)                indexIntOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWordOffForeignObjzh(r,fo,i)       indexWordOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexAddrOffForeignObjzh(r,fo,i)       indexAddrOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexFloatOffForeignObjzh(r,fo,i)      indexFloatOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexDoubleOffForeignObjzh(r,fo,i)     indexDoubleOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexStablePtrOffForeignObjzh(r,fo,i)  indexStablePtrOffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexInt8OffForeignObjzh(r,fo,i)       indexInt8OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexInt16OffForeignObjzh(r,fo,i)      indexInt16OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexInt32OffForeignObjzh(r,fo,i)      indexInt32OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWord8OffForeignObjzh(r,fo,i)      indexWord8OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWord16OffForeignObjzh(r,fo,i)     indexWord16OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWord32OffForeignObjzh(r,fo,i)     indexWord32OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexInt64OffForeignObjzh(r,fo,i)      indexInt64OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-#define indexWord64OffForeignObjzh(r,fo,i)     indexWord64OffAddrzh(r,ForeignObj_CLOSURE_DATA(fo),i)
-
-/* -----------------------------------------------------------------------------
-   Constructor tags
-   -------------------------------------------------------------------------- */
-
-#define dataToTagzh(r,a)  r=(GET_TAG(((StgClosure *)a)->header.info))
-
-/*  tagToEnum# is handled directly by the code generator. */
-
-/* -----------------------------------------------------------------------------
-   BCOs and BCO linkery
-   -------------------------------------------------------------------------- */
-
-EXTFUN_RTS(newBCOzh_fast);
-EXTFUN_RTS(mkApUpd0zh_fast);
-
-/* -----------------------------------------------------------------------------
-   Signal processing.  Not really primops, but called directly from
-   Haskell. 
-   -------------------------------------------------------------------------- */
-
-#define STG_SIG_DFL  (-1)
-#define STG_SIG_IGN  (-2)
-#define STG_SIG_ERR  (-3)
-#define STG_SIG_HAN  (-4)
-
-extern StgInt stg_sig_install (StgInt, StgInt, StgStablePtr, sigset_t *);
-#define stg_sig_default(sig,mask) stg_sig_install(sig,STG_SIG_DFL,0,(sigset_t *)mask)
-#define stg_sig_ignore(sig,mask) stg_sig_install(sig,STG_SIG_IGN,0,(sigset_t *)mask)
-#define stg_sig_catch(sig,ptr,mask) stg_sig_install(sig,STG_SIG_HAN,ptr,(sigset_t *)mask)
-
 #endif /* PRIMOPS_H */
index f6a74df..f2140ca 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Stg.h,v 1.42 2001/11/26 16:54:22 simonmar Exp $
+ * $Id: Stg.h,v 1.43 2001/12/05 17:35:14 sewardj Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -217,6 +217,7 @@ typedef StgWord64       LW_;
 #include "StgTicky.h"
 #include "CCall.h"
 #include "Stable.h"
+#include "PrimOpHelpers.h"
 
 /* Built-in entry points */
 #include "StgMiscClosures.h"
index d478480..d9ae781 100644 (file)
@@ -238,8 +238,6 @@ __export PrelGHC
   word32ToIntegerzh
 #endif  
 #if WORD_SIZE_IN_BITS < 64
-  integerToInt64zh
-  integerToWord64zh
   int64ToIntegerzh
   word64ToIntegerzh
 #endif
@@ -422,8 +420,6 @@ __export PrelGHC
   eqStableNamezh
   stableNameToIntzh
 
-  reallyUnsafePtrEqualityzh
-
   newBCOzh
   BCOzh
   mkApUpd0zh
index e282716..13f7c4a 100644 (file)
@@ -648,6 +648,8 @@ foreign import "stg_iShiftRA64"    unsafe iShiftRA64#    :: Int64# -> Int# -> In
 foreign import "stg_shiftL64"      unsafe shiftL64#      :: Word64# -> Int# -> Word64#
 foreign import "stg_shiftRL64"     unsafe shiftRL64#     :: Word64# -> Int# -> Word64#
 
+foreign import "stg_integerToInt64"  unsafe integerToInt64#  :: Int# -> ByteArray# -> Int64#
+
 {-# RULES
 "fromIntegral/Int->Int64"    fromIntegral = \(I#   x#) -> I64# (intToInt64# x#)
 "fromIntegral/Word->Int64"   fromIntegral = \(W#   x#) -> I64# (word64ToInt64# (wordToWord64# x#))
index fb12ea1..30af9fc 100644 (file)
@@ -746,6 +746,9 @@ foreign import "stg_not64"         unsafe not64#         :: Word64# -> Word64#
 foreign import "stg_shiftL64"      unsafe shiftL64#      :: Word64# -> Int# -> Word64#
 foreign import "stg_shiftRL64"     unsafe shiftRL64#     :: Word64# -> Int# -> Word64#
 
+foreign import "stg_integerToWord64" unsafe integerToWord64# :: Int# -> ByteArray# -> Word64#
+
+
 {-# RULES
 "fromIntegral/Int->Word64"    fromIntegral = \(I#   x#) -> W64# (int64ToWord64# (intToInt64# x#))
 "fromIntegral/Word->Word64"   fromIntegral = \(W#   x#) -> W64# (wordToWord64# x#)
index 5a7bd55..fdc7603 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: longlong.c,v 1.3 2001/07/23 15:11:55 simonmar Exp $
+ * $Id: longlong.c,v 1.4 2001/12/05 17:35:15 sewardj Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -74,8 +74,8 @@ StgInt64  stg_iShiftRA64 (StgInt64 a,  StgInt b)    {return a >> b;}
 StgInt64  stg_iShiftRL64 (StgInt64 a,  StgInt b)
 {return (StgInt64) ((StgWord64) a >> b);}
 
-/* Casting between longs and longer longs:
-   (the primops that cast between Integers and long longs are
+/* Casting between longs and longer longs.
+   (the primops that cast from long longs to Integers
    expressed as macros, since these may cause some heap allocation).
 */
 
@@ -86,4 +86,40 @@ StgWord64 stg_wordToWord64  (StgWord   w) {return (StgWord64) w;}
 StgWord   stg_word64ToWord  (StgWord64 w) {return (StgWord)   w;}
 StgInt64  stg_word64ToInt64 (StgWord64 w) {return (StgInt64)  w;}
 
+StgWord64 stg_integerToWord64 (I_ sa, StgByteArray /* Really: mp_limb_t* */ da)
+{ 
+  mp_limb_t* d;
+  I_ s;
+  StgWord64 res;
+  d = (mp_limb_t *)da;
+  s = sa;
+  switch (s) {
+    case  0: res = 0;     break;
+    case  1: res = d[0];  break;
+    case -1: res = -d[0]; break;
+    default:
+      res = d[0] + ((StgWord64) d[1] << (BITS_IN (mp_limb_t)));
+      if (s < 0) res = -res;
+  }
+  return res;
+}
+
+StgInt64 stg_integerToInt64 (StgInt sa, StgByteArray /* Really: mp_limb_t* */ da)
+{ 
+  mp_limb_t* d;
+  I_ s;
+  StgInt64 res;
+  d = (mp_limb_t *)da;
+  s = (sa);
+  switch (s) {
+    case  0: res = 0;     break;
+    case  1: res = d[0];  break;
+    case -1: res = -d[0]; break;
+    default:
+      res = d[0] + ((StgWord64) d[1] << (BITS_IN (mp_limb_t)));
+      if (s < 0) res = -res;
+  }
+  return res;
+}
+
 #endif /* SUPPORT_LONG_LONGS */
index 8cb24e9..817d6c2 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Exception.hc,v 1.22 2001/11/22 14:25:12 simonmar Exp $
+ * $Id: Exception.hc,v 1.23 2001/12/05 17:35:15 sewardj Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -212,6 +212,17 @@ FN_(killThreadzh_fast)
   FE_
 }
 
+
+FN_(myThreadIdzh_fast)
+{
+  /* no args. */
+  FB_
+  R1.p = (P_)CurrentTSO;
+  JMP_(ENTRY_CODE(Sp[0]));
+  FE_
+}
+
+
 /* -----------------------------------------------------------------------------
    Catch frames
    -------------------------------------------------------------------------- */
index 2036768..46ad653 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.85 2001/11/22 14:25:12 simonmar Exp $
+ * $Id: PrimOps.hc,v 1.86 2001/12/05 17:35:15 sewardj Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -329,7 +329,6 @@ FN_(newMutVarzh_fast)
 
 /* -----------------------------------------------------------------------------
    Foreign Object Primitives
-
    -------------------------------------------------------------------------- */
 
 FN_(mkForeignObjzh_fast)
@@ -451,6 +450,25 @@ FN_(finalizzeWeakzh_fast)
   FE_
 }
 
+FN_(deRefWeakzh_fast)
+{
+  /* R1.p = weak ptr */
+  StgWeak* w;
+  I_       code;
+  P_       val;
+  FB_
+  w = (StgWeak*)R1.p;
+  if (w->header.info == &stg_WEAK_info) {
+    code = 1;
+    val = (P_)((StgWeak *)w)->value;
+  } else {
+    code = 0;
+    val = (P_)w;
+  }
+  RET_NP(code,val);
+  FE_
+}
+
 /* -----------------------------------------------------------------------------
    Arbitrary-precision Integer operations.
    -------------------------------------------------------------------------- */
@@ -751,6 +769,97 @@ GMP_TAKE1_RET1(complementIntegerzh_fast, mpz_com);
 GMP_TAKE2_RET2(quotRemIntegerzh_fast, mpz_tdiv_qr);
 GMP_TAKE2_RET2(divModIntegerzh_fast,  mpz_fdiv_qr);
 
+
+FN_(gcdIntzh_fast)
+{
+  /* R1 = the first Int#; R2 = the second Int# */
+  mp_limb_t aa;
+  I_        r;
+  FB_
+  aa = (mp_limb_t)(R1.i);
+  r = RET_STGCALL3(StgInt, mpn_gcd_1, (mp_limb_t *)(&aa), 1, (mp_limb_t)(R2.i));
+  RET_N(r);
+  FE_
+}
+
+FN_(gcdIntegerIntzh_fast)
+{
+  /* R1 = s1; R2 = d1; R3 = the int */
+  I_ r;
+  FB_
+  MAYBE_GC(R2_PTR, gcdIntegerIntzh_fast);
+  r = RET_STGCALL3(I_,mpn_gcd_1,(mp_limb_t *)(BYTE_ARR_CTS(R2.p)), R1.i, R3.i);
+  RET_N(r);
+  FE_
+}
+
+FN_(cmpIntegerIntzh_fast)
+{
+  /* R1 = s1; R2 = d1; R3 = the int */
+  MP_INT arg;
+  I_ r;
+  FB_
+  MAYBE_GC(R2_PTR, cmpIntegerIntzh_fast);
+  arg._mp_size = R1.i;
+  arg._mp_alloc = ((StgArrWords *)R2.p)->words;
+  arg._mp_d    = (mp_limb_t *) (BYTE_ARR_CTS(R2.p));
+  r = RET_STGCALL2(I_,mpz_cmp_si,&arg,R3.i);
+  RET_N(r);
+  FE_
+}
+
+FN_(cmpIntegerzh_fast)
+{
+  /* R1 = s1; R2 = d1; R3 = s2; R4 = d2 */
+  MP_INT arg1, arg2;
+  I_ r;
+  FB_
+  MAYBE_GC(R2_PTR | R4_PTR, cmpIntegerIntzh_fast);
+  arg1._mp_size        = R1.i;
+  arg1._mp_alloc= ((StgArrWords *)R2.p)->words;
+  arg1._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(R2.p));
+  arg2._mp_size        = R3.i;
+  arg2._mp_alloc= ((StgArrWords *)R4.p)->words;
+  arg2._mp_d   = (mp_limb_t *) (BYTE_ARR_CTS(R4.p));
+  r = RET_STGCALL2(I_,mpz_cmp,&arg1,&arg2);
+  RET_N(r);
+  FE_
+}
+
+FN_(integer2Intzh_fast)
+{
+  /* R1 = s; R2 = d */
+  I_ r, s;
+  FB_
+  s = R1.i;
+  if (s == 0)
+    r = 0;
+  else {
+    r = ((mp_limb_t *) (BYTE_ARR_CTS(R2.p)))[0];
+    if (s < 0) r = -r;
+  }
+  RET_N(r);
+  FE_
+}
+
+FN_(integer2Wordzh_fast)
+{
+  /* R1 = s; R2 = d */
+  I_ s;
+  W_ r;
+  FB_
+  s = R1.i;
+  if (s == 0)
+    r = 0;
+  else {
+    r = ((mp_limb_t *) (BYTE_ARR_CTS(R2.p)))[0];
+    if (s < 0) r = -r;
+  }
+  RET_N(r);
+  FE_
+}
+
+
 FN_(decodeFloatzh_fast)
 { 
   MP_INT mantissa;
@@ -875,6 +984,17 @@ FN_(yieldzh_fast)
  *
  * -------------------------------------------------------------------------- */
 
+FN_(isEmptyMVarzh_fast)
+{
+  /* args: R1 = MVar closure */
+  I_ r;
+  FB_
+  r = (I_)((GET_INFO((StgMVar*)(R1.p))) == &stg_EMPTY_MVAR_info);
+  RET_N(r);
+  FE_
+}
+
+
 FN_(newMVarzh_fast)
 {
   StgMVar *mvar;
@@ -1218,6 +1338,31 @@ FN_(makeStableNamezh_fast)
   RET_P(sn_obj);
 }
 
+
+FN_(makeStablePtrzh_fast)
+{
+  /* Args: R1 = a */
+  StgStablePtr sp;
+  FB_
+  MAYBE_GC(R1_PTR, makeStablePtrzh_fast);
+  sp = RET_STGCALL1(StgStablePtr,getStablePtr,R1.p);
+  RET_N(sp);
+  FE_
+}
+
+FN_(deRefStablePtrzh_fast)
+{
+  /* Args: R1 = the stable ptr */
+  P_ r;
+  StgStablePtr sp;
+  FB_
+  sp = (StgStablePtr)R1.w;
+  ASSERT(stable_ptr_table[(StgWord)sp].weight > 0);
+  r = stable_ptr_table[(StgWord)sp].addr;
+  RET_P(r);
+  FE_
+}
+
 /* -----------------------------------------------------------------------------
    Bytecode object primitives
    -------------------------------------------------------------------------  */