{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}

{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

----------------------------------------------------------------------------
--
-- Stg to C--: primitive operations
--
-- (c) The University of Glasgow 2004-2006
--
-----------------------------------------------------------------------------

module GHC.StgToCmm.Prim (
   cgOpApp,
   shouldInlinePrimOp
 ) where

import GHC.Prelude hiding ((<*>))

import GHC.Platform
import GHC.Platform.Profile

import GHC.StgToCmm.Config
import GHC.StgToCmm.Layout
import GHC.StgToCmm.Foreign
import GHC.StgToCmm.Monad
import GHC.StgToCmm.Utils
import GHC.StgToCmm.Ticky
import GHC.StgToCmm.Heap
import GHC.StgToCmm.Prof ( costCentreFrom )

import GHC.Types.Basic
import GHC.Cmm.BlockId
import GHC.Cmm.Graph
import GHC.Stg.Syntax
import GHC.Cmm
import GHC.Unit         ( rtsUnit )
import GHC.Core.Type    ( Type, tyConAppTyCon_maybe )
import GHC.Core.TyCon
import GHC.Cmm.CLabel
import GHC.Cmm.Info     ( closureInfoPtr )
import GHC.Cmm.Utils
import GHC.Builtin.PrimOps
import GHC.Runtime.Heap.Layout
import GHC.Data.FastString
import GHC.Utils.Misc
import GHC.Utils.Panic
import Data.Maybe

import Control.Monad (liftM, when, unless, zipWithM_)
import GHC.Utils.Outputable

------------------------------------------------------------------------
--      Primitive operations and foreign calls
------------------------------------------------------------------------

{- Note [Foreign call results]
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
A foreign call always returns an unboxed tuple of results, one
of which is the state token.  This seems to happen even for pure
calls.

Even if we returned a single result for pure calls, it'd still be
right to wrap it in a singleton unboxed tuple, because the result
might be a Haskell closure pointer, we don't want to evaluate it. -}

----------------------------------
cgOpApp :: StgOp        -- The op
        -> [StgArg]     -- Arguments
        -> Type         -- Result type (always an unboxed tuple)
        -> FCode ReturnKind

-- Foreign calls
cgOpApp :: StgOp -> [StgArg] -> Type -> FCode ReturnKind
cgOpApp (StgFCallOp ForeignCall
fcall Type
ty) [StgArg]
stg_args Type
res_ty
  = ForeignCall -> Type -> [StgArg] -> Type -> FCode ReturnKind
cgForeignCall ForeignCall
fcall Type
ty [StgArg]
stg_args Type
res_ty
      -- See Note [Foreign call results]

cgOpApp (StgPrimOp PrimOp
primop) [StgArg]
args Type
res_ty = do
    cfg <- FCode StgToCmmConfig
getStgToCmmConfig
    cmm_args <- getNonVoidArgAmodes args
    cmmPrimOpApp cfg primop cmm_args (Just res_ty)

cgOpApp (StgPrimCallOp PrimCall
primcall) [StgArg]
args Type
_res_ty
  = do  { cmm_args <- [StgArg] -> FCode [CmmExpr]
getNonVoidArgAmodes [StgArg]
args
        ; let fun = CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel (PrimCall -> CLabel
mkPrimCallLabel PrimCall
primcall))
        ; emitCall (NativeNodeCall, NativeReturn) fun cmm_args }

cmmPrimOpApp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> Maybe Type -> FCode ReturnKind
cmmPrimOpApp :: StgToCmmConfig
-> PrimOp -> [CmmExpr] -> Maybe Type -> FCode ReturnKind
cmmPrimOpApp StgToCmmConfig
cfg PrimOp
primop [CmmExpr]
cmm_args Maybe Type
mres_ty =
  case StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
primop [CmmExpr]
cmm_args of
    PrimopCmmEmit_Internal Type -> FCode [CmmExpr]
f ->
      let
         -- if the result type isn't explicitly given, we directly use the
         -- result type of the primop.
         res_ty :: Type
res_ty = Type -> Maybe Type -> Type
forall a. a -> Maybe a -> a
fromMaybe (PrimOp -> Type
primOpResultType PrimOp
primop) Maybe Type
mres_ty
      in [CmmExpr] -> FCode ReturnKind
emitReturn ([CmmExpr] -> FCode ReturnKind)
-> FCode [CmmExpr] -> FCode ReturnKind
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Type -> FCode [CmmExpr]
f Type
res_ty
    PrimopCmmEmit
PrimopCmmEmit_External -> do
      let fun :: CmmExpr
fun = CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel (PrimOp -> CLabel
mkRtsPrimOpLabel PrimOp
primop))
      (Convention, Convention)
-> CmmExpr -> [CmmExpr] -> FCode ReturnKind
emitCall (Convention
NativeNodeCall, Convention
NativeReturn) CmmExpr
fun [CmmExpr]
cmm_args


-- | Interpret the argument as an unsigned value, assuming the value
-- is given in two-complement form in the given width.
--
-- Example: @asUnsigned W64 (-1)@ is 18446744073709551615.
--
-- This function is used to work around the fact that many array
-- primops take Int# arguments, but we interpret them as unsigned
-- quantities in the code gen. This means that we have to be careful
-- every time we work on e.g. a CmmInt literal that corresponds to the
-- array size, as it might contain a negative Integer value if the
-- user passed a value larger than 2^(wORD_SIZE_IN_BITS-1) as the Int#
-- literal.
asUnsigned :: Width -> Integer -> Integer
asUnsigned :: Width -> Integer -> Integer
asUnsigned Width
w Integer
n = Integer
n Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.&. (Int -> Integer
forall a. (Num a, Bits a) => Int -> a
bit (Width -> Int
widthInBits Width
w) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)

------------------------------------------------------------------------
--      Emitting code for a primop
------------------------------------------------------------------------

shouldInlinePrimOp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> Bool
shouldInlinePrimOp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> Bool
shouldInlinePrimOp StgToCmmConfig
cfg PrimOp
op [CmmExpr]
args = case StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
op [CmmExpr]
args of
  PrimopCmmEmit
PrimopCmmEmit_External -> Bool
False
  PrimopCmmEmit_Internal Type -> FCode [CmmExpr]
_ -> Bool
True

-- TODO: Several primop implementations (e.g. 'doNewByteArrayOp') use
-- ByteOff (or some other fixed width signed type) to represent
-- array sizes or indices. This means that these will overflow for
-- large enough sizes.

-- TODO: Several primops, such as 'copyArray#', only have an inline
-- implementation (below) but could possibly have both an inline
-- implementation and an out-of-line implementation, just like
-- 'newArray#'. This would lower the amount of code generated,
-- hopefully without a performance impact (needs to be measured).

-- | The big function handling all the primops.
--
-- In the simple case, there is just one implementation, and we emit that.
--
-- In more complex cases, there is a foreign call (out of line) fallback. This
-- might happen e.g. if there's enough static information, such as statically
-- known arguments.
emitPrimOp
  :: StgToCmmConfig
  -> PrimOp            -- ^ The primop
  -> [CmmExpr]         -- ^ The primop arguments
  -> PrimopCmmEmit
emitPrimOp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
primop =
  let max_inl_alloc_size :: Integer
max_inl_alloc_size = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (StgToCmmConfig -> Int
stgToCmmMaxInlAllocSize StgToCmmConfig
cfg)
  in case PrimOp
primop of
  PrimOp
NewByteArrayOp_Char -> \case
    [(CmmLit (CmmInt Integer
n Width
w))]
      | Width -> Integer -> Integer
asUnsigned Width
w Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs  (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> LocalReg -> Int -> FCode ()
doNewByteArrayOp LocalReg
res (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
NewArrayOp -> \case
    [(CmmLit (CmmInt Integer
n Width
w)), CmmExpr
init]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> LocalReg
-> SMRep
-> CLabel
-> [(CmmExpr, Int)]
-> Int
-> CmmExpr
-> FCode ()
doNewArrayOp LocalReg
res (Platform -> Int -> SMRep
arrPtrsRep Platform
platform (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)) CLabel
mkMAP_DIRTY_infoLabel
        [ (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n),
           Profile -> Int
fixedHdrSize Profile
profile Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgMutArrPtrs_ptrs (Platform -> PlatformConstants
platformConstants Platform
platform))
        , (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (SMRep -> Int
nonHdrSizeW (Platform -> Int -> SMRep
arrPtrsRep Platform
platform (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n))),
           Profile -> Int
fixedHdrSize Profile
profile Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgMutArrPtrs_size (Platform -> PlatformConstants
platformConstants Platform
platform))
        ]
        (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n) CmmExpr
init
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CopyArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, CmmExpr
dst, CmmExpr
dst_off, (CmmLit (CmmInt Integer
n Width
_))] ->
      ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [] -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopyArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CopyMutableArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, CmmExpr
dst, CmmExpr
dst_off, (CmmLit (CmmInt Integer
n Width
_))] ->
      ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [] -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopyMutableArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CloneArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneArray CLabel
mkMAP_FROZEN_CLEAN_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CloneMutableArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneArray CLabel
mkMAP_DIRTY_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
FreezeArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneArray CLabel
mkMAP_FROZEN_CLEAN_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
ThawArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneArray CLabel
mkMAP_DIRTY_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
NewSmallArrayOp -> \case
    [(CmmLit (CmmInt Integer
n Width
w)), CmmExpr
init]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] ->
        LocalReg
-> SMRep
-> CLabel
-> [(CmmExpr, Int)]
-> Int
-> CmmExpr
-> FCode ()
doNewArrayOp LocalReg
res (Int -> SMRep
smallArrPtrsRep (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)) CLabel
mkSMAP_DIRTY_infoLabel
        [ (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n),
           Profile -> Int
fixedHdrSize Profile
profile Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgSmallMutArrPtrs_ptrs (Platform -> PlatformConstants
platformConstants Platform
platform))
        ]
        (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n) CmmExpr
init
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CopySmallArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, CmmExpr
dst, CmmExpr
dst_off, (CmmLit (CmmInt Integer
n Width
_))] ->
      ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [] -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopySmallArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CopySmallMutableArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, CmmExpr
dst, CmmExpr
dst_off, (CmmLit (CmmInt Integer
n Width
_))] ->
      ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [] -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopySmallMutableArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CloneSmallArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneSmallArray CLabel
mkSMAP_FROZEN_CLEAN_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
CloneSmallMutableArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneSmallArray CLabel
mkSMAP_DIRTY_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
FreezeSmallArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneSmallArray CLabel
mkSMAP_FROZEN_CLEAN_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  PrimOp
ThawSmallArrayOp -> \case
    [CmmExpr
src, CmmExpr
src_off, (CmmLit (CmmInt Integer
n Width
w))]
      | Platform -> Integer -> Integer
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform (Width -> Integer -> Integer
asUnsigned Width
w Integer
n) Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
max_inl_alloc_size
      -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneSmallArray CLabel
mkSMAP_DIRTY_infoLabel LocalReg
res CmmExpr
src CmmExpr
src_off (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
n)
    [CmmExpr]
_ -> PrimopCmmEmit
PrimopCmmEmit_External

-- First we handle various awkward cases specially.

  PrimOp
ParOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    -- for now, just implement this in a C function
    -- later, we might want to inline it.
    [(LocalReg, ForeignHint)]
-> CmmExpr -> [(CmmExpr, ForeignHint)] -> FCode ()
emitCCall
        [(LocalReg
res,ForeignHint
NoHint)]
        (CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel (FastString -> ForeignLabelSource -> FunctionOrData -> CLabel
mkForeignLabel (String -> FastString
fsLit String
"newSpark") ForeignLabelSource
ForeignLabelInExternalPackage FunctionOrData
IsFunction)))
        [(Platform -> CmmExpr
baseExpr Platform
platform, ForeignHint
AddrHint), (CmmExpr
arg,ForeignHint
AddrHint)]

  PrimOp
SparkOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    -- returns the value of arg in res.  We're going to therefore
    -- refer to arg twice (once to pass to newSpark(), and once to
    -- assign to res), so put it in a temporary.
    tmp <- CmmExpr -> FCode LocalReg
assignTemp CmmExpr
arg
    tmp2 <- newTemp (bWord platform)
    emitCCall
        [(tmp2,NoHint)]
        (CmmLit (CmmLabel (mkForeignLabel (fsLit "newSpark") ForeignLabelInExternalPackage IsFunction)))
        [(baseExpr platform, AddrHint), ((CmmReg (CmmLocal tmp)), AddrHint)]
    emitAssign (CmmLocal res) (CmmReg (CmmLocal tmp))

  PrimOp
GetCCSOfOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    let
      val :: CmmExpr
val
       | Profile -> Bool
profileIsProfiling Profile
profile = Platform -> CmmExpr -> CmmExpr
costCentreFrom Platform
platform (Platform -> CmmExpr -> CmmExpr
cmmUntag Platform
platform CmmExpr
arg)
       | Bool
otherwise                  = CmmLit -> CmmExpr
CmmLit (Platform -> CmmLit
zeroCLit Platform
platform)
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
val

  PrimOp
GetCurrentCCSOp -> \[CmmExpr
_] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> CmmExpr
cccsExpr Platform
platform)

  PrimOp
MyThreadIdOp -> \[] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> CmmExpr
currentTSOExpr Platform
platform)

  PrimOp
ReadMutVarOp -> \[CmmExpr
mutv] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> MemoryOrdering -> CallishMachOp
MO_AtomicRead (Platform -> Width
wordWidth Platform
platform) MemoryOrdering
MemOrderAcquire)
        [ Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetW Platform
platform CmmExpr
mutv (Profile -> Int
fixedHdrSizeW Profile
profile) ]

  PrimOp
WriteMutVarOp -> \[CmmExpr
mutv, CmmExpr
var] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] -> do
    old_val <- LocalReg -> CmmReg
CmmLocal (LocalReg -> CmmReg) -> FCode LocalReg -> FCode CmmReg
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CmmType -> FCode LocalReg
forall (m :: * -> *). MonadGetUnique m => CmmType -> m LocalReg
newTemp (Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
var)
    emitAssign old_val (cmmLoadIndexW platform mutv (fixedHdrSizeW profile) (gcWord platform))

    -- Without this write barrier, other CPUs may see this pointer before
    -- the writes for the closure it points to have occurred.
    -- Note that this also must come after we read the old value to ensure
    -- that the read of old_val comes before another core's write to the
    -- MutVar's value.
    emitPrimCall [] (MO_AtomicWrite (wordWidth platform) MemOrderRelease)
        [ cmmOffsetW platform mutv (fixedHdrSizeW profile), var ]
    emitDirtyMutVar mutv (CmmReg old_val)

  PrimOp
AtomicSwapMutVarOp -> \[CmmExpr
mutv, CmmExpr
val] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    let dst :: CmmExpr
dst = Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetW Platform
platform CmmExpr
mutv (Profile -> Int
fixedHdrSizeW Profile
profile)
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Xchg (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
dst, CmmExpr
val]
    CmmExpr -> CmmExpr -> FCode ()
emitDirtyMutVar CmmExpr
mutv (CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
res))

--  #define sizzeofByteArrayzh(r,a) \
--     r = ((StgArrBytes *)(a))->bytes
  PrimOp
SizeofByteArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> Profile -> CmmExpr -> CmmExpr
byteArraySize Platform
platform Profile
profile CmmExpr
arg)

--  #define sizzeofMutableByteArrayzh(r,a) \
--      r = ((StgArrBytes *)(a))->bytes
  PrimOp
SizeofMutableByteArrayOp -> StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
SizeofByteArrayOp

--  #define getSizzeofMutableByteArrayzh(r,a) \
--      r = ((StgArrBytes *)(a))->bytes
  PrimOp
GetSizeofMutableByteArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> Profile -> CmmExpr -> CmmExpr
byteArraySize Platform
platform Profile
profile CmmExpr
arg)


--  #define touchzh(o)                  /* nothing */
  PrimOp
TouchOp -> \args :: [CmmExpr]
args@[CmmExpr
_] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \res :: [LocalReg]
res@[] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg]
res CallishMachOp
MO_Touch [CmmExpr]
args

--  #define byteArrayContentszh(r,a) r = BYTE_ARR_CTS(a)
  PrimOp
ByteArrayContents_Char -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
arg (Profile -> Int
arrWordsHdrSize Profile
profile))

--  #define mutableByteArrayContentszh(r,a) r = BYTE_ARR_CTS(a)
  PrimOp
MutableByteArrayContents_Char -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
arg (Profile -> Int
arrWordsHdrSize Profile
profile))

--  #define stableNameToIntzh(r,s)   (r = ((StgStableName *)s)->sn)
  PrimOp
StableNameToIntOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> CmmExpr -> Int -> CmmType -> CmmExpr
cmmLoadIndexW Platform
platform CmmExpr
arg (Profile -> Int
fixedHdrSizeW Profile
profile) (Platform -> CmmType
bWord Platform
platform))

  PrimOp
EqStablePtrOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordEq Platform
platform)

  PrimOp
ReallyUnsafePtrEqualityOp -> \[CmmExpr
arg1, CmmExpr
arg2] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Platform -> MachOp
mo_wordEq Platform
platform) [CmmExpr
arg1,CmmExpr
arg2])

--  #define addrToHValuezh(r,a) r=(P_)a
  PrimOp
AddrToAnyOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg

--  #define hvalueToAddrzh(r, a) r=(W_)a
  PrimOp
AnyToAddrOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg

{- 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_DIRTY_info);
--        r = a;
--      }
  PrimOp
UnsafeFreezeArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ [CmmAGraph] -> CmmAGraph
catAGraphs
      [ CmmExpr -> CmmExpr -> CmmAGraph
setInfo CmmExpr
arg (CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel CLabel
mkMAP_FROZEN_DIRTY_infoLabel)),
        CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg ]
  PrimOp
UnsafeFreezeSmallArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ [CmmAGraph] -> CmmAGraph
catAGraphs
      [ CmmExpr -> CmmExpr -> CmmAGraph
setInfo CmmExpr
arg (CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel CLabel
mkSMAP_FROZEN_DIRTY_infoLabel)),
        CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg ]

--  #define unsafeFreezzeByteArrayzh(r,a)       r=(a)
  PrimOp
UnsafeFreezeByteArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg

--  #define unsafeThawByteArrayzh(r,a)       r=(a)
  PrimOp
UnsafeThawByteArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg

-- Reading/writing pointer arrays

  PrimOp
ReadArrayOp -> \[CmmExpr
obj, CmmExpr
ix] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadPtrArrayOp LocalReg
res CmmExpr
obj CmmExpr
ix
  PrimOp
IndexArrayOp -> \[CmmExpr
obj, CmmExpr
ix] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadPtrArrayOp LocalReg
res CmmExpr
obj CmmExpr
ix
  PrimOp
WriteArrayOp -> \[CmmExpr
obj, CmmExpr
ix, CmmExpr
v] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doWritePtrArrayOp CmmExpr
obj CmmExpr
ix CmmExpr
v

  PrimOp
ReadSmallArrayOp -> \[CmmExpr
obj, CmmExpr
ix] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadSmallPtrArrayOp LocalReg
res CmmExpr
obj CmmExpr
ix
  PrimOp
IndexSmallArrayOp -> \[CmmExpr
obj, CmmExpr
ix] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadSmallPtrArrayOp LocalReg
res CmmExpr
obj CmmExpr
ix
  PrimOp
WriteSmallArrayOp -> \[CmmExpr
obj,CmmExpr
ix,CmmExpr
v] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doWriteSmallPtrArrayOp CmmExpr
obj CmmExpr
ix CmmExpr
v

-- Getting the size of pointer arrays

  PrimOp
SizeofArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> Profile -> CmmExpr -> CmmExpr
ptrArraySize Platform
platform Profile
profile CmmExpr
arg)
  PrimOp
SizeofMutableArrayOp      -> StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
SizeofArrayOp
  PrimOp
SizeofSmallArrayOp -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (Platform -> Profile -> CmmExpr -> CmmExpr
smallPtrArraySize Platform
platform Profile
profile CmmExpr
arg)

  PrimOp
SizeofSmallMutableArrayOp    -> StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
SizeofSmallArrayOp
  PrimOp
GetSizeofSmallMutableArrayOp -> StgToCmmConfig -> PrimOp -> [CmmExpr] -> PrimopCmmEmit
emitPrimOp StgToCmmConfig
cfg PrimOp
SizeofSmallArrayOp

-- IndexXXXoffAddr

  PrimOp
IndexOffAddrOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args

-- ReadXXXoffAddr, which are identical, for our purposes, to IndexXXXoffAddr.

  PrimOp
ReadOffAddrOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args

-- IndexWord8OffAddrAsXXX

  PrimOp
IndexOffAddrOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexOffAddrOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- ReadWord8OffAddrAsXXX, identical to IndexWord8OffAddrAsXXX

  PrimOp
ReadOffAddrOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadOffAddrOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- WriteWord8ArrayAsXXX
  PrimOp
WriteOffAddrOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo8 Platform
platform))  CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo32 Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- IndexXXXArray

  PrimOp
IndexByteArrayOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32  [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64  [LocalReg]
res [CmmExpr]
args

-- ReadXXXArray, identical to IndexXXXArray.

  PrimOp
ReadByteArrayOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32  [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64  [LocalReg]
res [CmmExpr]
args

-- IndexWord8ArrayAsXXX

  PrimOp
IndexByteArrayOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
IndexByteArrayOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- ReadInt8ArrayAsXXX, identical to IndexInt8ArrayAsXXX

  PrimOp
ReadByteArrayOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_8ToWord Platform
platform)) CmmType
b8 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_u_32ToWord Platform
platform)) CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
ReadByteArrayOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs   Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- WriteXXXoffAddr

  PrimOp
WriteOffAddrOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo8 Platform
platform))  CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo32 Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteOffAddrOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args

-- WriteXXXArray

  PrimOp
WriteByteArrayOp_Char -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo8 Platform
platform))  CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_WideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo32 Platform
platform)) CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Int -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Addr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Float -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
f32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Double -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
f64 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_StablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing (Platform -> CmmType
bWord Platform
platform) [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Int8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Int16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Int32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Int64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8  [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b16 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b32 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b64 [LocalReg]
res [CmmExpr]
args

-- WriteInt8ArrayAsXXX

  PrimOp
WriteByteArrayOp_Word8AsChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo8 Platform
platform))  CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsWideChar -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp (MachOp -> Maybe MachOp
forall a. a -> Maybe a
Just (Platform -> MachOp
mo_WordTo32 Platform
platform)) CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsInt -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsWord -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsAddr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsFloat -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsDouble -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsStablePtr -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsInt16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsInt32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsInt64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsWord16 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsWord32 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args
  PrimOp
WriteByteArrayOp_Word8AsWord64 -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res ->
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
b8 [LocalReg]
res [CmmExpr]
args

-- Copying and setting byte arrays
  PrimOp
CopyByteArrayOp -> \[CmmExpr
src,CmmExpr
src_off,CmmExpr
dst,CmmExpr
dst_off,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off CmmExpr
n
  PrimOp
CopyMutableByteArrayOp -> \[CmmExpr
src,CmmExpr
src_off,CmmExpr
dst,CmmExpr
dst_off,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off CmmExpr
n
  PrimOp
CopyMutableByteArrayNonOverlappingOp -> \[CmmExpr
src,CmmExpr
src_off,CmmExpr
dst,CmmExpr
dst_off,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayNonOverlappingOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off CmmExpr
n
  PrimOp
CopyByteArrayToAddrOp -> \[CmmExpr
src,CmmExpr
src_off,CmmExpr
dst,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayToAddrOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
n
  PrimOp
CopyMutableByteArrayToAddrOp -> \[CmmExpr
src,CmmExpr
src_off,CmmExpr
dst,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayToAddrOp CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
n
  PrimOp
CopyAddrToByteArrayOp -> \[CmmExpr
src,CmmExpr
dst,CmmExpr
dst_off,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToByteArrayOp CmmExpr
src CmmExpr
dst CmmExpr
dst_off CmmExpr
n
  PrimOp
CopyAddrToAddrOp -> \[CmmExpr
src,CmmExpr
dst,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrOp CmmExpr
src CmmExpr
dst CmmExpr
n
  PrimOp
CopyAddrToAddrNonOverlappingOp -> \[CmmExpr
src,CmmExpr
dst,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrNonOverlappingOp CmmExpr
src CmmExpr
dst CmmExpr
n
  PrimOp
SetByteArrayOp -> \[CmmExpr
ba,CmmExpr
off,CmmExpr
len,CmmExpr
c] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doSetByteArrayOp CmmExpr
ba CmmExpr
off CmmExpr
len CmmExpr
c
  PrimOp
SetAddrRangeOp -> \[CmmExpr
dst,CmmExpr
len,CmmExpr
c] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doSetAddrRangeOp CmmExpr
dst CmmExpr
len CmmExpr
c

-- Comparing byte arrays
  PrimOp
CompareByteArraysOp -> \[CmmExpr
ba1,CmmExpr
ba1_off,CmmExpr
ba2,CmmExpr
ba2_off,CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCompareByteArraysOp LocalReg
res CmmExpr
ba1 CmmExpr
ba1_off CmmExpr
ba2 CmmExpr
ba2_off CmmExpr
n

  PrimOp
BSwap16Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall LocalReg
res CmmExpr
w Width
W16
  PrimOp
BSwap32Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall LocalReg
res CmmExpr
w Width
W32
  PrimOp
BSwap64Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall LocalReg
res CmmExpr
w Width
W64
  PrimOp
BSwapOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall LocalReg
res CmmExpr
w (Platform -> Width
wordWidth Platform
platform)

  PrimOp
BRev8Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
w Width
W8
  PrimOp
BRev16Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
w Width
W16
  PrimOp
BRev32Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
w Width
W32
  PrimOp
BRev64Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
w Width
W64
  PrimOp
BRevOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
w (Platform -> Width
wordWidth Platform
platform)

-- Population count
  PrimOp
PopCnt8Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
w Width
W8
  PrimOp
PopCnt16Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
w Width
W16
  PrimOp
PopCnt32Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
w Width
W32
  PrimOp
PopCnt64Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
w Width
W64
  PrimOp
PopCntOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
w (Platform -> Width
wordWidth Platform
platform)

-- Parallel bit deposit
  PrimOp
Pdep8Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W8
  PrimOp
Pdep16Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W16
  PrimOp
Pdep32Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W32
  PrimOp
Pdep64Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W64
  PrimOp
PdepOp -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
src CmmExpr
mask (Platform -> Width
wordWidth Platform
platform)

-- Parallel bit extract
  PrimOp
Pext8Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W8
  PrimOp
Pext16Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W16
  PrimOp
Pext32Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W32
  PrimOp
Pext64Op -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
src CmmExpr
mask Width
W64
  PrimOp
PextOp -> \[CmmExpr
src, CmmExpr
mask] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
src CmmExpr
mask (Platform -> Width
wordWidth Platform
platform)

-- count leading zeros
  PrimOp
Clz8Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
w Width
W8
  PrimOp
Clz16Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
w Width
W16
  PrimOp
Clz32Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
w Width
W32
  PrimOp
Clz64Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
w Width
W64
  PrimOp
ClzOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
w (Platform -> Width
wordWidth Platform
platform)

-- count trailing zeros
  PrimOp
Ctz8Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
w Width
W8
  PrimOp
Ctz16Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
w Width
W16
  PrimOp
Ctz32Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
w Width
W32
  PrimOp
Ctz64Op -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
w Width
W64
  PrimOp
CtzOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
w (Platform -> Width
wordWidth Platform
platform)

-- Unsigned int to floating point conversions
  PrimOp
WordToFloatOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_UF_Conv Width
W32) [CmmExpr
w]
  PrimOp
WordToDoubleOp -> \[CmmExpr
w] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_UF_Conv Width
W64) [CmmExpr
w]

-- Atomic operations
  PrimOp
InterlockedExchange_Addr -> \[CmmExpr
src, CmmExpr
value] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Xchg (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
src, CmmExpr
value]
  PrimOp
InterlockedExchange_Word -> \[CmmExpr
src, CmmExpr
value] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Xchg (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
src, CmmExpr
value]

  PrimOp
FetchAddAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_Add CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchSubAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_Sub CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchAndAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_And CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchNandAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_Nand CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchOrAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_Or CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchXorAddrOp_Word -> \[CmmExpr
addr, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
AMO_Xor CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
n

  PrimOp
AtomicReadAddrOp_Word -> \[CmmExpr
addr] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmType -> FCode ()
doAtomicReadAddr LocalReg
res CmmExpr
addr (Platform -> CmmType
bWord Platform
platform)
  PrimOp
AtomicWriteAddrOp_Word -> \[CmmExpr
addr, CmmExpr
val] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicWriteAddr CmmExpr
addr (Platform -> CmmType
bWord Platform
platform) CmmExpr
val

  PrimOp
CasAddrOp_Addr -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]
  PrimOp
CasAddrOp_Word -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]
  PrimOp
CasAddrOp_Word8 -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg Width
W8) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]
  PrimOp
CasAddrOp_Word16 -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg Width
W16) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]
  PrimOp
CasAddrOp_Word32 -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg Width
W32) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]
  PrimOp
CasAddrOp_Word64 -> \[CmmExpr
dst, CmmExpr
expected, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] (Width -> CallishMachOp
MO_Cmpxchg Width
W64) [CmmExpr
dst, CmmExpr
expected, CmmExpr
new]

-- SIMD primops
  (VecBroadcastOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr
e] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    CmmType -> CmmExpr -> LocalReg -> FCode ()
doVecBroadcastOp CmmType
ty CmmExpr
e LocalReg
res
   where

    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecPackOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
es -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([CmmExpr]
es [CmmExpr] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIsNot` Int
n) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$
        String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"emitPrimOp: VecPackOp has wrong number of arguments"
    CmmType -> [CmmExpr] -> LocalReg -> FCode ()
doVecPackOp CmmType
ty [CmmExpr]
es LocalReg
res
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecUnpackOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr
arg] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([LocalReg]
res [LocalReg] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIsNot` Int
n) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$
        String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"emitPrimOp: VecUnpackOp has wrong number of results"
    CmmType -> CmmExpr -> [LocalReg] -> FCode ()
doVecUnpackOp CmmType
ty CmmExpr
arg [LocalReg]
res
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecInsertOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr
v,CmmExpr
e,CmmExpr
i] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    CmmType -> CmmExpr -> CmmExpr -> CmmExpr -> LocalReg -> FCode ()
doVecInsertOp CmmType
ty CmmExpr
v CmmExpr
e CmmExpr
i LocalReg
res
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecIndexByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecReadByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecWriteByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecIndexOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecReadOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecWriteOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

  (VecIndexScalarByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs Maybe MachOp
forall a. Maybe a
Nothing CmmType
vecty CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    vecty :: CmmType
    vecty :: CmmType
vecty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  (VecReadScalarByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs Maybe MachOp
forall a. Maybe a
Nothing CmmType
vecty CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    vecty :: CmmType
    vecty :: CmmType
vecty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  (VecWriteScalarByteArrayOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  (VecIndexScalarOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs Maybe MachOp
forall a. Maybe a
Nothing CmmType
vecty CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    vecty :: CmmType
    vecty :: CmmType
vecty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  (VecReadScalarOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs Maybe MachOp
forall a. Maybe a
Nothing CmmType
vecty CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    vecty :: CmmType
    vecty :: CmmType
vecty = PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w

    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  (VecWriteScalarOffAddrOp PrimOpVecCat
vcat Int
n Width
w) -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
forall a. Maybe a
Nothing CmmType
ty [LocalReg]
res0 [CmmExpr]
args
   where
    ty :: CmmType
    ty :: CmmType
ty = PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
vcat Width
w

  VecShuffleOp PrimOpVecCat
vcat Int
n Width
w -> \ [CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> do
    StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
n Width
w
    CmmType -> [CmmExpr] -> LocalReg -> FCode ()
doShuffleOp (PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
n Width
w) [CmmExpr]
args LocalReg
res

-- Prefetch
  PrimOp
PrefetchByteArrayOp3         -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchByteArrayOp Int
3  [CmmExpr]
args
  PrimOp
PrefetchMutableByteArrayOp3  -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchMutableByteArrayOp Int
3  [CmmExpr]
args
  PrimOp
PrefetchAddrOp3              -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchAddrOp  Int
3  [CmmExpr]
args
  PrimOp
PrefetchValueOp3             -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchValueOp Int
3 [CmmExpr]
args

  PrimOp
PrefetchByteArrayOp2         -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchByteArrayOp Int
2  [CmmExpr]
args
  PrimOp
PrefetchMutableByteArrayOp2  -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchMutableByteArrayOp Int
2  [CmmExpr]
args
  PrimOp
PrefetchAddrOp2              -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchAddrOp Int
2  [CmmExpr]
args
  PrimOp
PrefetchValueOp2             -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchValueOp Int
2 [CmmExpr]
args
  PrimOp
PrefetchByteArrayOp1         -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchByteArrayOp Int
1  [CmmExpr]
args
  PrimOp
PrefetchMutableByteArrayOp1  -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchMutableByteArrayOp Int
1  [CmmExpr]
args
  PrimOp
PrefetchAddrOp1              -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchAddrOp Int
1  [CmmExpr]
args
  PrimOp
PrefetchValueOp1             -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchValueOp Int
1 [CmmExpr]
args

  PrimOp
PrefetchByteArrayOp0         -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchByteArrayOp Int
0  [CmmExpr]
args
  PrimOp
PrefetchMutableByteArrayOp0  -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchMutableByteArrayOp Int
0  [CmmExpr]
args
  PrimOp
PrefetchAddrOp0              -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchAddrOp Int
0  [CmmExpr]
args
  PrimOp
PrefetchValueOp0             -> \[CmmExpr]
args -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    Int -> [CmmExpr] -> FCode ()
doPrefetchValueOp Int
0 [CmmExpr]
args

-- Atomic read-modify-write
  PrimOp
FetchAddByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_Add CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchSubByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_Sub CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchAndByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_And CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchNandByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_Nand CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchOrByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_Or CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
FetchXorByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
n] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
AMO_Xor CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
n
  PrimOp
AtomicReadByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg -> CmmExpr -> CmmExpr -> CmmType -> FCode ()
doAtomicReadByteArray LocalReg
res CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform)
  PrimOp
AtomicWriteByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
val] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[] ->
    CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicWriteByteArray CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
val
  PrimOp
CasByteArrayOp_Int -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
old, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
ix (Platform -> CmmType
bWord Platform
platform) CmmExpr
old CmmExpr
new
  PrimOp
CasByteArrayOp_Int8 -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
old, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
ix CmmType
b8 CmmExpr
old CmmExpr
new
  PrimOp
CasByteArrayOp_Int16 -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
old, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
ix CmmType
b16 CmmExpr
old CmmExpr
new
  PrimOp
CasByteArrayOp_Int32 -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
old, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
ix CmmType
b32 CmmExpr
old CmmExpr
new
  PrimOp
CasByteArrayOp_Int64 -> \[CmmExpr
mba, CmmExpr
ix, CmmExpr
old, CmmExpr
new] -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] ->
    LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
ix CmmType
b64 CmmExpr
old CmmExpr
new

-- The rest just translate straightforwardly

  PrimOp
Int8ToWord8Op   -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Word8ToInt8Op   -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Int16ToWord16Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Word16ToInt16Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Int32ToWord32Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Word32ToInt32Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Int64ToWord64Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
Word64ToInt64Op -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
IntToWordOp     -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
WordToIntOp     -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
IntToAddrOp     -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
AddrToIntOp     -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args
  PrimOp
ChrOp           -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args  -- Int# and Char# are rep'd the same
  PrimOp
OrdOp           -> \[CmmExpr]
args -> [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args

  PrimOp
Narrow8IntOp   -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_SS_Conv, Width
W8)
  PrimOp
Narrow16IntOp  -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_SS_Conv, Width
W16)
  PrimOp
Narrow32IntOp  -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_SS_Conv, Width
W32)
  PrimOp
Narrow8WordOp  -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_UU_Conv, Width
W8)
  PrimOp
Narrow16WordOp -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_UU_Conv, Width
W16)
  PrimOp
Narrow32WordOp -> \[CmmExpr]
args -> [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
MO_UU_Conv, Width
W32)

  PrimOp
DoublePowerOp  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Pwr
  PrimOp
DoubleSinOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Sin
  PrimOp
DoubleCosOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Cos
  PrimOp
DoubleTanOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Tan
  PrimOp
DoubleSinhOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Sinh
  PrimOp
DoubleCoshOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Cosh
  PrimOp
DoubleTanhOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Tanh
  PrimOp
DoubleAsinOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Asin
  PrimOp
DoubleAcosOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Acos
  PrimOp
DoubleAtanOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Atan
  PrimOp
DoubleAsinhOp  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Asinh
  PrimOp
DoubleAcoshOp  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Acosh
  PrimOp
DoubleAtanhOp  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Atanh
  PrimOp
DoubleLogOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Log
  PrimOp
DoubleLog1POp  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Log1P
  PrimOp
DoubleExpOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Exp
  PrimOp
DoubleExpM1Op  -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_ExpM1
  PrimOp
DoubleSqrtOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Sqrt
  PrimOp
DoubleFabsOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F64_Fabs

  PrimOp
FloatPowerOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Pwr
  PrimOp
FloatSinOp     -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Sin
  PrimOp
FloatCosOp     -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Cos
  PrimOp
FloatTanOp     -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Tan
  PrimOp
FloatSinhOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Sinh
  PrimOp
FloatCoshOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Cosh
  PrimOp
FloatTanhOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Tanh
  PrimOp
FloatAsinOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Asin
  PrimOp
FloatAcosOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Acos
  PrimOp
FloatAtanOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Atan
  PrimOp
FloatAsinhOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Asinh
  PrimOp
FloatAcoshOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Acosh
  PrimOp
FloatAtanhOp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Atanh
  PrimOp
FloatLogOp     -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Log
  PrimOp
FloatLog1POp   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Log1P
  PrimOp
FloatExpOp     -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Exp
  PrimOp
FloatExpM1Op   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_ExpM1
  PrimOp
FloatSqrtOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Sqrt
  PrimOp
FloatFabsOp    -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_F32_Fabs

-- Native word signless ops

  PrimOp
IntAddOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordAdd Platform
platform)
  PrimOp
IntSubOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSub Platform
platform)
  PrimOp
WordAddOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordAdd Platform
platform)
  PrimOp
WordSubOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSub Platform
platform)
  PrimOp
AddrAddOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordAdd Platform
platform)
  PrimOp
AddrSubOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSub Platform
platform)

  PrimOp
IntEqOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordEq Platform
platform)
  PrimOp
IntNeOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordNe Platform
platform)
  PrimOp
WordEqOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordEq Platform
platform)
  PrimOp
WordNeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordNe Platform
platform)
  PrimOp
AddrEqOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordEq Platform
platform)
  PrimOp
AddrNeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordNe Platform
platform)

  PrimOp
WordAndOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordAnd Platform
platform)
  PrimOp
WordOrOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordOr Platform
platform)
  PrimOp
WordXorOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordXor Platform
platform)
  PrimOp
WordNotOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordNot Platform
platform)
  PrimOp
WordSllOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordShl Platform
platform)
  PrimOp
WordSrlOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUShr Platform
platform)

  PrimOp
AddrRemOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordURem Platform
platform)

-- Native word signed ops

  PrimOp
IntMulOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordMul Platform
platform)
  PrimOp
IntMulMayOfloOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_MulMayOflo (Platform -> Width
wordWidth Platform
platform))
  PrimOp
IntQuotOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSQuot Platform
platform)
  PrimOp
IntRemOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSRem Platform
platform)
  PrimOp
IntNegOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSNeg Platform
platform)

  PrimOp
IntGeOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSGe Platform
platform)
  PrimOp
IntLeOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSLe Platform
platform)
  PrimOp
IntGtOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSGt Platform
platform)
  PrimOp
IntLtOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSLt Platform
platform)

  PrimOp
IntAndOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordAnd Platform
platform)
  PrimOp
IntOrOp        -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordOr Platform
platform)
  PrimOp
IntXorOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordXor Platform
platform)
  PrimOp
IntNotOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordNot Platform
platform)
  PrimOp
IntSllOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordShl Platform
platform)
  PrimOp
IntSraOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordSShr Platform
platform)
  PrimOp
IntSrlOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUShr Platform
platform)

-- Native word unsigned ops

  PrimOp
WordGeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUGe Platform
platform)
  PrimOp
WordLeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordULe Platform
platform)
  PrimOp
WordGtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUGt Platform
platform)
  PrimOp
WordLtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordULt Platform
platform)

  PrimOp
WordMulOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordMul Platform
platform)
  PrimOp
WordQuotOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUQuot Platform
platform)
  PrimOp
WordRemOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordURem Platform
platform)

  PrimOp
AddrGeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUGe Platform
platform)
  PrimOp
AddrLeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordULe Platform
platform)
  PrimOp
AddrGtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordUGt Platform
platform)
  PrimOp
AddrLtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Platform -> MachOp
mo_wordULt Platform
platform)

-- Int8# signed ops

  PrimOp
Int8ToIntOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv Width
W8 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
IntToInt8Op    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv (Platform -> Width
wordWidth Platform
platform) Width
W8)
  PrimOp
Int8NegOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Neg Width
W8)
  PrimOp
Int8AddOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W8)
  PrimOp
Int8SubOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W8)
  PrimOp
Int8MulOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W8)
  PrimOp
Int8QuotOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Quot Width
W8)
  PrimOp
Int8RemOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Rem Width
W8)

  PrimOp
Int8SllOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W8)
  PrimOp
Int8SraOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Shr Width
W8)
  PrimOp
Int8SrlOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W8)

  PrimOp
Int8EqOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W8)
  PrimOp
Int8GeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Ge Width
W8)
  PrimOp
Int8GtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Gt Width
W8)
  PrimOp
Int8LeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Le Width
W8)
  PrimOp
Int8LtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Lt Width
W8)
  PrimOp
Int8NeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W8)

-- Word8# unsigned ops

  PrimOp
Word8ToWordOp  -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv Width
W8 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
WordToWord8Op  -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv (Platform -> Width
wordWidth Platform
platform) Width
W8)
  PrimOp
Word8AddOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W8)
  PrimOp
Word8SubOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W8)
  PrimOp
Word8MulOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W8)
  PrimOp
Word8QuotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Quot Width
W8)
  PrimOp
Word8RemOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Rem Width
W8)

  PrimOp
Word8AndOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_And Width
W8)
  PrimOp
Word8OrOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Or Width
W8)
  PrimOp
Word8XorOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Xor Width
W8)
  PrimOp
Word8NotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Not Width
W8)
  PrimOp
Word8SllOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W8)
  PrimOp
Word8SrlOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W8)

  PrimOp
Word8EqOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W8)
  PrimOp
Word8GeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Ge Width
W8)
  PrimOp
Word8GtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Gt Width
W8)
  PrimOp
Word8LeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Le Width
W8)
  PrimOp
Word8LtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Lt Width
W8)
  PrimOp
Word8NeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W8)

-- Int16# signed ops

  PrimOp
Int16ToIntOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv Width
W16 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
IntToInt16Op   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv (Platform -> Width
wordWidth Platform
platform) Width
W16)
  PrimOp
Int16NegOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Neg Width
W16)
  PrimOp
Int16AddOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W16)
  PrimOp
Int16SubOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W16)
  PrimOp
Int16MulOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W16)
  PrimOp
Int16QuotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Quot Width
W16)
  PrimOp
Int16RemOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Rem Width
W16)

  PrimOp
Int16SllOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W16)
  PrimOp
Int16SraOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Shr Width
W16)
  PrimOp
Int16SrlOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W16)

  PrimOp
Int16EqOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W16)
  PrimOp
Int16GeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Ge Width
W16)
  PrimOp
Int16GtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Gt Width
W16)
  PrimOp
Int16LeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Le Width
W16)
  PrimOp
Int16LtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Lt Width
W16)
  PrimOp
Int16NeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W16)

-- Word16# unsigned ops

  PrimOp
Word16ToWordOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv Width
W16 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
WordToWord16Op -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv (Platform -> Width
wordWidth Platform
platform) Width
W16)
  PrimOp
Word16AddOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W16)
  PrimOp
Word16SubOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W16)
  PrimOp
Word16MulOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W16)
  PrimOp
Word16QuotOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Quot Width
W16)
  PrimOp
Word16RemOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Rem Width
W16)

  PrimOp
Word16AndOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_And Width
W16)
  PrimOp
Word16OrOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Or Width
W16)
  PrimOp
Word16XorOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Xor Width
W16)
  PrimOp
Word16NotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Not Width
W16)
  PrimOp
Word16SllOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W16)
  PrimOp
Word16SrlOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W16)

  PrimOp
Word16EqOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W16)
  PrimOp
Word16GeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Ge Width
W16)
  PrimOp
Word16GtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Gt Width
W16)
  PrimOp
Word16LeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Le Width
W16)
  PrimOp
Word16LtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Lt Width
W16)
  PrimOp
Word16NeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W16)

-- Int32# signed ops

  PrimOp
Int32ToIntOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv Width
W32 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
IntToInt32Op   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SS_Conv (Platform -> Width
wordWidth Platform
platform) Width
W32)
  PrimOp
Int32NegOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Neg Width
W32)
  PrimOp
Int32AddOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W32)
  PrimOp
Int32SubOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W32)
  PrimOp
Int32MulOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W32)
  PrimOp
Int32QuotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Quot Width
W32)
  PrimOp
Int32RemOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Rem Width
W32)

  PrimOp
Int32SllOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W32)
  PrimOp
Int32SraOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Shr Width
W32)
  PrimOp
Int32SrlOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W32)

  PrimOp
Int32EqOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W32)
  PrimOp
Int32GeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Ge Width
W32)
  PrimOp
Int32GtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Gt Width
W32)
  PrimOp
Int32LeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Le Width
W32)
  PrimOp
Int32LtOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Lt Width
W32)
  PrimOp
Int32NeOp      -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W32)

-- Word32# unsigned ops

  PrimOp
Word32ToWordOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv Width
W32 (Platform -> Width
wordWidth Platform
platform))
  PrimOp
WordToWord32Op -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_UU_Conv (Platform -> Width
wordWidth Platform
platform) Width
W32)
  PrimOp
Word32AddOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Add Width
W32)
  PrimOp
Word32SubOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Sub Width
W32)
  PrimOp
Word32MulOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Mul Width
W32)
  PrimOp
Word32QuotOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Quot Width
W32)
  PrimOp
Word32RemOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Rem Width
W32)

  PrimOp
Word32AndOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_And Width
W32)
  PrimOp
Word32OrOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Or Width
W32)
  PrimOp
Word32XorOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Xor Width
W32)
  PrimOp
Word32NotOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Not Width
W32)
  PrimOp
Word32SllOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Shl Width
W32)
  PrimOp
Word32SrlOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Shr Width
W32)

  PrimOp
Word32EqOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq Width
W32)
  PrimOp
Word32GeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Ge Width
W32)
  PrimOp
Word32GtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Gt Width
W32)
  PrimOp
Word32LeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Le Width
W32)
  PrimOp
Word32LtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Lt Width
W32)
  PrimOp
Word32NeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne Width
W32)

-- Int64# signed ops

  PrimOp
Int64ToIntOp   -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> Width -> MachOp
MO_SS_Conv Width
W64 (Platform -> Width
wordWidth Platform
platform)) CallishMachOp
MO_I64_ToI
  PrimOp
IntToInt64Op   -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> Width -> MachOp
MO_SS_Conv (Platform -> Width
wordWidth Platform
platform) Width
W64) CallishMachOp
MO_I64_FromI
  PrimOp
Int64NegOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Neg  Width
W64) CallishMachOp
MO_x64_Neg
  PrimOp
Int64AddOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Add    Width
W64) CallishMachOp
MO_x64_Add
  PrimOp
Int64SubOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Sub    Width
W64) CallishMachOp
MO_x64_Sub
  PrimOp
Int64MulOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Mul    Width
W64) CallishMachOp
MO_x64_Mul
  PrimOp
Int64QuotOp
    | Bool
allowQuot64 -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Quot Width
W64)
    | Bool
otherwise   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_I64_Quot
  PrimOp
Int64RemOp
    | Bool
allowQuot64 -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_S_Rem Width
W64)
    | Bool
otherwise   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
MO_I64_Rem

  PrimOp
Int64SllOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Shl   Width
W64) CallishMachOp
MO_x64_Shl
  PrimOp
Int64SraOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Shr Width
W64) CallishMachOp
MO_I64_Shr
  PrimOp
Int64SrlOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Shr Width
W64) CallishMachOp
MO_W64_Shr

  PrimOp
Int64EqOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Eq   Width
W64)  CallishMachOp
MO_x64_Eq
  PrimOp
Int64GeOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Ge Width
W64)  CallishMachOp
MO_I64_Ge
  PrimOp
Int64GtOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Gt Width
W64)  CallishMachOp
MO_I64_Gt
  PrimOp
Int64LeOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Le Width
W64)  CallishMachOp
MO_I64_Le
  PrimOp
Int64LtOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_S_Lt Width
W64)  CallishMachOp
MO_I64_Lt
  PrimOp
Int64NeOp      -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Ne   Width
W64)  CallishMachOp
MO_x64_Ne

-- Word64# unsigned ops

  PrimOp
Word64ToWordOp -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> Width -> MachOp
MO_UU_Conv Width
W64 (Platform -> Width
wordWidth Platform
platform)) CallishMachOp
MO_W64_ToW
  PrimOp
WordToWord64Op -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> Width -> MachOp
MO_UU_Conv (Platform -> Width
wordWidth Platform
platform) Width
W64) CallishMachOp
MO_W64_FromW
  PrimOp
Word64AddOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Add    Width
W64) CallishMachOp
MO_x64_Add
  PrimOp
Word64SubOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Sub    Width
W64) CallishMachOp
MO_x64_Sub
  PrimOp
Word64MulOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Mul    Width
W64) CallishMachOp
MO_x64_Mul
  PrimOp
Word64QuotOp
    | Bool
allowQuot64 -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Quot Width
W64)
    | Bool
otherwise   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish   CallishMachOp
MO_W64_Quot
  PrimOp
Word64RemOp
    | Bool
allowQuot64 -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Rem Width
W64)
    | Bool
otherwise   -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish   CallishMachOp
MO_W64_Rem

  PrimOp
Word64AndOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_And   Width
W64) CallishMachOp
MO_x64_And
  PrimOp
Word64OrOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Or    Width
W64) CallishMachOp
MO_x64_Or
  PrimOp
Word64XorOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Xor   Width
W64) CallishMachOp
MO_x64_Xor
  PrimOp
Word64NotOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Not   Width
W64) CallishMachOp
MO_x64_Not
  PrimOp
Word64SllOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Shl   Width
W64) CallishMachOp
MO_x64_Shl
  PrimOp
Word64SrlOp    -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Shr Width
W64) CallishMachOp
MO_W64_Shr

  PrimOp
Word64EqOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Eq   Width
W64)  CallishMachOp
MO_x64_Eq
  PrimOp
Word64GeOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Ge Width
W64)  CallishMachOp
MO_W64_Ge
  PrimOp
Word64GtOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Gt Width
W64)  CallishMachOp
MO_W64_Gt
  PrimOp
Word64LeOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Le Width
W64)  CallishMachOp
MO_W64_Le
  PrimOp
Word64LtOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_U_Lt Width
W64)  CallishMachOp
MO_W64_Lt
  PrimOp
Word64NeOp     -> MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 (Width -> MachOp
MO_Ne   Width
W64)  CallishMachOp
MO_x64_Ne

-- Char# ops

  PrimOp
CharEqOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Eq (Platform -> Width
wordWidth Platform
platform))
  PrimOp
CharNeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_Ne (Platform -> Width
wordWidth Platform
platform))
  PrimOp
CharGeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Ge (Platform -> Width
wordWidth Platform
platform))
  PrimOp
CharLeOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Le (Platform -> Width
wordWidth Platform
platform))
  PrimOp
CharGtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Gt (Platform -> Width
wordWidth Platform
platform))
  PrimOp
CharLtOp       -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_U_Lt (Platform -> Width
wordWidth Platform
platform))

-- Double ops

  PrimOp
DoubleEqOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Eq Width
W64)
  PrimOp
DoubleNeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Ne Width
W64)
  PrimOp
DoubleGeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Ge Width
W64)
  PrimOp
DoubleLeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Le Width
W64)
  PrimOp
DoubleGtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Gt Width
W64)
  PrimOp
DoubleLtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Lt Width
W64)

  PrimOp
DoubleMinOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Min Width
W64)
  PrimOp
DoubleMaxOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Max Width
W64)

  PrimOp
DoubleAddOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Add Width
W64)
  PrimOp
DoubleSubOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Sub Width
W64)
  PrimOp
DoubleMulOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Mul Width
W64)
  PrimOp
DoubleDivOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Quot Width
W64)
  PrimOp
DoubleNegOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Neg Width
W64)

  PrimOp
DoubleFMAdd    -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd  Int
1 Width
W64
  PrimOp
DoubleFMSub    -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMSub  Int
1 Width
W64
  PrimOp
DoubleFNMAdd   -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMAdd Int
1 Width
W64
  PrimOp
DoubleFNMSub   -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMSub Int
1 Width
W64

-- Float ops

  PrimOp
FloatEqOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Eq Width
W32)
  PrimOp
FloatNeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Ne Width
W32)
  PrimOp
FloatGeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Ge Width
W32)
  PrimOp
FloatLeOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Le Width
W32)
  PrimOp
FloatGtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Gt Width
W32)
  PrimOp
FloatLtOp     -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Lt Width
W32)

  PrimOp
FloatAddOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Add  Width
W32)
  PrimOp
FloatSubOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Sub  Width
W32)
  PrimOp
FloatMulOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Mul  Width
W32)
  PrimOp
FloatDivOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Quot Width
W32)
  PrimOp
FloatNegOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Neg  Width
W32)

  PrimOp
FloatFMAdd    -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd  Int
1 Width
W32
  PrimOp
FloatFMSub    -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMSub  Int
1 Width
W32
  PrimOp
FloatFNMAdd   -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMAdd Int
1 Width
W32
  PrimOp
FloatFNMSub   -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMSub Int
1 Width
W32

  PrimOp
FloatMinOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Min Width
W32)
  PrimOp
FloatMaxOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> MachOp
MO_F_Max Width
W32)

-- Vector ops

  (VecAddOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Add  Int
n Width
w)
  (VecSubOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Sub  Int
n Width
w)
  (VecMulOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Mul  Int
n Width
w)
  (VecDivOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Quot Int
n Width
w)
  (VecQuotOp PrimOpVecCat
FloatVec Int
_ Width
_) -> \[CmmExpr]
_ -> String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"unsupported primop"
  (VecRemOp  PrimOpVecCat
FloatVec Int
_ Width
_) -> \[CmmExpr]
_ -> String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"unsupported primop"
  (VecNegOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Neg  Int
n Width
w)
  (VecMinOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Min  Int
n Width
w)
  (VecMaxOp  PrimOpVecCat
FloatVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VF_Max  Int
n Width
w)

  (VecAddOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Add   Int
n Width
w)
  (VecSubOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Sub   Int
n Width
w)
  (VecMulOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Mul   Int
n Width
w)
  (VecDivOp  PrimOpVecCat
IntVec Int
_ Width
_) -> \[CmmExpr]
_ -> String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"unsupported primop"
  (VecQuotOp PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VS_Quot Int
n Width
w)
  (VecRemOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VS_Rem  Int
n Width
w)
  (VecNegOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VS_Neg  Int
n Width
w)
  (VecMinOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VS_Min  Int
n Width
w)
  (VecMaxOp  PrimOpVecCat
IntVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VS_Max  Int
n Width
w)

  (VecAddOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Add   Int
n Width
w)
  (VecSubOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Sub   Int
n Width
w)
  (VecMulOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_V_Mul   Int
n Width
w)
  (VecDivOp  PrimOpVecCat
WordVec Int
_ Width
_) -> \[CmmExpr]
_ -> String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"unsupported primop"
  (VecQuotOp PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VU_Quot Int
n Width
w)
  (VecRemOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VU_Rem  Int
n Width
w)
  (VecNegOp  PrimOpVecCat
WordVec Int
_ Width
_) -> \[CmmExpr]
_ -> String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"unsupported primop"
  (VecMinOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VU_Min  Int
n Width
w)
  (VecMaxOp  PrimOpVecCat
WordVec Int
n Width
w) -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Int -> Width -> MachOp
MO_VU_Max  Int
n Width
w)

  -- Vector FMA instructions
  VecFMAdd  PrimOpVecCat
_ Int
n Width
w -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd  Int
n Width
w
  VecFMSub  PrimOpVecCat
_ Int
n Width
w -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMSub  Int
n Width
w
  VecFNMAdd PrimOpVecCat
_ Int
n Width
w -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMAdd Int
n Width
w
  VecFNMSub PrimOpVecCat
_ Int
n Width
w -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FNMSub Int
n Width
w

-- Conversions

  PrimOp
IntToDoubleOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SF_Round (Platform -> Width
wordWidth Platform
platform) Width
W64)
  PrimOp
DoubleToIntOp   -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_FS_Truncate Width
W64 (Platform -> Width
wordWidth Platform
platform))

  PrimOp
IntToFloatOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_SF_Round (Platform -> Width
wordWidth Platform
platform) Width
W32)
  PrimOp
FloatToIntOp    -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_FS_Truncate Width
W32 (Platform -> Width
wordWidth Platform
platform))

  PrimOp
FloatToDoubleOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_FF_Conv Width
W32 Width
W64)
  PrimOp
DoubleToFloatOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (Width -> Width -> MachOp
MO_FF_Conv Width
W64 Width
W32)

  PrimOp
CastFloatToWord32Op  -> MachOp -> [CmmExpr] -> PrimopCmmEmit
translateBitcasts (Width -> MachOp
MO_FW_Bitcast Width
W32)
  PrimOp
CastWord32ToFloatOp  -> MachOp -> [CmmExpr] -> PrimopCmmEmit
translateBitcasts (Width -> MachOp
MO_WF_Bitcast Width
W32)
  PrimOp
CastDoubleToWord64Op -> MachOp -> [CmmExpr] -> PrimopCmmEmit
translateBitcasts (Width -> MachOp
MO_FW_Bitcast Width
W64)
  PrimOp
CastWord64ToDoubleOp -> MachOp -> [CmmExpr] -> PrimopCmmEmit
translateBitcasts (Width -> MachOp
MO_WF_Bitcast Width
W64)

  PrimOp
IntQuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_S_QuotRem  (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericIntQuotRemOp (Platform -> Width
wordWidth Platform
platform))

  PrimOp
Int8QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_S_QuotRem Width
W8)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericIntQuotRemOp Width
W8)

  PrimOp
Int16QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_S_QuotRem Width
W16)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericIntQuotRemOp Width
W16)

  PrimOp
Int32QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_S_QuotRem Width
W32)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericIntQuotRemOp Width
W32)

  PrimOp
WordQuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_QuotRem  (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRemOp (Platform -> Width
wordWidth Platform
platform))

  PrimOp
WordQuotRem2Op -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem2
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_QuotRem2 (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Platform -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRem2Op Platform
platform)

  PrimOp
Word8QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_QuotRem Width
W8)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRemOp Width
W8)

  PrimOp
Word16QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_QuotRem Width
W16)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRemOp Width
W16)

  PrimOp
Word32QuotRemOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowQuotRem
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_QuotRem Width
W32)
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right (Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRemOp Width
W32)

  PrimOp
WordAdd2Op -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowExtAdd
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_Add2       (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericWordAdd2Op

  PrimOp
WordAddCOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowExtAdd
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_AddWordC   (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericWordAddCOp

  PrimOp
WordSubCOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowExtAdd
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_SubWordC   (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericWordSubCOp

  PrimOp
IntAddCOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowExtAdd
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_AddIntC    (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericIntAddCOp

  PrimOp
IntSubCOp -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowExtAdd
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_SubIntC    (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericIntSubCOp

  PrimOp
WordMul2Op -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowWord2Mul
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_U_Mul2     (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericWordMul2Op

  PrimOp
IntMul2Op  -> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater (Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
 -> [CmmExpr] -> PrimopCmmEmit)
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr]
-> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$
    if Bool
allowInt2Mul
    then CallishMachOp
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. a -> Either a b
Left (Width -> CallishMachOp
MO_S_Mul2     (Platform -> Width
wordWidth Platform
platform))
    else ([LocalReg] -> [CmmExpr] -> FCode ())
-> Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
forall a b. b -> Either a b
Right [LocalReg] -> [CmmExpr] -> FCode ()
genericIntMul2Op

  -- tagToEnum# is special: we need to pull the constructor
  -- out of the table, and perform an appropriate return.
  PrimOp
TagToEnumOp -> \[CmmExpr
amode] -> (Type -> FCode [CmmExpr]) -> PrimopCmmEmit
PrimopCmmEmit_Internal ((Type -> FCode [CmmExpr]) -> PrimopCmmEmit)
-> (Type -> FCode [CmmExpr]) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \Type
res_ty -> do
    -- If you're reading this code in the attempt to figure
    -- out why the compiler panic'ed here, it is probably because
    -- you used tagToEnum# in a non-monomorphic setting, e.g.,
    --         intToTg :: Enum a => Int -> a ; intToTg (I# x#) = tagToEnum# x#
    -- That won't work.
    let tycon :: TyCon
tycon = TyCon -> Maybe TyCon -> TyCon
forall a. a -> Maybe a -> a
fromMaybe (String -> SDoc -> TyCon
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"tagToEnum#: Applied to non-concrete type" (Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr Type
res_ty)) (Type -> Maybe TyCon
tyConAppTyCon_maybe Type
res_ty)
    Bool -> FCode ()
forall (m :: * -> *). (HasCallStack, Applicative m) => Bool -> m ()
massert (TyCon -> Bool
isEnumerationTyCon TyCon
tycon)
    platform <- FCode Platform
getPlatform
    pure [tagToClosure platform tycon amode]

-- Out of line primops.
-- TODO compiler need not know about these

  PrimOp
UnsafeThawArrayOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CasArrayOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
UnsafeThawSmallArrayOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CasSmallArrayOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewPinnedByteArrayOp_Char -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewAlignedPinnedByteArrayOp_Char -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MutableByteArrayIsPinnedOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MutableByteArrayIsWeaklyPinnedOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DoubleDecode_2IntOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DoubleDecode_Int64Op -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
FloatDecode_IntOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ByteArrayIsPinnedOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ByteArrayIsWeaklyPinnedOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ShrinkMutableByteArrayOp_Char -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ResizeMutableByteArrayOp_Char -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ShrinkSmallMutableArrayOp_Char -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewMutVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
AtomicModifyMutVar2Op -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
AtomicModifyMutVar_Op -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CasMutVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CatchOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RaiseOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RaiseUnderflowOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RaiseOverflowOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RaiseDivZeroOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RaiseIOOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MaskAsyncExceptionsOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MaskUninterruptibleOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
UnmaskAsyncExceptionsOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MaskStatus -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewPromptTagOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
PromptOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
Control0Op -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
AtomicallyOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
RetryOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CatchRetryOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CatchSTMOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewTVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ReadTVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ReadTVarIOOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
WriteTVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TakeMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TryTakeMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
PutMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TryPutMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ReadMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TryReadMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
IsEmptyMVarOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewIOPortOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ReadIOPortOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
WriteIOPortOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DelayOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
WaitReadOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
WaitWriteOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ForkOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ForkOnOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
KillThreadOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
YieldOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
LabelThreadOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
IsCurrentThreadBoundOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NoDuplicateOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
GetThreadLabelOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ThreadStatusOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MkWeakOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MkWeakNoFinalizerOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
AddCFinalizerToWeakOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DeRefWeakOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
FinalizeWeakOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MakeStablePtrOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DeRefStablePtrOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MakeStableNameOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactNewOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactResizeOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactContainsOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactContainsAnyOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactGetFirstBlockOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactGetNextBlockOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactAllocateBlockOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactFixupPointersOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactAdd -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactAddWithSharing -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
CompactSize -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
GetSparkOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NumSparks -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DataToTagSmallOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
DataToTagLargeOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
MkApUpd0_Op -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
NewBCOOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
UnpackClosureOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ListThreadsOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ClosureSizeOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
WhereFromOp   -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
GetApStackValOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
ClearCCSOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TraceEventOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TraceEventBinaryOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
TraceMarkerOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
SetThreadAllocationCounter -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
  PrimOp
KeepAliveOp -> [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal

 where
  profile :: Profile
profile  = StgToCmmConfig -> Profile
stgToCmmProfile  StgToCmmConfig
cfg
  platform :: Platform
platform = StgToCmmConfig -> Platform
stgToCmmPlatform StgToCmmConfig
cfg
  result_info :: PrimOpResultInfo
result_info = PrimOp -> PrimOpResultInfo
getPrimOpResultInfo PrimOp
primop

  opNop :: [CmmExpr] -> PrimopCmmEmit
  opNop :: [CmmExpr] -> PrimopCmmEmit
opNop [CmmExpr]
args = ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) CmmExpr
arg
    where [CmmExpr
arg] = [CmmExpr]
args

  opNarrow
    :: [CmmExpr]
    -> (Width -> Width -> MachOp, Width)
    -> PrimopCmmEmit
  opNarrow :: [CmmExpr] -> (Width -> Width -> MachOp, Width) -> PrimopCmmEmit
opNarrow [CmmExpr]
args (Width -> Width -> MachOp
mop, Width
rep) = ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (CmmExpr -> FCode ()) -> CmmExpr -> FCode ()
forall a b. (a -> b) -> a -> b
$
    MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> Width -> MachOp
mop Width
rep (Platform -> Width
wordWidth Platform
platform)) [MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> Width -> MachOp
mop (Platform -> Width
wordWidth Platform
platform) Width
rep) [CmmExpr
arg]]
    where [CmmExpr
arg] = [CmmExpr]
args

  -- These primops are implemented by CallishMachOps, because they sometimes
  -- turn into foreign calls depending on the backend.
  opCallish :: CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
  opCallish :: CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
prim [CmmExpr]
args = ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall [LocalReg
res] CallishMachOp
prim [CmmExpr]
args

  opTranslate :: MachOp -> [CmmExpr] -> PrimopCmmEmit
  opTranslate :: MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate MachOp
mop [CmmExpr]
args = ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg
res] -> do
    let stmt :: CmmAGraph
stmt = CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
mop [CmmExpr]
args)
    CmmAGraph -> FCode ()
emit CmmAGraph
stmt

  opTranslate64
    :: MachOp
    -> CallishMachOp
    -> [CmmExpr]
    -> PrimopCmmEmit
  opTranslate64 :: MachOp -> CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate64 MachOp
mop CallishMachOp
callish
    | Bool
allowArith64 = MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate MachOp
mop
    | Bool
otherwise    = CallishMachOp -> [CmmExpr] -> PrimopCmmEmit
opCallish CallishMachOp
callish
      -- backends not supporting 64-bit arithmetic primops: use callish machine
      -- ops

  -- Basically a "manual" case, rather than one of the common repetitive forms
  -- above. The results are a parameter to the returned function so we know the
  -- choice of variant never depends on them.
  opCallishHandledLater
    :: Either CallishMachOp GenericOp
    -> [CmmExpr]
    -> PrimopCmmEmit
  opCallishHandledLater :: Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
-> [CmmExpr] -> PrimopCmmEmit
opCallishHandledLater Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
callOrNot [CmmExpr]
args = ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \[LocalReg]
res0 -> case Either CallishMachOp ([LocalReg] -> [CmmExpr] -> FCode ())
callOrNot of
    Left CallishMachOp
op   -> CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ ForeignTarget -> [LocalReg] -> [CmmExpr] -> CmmAGraph
mkUnsafeCall (CallishMachOp -> ForeignTarget
PrimTarget CallishMachOp
op) [LocalReg]
res0 [CmmExpr]
args
    Right [LocalReg] -> [CmmExpr] -> FCode ()
gen -> [LocalReg] -> [CmmExpr] -> FCode ()
gen [LocalReg]
res0 [CmmExpr]
args

  opIntoRegs
    :: ([LocalReg] -- where to put the results
        -> FCode ())
    -> PrimopCmmEmit
  opIntoRegs :: ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs [LocalReg] -> FCode ()
f = (Type -> FCode [CmmExpr]) -> PrimopCmmEmit
PrimopCmmEmit_Internal ((Type -> FCode [CmmExpr]) -> PrimopCmmEmit)
-> (Type -> FCode [CmmExpr]) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \Type
res_ty -> do
    regs <- case PrimOpResultInfo
result_info of
      PrimOpResultInfo
ReturnsVoid -> [LocalReg] -> FCode [LocalReg]
forall a. a -> FCode a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
      ReturnsPrim PrimRep
rep
        -> do reg <- CmmType -> FCode LocalReg
forall (m :: * -> *). MonadGetUnique m => CmmType -> m LocalReg
newTemp (Platform -> PrimRep -> CmmType
primRepCmmType Platform
platform PrimRep
rep)
              pure [reg]

      PrimOpResultInfo
ReturnsTuple
        -> do (regs, _hints) <- Type -> FCode ([LocalReg], [ForeignHint])
newUnboxedTupleRegs Type
res_ty
              pure regs
    f regs
    pure $ map (CmmReg . CmmLocal) regs

  alwaysExternal :: p -> PrimopCmmEmit
alwaysExternal = \p
_ -> PrimopCmmEmit
PrimopCmmEmit_External

  allowQuotRem :: Bool
allowQuotRem  = StgToCmmConfig -> Bool
stgToCmmAllowQuotRemInstr         StgToCmmConfig
cfg
  allowQuotRem2 :: Bool
allowQuotRem2 = StgToCmmConfig -> Bool
stgToCmmAllowQuotRem2             StgToCmmConfig
cfg
  allowExtAdd :: Bool
allowExtAdd   = StgToCmmConfig -> Bool
stgToCmmAllowExtendedAddSubInstrs StgToCmmConfig
cfg
  allowInt2Mul :: Bool
allowInt2Mul  = StgToCmmConfig -> Bool
stgToCmmAllowIntMul2Instr         StgToCmmConfig
cfg
  allowWord2Mul :: Bool
allowWord2Mul = StgToCmmConfig -> Bool
stgToCmmAllowWordMul2Instr        StgToCmmConfig
cfg
  allowArith64 :: Bool
allowArith64  = StgToCmmConfig -> Bool
stgToCmmAllowArith64              StgToCmmConfig
cfg
  allowQuot64 :: Bool
allowQuot64   = StgToCmmConfig -> Bool
stgToCmmAllowQuot64               StgToCmmConfig
cfg

  -- a bit of a hack, for certain code generaters, e.g. PPC, and i386 we
  -- continue to use the cmm versions of these functions instead of inline
  -- assembly. Tracked in #24841.
  ppc :: Bool
ppc  = Arch -> Bool
isPPC (Arch -> Bool) -> Arch -> Bool
forall a b. (a -> b) -> a -> b
$ Platform -> Arch
platformArch Platform
platform
  i386 :: Bool
i386 = Platform -> Bool
target32Bit Platform
platform
  translateBitcasts :: MachOp -> [CmmExpr] -> PrimopCmmEmit
translateBitcasts MachOp
mop | Bool
ppc Bool -> Bool -> Bool
|| Bool
i386 = [CmmExpr] -> PrimopCmmEmit
forall {p}. p -> PrimopCmmEmit
alwaysExternal
                        | Bool
otherwise   = MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate MachOp
mop

  allowFMA :: FMASign -> Bool
allowFMA = StgToCmmConfig -> FMASign -> Bool
stgToCmmAllowFMAInstr StgToCmmConfig
cfg

  fmaOp :: FMASign -> Length -> Width -> [CmmActual] -> PrimopCmmEmit
  fmaOp :: FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
signs Int
l Width
w args :: [CmmExpr]
args@[CmmExpr
arg_x, CmmExpr
arg_y, CmmExpr
arg_z]
    |  FMASign -> Bool
allowFMA FMASign
signs
    Bool -> Bool -> Bool
|| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 -- (always use the MachOp for vector FMA)
    = MachOp -> [CmmExpr] -> PrimopCmmEmit
opTranslate (FMASign -> Int -> Width -> MachOp
MO_FMA FMASign
signs Int
l Width
w) [CmmExpr]
args
    | Bool
otherwise
    = case FMASign
signs of

        -- For fused multiply-add x * y + z, we fall back to the C implementation.
        FMASign
FMAdd -> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
opIntoRegs (([LocalReg] -> FCode ()) -> PrimopCmmEmit)
-> ([LocalReg] -> FCode ()) -> PrimopCmmEmit
forall a b. (a -> b) -> a -> b
$ \ [LocalReg
res] -> Width -> LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
fmaCCall Width
w LocalReg
res CmmExpr
arg_x CmmExpr
arg_y CmmExpr
arg_z

        -- Other fused multiply-add operations are implemented in terms of fmadd
        -- This is sound: it does not lose any precision.
        FMASign
FMSub  -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd Int
l Width
w [CmmExpr
arg_x, CmmExpr
arg_y, CmmExpr -> CmmExpr
neg CmmExpr
arg_z]
        FMASign
FNMAdd -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd Int
l Width
w [CmmExpr -> CmmExpr
neg CmmExpr
arg_x, CmmExpr
arg_y, CmmExpr
arg_z]
        FMASign
FNMSub -> FMASign -> Int -> Width -> [CmmExpr] -> PrimopCmmEmit
fmaOp FMASign
FMAdd Int
l Width
w [CmmExpr -> CmmExpr
neg CmmExpr
arg_x, CmmExpr
arg_y, CmmExpr -> CmmExpr
neg CmmExpr
arg_z]
    where
      neg :: CmmExpr -> CmmExpr
neg CmmExpr
x
        | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
        = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_F_Neg Width
w) [CmmExpr
x]
        | Bool
otherwise
        = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_VF_Neg Int
l Width
w) [CmmExpr
x]
  fmaOp FMASign
_ Int
_ Width
_ [CmmExpr]
_ = String -> PrimopCmmEmit
forall a. HasCallStack => String -> a
panic String
"fmaOp: wrong number of arguments (expected 3)"

data PrimopCmmEmit
  -- | Out of line fake primop that's actually just a foreign call to other
  -- (presumably) C--.
  = PrimopCmmEmit_External
  -- | Real primop turned into inline C--.
  | PrimopCmmEmit_Internal (Type -- the return type, some primops are specialized to it
                            -> FCode [CmmExpr]) -- just for TagToEnum for now

type GenericOp = [CmmFormal] -> [CmmActual] -> FCode ()

genericIntQuotRemOp :: Width -> GenericOp
genericIntQuotRemOp :: Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericIntQuotRemOp Width
width [LocalReg
res_q, LocalReg
res_r] [CmmExpr
arg_x, CmmExpr
arg_y]
   = CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res_q)
              (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_S_Quot Width
width) [CmmExpr
arg_x, CmmExpr
arg_y]) CmmAGraph -> CmmAGraph -> CmmAGraph
<*>
            CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res_r)
              (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_S_Rem  Width
width) [CmmExpr
arg_x, CmmExpr
arg_y])
genericIntQuotRemOp Width
_ [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericIntQuotRemOp"

genericWordQuotRemOp :: Width -> GenericOp
genericWordQuotRemOp :: Width -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRemOp Width
width [LocalReg
res_q, LocalReg
res_r] [CmmExpr
arg_x, CmmExpr
arg_y]
    = CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res_q)
               (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Quot Width
width) [CmmExpr
arg_x, CmmExpr
arg_y]) CmmAGraph -> CmmAGraph -> CmmAGraph
<*>
             CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res_r)
               (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Rem  Width
width) [CmmExpr
arg_x, CmmExpr
arg_y])
genericWordQuotRemOp Width
_ [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordQuotRemOp"

-- Based on the algorithm from LLVM's compiler-rt:
-- https://github.com/llvm/llvm-project/blob/7339f7ba3053db7595ece1ca5f49bd2e4c3c8305/compiler-rt/lib/builtins/udivmodti4.c#L23
-- See that file for licensing and copyright.
genericWordQuotRem2Op :: Platform -> GenericOp
genericWordQuotRem2Op :: Platform -> [LocalReg] -> [CmmExpr] -> FCode ()
genericWordQuotRem2Op Platform
platform [LocalReg
res_q, LocalReg
res_r] [CmmExpr
arg_u1, CmmExpr
arg_u0, CmmExpr
arg_v]
    = do
      -- v gets modified below based on clz v
      v <- CmmType -> FCode LocalReg
forall (m :: * -> *). MonadGetUnique m => CmmType -> m LocalReg
newTemp CmmType
ty
      emit $ mkAssign (CmmLocal v) arg_v
      go arg_u1 arg_u0 v
  where   ty :: CmmType
ty = Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
arg_u1
          shl :: CmmExpr -> CmmExpr -> CmmExpr
shl   CmmExpr
x CmmExpr
i = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Shl    (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
i]
          shr :: CmmExpr -> CmmExpr -> CmmExpr
shr   CmmExpr
x CmmExpr
i = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Shr  (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
i]
          or :: CmmExpr -> CmmExpr -> CmmExpr
or    CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Or     (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          ge :: CmmExpr -> CmmExpr -> CmmExpr
ge    CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Ge   (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          le :: CmmExpr -> CmmExpr -> CmmExpr
le    CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Le   (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          eq :: CmmExpr -> CmmExpr -> CmmExpr
eq    CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Eq     (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          plus :: CmmExpr -> CmmExpr -> CmmExpr
plus  CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add    (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          minus :: CmmExpr -> CmmExpr -> CmmExpr
minus CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Sub    (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          times :: CmmExpr -> CmmExpr -> CmmExpr
times CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Mul    (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          udiv :: CmmExpr -> CmmExpr -> CmmExpr
udiv  CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Quot (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          and :: CmmExpr -> CmmExpr -> CmmExpr
and   CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_And    (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          lit :: Integer -> CmmExpr
lit Integer
i     = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt Integer
i (Platform -> Width
wordWidth Platform
platform))
          one :: CmmExpr
one       = Integer -> CmmExpr
lit Integer
1
          zero :: CmmExpr
zero      = Integer -> CmmExpr
lit Integer
0
          masklow :: CmmExpr
masklow   = Integer -> CmmExpr
lit ((Integer
1 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` (Platform -> Int
platformWordSizeInBits Platform
platform Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2)) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
          gotoIf :: CmmExpr -> BlockId -> FCode ()
gotoIf CmmExpr
pred BlockId
target = CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> FCode CmmAGraph -> FCode ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< CmmExpr -> BlockId -> FCode CmmAGraph
mkCmmIfGoto CmmExpr
pred BlockId
target
          mkTmp :: CmmType -> m (LocalReg, CmmExpr)
mkTmp CmmType
ty = do
            t <- CmmType -> m LocalReg
forall (m :: * -> *). MonadGetUnique m => CmmType -> m LocalReg
newTemp CmmType
ty
            pure (t, CmmReg (CmmLocal t))
          infixr 8 .=
          LocalReg
r .= :: LocalReg -> CmmExpr -> FCode ()
.= CmmExpr
e = CmmAGraph -> FCode ()
emit (CmmAGraph -> FCode ()) -> CmmAGraph -> FCode ()
forall a b. (a -> b) -> a -> b
$ CmmReg -> CmmExpr -> CmmAGraph
mkAssign (LocalReg -> CmmReg
CmmLocal LocalReg
r) CmmExpr
e

          go :: CmmActual -> CmmActual -> LocalReg -> FCode ()
          go :: CmmExpr -> CmmExpr -> LocalReg -> FCode ()
go CmmExpr
u1 CmmExpr
u0 LocalReg
v = do
            -- Computes (ret,r) = (u1<<WORDSIZE*8+u0) `divMod` v
            -- du_int udiv128by64to64default(du_int u1, du_int u0, du_int v, du_int *r)
            -- const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
            let n_udword_bits' :: Int
n_udword_bits' = Width -> Int
widthInBits (Platform -> Width
wordWidth Platform
platform)
                n_udword_bits :: Integer
n_udword_bits = Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n_udword_bits'
            -- const du_int b = (1ULL << (n_udword_bits / 2)); // Number base (32 bits)
                b :: Integer
b = Integer
1 Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftL` (Int
n_udword_bits' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2)
                v' :: CmmExpr
v' = CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
v)
            -- du_int un1, un0;                                // Norm. dividend LSD's
            (un1, un1')   <- CmmType -> FCode (LocalReg, CmmExpr)
forall {m :: * -> *}.
MonadGetUnique m =>
CmmType -> m (LocalReg, CmmExpr)
mkTmp CmmType
ty
            (un0, un0')   <- mkTmp ty
            -- du_int vn1, vn0;                                // Norm. divisor digits
            (vn1, vn1')   <- mkTmp ty
            (vn0, vn0')   <- mkTmp ty
            -- du_int q1, q0;                                  // Quotient digits
            (q1, q1')     <- mkTmp ty
            (q0, q0')     <- mkTmp ty
            -- du_int un64, un21, un10;                        // Dividend digit pairs
            (un64, un64') <- mkTmp ty
            (un21, un21') <- mkTmp ty
            (un10, un10') <- mkTmp ty

            -- du_int rhat;                                    // A remainder
            (rhat, rhat') <- mkTmp ty
            -- si_int s;                                       // Shift amount for normalization
            (s, s')       <- mkTmp ty

            -- s = __builtin_clzll(v);
            -- clz(0) in GHC returns N on N bit systems, whereas
            -- __builtin_clzll returns 0 (or is undefined)
            emitClzCall s v' (wordWidth platform)

            if_else <- newBlockId
            if_done <- newBlockId
            -- if (s > 0) {
            -- actually if (s > 0 && s /= wordSizeInBits) {
            gotoIf (s' `eq` zero) if_else
            gotoIf (s' `eq` lit n_udword_bits) if_else
            do
              --   // Normalize the divisor.
              --   v = v << s;
              v .= shl v' s'
              --   un64 = (u1 << s) | (u0 >> (n_udword_bits - s));
              un64 .= (u1 `shl` s') `or` (u0 `shr` (lit n_udword_bits `minus` s'))
              --   un10 = u0 << s; // Shift dividend left
              un10 .= shl u0 s'
              emit $ mkBranch if_done
            -- } else {
            do
              --   // Avoid undefined behavior of (u0 >> 64).
              emitLabel if_else
              --   un64 = u1;
              un64 .= u1
              --   un10 = u0;
              un10 .= u0
              s .= lit 0 -- Otherwise leads to >>/<< 64
              -- }
            emitLabel if_done

            -- // Break divisor up into two 32-bit digits.
            -- vn1 = v >> (n_udword_bits / 2);
            vn1 .= v' `shr` lit (n_udword_bits `div` 2)
            -- vn0 = v & 0xFFFFFFFF;
            vn0 .= v' `and` masklow

            -- // Break right half of dividend into two digits.
            -- un1 = un10 >> (n_udword_bits / 2);
            un1 .= un10' `shr`  lit (n_udword_bits `div` 2)
            -- un0 = un10 & 0xFFFFFFFF;
            un0 .= un10' `and` masklow

            -- // Compute the first quotient digit, q1.
            -- q1 = un64 / vn1;
            q1 .= un64' `udiv` vn1'
            -- rhat = un64 - q1 * vn1;
            rhat .= un64' `minus` times q1' vn1'

            while_1_entry <- newBlockId
            while_1_body  <- newBlockId
            while_1_done  <- newBlockId
            -- // q1 has at most error 2. No more than 2 iterations.
            -- while (q1 >= b || q1 * vn0 > b * rhat + un1) {
            emitLabel while_1_entry
            gotoIf (q1' `ge` lit b) while_1_body
            gotoIf (le (times q1' vn0')
                       (times (lit b) rhat' `plus` un1'))
                  while_1_done
            do
              emitLabel while_1_body
              --   q1 = q1 - 1;
              q1 .= q1' `minus` one
              --   rhat = rhat + vn1;
              rhat .= rhat' `plus` vn1'
              --   if (rhat >= b)
              --     break;
              gotoIf (rhat' `ge` lit b)
                      while_1_done
              emit $ mkBranch while_1_entry
            -- }
            emitLabel while_1_done

            -- un21 = un64 * b + un1 - q1 * v;
            un21 .= (times un64' (lit b) `plus` un1') `minus` times q1' v'

            -- // Compute the second quotient digit.
            -- q0 = un21 / vn1;
            q0 .= un21' `udiv` vn1'
            -- rhat = un21 - q0 * vn1;
            rhat .= un21' `minus` times q0' vn1'

            -- // q0 has at most error 2. No more than 2 iterations.
            while_2_entry <- newBlockId
            while_2_body  <- newBlockId
            while_2_done  <- newBlockId
            emitLabel while_2_entry
            -- while (q0 >= b || q0 * vn0 > b * rhat + un0) {
            gotoIf (q0' `ge` lit b)
                   while_2_body
            gotoIf (le (times q0' vn0')
                       (times (lit b) rhat' `plus` un0'))
                   while_2_done
            do
              emitLabel while_2_body
              --   q0 = q0 - 1;
              q0 .= q0' `minus` one
              --   rhat = rhat + vn1;
              rhat .= rhat' `plus` vn1'
              --   if (rhat >= b)
              --     break;
              gotoIf (rhat' `ge` lit b) while_2_done
              emit $ mkBranch while_2_entry
            -- }
            emitLabel while_2_done

            --   r = (un21 * b + un0 - q0 * v) >> s;
            res_r .= ((times un21' (lit b) `plus` un0') `minus` times q0' v') `shr` s'
            -- return q1 * b + q0;
            res_q .= times q1' (lit b) `plus` q0'
genericWordQuotRem2Op Platform
_ [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordQuotRem2Op"

genericWordAdd2Op :: GenericOp
genericWordAdd2Op :: [LocalReg] -> [CmmExpr] -> FCode ()
genericWordAdd2Op [LocalReg
res_h, LocalReg
res_l] [CmmExpr
arg_x, CmmExpr
arg_y]
  = do platform <- FCode Platform
getPlatform
       r1 <- newTemp (cmmExprType platform arg_x)
       r2 <- newTemp (cmmExprType platform arg_x)
       let topHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Shr (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hww]
           toTopHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Shl (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hww]
           bottomHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_And (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hwm]
           add CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
           or CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Or (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
           hww = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Int
widthInBits (Platform -> Width
halfWordWidth Platform
platform)))
                                (Platform -> Width
wordWidth Platform
platform))
           hwm = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Platform -> Integer
halfWordMask Platform
platform) (Platform -> Width
wordWidth Platform
platform))
       emit $ catAGraphs
          [mkAssign (CmmLocal r1)
               (add (bottomHalf arg_x) (bottomHalf arg_y)),
           mkAssign (CmmLocal r2)
               (add (topHalf (CmmReg (CmmLocal r1)))
                    (add (topHalf arg_x) (topHalf arg_y))),
           mkAssign (CmmLocal res_h)
               (topHalf (CmmReg (CmmLocal r2))),
           mkAssign (CmmLocal res_l)
               (or (toTopHalf (CmmReg (CmmLocal r2)))
                   (bottomHalf (CmmReg (CmmLocal r1))))]
genericWordAdd2Op [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordAdd2Op"

-- | Implements branchless recovery of the carry flag @c@ by checking the
-- leftmost bits of both inputs @a@ and @b@ and result @r = a + b@:
--
-- @
--    c = a&b | (a|b)&~r
-- @
--
-- https://brodowsky.it-sky.net/2015/04/02/how-to-recover-the-carry-bit/
genericWordAddCOp :: GenericOp
genericWordAddCOp :: [LocalReg] -> [CmmExpr] -> FCode ()
genericWordAddCOp [LocalReg
res_r, LocalReg
res_c] [CmmExpr
aa, CmmExpr
bb]
 = do platform <- FCode Platform
getPlatform
      emit $ catAGraphs [
        mkAssign (CmmLocal res_r) (CmmMachOp (mo_wordAdd platform) [aa,bb]),
        mkAssign (CmmLocal res_c) $
          CmmMachOp (mo_wordUShr platform) [
            CmmMachOp (mo_wordOr platform) [
              CmmMachOp (mo_wordAnd platform) [aa,bb],
              CmmMachOp (mo_wordAnd platform) [
                CmmMachOp (mo_wordOr platform) [aa,bb],
                CmmMachOp (mo_wordNot platform) [CmmReg (CmmLocal res_r)]
              ]
            ],
            mkIntExpr platform (platformWordSizeInBits platform - 1)
          ]
        ]
genericWordAddCOp [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordAddCOp"

-- | Implements branchless recovery of the carry flag @c@ by checking the
-- leftmost bits of both inputs @a@ and @b@ and result @r = a - b@:
--
-- @
--    c = ~a&b | (~a|b)&r
-- @
--
-- https://brodowsky.it-sky.net/2015/04/02/how-to-recover-the-carry-bit/
genericWordSubCOp :: GenericOp
genericWordSubCOp :: [LocalReg] -> [CmmExpr] -> FCode ()
genericWordSubCOp [LocalReg
res_r, LocalReg
res_c] [CmmExpr
aa, CmmExpr
bb]
 = do platform <- FCode Platform
getPlatform
      emit $ catAGraphs [
        mkAssign (CmmLocal res_r) (CmmMachOp (mo_wordSub platform) [aa,bb]),
        mkAssign (CmmLocal res_c) $
          CmmMachOp (mo_wordUShr platform) [
            CmmMachOp (mo_wordOr platform) [
              CmmMachOp (mo_wordAnd platform) [
                CmmMachOp (mo_wordNot platform) [aa],
                bb
              ],
              CmmMachOp (mo_wordAnd platform) [
                CmmMachOp (mo_wordOr platform) [
                  CmmMachOp (mo_wordNot platform) [aa],
                  bb
                ],
                CmmReg (CmmLocal res_r)
              ]
            ],
            mkIntExpr platform (platformWordSizeInBits platform - 1)
          ]
        ]
genericWordSubCOp [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordSubCOp"

genericIntAddCOp :: GenericOp
genericIntAddCOp :: [LocalReg] -> [CmmExpr] -> FCode ()
genericIntAddCOp [LocalReg
res_r, LocalReg
res_c] [CmmExpr
aa, CmmExpr
bb]
{-
   With some bit-twiddling, we can define int{Add,Sub}Czh portably in
   C, and without needing any comparisons.  This may not be the
   fastest way to do it - if you have better code, please send it! --SDM

   Return : r = a + b,  c = 0 if no overflow, 1 on overflow.

   We currently don't make use of the r value if c is != 0 (i.e.
   overflow), we just convert to big integers and try again.  This
   could be improved by making r and c the correct values for
   plugging into a new J#.

   { r = ((I_)(a)) + ((I_)(b));                                 \
     c = ((StgWord)(~(((I_)(a))^((I_)(b))) & (((I_)(a))^r)))    \
         >> (BITS_IN (I_) - 1);                                 \
   }
   Wading through the mass of bracketry, it seems to reduce to:
   c = ( (~(a^b)) & (a^r) ) >>unsigned (BITS_IN(I_)-1)

-}
 = do platform <- FCode Platform
getPlatform
      emit $ catAGraphs [
        mkAssign (CmmLocal res_r) (CmmMachOp (mo_wordAdd platform) [aa,bb]),
        mkAssign (CmmLocal res_c) $
          CmmMachOp (mo_wordUShr platform) [
                CmmMachOp (mo_wordAnd platform) [
                    CmmMachOp (mo_wordNot platform) [CmmMachOp (mo_wordXor platform) [aa,bb]],
                    CmmMachOp (mo_wordXor platform) [aa, CmmReg (CmmLocal res_r)]
                ],
                mkIntExpr platform (platformWordSizeInBits platform - 1)
          ]
        ]
genericIntAddCOp [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericIntAddCOp"

genericIntSubCOp :: GenericOp
genericIntSubCOp :: [LocalReg] -> [CmmExpr] -> FCode ()
genericIntSubCOp [LocalReg
res_r, LocalReg
res_c] [CmmExpr
aa, CmmExpr
bb]
{- Similarly:
   #define subIntCzh(r,c,a,b)                                   \
   { r = ((I_)(a)) - ((I_)(b));                                 \
     c = ((StgWord)((((I_)(a))^((I_)(b))) & (((I_)(a))^r)))     \
         >> (BITS_IN (I_) - 1);                                 \
   }

   c =  ((a^b) & (a^r)) >>unsigned (BITS_IN(I_)-1)
-}
 = do platform <- FCode Platform
getPlatform
      emit $ catAGraphs [
        mkAssign (CmmLocal res_r) (CmmMachOp (mo_wordSub platform) [aa,bb]),
        mkAssign (CmmLocal res_c) $
          CmmMachOp (mo_wordUShr platform) [
                CmmMachOp (mo_wordAnd platform) [
                    CmmMachOp (mo_wordXor platform) [aa,bb],
                    CmmMachOp (mo_wordXor platform) [aa, CmmReg (CmmLocal res_r)]
                ],
                mkIntExpr platform (platformWordSizeInBits platform - 1)
          ]
        ]
genericIntSubCOp [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericIntSubCOp"

genericWordMul2Op :: GenericOp
genericWordMul2Op :: [LocalReg] -> [CmmExpr] -> FCode ()
genericWordMul2Op [LocalReg
res_h, LocalReg
res_l] [CmmExpr
arg_x, CmmExpr
arg_y]
 = do platform <- FCode Platform
getPlatform
      let t = Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
arg_x
      xlyl <- liftM CmmLocal $ newTemp t
      xlyh <- liftM CmmLocal $ newTemp t
      xhyl <- liftM CmmLocal $ newTemp t
      r    <- liftM CmmLocal $ newTemp t
      -- This generic implementation is very simple and slow. We might
      -- well be able to do better, but for now this at least works.
      let topHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_U_Shr (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hww]
          toTopHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Shl (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hww]
          bottomHalf CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_And (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
hwm]
          add CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Add (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          sum = (CmmExpr -> CmmExpr -> CmmExpr) -> [CmmExpr] -> CmmExpr
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 CmmExpr -> CmmExpr -> CmmExpr
add
          mul CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Mul (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          or CmmExpr
x CmmExpr
y = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Or (Platform -> Width
wordWidth Platform
platform)) [CmmExpr
x, CmmExpr
y]
          hww = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Int
widthInBits (Platform -> Width
halfWordWidth Platform
platform)))
                               (Platform -> Width
wordWidth Platform
platform))
          hwm = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Platform -> Integer
halfWordMask Platform
platform) (Platform -> Width
wordWidth Platform
platform))
      emit $ catAGraphs
             [mkAssign xlyl
                  (mul (bottomHalf arg_x) (bottomHalf arg_y)),
              mkAssign xlyh
                  (mul (bottomHalf arg_x) (topHalf arg_y)),
              mkAssign xhyl
                  (mul (topHalf arg_x) (bottomHalf arg_y)),
              mkAssign r
                  (sum [topHalf    (CmmReg xlyl),
                        bottomHalf (CmmReg xhyl),
                        bottomHalf (CmmReg xlyh)]),
              mkAssign (CmmLocal res_l)
                  (or (bottomHalf (CmmReg xlyl))
                      (toTopHalf (CmmReg r))),
              mkAssign (CmmLocal res_h)
                  (sum [mul (topHalf arg_x) (topHalf arg_y),
                        topHalf (CmmReg xhyl),
                        topHalf (CmmReg xlyh),
                        topHalf (CmmReg r)])]
genericWordMul2Op [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericWordMul2Op"

genericIntMul2Op :: GenericOp
genericIntMul2Op :: [LocalReg] -> [CmmExpr] -> FCode ()
genericIntMul2Op [LocalReg
res_c, LocalReg
res_h, LocalReg
res_l] both_args :: [CmmExpr]
both_args@[CmmExpr
arg_x, CmmExpr
arg_y]
 = do cfg <- FCode StgToCmmConfig
getStgToCmmConfig
      -- Implement algorithm from Hacker's Delight, 2nd edition, p.174
      let t        = Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
arg_x
          platform = StgToCmmConfig -> Platform
stgToCmmPlatform StgToCmmConfig
cfg
      p   <- newTemp t
      -- 1) compute the multiplication as if numbers were unsigned
      _ <- withSequel (AssignTo [p, res_l] False) $
             cmmPrimOpApp cfg WordMul2Op both_args Nothing
      -- 2) correct the high bits of the unsigned result
      let carryFill CmmExpr
x = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_S_Shr Width
ww) [CmmExpr
x, CmmExpr
wwm1]
          sub CmmExpr
x CmmExpr
y     = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Sub   Width
ww) [CmmExpr
x, CmmExpr
y]
          and CmmExpr
x CmmExpr
y     = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_And   Width
ww) [CmmExpr
x, CmmExpr
y]
          neq CmmExpr
x CmmExpr
y     = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> MachOp
MO_Ne    Width
ww) [CmmExpr
x, CmmExpr
y]
          f   CmmExpr
x CmmExpr
y     = (CmmExpr -> CmmExpr
carryFill CmmExpr
x) CmmExpr -> CmmExpr -> CmmExpr
`and` CmmExpr
y
          wwm1        = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Width -> Int
widthInBits Width
ww Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) Width
ww)
          rl LocalReg
x        = CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
x)
          ww          = Platform -> Width
wordWidth Platform
platform
      emit $ catAGraphs
             [ mkAssign (CmmLocal res_h) (rl p `sub` f arg_x arg_y `sub` f arg_y arg_x)
             , mkAssign (CmmLocal res_c) (rl res_h `neq` carryFill (rl res_l))
             ]
genericIntMul2Op [LocalReg]
_ [CmmExpr]
_ = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"genericIntMul2Op"

fmaCCall :: Width -> CmmFormal -> CmmActual -> CmmActual -> CmmActual -> FCode ()
fmaCCall :: Width -> LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
fmaCCall Width
width LocalReg
res CmmExpr
arg_x CmmExpr
arg_y CmmExpr
arg_z =
  [(LocalReg, ForeignHint)]
-> CmmExpr -> [(CmmExpr, ForeignHint)] -> FCode ()
emitCCall
    [(LocalReg
res,ForeignHint
NoHint)]
    (CmmLit -> CmmExpr
CmmLit (CLabel -> CmmLit
CmmLabel CLabel
fma_lbl))
    [(CmmExpr
arg_x,ForeignHint
NoHint), (CmmExpr
arg_y,ForeignHint
NoHint), (CmmExpr
arg_z,ForeignHint
NoHint)]
  where
    fma_lbl :: CLabel
fma_lbl = FastString -> ForeignLabelSource -> FunctionOrData -> CLabel
mkForeignLabel FastString
fma_op ForeignLabelSource
ForeignLabelInExternalPackage FunctionOrData
IsFunction
    fma_op :: FastString
fma_op = case Width
width of
      Width
W32 -> String -> FastString
fsLit String
"fmaf"
      Width
W64 -> String -> FastString
fsLit String
"fma"
      Width
_   -> String -> FastString
forall a. HasCallStack => String -> a
panic (String
"fmaCall: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Width -> String
forall a. Show a => a -> String
show Width
width)

------------------------------------------------------------------------------
-- Helpers for translating various minor variants of array indexing.

alignmentFromTypes :: CmmType  -- ^ element type
                   -> CmmType  -- ^ index type
                   -> AlignmentSpec
alignmentFromTypes :: CmmType -> CmmType -> AlignmentSpec
alignmentFromTypes CmmType
ty CmmType
idx_ty
  | CmmType -> Width
typeWidth CmmType
ty Width -> Width -> Bool
forall a. Ord a => a -> a -> Bool
<= CmmType -> Width
typeWidth CmmType
idx_ty = AlignmentSpec
NaturallyAligned
  | Bool
otherwise                        = AlignmentSpec
Unaligned

doIndexOffAddrOp :: Maybe MachOp
                 -> CmmType
                 -> [LocalReg]
                 -> [CmmExpr]
                 -> FCode ()
doIndexOffAddrOp :: Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOp Maybe MachOp
maybe_post_read_cast CmmType
rep [LocalReg
res] [CmmExpr
addr,CmmExpr
idx]
   = Bool
-> AlignmentSpec
-> Int
-> Maybe MachOp
-> CmmType
-> LocalReg
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
mkBasicIndexedRead Bool
False AlignmentSpec
NaturallyAligned Int
0 Maybe MachOp
maybe_post_read_cast CmmType
rep LocalReg
res CmmExpr
addr CmmType
rep CmmExpr
idx
doIndexOffAddrOp Maybe MachOp
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doIndexOffAddrOp"

doIndexOffAddrOpAs :: Maybe MachOp
                   -> CmmType
                   -> CmmType
                   -> [LocalReg]
                   -> [CmmExpr]
                   -> FCode ()
doIndexOffAddrOpAs :: Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexOffAddrOpAs Maybe MachOp
maybe_post_read_cast CmmType
rep CmmType
idx_rep [LocalReg
res] [CmmExpr
addr,CmmExpr
idx]
   = let alignment :: AlignmentSpec
alignment = CmmType -> CmmType -> AlignmentSpec
alignmentFromTypes CmmType
rep CmmType
idx_rep
     in Bool
-> AlignmentSpec
-> Int
-> Maybe MachOp
-> CmmType
-> LocalReg
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
mkBasicIndexedRead Bool
False AlignmentSpec
alignment Int
0 Maybe MachOp
maybe_post_read_cast CmmType
rep LocalReg
res CmmExpr
addr CmmType
idx_rep CmmExpr
idx
doIndexOffAddrOpAs Maybe MachOp
_ CmmType
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doIndexOffAddrOpAs"

doIndexByteArrayOp :: Maybe MachOp
                   -> CmmType
                   -> [LocalReg]
                   -> [CmmExpr]
                   -> FCode ()
doIndexByteArrayOp :: Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOp Maybe MachOp
maybe_post_read_cast CmmType
rep [LocalReg
res] [CmmExpr
addr,CmmExpr
idx]
   = do profile <- FCode Profile
getProfile
        doByteArrayBoundsCheck idx addr rep rep
        mkBasicIndexedRead False NaturallyAligned (arrWordsHdrSize profile) maybe_post_read_cast rep res addr rep idx
doIndexByteArrayOp Maybe MachOp
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doIndexByteArrayOp"

doIndexByteArrayOpAs :: Maybe MachOp
                    -> CmmType
                    -> CmmType
                    -> [LocalReg]
                    -> [CmmExpr]
                    -> FCode ()
doIndexByteArrayOpAs :: Maybe MachOp
-> CmmType -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doIndexByteArrayOpAs Maybe MachOp
maybe_post_read_cast CmmType
rep CmmType
idx_rep [LocalReg
res] [CmmExpr
addr,CmmExpr
idx]
   = do profile <- FCode Profile
getProfile
        doByteArrayBoundsCheck idx addr idx_rep rep
        let alignment = CmmType -> CmmType -> AlignmentSpec
alignmentFromTypes CmmType
rep CmmType
idx_rep
        mkBasicIndexedRead False alignment (arrWordsHdrSize profile) maybe_post_read_cast rep res addr idx_rep idx
doIndexByteArrayOpAs Maybe MachOp
_ CmmType
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doIndexByteArrayOpAs"

doReadPtrArrayOp :: LocalReg
                 -> CmmExpr
                 -> CmmExpr
                 -> FCode ()
doReadPtrArrayOp :: LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadPtrArrayOp LocalReg
res CmmExpr
addr CmmExpr
idx
   = do profile <- FCode Profile
getProfile
        platform <- getPlatform
        doPtrArrayBoundsCheck idx addr
        mkBasicIndexedRead True NaturallyAligned (arrPtrsHdrSize profile) Nothing (gcWord platform) res addr (gcWord platform) idx

doWriteOffAddrOp :: Maybe MachOp
                 -> CmmType
                 -> [LocalReg]
                 -> [CmmExpr]
                 -> FCode ()
doWriteOffAddrOp :: Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteOffAddrOp Maybe MachOp
castOp CmmType
idx_ty [] [CmmExpr
addr,CmmExpr
idx, CmmExpr
val]
   = Bool -> Int -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
mkBasicIndexedWrite Bool
False Int
0 CmmExpr
addr CmmType
idx_ty CmmExpr
idx (Maybe MachOp -> CmmExpr -> CmmExpr
maybeCast Maybe MachOp
castOp CmmExpr
val)
doWriteOffAddrOp Maybe MachOp
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doWriteOffAddrOp"

doWriteByteArrayOp :: Maybe MachOp
                   -> CmmType
                   -> [LocalReg]
                   -> [CmmExpr]
                   -> FCode ()
doWriteByteArrayOp :: Maybe MachOp -> CmmType -> [LocalReg] -> [CmmExpr] -> FCode ()
doWriteByteArrayOp Maybe MachOp
castOp CmmType
idx_ty [] [CmmExpr
addr,CmmExpr
idx, CmmExpr
rawVal]
   = do profile <- FCode Profile
getProfile
        platform <- getPlatform
        let val = Maybe MachOp -> CmmExpr -> CmmExpr
maybeCast Maybe MachOp
castOp CmmExpr
rawVal
        doByteArrayBoundsCheck idx addr idx_ty (cmmExprType platform val)
        mkBasicIndexedWrite False (arrWordsHdrSize profile) addr idx_ty idx val
doWriteByteArrayOp Maybe MachOp
_ CmmType
_ [LocalReg]
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doWriteByteArrayOp"

doWritePtrArrayOp :: CmmExpr
                  -> CmmExpr
                  -> CmmExpr
                  -> FCode ()
doWritePtrArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doWritePtrArrayOp CmmExpr
addr CmmExpr
idx CmmExpr
val
  = do profile  <- FCode Profile
getProfile
       platform <- getPlatform
       let ty = Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
val
           hdr_size = Profile -> Int
arrPtrsHdrSize Profile
profile

       doPtrArrayBoundsCheck idx addr

       -- Update remembered set for non-moving collector
       whenUpdRemSetEnabled
           $ emitUpdRemSetPush (cmmLoadIndexOffExpr platform NaturallyAligned hdr_size ty addr ty idx)
       -- This write barrier is to ensure that the heap writes to the object
       -- referred to by val have happened before we write val into the array.
       -- See #12469 for details.
       mkBasicIndexedWrite True hdr_size addr ty idx val

       emit (setInfo addr (CmmLit (CmmLabel mkMAP_DIRTY_infoLabel)))
       -- the write barrier.  We must write a byte into the mark table:
       -- bits8[a + header_size + StgMutArrPtrs_size(a) + x >> N]
       emit $ mkStore (
         cmmOffsetExpr platform
          (cmmOffsetExprW platform (cmmOffsetB platform addr hdr_size)
                         (ptrArraySize platform profile addr))
          (CmmMachOp (mo_wordUShr platform) [idx, mkIntExpr platform (pc_MUT_ARR_PTRS_CARD_BITS (platformConstants platform))])
         ) (CmmLit (CmmInt 1 W8))

mkBasicIndexedRead :: Bool         -- Should this imply an acquire barrier
                   -> AlignmentSpec
                   -> ByteOff      -- Initial offset in bytes
                   -> Maybe MachOp -- Optional result cast
                   -> CmmType      -- Type of element we are accessing
                   -> LocalReg     -- Destination
                   -> CmmExpr      -- Base address
                   -> CmmType      -- Type of element by which we are indexing
                   -> CmmExpr      -- Index
                   -> FCode ()
mkBasicIndexedRead :: Bool
-> AlignmentSpec
-> Int
-> Maybe MachOp
-> CmmType
-> LocalReg
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
mkBasicIndexedRead Bool
barrier AlignmentSpec
alignment Int
off Maybe MachOp
mb_cast CmmType
ty LocalReg
res CmmExpr
base CmmType
idx_ty CmmExpr
idx
   = do platform <- FCode Platform
getPlatform
        let addr = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform Int
off (CmmType -> Width
typeWidth CmmType
idx_ty) CmmExpr
base CmmExpr
idx
        result <-
          if barrier
          then do
            res <- newTemp ty
            emitPrimCall [res] (MO_AtomicRead (typeWidth ty) MemOrderAcquire) [addr]
            return $ CmmReg (CmmLocal res)
          else
            return $ CmmLoad addr ty alignment

        let casted =
              case Maybe MachOp
mb_cast of
                Just MachOp
cast -> MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
cast [CmmExpr
result]
                Maybe MachOp
Nothing   -> CmmExpr
result
        emitAssign (CmmLocal res) casted

mkBasicIndexedWrite :: Bool         -- Should this imply a release barrier
                    -> ByteOff      -- Initial offset in bytes
                    -> CmmExpr      -- Base address
                    -> CmmType      -- Type of element by which we are indexing
                    -> CmmExpr      -- Index
                    -> CmmExpr      -- Value to write
                    -> FCode ()
mkBasicIndexedWrite :: Bool -> Int -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
mkBasicIndexedWrite Bool
barrier Int
off CmmExpr
base CmmType
idx_ty CmmExpr
idx CmmExpr
val
   = do platform <- FCode Platform
getPlatform
        let alignment = CmmType -> CmmType -> AlignmentSpec
alignmentFromTypes (Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
val) CmmType
idx_ty
            addr = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform Int
off (CmmType -> Width
typeWidth CmmType
idx_ty) CmmExpr
base CmmExpr
idx
        if barrier
          then let w = CmmType -> Width
typeWidth CmmType
idx_ty
                   op = Width -> MemoryOrdering -> CallishMachOp
MO_AtomicWrite Width
w MemoryOrdering
MemOrderRelease
               in emitPrimCall [] op [addr, val]
          else emitStore' alignment addr val

-- ----------------------------------------------------------------------------
-- Misc utils

cmmIndexOffExpr :: Platform
                -> ByteOff  -- Initial offset in bytes
                -> Width    -- Width of element by which we are indexing
                -> CmmExpr  -- Base address
                -> CmmExpr  -- Index
                -> CmmExpr
cmmIndexOffExpr :: Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform Int
off Width
width CmmExpr
base CmmExpr
idx
   = Platform -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexExpr Platform
platform Width
width (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
base Int
off) CmmExpr
idx

cmmLoadIndexOffExpr :: Platform
                    -> AlignmentSpec
                    -> ByteOff  -- Initial offset in bytes
                    -> CmmType  -- Type of element we are accessing
                    -> CmmExpr  -- Base address
                    -> CmmType  -- Type of element by which we are indexing
                    -> CmmExpr  -- Index
                    -> CmmExpr
cmmLoadIndexOffExpr :: Platform
-> AlignmentSpec
-> Int
-> CmmType
-> CmmExpr
-> CmmType
-> CmmExpr
-> CmmExpr
cmmLoadIndexOffExpr Platform
platform AlignmentSpec
alignment Int
off CmmType
ty CmmExpr
base CmmType
idx_ty CmmExpr
idx
   = CmmExpr -> CmmType -> AlignmentSpec -> CmmExpr
CmmLoad (Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform Int
off (CmmType -> Width
typeWidth CmmType
idx_ty) CmmExpr
base CmmExpr
idx) CmmType
ty AlignmentSpec
alignment

setInfo :: CmmExpr -> CmmExpr -> CmmAGraph
setInfo :: CmmExpr -> CmmExpr -> CmmAGraph
setInfo CmmExpr
closure_ptr CmmExpr
info_ptr = CmmExpr -> CmmExpr -> CmmAGraph
mkStore CmmExpr
closure_ptr CmmExpr
info_ptr

maybeCast :: Maybe MachOp -> CmmExpr -> CmmExpr
maybeCast :: Maybe MachOp -> CmmExpr -> CmmExpr
maybeCast Maybe MachOp
Nothing CmmExpr
val = CmmExpr
val
maybeCast (Just MachOp
cast) CmmExpr
val = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp MachOp
cast [CmmExpr
val]

ptrArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
ptrArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
ptrArraySize Platform
platform Profile
profile CmmExpr
arr =
  Platform -> CmmExpr -> CmmExpr
cmmLoadBWord Platform
platform (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
arr Int
sz_off)
  where sz_off :: Int
sz_off = Profile -> Int
fixedHdrSize Profile
profile
               Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgMutArrPtrs_ptrs (Platform -> PlatformConstants
platformConstants Platform
platform)

smallPtrArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
smallPtrArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
smallPtrArraySize Platform
platform Profile
profile CmmExpr
arr =
  Platform -> CmmExpr -> CmmExpr
cmmLoadBWord Platform
platform (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
arr Int
sz_off)
  where sz_off :: Int
sz_off = Profile -> Int
fixedHdrSize Profile
profile
               Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgSmallMutArrPtrs_ptrs (Platform -> PlatformConstants
platformConstants Platform
platform)

byteArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
byteArraySize :: Platform -> Profile -> CmmExpr -> CmmExpr
byteArraySize Platform
platform Profile
profile CmmExpr
arr =
  Platform -> CmmExpr -> CmmExpr
cmmLoadBWord Platform
platform (Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetB Platform
platform CmmExpr
arr Int
sz_off)
  where sz_off :: Int
sz_off = Profile -> Int
fixedHdrSize Profile
profile
               Int -> Int -> Int
forall a. Num a => a -> a -> a
+ PlatformConstants -> Int
pc_OFFSET_StgArrBytes_bytes (Platform -> PlatformConstants
platformConstants Platform
platform)



------------------------------------------------------------------------------
-- Helpers for translating vector primops.

vecCmmType :: PrimOpVecCat -> Length -> Width -> CmmType
vecCmmType :: PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
pocat Int
n Width
w = Int -> CmmType -> CmmType
vec Int
n (PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
pocat Width
w)

vecCmmCat :: PrimOpVecCat -> Width -> CmmType
vecCmmCat :: PrimOpVecCat -> Width -> CmmType
vecCmmCat PrimOpVecCat
IntVec   = Width -> CmmType
cmmBits
vecCmmCat PrimOpVecCat
WordVec  = Width -> CmmType
cmmBits
vecCmmCat PrimOpVecCat
FloatVec = Width -> CmmType
cmmFloat

-- Note [SIMD Design for the future]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Check to make sure that we can generate code for the specified vector type
-- given the current set of dynamic flags.
-- Currently these checks are specific to x86, x86_64 and AArch64 architectures.
-- This should be fixed!
-- In particular,
-- 1) Add better support for other architectures! (this may require a redesign)
-- 2) Decouple design choices from LLVM's pseudo SIMD model!
--   The high level LLVM naive rep makes per CPU family SIMD generation is own
--   optimization problem, and hides important differences in eg ARM vs x86_64 simd
-- 3) Depending on the architecture, the SIMD registers may also support general
--    computations on Float/Double/Word/Int scalars, but currently on
--    for example x86_64, we always put Word/Int (or sized) in GPR
--    (general purpose) registers. Would relaxing that allow for
--    useful optimization opportunities?
--      Phrased differently, it is worth experimenting with supporting
--    different register mapping strategies than we currently have, especially if
--    someday we want SIMD to be a first class denizen in GHC along with scalar
--    values!
--      The current design with respect to register mapping of scalars could
--    very well be the best,but exploring the  design space and doing careful
--    measurements is the only way to validate that.
--      In some next generation CPU ISAs, notably RISC V, the SIMD extension
--    includes  support for a sort of run time CPU dependent vectorization parameter,
--    where a loop may act upon a single scalar each iteration OR some 2,4,8 ...
--    element chunk! Time will tell if that direction sees wide adoption,
--    but it is from that context that unifying our handling of simd and scalars
--    may benefit. It is not likely to benefit current architectures, though
--    it may very well be a design perspective that helps guide improving the NCG.


checkVecCompatibility :: StgToCmmConfig -> PrimOpVecCat -> Length -> Width -> FCode ()
checkVecCompatibility :: StgToCmmConfig -> PrimOpVecCat -> Int -> Width -> FCode ()
checkVecCompatibility StgToCmmConfig
cfg PrimOpVecCat
vcat Int
l Width
w =
  case StgToCmmConfig -> Maybe String
stgToCmmVecInstrsErr StgToCmmConfig
cfg of
    Maybe String
Nothing | Bool
isX86 -> Width -> PrimOpVecCat -> Int -> Width -> FCode ()
checkX86 Width
vecWidth PrimOpVecCat
vcat Int
l Width
w
            | Platform -> Arch
platformArch Platform
platform Arch -> Arch -> Bool
forall a. Eq a => a -> a -> Bool
== Arch
ArchAArch64 -> Width -> FCode ()
checkAArch64 Width
vecWidth
            | Bool
otherwise -> String -> FCode ()
forall a. HasCallStack => String -> a
sorry String
"SIMD vector instructions are not supported on this architecture."
    Just String
err -> String -> FCode ()
forall a. HasCallStack => String -> a
sorry String
err  -- incompatible backend, do panic
  where
    platform :: Platform
platform = StgToCmmConfig -> Platform
stgToCmmPlatform StgToCmmConfig
cfg
    isX86 :: Bool
isX86 = case Platform -> Arch
platformArch Platform
platform of
      Arch
ArchX86_64 -> Bool
True
      Arch
ArchX86 -> Bool
True
      Arch
_ -> Bool
False
    checkX86 :: Width -> PrimOpVecCat -> Length -> Width -> FCode ()
    checkX86 :: Width -> PrimOpVecCat -> Int -> Width -> FCode ()
checkX86 Width
W128 PrimOpVecCat
FloatVec Int
4 Width
W32 | Platform -> Bool
isSseEnabled Platform
platform = () -> FCode ()
forall a. a -> FCode a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                                 | Bool
otherwise =
        String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"128-bit wide single-precision floating point " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                String
"SIMD vector instructions require at least -msse."
    checkX86 Width
W128 PrimOpVecCat
_ Int
_ Width
_ | Bool -> Bool
not (Platform -> Bool
isSse2Enabled Platform
platform) =
        String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"128-bit wide integer and double precision " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                String
"SIMD vector instructions require at least -msse2."
    checkX86 Width
W256 PrimOpVecCat
FloatVec Int
_ Width
_ | StgToCmmConfig -> Bool
stgToCmmAvx StgToCmmConfig
cfg = () -> FCode ()
forall a. a -> FCode a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                               | Bool
otherwise =
        String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"256-bit wide floating point " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                String
"SIMD vector instructions require at least -mavx."
    checkX86 Width
W256 PrimOpVecCat
_ Int
_ Width
_ | Bool -> Bool
not (StgToCmmConfig -> Bool
stgToCmmAvx2 StgToCmmConfig
cfg) =
        String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"256-bit wide integer " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                String
"SIMD vector instructions require at least -mavx2."
    checkX86 Width
W512 PrimOpVecCat
_ Int
_ Width
_ | Bool -> Bool
not (StgToCmmConfig -> Bool
stgToCmmAvx512f StgToCmmConfig
cfg) =
        String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"512-bit wide " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                String
"SIMD vector instructions require -mavx512f."
    checkX86 Width
_ PrimOpVecCat
_ Int
_ Width
_ = () -> FCode ()
forall a. a -> FCode a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    checkAArch64 :: Width -> FCode ()
    checkAArch64 :: Width -> FCode ()
checkAArch64 Width
W256 = String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"256-bit wide SIMD vector instructions are not supported."
    checkAArch64 Width
W512 = String -> FCode ()
forall a. HasCallStack => String -> a
sorry (String -> FCode ()) -> String -> FCode ()
forall a b. (a -> b) -> a -> b
$ String
"512-bit wide SIMD vector instructions are not supported."
    checkAArch64 Width
_ = () -> FCode ()
forall a. a -> FCode a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    vecWidth :: Width
vecWidth = CmmType -> Width
typeWidth (PrimOpVecCat -> Int -> Width -> CmmType
vecCmmType PrimOpVecCat
vcat Int
l Width
w)

------------------------------------------------------------------------------
-- Helpers for translating vector packing and unpacking.

doVecBroadcastOp :: CmmType       -- Type of vector
                 -> CmmExpr       -- Element
                 -> CmmFormal     -- Destination for result
                 -> FCode ()
doVecBroadcastOp :: CmmType -> CmmExpr -> LocalReg -> FCode ()
doVecBroadcastOp CmmType
ty CmmExpr
e LocalReg
dst
  | CmmType -> Bool
isFloatType (CmmType -> CmmType
vecElemType CmmType
ty)
  = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
dst) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_VF_Broadcast Int
len Width
wid) [CmmExpr
e])
  | Bool
otherwise
  = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
dst) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_V_Broadcast Int
len Width
wid) [CmmExpr
e])
  where
    len :: Length
    len :: Int
len = CmmType -> Int
vecLength CmmType
ty
    wid :: Width
    wid :: Width
wid = CmmType -> Width
typeWidth (CmmType -> CmmType
vecElemType CmmType
ty)

doVecPackOp :: CmmType       -- Type of vector
            -> [CmmExpr]     -- Elements
            -> CmmFormal     -- Destination for result
            -> FCode ()
doVecPackOp :: CmmType -> [CmmExpr] -> LocalReg -> FCode ()
doVecPackOp CmmType
ty [CmmExpr]
es LocalReg
dst = do
  CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
dst) (CmmLit -> CmmExpr
CmmLit (CmmLit -> CmmExpr) -> CmmLit -> CmmExpr
forall a b. (a -> b) -> a -> b
$ [CmmLit] -> CmmLit
CmmVec (Int -> CmmLit -> [CmmLit]
forall a. Int -> a -> [a]
replicate Int
l CmmLit
zero))
  (CmmExpr -> Int -> FCode ()) -> [CmmExpr] -> [Int] -> FCode ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ CmmExpr -> Int -> FCode ()
vecPack [CmmExpr]
es [Int
0..]
  where
    -- SIMD NCG TODO: it should be possible to emit better code
    -- for "pack" than doing a bunch of vector insertions in a row.
    vecPack :: CmmExpr -> Int -> FCode ()
    vecPack :: CmmExpr -> Int -> FCode ()
vecPack CmmExpr
e Int
i
      | CmmType -> Bool
isFloatType (CmmType -> CmmType
vecElemType CmmType
ty)
      = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
dst) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_VF_Insert Int
l Width
w)
                                             [CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
dst), CmmExpr
e, CmmExpr
iLit])
      | Bool
otherwise
      = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
dst) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_V_Insert Int
l Width
w)
                                             [CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
dst), CmmExpr
e, CmmExpr
iLit])
      where
        -- vector indices are always 32-bits
        iLit :: CmmExpr
iLit = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
i) Width
W32)

    l :: Length
    l :: Int
l = CmmType -> Int
vecLength CmmType
ty
    w :: Width
    w :: Width
w = CmmType -> Width
typeWidth (CmmType -> CmmType
vecElemType CmmType
ty)

    zero :: CmmLit
    zero :: CmmLit
zero
      | CmmType -> Bool
isFloatType (CmmType -> CmmType
vecElemType CmmType
ty)
      = Rational -> Width -> CmmLit
CmmFloat Rational
0 Width
w
      | Bool
otherwise
      = Integer -> Width -> CmmLit
CmmInt Integer
0 Width
w

doVecUnpackOp :: CmmType       -- Type of vector
              -> CmmExpr       -- Vector
              -> [CmmFormal]   -- Element results
              -> FCode ()
doVecUnpackOp :: CmmType -> CmmExpr -> [LocalReg] -> FCode ()
doVecUnpackOp CmmType
ty CmmExpr
e [LocalReg]
res = (LocalReg -> Int -> FCode ()) -> [LocalReg] -> [Int] -> FCode ()
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m ()
zipWithM_ LocalReg -> Int -> FCode ()
vecUnpack [LocalReg]
res [Int
0..]
  where
    vecUnpack :: CmmFormal -> Int -> FCode ()
    vecUnpack :: LocalReg -> Int -> FCode ()
vecUnpack LocalReg
r Int
i
      | CmmType -> Bool
isFloatType (CmmType -> CmmType
vecElemType CmmType
ty)
      = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
r) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_VF_Extract Int
len Width
wid) [CmmExpr
e, CmmExpr
iLit])
      | Bool
otherwise
      = CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
r) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Int -> Width -> MachOp
MO_V_Extract Int
len Width
wid) [CmmExpr
e, CmmExpr
iLit])
      where
        -- vector indices are always 32-bits
        iLit :: CmmExpr
iLit = CmmLit -> CmmExpr
CmmLit (Integer -> Width -> CmmLit
CmmInt (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
i) Width
W32)

    len :: Length
    len :: Int
len = CmmType -> Int
vecLength CmmType
ty

    wid :: Width
    wid :: Width
wid = CmmType -> Width
typeWidth (CmmType -> CmmType
vecElemType CmmType
ty)

doVecInsertOp :: CmmType       -- Vector type
              -> CmmExpr       -- Source vector
              -> CmmExpr       -- Element
              -> CmmExpr       -- Index at which to insert element
              -> CmmFormal     -- Destination for result
              -> FCode ()
doVecInsertOp :: CmmType -> CmmExpr -> CmmExpr -> CmmExpr -> LocalReg -> FCode ()
doVecInsertOp CmmType
ty CmmExpr
src CmmExpr
e CmmExpr
idx LocalReg
res = do
    platform <- FCode Platform
getPlatform
    -- vector indices are always 32-bits
    let idx' :: CmmExpr
        idx' = MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp (Width -> Width -> MachOp
MO_SS_Conv (Platform -> Width
wordWidth Platform
platform) Width
W32) [CmmExpr
idx]
    if isFloatType (vecElemType ty)
    then emitAssign (CmmLocal res) (CmmMachOp (MO_VF_Insert len wid) [src, e, idx'])
    else emitAssign (CmmLocal res) (CmmMachOp (MO_V_Insert len wid) [src, e, idx'])
  where

    len :: Length
    len :: Int
len = CmmType -> Int
vecLength CmmType
ty

    wid :: Width
    wid :: Width
wid = CmmType -> Width
typeWidth (CmmType -> CmmType
vecElemType CmmType
ty)

------------------------------------------------------------------------------
-- Shuffles

doShuffleOp :: CmmType -> [CmmExpr] -> LocalReg -> FCode ()
doShuffleOp :: CmmType -> [CmmExpr] -> LocalReg -> FCode ()
doShuffleOp CmmType
ty (CmmExpr
v1:CmmExpr
v2:[CmmExpr]
idxs) LocalReg
res
  | CmmType -> Bool
isVecType CmmType
ty
  = case (CmmExpr -> Maybe Int) -> [CmmExpr] -> [Int]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe CmmExpr -> Maybe Int
idx_maybe [CmmExpr]
idxs of
      [Int]
is
        | [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Int]
is Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len
        -> CmmReg -> CmmExpr -> FCode ()
emitAssign (LocalReg -> CmmReg
CmmLocal LocalReg
res) (MachOp -> [CmmExpr] -> CmmExpr
CmmMachOp ([Int] -> MachOp
mo [Int]
is) [CmmExpr
v1,CmmExpr
v2])
        | Bool
otherwise
        -> String -> SDoc -> FCode ()
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"doShuffleOp" (SDoc -> FCode ()) -> SDoc -> FCode ()
forall a b. (a -> b) -> a -> b
$
             [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"shuffle indices must be literals, 0 <= i <" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
len) ]
  | Bool
otherwise
  = String -> SDoc -> FCode ()
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"doShuffleOp" (SDoc -> FCode ()) -> SDoc -> FCode ()
forall a b. (a -> b) -> a -> b
$
        [SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"non-vector argument type:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CmmType -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmType
ty ]
  where
    len :: Int
len = CmmType -> Int
vecLength CmmType
ty
    wid :: Width
wid = CmmType -> Width
typeWidth (CmmType -> Width) -> CmmType -> Width
forall a b. (a -> b) -> a -> b
$ CmmType -> CmmType
vecElemType CmmType
ty
    mo :: [Int] -> MachOp
mo = if CmmType -> Bool
isFloatType (CmmType -> CmmType
vecElemType CmmType
ty)
         then Int -> Width -> [Int] -> MachOp
MO_VF_Shuffle Int
len Width
wid
         else Int -> Width -> [Int] -> MachOp
MO_V_Shuffle  Int
len Width
wid
    idx_maybe :: CmmExpr -> Maybe Int
idx_maybe (CmmLit (CmmInt Integer
i Width
_))
      | let j :: Int; j :: Int
j = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
i
      , Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0, Int
j Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
len
      = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
j
    idx_maybe CmmExpr
_ = Maybe Int
forall a. Maybe a
Nothing
doShuffleOp CmmType
_ [CmmExpr]
_ LocalReg
_ =
  String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"doShuffleOp: wrong number of arguments"

------------------------------------------------------------------------------
-- Helpers for translating prefetching.


-- | Translate byte array prefetch operations into proper primcalls.
doPrefetchByteArrayOp :: Int
                      -> [CmmExpr]
                      -> FCode ()
doPrefetchByteArrayOp :: Int -> [CmmExpr] -> FCode ()
doPrefetchByteArrayOp Int
locality  [CmmExpr
addr,CmmExpr
idx]
   = do profile <- FCode Profile
getProfile
        mkBasicPrefetch locality (arrWordsHdrSize profile)  addr idx
doPrefetchByteArrayOp Int
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doPrefetchByteArrayOp"

-- | Translate mutable byte array prefetch operations into proper primcalls.
doPrefetchMutableByteArrayOp :: Int
                      -> [CmmExpr]
                      -> FCode ()
doPrefetchMutableByteArrayOp :: Int -> [CmmExpr] -> FCode ()
doPrefetchMutableByteArrayOp Int
locality  [CmmExpr
addr,CmmExpr
idx]
   = do profile <- FCode Profile
getProfile
        mkBasicPrefetch locality (arrWordsHdrSize profile)  addr idx
doPrefetchMutableByteArrayOp Int
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doPrefetchByteArrayOp"

-- | Translate address prefetch operations into proper primcalls.
doPrefetchAddrOp ::Int
                 -> [CmmExpr]
                 -> FCode ()
doPrefetchAddrOp :: Int -> [CmmExpr] -> FCode ()
doPrefetchAddrOp Int
locality   [CmmExpr
addr,CmmExpr
idx]
   = Int -> Int -> CmmExpr -> CmmExpr -> FCode ()
mkBasicPrefetch Int
locality Int
0  CmmExpr
addr CmmExpr
idx
doPrefetchAddrOp Int
_ [CmmExpr]
_
   = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doPrefetchAddrOp"

-- | Translate value prefetch operations into proper primcalls.
doPrefetchValueOp :: Int
                 -> [CmmExpr]
                 -> FCode ()
doPrefetchValueOp :: Int -> [CmmExpr] -> FCode ()
doPrefetchValueOp  Int
locality   [CmmExpr
addr]
  =  do platform <- FCode Platform
getPlatform
        mkBasicPrefetch locality 0 addr  (CmmLit (CmmInt 0 (wordWidth platform)))
doPrefetchValueOp Int
_ [CmmExpr]
_
  = String -> FCode ()
forall a. HasCallStack => String -> a
panic String
"GHC.StgToCmm.Prim: doPrefetchValueOp"

-- | helper to generate prefetch primcalls
mkBasicPrefetch :: Int          -- Locality level 0-3
                -> ByteOff      -- Initial offset in bytes
                -> CmmExpr      -- Base address
                -> CmmExpr      -- Index
                -> FCode ()
mkBasicPrefetch :: Int -> Int -> CmmExpr -> CmmExpr -> FCode ()
mkBasicPrefetch Int
locality Int
off CmmExpr
base CmmExpr
idx
   = do platform <- FCode Platform
getPlatform
        emitPrimCall [] (MO_Prefetch_Data locality) [cmmIndexExpr platform W8 (cmmOffsetB platform base off) idx]
        return ()

-- ----------------------------------------------------------------------------
-- Allocating byte arrays

-- | Takes a register to return the newly allocated array in and the
-- size of the new array in bytes. Allocates a new
-- 'MutableByteArray#'.
doNewByteArrayOp :: CmmFormal -> ByteOff -> FCode ()
doNewByteArrayOp :: LocalReg -> Int -> FCode ()
doNewByteArrayOp LocalReg
res_r Int
n = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    let info_ptr = CLabel -> CmmExpr
mkLblExpr CLabel
mkArrWords_infoLabel
        rep = Platform -> Int -> SMRep
arrWordsRep Platform
platform Int
n

    tickyAllocPrim (mkIntExpr platform (arrWordsHdrSize profile))
        (mkIntExpr platform (nonHdrSize platform rep))
        (zeroExpr platform)

    let hdr_size = Profile -> Int
fixedHdrSize Profile
profile

    base <- allocHeapClosure rep info_ptr (cccsExpr platform)
                     [ (mkIntExpr platform n,
                        hdr_size + pc_OFFSET_StgArrBytes_bytes (platformConstants platform))
                     ]

    emit $ mkAssign (CmmLocal res_r) base

-- ----------------------------------------------------------------------------
-- Comparing byte arrays

doCompareByteArraysOp :: LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                     -> FCode ()
doCompareByteArraysOp :: LocalReg
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCompareByteArraysOp LocalReg
res CmmExpr
ba1 CmmExpr
ba1_off CmmExpr
ba2 CmmExpr
ba2_off CmmExpr
n = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    whenCheckBounds $ ifNonZero n $ do
        emitRangeBoundsCheck ba1_off n (byteArraySize platform profile ba1)
        emitRangeBoundsCheck ba2_off n (byteArraySize platform profile ba2)

    ba1_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform ba1 (arrWordsHdrSize profile)) ba1_off
    ba2_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform ba2 (arrWordsHdrSize profile)) ba2_off

    -- short-cut in case of equal pointers avoiding a costly
    -- subroutine call to the memcmp(3) routine; the Cmm logic below
    -- results in assembly code being generated for
    --
    --   cmpPrefix10 :: ByteArray# -> ByteArray# -> Int#
    --   cmpPrefix10 ba1 ba2 = compareByteArrays# ba1 0# ba2 0# 10#
    --
    -- that looks like
    --
    --          leaq 16(%r14),%rax
    --          leaq 16(%rsi),%rbx
    --          xorl %ecx,%ecx
    --          cmpq %rbx,%rax
    --          je l_ptr_eq
    --
    --          ; NB: the common case (unequal pointers) falls-through
    --          ; the conditional jump, and therefore matches the
    --          ; usual static branch prediction convention of modern cpus
    --
    --          subq $8,%rsp
    --          movq %rbx,%rsi
    --          movq %rax,%rdi
    --          movl $10,%edx
    --          xorl %eax,%eax
    --          call memcmp
    --          addq $8,%rsp
    --          movslq %eax,%rax
    --          movq %rax,%rcx
    --  l_ptr_eq:
    --          movq %rcx,%rbx
    --          jmp *(%rbp)

    l_ptr_eq <- newBlockId
    l_ptr_ne <- newBlockId

    emit (mkAssign (CmmLocal res) (zeroExpr platform))
    emit (mkCbranch (cmmEqWord platform ba1_p ba2_p)
                    l_ptr_eq l_ptr_ne (Just False))

    emitLabel l_ptr_ne
    emitMemcmpCall res ba1_p ba2_p n 1

    emitLabel l_ptr_eq

-- ----------------------------------------------------------------------------
-- Copying byte arrays

-- | Takes a source 'ByteArray#', an offset in the source array, a
-- destination 'MutableByteArray#', an offset into the destination
-- array, and the number of bytes to copy.  Copies the given number of
-- bytes from the source array to the destination array.
doCopyByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                  -> FCode ()
doCopyByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayOp = (CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> Alignment
 -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
emitCopyByteArray CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> Alignment
-> FCode ()
forall {p} {p}.
p -> p -> CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
copy
  where
    -- Copy data (we assume the arrays aren't overlapping since
    -- they're of different types)
    copy :: p -> p -> CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
copy p
_src p
_dst CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes Alignment
align =
        CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitCheckedMemcpyCall CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes Alignment
align

-- | Takes a source 'MutableByteArray#', an offset in the source
-- array, a destination 'MutableByteArray#', an offset into the
-- destination array, and the number of bytes to copy.  Copies the
-- given number of bytes from the source array to the destination
-- array.
doCopyMutableByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                         -> FCode ()
doCopyMutableByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayOp = (CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> Alignment
 -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
emitCopyByteArray CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> Alignment
-> FCode ()
copy
  where
    -- The only time the memory might overlap is when the two arrays
    -- we were provided are the same array!
    -- TODO: Optimize branch for common case of no aliasing.
    copy :: CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> Alignment
-> FCode ()
copy CmmExpr
src CmmExpr
dst CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes Alignment
align = do
        platform <- FCode Platform
getPlatform
        (moveCall, cpyCall) <- forkAltPair
            (getCode $ emitMemmoveCall dst_p src_p bytes align)
            (getCode $ emitMemcpyCall  dst_p src_p bytes align)
        emit =<< mkCmmIfThenElse (cmmEqWord platform src dst) moveCall cpyCall

-- | Takes a source 'MutableByteArray#', an offset in the source
-- array, a destination 'MutableByteArray#', an offset into the
-- destination array, and the number of bytes to copy.  Copies the
-- given number of bytes from the source array to the destination
-- array.  Assumes the two ranges are disjoint
doCopyMutableByteArrayNonOverlappingOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                         -> FCode ()
doCopyMutableByteArrayNonOverlappingOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayNonOverlappingOp = (CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> Alignment
 -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
emitCopyByteArray CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> Alignment
-> FCode ()
forall {p} {p}.
p -> p -> CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
copy
  where
    copy :: p -> p -> CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
copy p
_src p
_dst CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes Alignment
align = do
        CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitCheckedMemcpyCall CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes Alignment
align


emitCopyByteArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                      -> Alignment -> FCode ())
                  -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                  -> FCode ()
emitCopyByteArray :: (CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> CmmExpr
 -> Alignment
 -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
emitCopyByteArray CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> CmmExpr
-> Alignment
-> FCode ()
copy CmmExpr
src CmmExpr
src_off CmmExpr
dst CmmExpr
dst_off CmmExpr
n = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    whenCheckBounds $ ifNonZero n $ do
        emitRangeBoundsCheck src_off n (byteArraySize platform profile src)
        emitRangeBoundsCheck dst_off n (byteArraySize platform profile dst)

    let byteArrayAlignment = Platform -> Alignment
wordAlignment Platform
platform
        srcOffAlignment = CmmExpr -> Alignment
cmmExprAlignment CmmExpr
src_off
        dstOffAlignment = CmmExpr -> Alignment
cmmExprAlignment CmmExpr
dst_off
        align = [Alignment] -> Alignment
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [Alignment
byteArrayAlignment, Alignment
srcOffAlignment, Alignment
dstOffAlignment]
    dst_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform dst (arrWordsHdrSize profile)) dst_off
    src_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform src (arrWordsHdrSize profile)) src_off
    copy src dst dst_p src_p n align

-- | Takes a source 'ByteArray#', an offset in the source array, a
-- destination 'Addr#', and the number of bytes to copy.  Copies the given
-- number of bytes from the source array to the destination memory region.
doCopyByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayToAddrOp CmmExpr
src CmmExpr
src_off CmmExpr
dst_p CmmExpr
bytes = do
    -- Use memcpy (we are allowed to assume the arrays aren't overlapping)
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    whenCheckBounds $ ifNonZero bytes $ do
        emitRangeBoundsCheck src_off bytes (byteArraySize platform profile src)
    src_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform src (arrWordsHdrSize profile)) src_off
    emitCheckedMemcpyCall dst_p src_p bytes (mkAlignment 1)

-- | Takes a source 'MutableByteArray#', an offset in the source array, a
-- destination 'Addr#', and the number of bytes to copy.  Copies the given
-- number of bytes from the source array to the destination memory region.
doCopyMutableByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                               -> FCode ()
doCopyMutableByteArrayToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyMutableByteArrayToAddrOp = CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyByteArrayToAddrOp

-- | Takes a source 'Addr#', a destination 'MutableByteArray#', an offset into
-- the destination array, and the number of bytes to copy.  Copies the given
-- number of bytes from the source memory region to the destination array.
doCopyAddrToByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToByteArrayOp CmmExpr
src_p CmmExpr
dst CmmExpr
dst_off CmmExpr
bytes = do
    -- Use memcpy (we are allowed to assume the arrays aren't overlapping)
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    whenCheckBounds $ ifNonZero bytes $ do
        emitRangeBoundsCheck dst_off bytes (byteArraySize platform profile dst)
    dst_p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform dst (arrWordsHdrSize profile)) dst_off
    emitCheckedMemcpyCall dst_p src_p bytes (mkAlignment 1)

-- | Takes a source 'Addr#', a destination 'Addr#', and the number of
-- bytes to copy.  Copies the given number of bytes from the source
-- memory region to the destination array.
doCopyAddrToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrOp CmmExpr
src_p CmmExpr
dst_p CmmExpr
bytes = do
    -- Use memmove; the ranges may overlap
    CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemmoveCall CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes (Int -> Alignment
mkAlignment Int
1)

-- | Takes a source 'Addr#', a destination 'Addr#', and the number of
-- bytes to copy.  Copies the given number of bytes from the source
-- memory region to the destination region.  The regions may not overlap.
doCopyAddrToAddrNonOverlappingOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrNonOverlappingOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doCopyAddrToAddrNonOverlappingOp CmmExpr
src_p CmmExpr
dst_p CmmExpr
bytes = do
    -- Use memcpy; the ranges may not overlap
    CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitCheckedMemcpyCall CmmExpr
dst_p CmmExpr
src_p CmmExpr
bytes (Int -> Alignment
mkAlignment Int
1)

ifNonZero :: CmmExpr -> FCode () -> FCode ()
ifNonZero :: CmmExpr -> FCode () -> FCode ()
ifNonZero CmmExpr
e FCode ()
it = do
    platform <- FCode Platform
getPlatform
    let pred = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmNeWord Platform
platform CmmExpr
e (Platform -> CmmExpr
zeroExpr Platform
platform)
    code <- getCode it
    emit =<< mkCmmIfThen' pred code (Just True)
      -- This function is used for range operation bounds-checks;
      -- Most calls to those ops will not have range length zero.


-- ----------------------------------------------------------------------------
-- Setting byte arrays

-- | Takes a 'MutableByteArray#', an offset into the array, a length,
-- and a byte, and sets each of the selected bytes in the array to the
-- given byte.
doSetByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr
                 -> FCode ()
doSetByteArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doSetByteArrayOp CmmExpr
ba CmmExpr
off CmmExpr
len CmmExpr
c = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    whenCheckBounds $ ifNonZero len $
      emitRangeBoundsCheck off len (byteArraySize platform profile ba)

    let byteArrayAlignment = Platform -> Alignment
wordAlignment Platform
platform -- known since BA is allocated on heap
        offsetAlignment = CmmExpr -> Alignment
cmmExprAlignment CmmExpr
off
        align = Alignment -> Alignment -> Alignment
forall a. Ord a => a -> a -> a
min Alignment
byteArrayAlignment Alignment
offsetAlignment

    p <- assignTempE $ cmmOffsetExpr platform (cmmOffsetB platform ba (arrWordsHdrSize profile)) off
    emitMemsetCall p c len align

-- | Takes an 'Addr#', a length, and a byte, and sets each of the
-- selected bytes in memory to the given byte.
doSetAddrRangeOp :: CmmExpr -> CmmExpr -> CmmExpr
                 -> FCode ()
doSetAddrRangeOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doSetAddrRangeOp CmmExpr
dst CmmExpr
len CmmExpr
c = do
    CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemsetCall CmmExpr
dst CmmExpr
c CmmExpr
len (Int -> Alignment
mkAlignment Int
1)


-- ----------------------------------------------------------------------------
-- Allocating arrays

-- | Allocate a new array.
doNewArrayOp :: CmmFormal             -- ^ return register
             -> SMRep                 -- ^ representation of the array
             -> CLabel                -- ^ info pointer
             -> [(CmmExpr, ByteOff)]  -- ^ header payload
             -> WordOff               -- ^ array size
             -> CmmExpr               -- ^ initial element
             -> FCode ()
doNewArrayOp :: LocalReg
-> SMRep
-> CLabel
-> [(CmmExpr, Int)]
-> Int
-> CmmExpr
-> FCode ()
doNewArrayOp LocalReg
res_r SMRep
rep CLabel
info [(CmmExpr, Int)]
payload Int
n CmmExpr
init = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    let info_ptr = CLabel -> CmmExpr
mkLblExpr CLabel
info

    tickyAllocPrim (mkIntExpr platform (hdrSize profile rep))
        (mkIntExpr platform (nonHdrSize platform rep))
        (zeroExpr platform)

    base <- allocHeapClosure rep info_ptr (cccsExpr platform) payload

    arr <- CmmLocal `fmap` newTemp (bWord platform)
    emit $ mkAssign arr base

    -- Initialise all elements of the array
    let mkOff Int
off = Platform -> CmmExpr -> Int -> CmmExpr
cmmOffsetW Platform
platform (CmmReg -> CmmExpr
CmmReg CmmReg
arr) (Profile -> SMRep -> Int
hdrSizeW Profile
profile SMRep
rep Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
off)
        initialization = [ CmmExpr -> CmmExpr -> CmmAGraph
mkStore (Int -> CmmExpr
mkOff Int
off) CmmExpr
init | Int
off <- [Int
0.. Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1] ]
    emit (catAGraphs initialization)

    emit $ mkAssign (CmmLocal res_r) (CmmReg arr)

-- ----------------------------------------------------------------------------
-- Copying pointer arrays

-- EZY: This code has an unusually high amount of assignTemp calls, seen
-- nowhere else in the code generator.  This is mostly because these
-- "primitive" ops result in a surprisingly large amount of code.  It
-- will likely be worthwhile to optimize what is emitted here, so that
-- our optimization passes don't waste time repeatedly optimizing the
-- same bits of code.

-- More closely imitates 'assignTemp' from the old code generator, which
-- returns a CmmExpr rather than a LocalReg.
assignTempE :: CmmExpr -> FCode CmmExpr
assignTempE :: CmmExpr -> FCode CmmExpr
assignTempE CmmExpr
e = do
    t <- CmmExpr -> FCode LocalReg
assignTemp CmmExpr
e
    return (CmmReg (CmmLocal t))

-- | Takes a source 'Array#', an offset in the source array, a
-- destination 'MutableArray#', an offset into the destination array,
-- and the number of elements to copy.  Copies the given number of
-- elements from the source array to the destination array.
doCopyArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> WordOff
              -> FCode ()
doCopyArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopyArrayOp = (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopyArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
forall {p} {p}. p -> p -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy
  where
    -- Copy data (we assume the arrays aren't overlapping since
    -- they're of different types)
    copy :: p -> p -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy p
_src p
_dst CmmExpr
dst_p CmmExpr
src_p Int
bytes =
        do platform <- FCode Platform
getPlatform
           emitCheckedMemcpyCall dst_p src_p (mkIntExpr platform bytes)
               (wordAlignment platform)


-- | Takes a source 'MutableArray#', an offset in the source array, a
-- destination 'MutableArray#', an offset into the destination array,
-- and the number of elements to copy.  Copies the given number of
-- elements from the source array to the destination array.
doCopyMutableArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> WordOff
                     -> FCode ()
doCopyMutableArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopyMutableArrayOp = (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopyArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy
  where
    -- The only time the memory might overlap is when the two arrays
    -- we were provided are the same array!
    -- TODO: Optimize branch for common case of no aliasing.
    copy :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy CmmExpr
src CmmExpr
dst CmmExpr
dst_p CmmExpr
src_p Int
bytes = do
        platform <- FCode Platform
getPlatform
        (moveCall, cpyCall) <- forkAltPair
            (getCode $ emitMemmoveCall dst_p src_p (mkIntExpr platform bytes)
             (wordAlignment platform))
            (getCode $ emitMemcpyCall  dst_p src_p (mkIntExpr platform bytes)
             (wordAlignment platform))
        emit =<< mkCmmIfThenElse (cmmEqWord platform src dst) moveCall cpyCall

emitCopyArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff
                  -> FCode ())  -- ^ copy function
              -> CmmExpr        -- ^ source array
              -> CmmExpr        -- ^ offset in source array
              -> CmmExpr        -- ^ destination array
              -> CmmExpr        -- ^ offset in destination array
              -> WordOff        -- ^ number of elements to copy
              -> FCode ()
emitCopyArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopyArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy CmmExpr
src0 CmmExpr
src_off CmmExpr
dst0 CmmExpr
dst_off0 Int
n =
    Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
        profile <- FCode Profile
getProfile
        platform <- getPlatform

        -- Passed as arguments (be careful)
        src     <- assignTempE src0
        dst     <- assignTempE dst0
        dst_off <- assignTempE dst_off0

        whenCheckBounds $ do
          emitRangeBoundsCheck src_off (mkIntExpr platform n)
                                       (ptrArraySize platform profile src)
          emitRangeBoundsCheck dst_off (mkIntExpr platform n)
                                       (ptrArraySize platform profile dst)

        -- Nonmoving collector write barrier
        emitCopyUpdRemSetPush platform (arrPtrsHdrSize profile) dst dst_off n

        -- Set the dirty bit in the header.
        emit (setInfo dst (CmmLit (CmmLabel mkMAP_DIRTY_infoLabel)))

        dst_elems_p <- assignTempE $ cmmOffsetB platform dst
                       (arrPtrsHdrSize profile)
        dst_p <- assignTempE $ cmmOffsetExprW platform dst_elems_p dst_off
        src_p <- assignTempE $ cmmOffsetExprW platform
                 (cmmOffsetB platform src (arrPtrsHdrSize profile)) src_off
        let bytes = Platform -> Int -> Int
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform Int
n

        copy src dst dst_p src_p bytes

        -- The base address of the destination card table
        dst_cards_p <- assignTempE $ cmmOffsetExprW platform dst_elems_p
                       (ptrArraySize platform profile dst)

        emitSetCards dst_off dst_cards_p n

doCopySmallArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> WordOff
                   -> FCode ()
doCopySmallArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopySmallArrayOp = (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopySmallArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
forall {p} {p}. p -> p -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy
  where
    -- Copy data (we assume the arrays aren't overlapping since
    -- they're of different types)
    copy :: p -> p -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy p
_src p
_dst CmmExpr
dst_p CmmExpr
src_p Int
bytes =
        do platform <- FCode Platform
getPlatform
           emitCheckedMemcpyCall dst_p src_p (mkIntExpr platform bytes)
               (wordAlignment platform)


doCopySmallMutableArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> WordOff
                          -> FCode ()
doCopySmallMutableArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
doCopySmallMutableArrayOp = (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopySmallArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy
  where
    -- The only time the memory might overlap is when the two arrays
    -- we were provided are the same array!
    -- TODO: Optimize branch for common case of no aliasing.
    copy :: CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy CmmExpr
src CmmExpr
dst CmmExpr
dst_p CmmExpr
src_p Int
bytes = do
        platform <- FCode Platform
getPlatform
        (moveCall, cpyCall) <- forkAltPair
            (getCode $ emitMemmoveCall dst_p src_p (mkIntExpr platform bytes)
             (wordAlignment platform))
            (getCode $ emitMemcpyCall  dst_p src_p (mkIntExpr platform bytes)
             (wordAlignment platform))
        emit =<< mkCmmIfThenElse (cmmEqWord platform src dst) moveCall cpyCall

emitCopySmallArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> ByteOff
                       -> FCode ())  -- ^ copy function
                   -> CmmExpr        -- ^ source array
                   -> CmmExpr        -- ^ offset in source array
                   -> CmmExpr        -- ^ destination array
                   -> CmmExpr        -- ^ offset in destination array
                   -> WordOff        -- ^ number of elements to copy
                   -> FCode ()
emitCopySmallArray :: (CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ())
-> CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopySmallArray CmmExpr -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
copy CmmExpr
src0 CmmExpr
src_off CmmExpr
dst0 CmmExpr
dst_off Int
n =
    Bool -> FCode () -> FCode ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
        profile <- FCode Profile
getProfile
        platform <- getPlatform

        -- Passed as arguments (be careful)
        src     <- assignTempE src0
        dst     <- assignTempE dst0

        whenCheckBounds $ do
          emitRangeBoundsCheck src_off (mkIntExpr platform n)
                                       (smallPtrArraySize platform profile src)
          emitRangeBoundsCheck dst_off (mkIntExpr platform n)
                                       (smallPtrArraySize platform profile dst)

        -- Nonmoving collector write barrier
        emitCopyUpdRemSetPush platform (smallArrPtrsHdrSize profile) dst dst_off n

        -- Set the dirty bit in the header.
        emit (setInfo dst (CmmLit (CmmLabel mkSMAP_DIRTY_infoLabel)))

        dst_p <- assignTempE $ cmmOffsetExprW platform
                 (cmmOffsetB platform dst (smallArrPtrsHdrSize profile)) dst_off
        src_p <- assignTempE $ cmmOffsetExprW platform
                 (cmmOffsetB platform src (smallArrPtrsHdrSize profile)) src_off
        let bytes = Platform -> Int -> Int
forall a. Num a => Platform -> a -> a
wordsToBytes Platform
platform Int
n

        copy src dst dst_p src_p bytes

-- | Takes an info table label, a register to return the newly
-- allocated array in, a source array, an offset in the source array,
-- and the number of elements to copy. Allocates a new array and
-- initializes it from the source array.
emitCloneArray :: CLabel -> CmmFormal -> CmmExpr -> CmmExpr -> WordOff
               -> FCode ()
emitCloneArray :: CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneArray CLabel
info_p LocalReg
res_r CmmExpr
src CmmExpr
src_off Int
n = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform

    let info_ptr = CLabel -> CmmExpr
mkLblExpr CLabel
info_p
        rep = Platform -> Int -> SMRep
arrPtrsRep Platform
platform Int
n

    tickyAllocPrim (mkIntExpr platform (arrPtrsHdrSize profile))
        (mkIntExpr platform (nonHdrSize platform rep))
        (zeroExpr platform)

    let hdr_size = Profile -> Int
fixedHdrSize Profile
profile
        constants = Platform -> PlatformConstants
platformConstants Platform
platform

    base <- allocHeapClosure rep info_ptr (cccsExpr platform)
                     [ (mkIntExpr platform n,
                        hdr_size + pc_OFFSET_StgMutArrPtrs_ptrs constants)
                     , (mkIntExpr platform (nonHdrSizeW rep),
                        hdr_size + pc_OFFSET_StgMutArrPtrs_size constants)
                     ]

    arr <- CmmLocal `fmap` newTemp (bWord platform)
    emit $ mkAssign arr base

    dst_p <- assignTempE $ cmmOffsetB platform (CmmReg arr)
             (arrPtrsHdrSize profile)
    src_p <- assignTempE $ cmmOffsetExprW platform src
             (cmmAddWord platform
              (mkIntExpr platform (arrPtrsHdrSizeW profile)) src_off)

    emitMemcpyCall dst_p src_p (mkIntExpr platform (wordsToBytes platform n))
        (wordAlignment platform)

    emit $ mkAssign (CmmLocal res_r) (CmmReg arr)

-- | Takes an info table label, a register to return the newly
-- allocated array in, a source array, an offset in the source array,
-- and the number of elements to copy. Allocates a new array and
-- initializes it from the source array.
emitCloneSmallArray :: CLabel -> CmmFormal -> CmmExpr -> CmmExpr -> WordOff
                    -> FCode ()
emitCloneSmallArray :: CLabel -> LocalReg -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCloneSmallArray CLabel
info_p LocalReg
res_r CmmExpr
src CmmExpr
src_off Int
n = do
    profile  <- FCode Profile
getProfile
    platform <- getPlatform

    let info_ptr = CLabel -> CmmExpr
mkLblExpr CLabel
info_p
        rep = Int -> SMRep
smallArrPtrsRep Int
n

    tickyAllocPrim (mkIntExpr platform (smallArrPtrsHdrSize profile))
        (mkIntExpr platform (nonHdrSize platform rep))
        (zeroExpr platform)

    let hdr_size = Profile -> Int
fixedHdrSize Profile
profile

    base <- allocHeapClosure rep info_ptr (cccsExpr platform)
                     [ (mkIntExpr platform n,
                        hdr_size + pc_OFFSET_StgSmallMutArrPtrs_ptrs (platformConstants platform))
                     ]

    arr <- CmmLocal `fmap` newTemp (bWord platform)
    emit $ mkAssign arr base

    dst_p <- assignTempE $ cmmOffsetB platform (CmmReg arr)
             (smallArrPtrsHdrSize profile)
    src_p <- assignTempE $ cmmOffsetExprW platform src
             (cmmAddWord platform
              (mkIntExpr platform (smallArrPtrsHdrSizeW profile)) src_off)

    emitMemcpyCall dst_p src_p (mkIntExpr platform (wordsToBytes platform n))
        (wordAlignment platform)

    emit $ mkAssign (CmmLocal res_r) (CmmReg arr)

-- | Takes an offset in the destination array, the base address of
-- the card table, and the number of elements affected (*not* the
-- number of cards). The number of elements may not be zero.
-- Marks the relevant cards as dirty.
emitSetCards :: CmmExpr -> CmmExpr -> WordOff -> FCode ()
emitSetCards :: CmmExpr -> CmmExpr -> Int -> FCode ()
emitSetCards CmmExpr
dst_start CmmExpr
dst_cards_start Int
n = do
    platform <- FCode Platform
getPlatform
    start_card <- assignTempE $ cardCmm platform dst_start
    let end_card = Platform -> CmmExpr -> CmmExpr
cardCmm Platform
platform
                   (Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmSubWord Platform
platform
                    (Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmAddWord Platform
platform CmmExpr
dst_start (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform Int
n))
                    (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform Int
1))
    emitMemsetCall (cmmAddWord platform dst_cards_start start_card)
        (mkIntExpr platform 1)
        (cmmAddWord platform (cmmSubWord platform end_card start_card) (mkIntExpr platform 1))
        (mkAlignment 1) -- no alignment (1 byte)

-- Convert an element index to a card index
cardCmm :: Platform -> CmmExpr -> CmmExpr
cardCmm :: Platform -> CmmExpr -> CmmExpr
cardCmm Platform
platform CmmExpr
i =
    Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmUShrWord Platform
platform CmmExpr
i (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (PlatformConstants -> Int
pc_MUT_ARR_PTRS_CARD_BITS (Platform -> PlatformConstants
platformConstants Platform
platform)))

------------------------------------------------------------------------------
-- SmallArray PrimOp implementations

doReadSmallPtrArrayOp :: LocalReg
                      -> CmmExpr
                      -> CmmExpr
                      -> FCode ()
doReadSmallPtrArrayOp :: LocalReg -> CmmExpr -> CmmExpr -> FCode ()
doReadSmallPtrArrayOp LocalReg
res CmmExpr
addr CmmExpr
idx = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    doSmallPtrArrayBoundsCheck idx addr
    mkBasicIndexedRead True NaturallyAligned (smallArrPtrsHdrSize profile) Nothing (gcWord platform) res addr
        (gcWord platform) idx

doWriteSmallPtrArrayOp :: CmmExpr
                       -> CmmExpr
                       -> CmmExpr
                       -> FCode ()
doWriteSmallPtrArrayOp :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
doWriteSmallPtrArrayOp CmmExpr
addr CmmExpr
idx CmmExpr
val = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    let ty = Platform -> CmmExpr -> CmmType
cmmExprType Platform
platform CmmExpr
val

    doSmallPtrArrayBoundsCheck idx addr

    -- Update remembered set for non-moving collector
    tmp <- newTemp ty
    mkBasicIndexedRead False NaturallyAligned (smallArrPtrsHdrSize profile) Nothing ty tmp addr ty idx
    whenUpdRemSetEnabled $ emitUpdRemSetPush (CmmReg (CmmLocal tmp))

    -- Write barrier needed due to #12469
    mkBasicIndexedWrite True (smallArrPtrsHdrSize profile) addr ty idx val
    emit (setInfo addr (CmmLit (CmmLabel mkSMAP_DIRTY_infoLabel)))

------------------------------------------------------------------------------
-- Atomic read-modify-write

-- | Emit an atomic modification to a byte array element. The result
-- reg contains that previous value of the element. Implies a full
-- memory barrier.
doAtomicByteArrayRMW
            :: LocalReg      -- ^ Result reg
            -> AtomicMachOp  -- ^ Atomic op (e.g. add)
            -> CmmExpr       -- ^ MutableByteArray#
            -> CmmExpr       -- ^ Index
            -> CmmType       -- ^ Type of element by which we are indexing
            -> CmmExpr       -- ^ Op argument (e.g. amount to add)
            -> FCode ()
doAtomicByteArrayRMW :: LocalReg
-> AtomicMachOp
-> CmmExpr
-> CmmExpr
-> CmmType
-> CmmExpr
-> FCode ()
doAtomicByteArrayRMW LocalReg
res AtomicMachOp
amop CmmExpr
mba CmmExpr
idx CmmType
idx_ty CmmExpr
n = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    doByteArrayBoundsCheck idx mba idx_ty idx_ty
    let width = CmmType -> Width
typeWidth CmmType
idx_ty
        addr  = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform (Profile -> Int
arrWordsHdrSize Profile
profile)
                Width
width CmmExpr
mba CmmExpr
idx
    doAtomicAddrRMW res amop addr idx_ty n

doAtomicAddrRMW
            :: LocalReg      -- ^ Result reg
            -> AtomicMachOp  -- ^ Atomic op (e.g. add)
            -> CmmExpr       -- ^ Addr#
            -> CmmType       -- ^ Pointed value type
            -> CmmExpr       -- ^ Op argument (e.g. amount to add)
            -> FCode ()
doAtomicAddrRMW :: LocalReg
-> AtomicMachOp -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicAddrRMW LocalReg
res AtomicMachOp
amop CmmExpr
addr CmmType
ty CmmExpr
n =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> AtomicMachOp -> CallishMachOp
MO_AtomicRMW (CmmType -> Width
typeWidth CmmType
ty) AtomicMachOp
amop)
        [ CmmExpr
addr, CmmExpr
n ]

-- | Emit an atomic read to a byte array that acts as a memory barrier.
doAtomicReadByteArray
    :: LocalReg  -- ^ Result reg
    -> CmmExpr   -- ^ MutableByteArray#
    -> CmmExpr   -- ^ Index
    -> CmmType   -- ^ Type of element by which we are indexing
    -> FCode ()
doAtomicReadByteArray :: LocalReg -> CmmExpr -> CmmExpr -> CmmType -> FCode ()
doAtomicReadByteArray LocalReg
res CmmExpr
mba CmmExpr
idx CmmType
idx_ty = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    doByteArrayBoundsCheck idx mba idx_ty idx_ty
    let width = CmmType -> Width
typeWidth CmmType
idx_ty
        addr  = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform (Profile -> Int
arrWordsHdrSize Profile
profile)
                Width
width CmmExpr
mba CmmExpr
idx
    doAtomicReadAddr res addr idx_ty

-- | Emit an atomic read to an address that acts as a memory barrier.
doAtomicReadAddr
    :: LocalReg  -- ^ Result reg
    -> CmmExpr   -- ^ Addr#
    -> CmmType   -- ^ Type of element by which we are indexing
    -> FCode ()
doAtomicReadAddr :: LocalReg -> CmmExpr -> CmmType -> FCode ()
doAtomicReadAddr LocalReg
res CmmExpr
addr CmmType
ty =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> MemoryOrdering -> CallishMachOp
MO_AtomicRead (CmmType -> Width
typeWidth CmmType
ty) MemoryOrdering
MemOrderSeqCst)
        [ CmmExpr
addr ]

-- | Emit an atomic write to a byte array that acts as a memory barrier.
doAtomicWriteByteArray
    :: CmmExpr   -- ^ MutableByteArray#
    -> CmmExpr   -- ^ Index
    -> CmmType   -- ^ Type of element by which we are indexing
    -> CmmExpr   -- ^ Value to write
    -> FCode ()
doAtomicWriteByteArray :: CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicWriteByteArray CmmExpr
mba CmmExpr
idx CmmType
idx_ty CmmExpr
val = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    doByteArrayBoundsCheck idx mba idx_ty idx_ty
    let width = CmmType -> Width
typeWidth CmmType
idx_ty
        addr  = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform (Profile -> Int
arrWordsHdrSize Profile
profile)
                Width
width CmmExpr
mba CmmExpr
idx
    doAtomicWriteAddr addr idx_ty val

-- | Emit an atomic write to an address that acts as a memory barrier.
doAtomicWriteAddr
    :: CmmExpr   -- ^ Addr#
    -> CmmType   -- ^ Type of element by which we are indexing
    -> CmmExpr   -- ^ Value to write
    -> FCode ()
doAtomicWriteAddr :: CmmExpr -> CmmType -> CmmExpr -> FCode ()
doAtomicWriteAddr CmmExpr
addr CmmType
ty CmmExpr
val =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ {- no results -} ]
        (Width -> MemoryOrdering -> CallishMachOp
MO_AtomicWrite (CmmType -> Width
typeWidth CmmType
ty) MemoryOrdering
MemOrderSeqCst)
        [ CmmExpr
addr, CmmExpr
val ]

doCasByteArray
    :: LocalReg  -- ^ Result reg
    -> CmmExpr   -- ^ MutableByteArray#
    -> CmmExpr   -- ^ Index
    -> CmmType   -- ^ Type of element by which we are indexing
    -> CmmExpr   -- ^ Old value
    -> CmmExpr   -- ^ New value
    -> FCode ()
doCasByteArray :: LocalReg
-> CmmExpr -> CmmExpr -> CmmType -> CmmExpr -> CmmExpr -> FCode ()
doCasByteArray LocalReg
res CmmExpr
mba CmmExpr
idx CmmType
idx_ty CmmExpr
old CmmExpr
new = do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    doByteArrayBoundsCheck idx mba idx_ty idx_ty
    let width = CmmType -> Width
typeWidth CmmType
idx_ty
        addr = Platform -> Int -> Width -> CmmExpr -> CmmExpr -> CmmExpr
cmmIndexOffExpr Platform
platform (Profile -> Int
arrWordsHdrSize Profile
profile)
               Width
width CmmExpr
mba CmmExpr
idx
    emitPrimCall
        [ res ]
        (MO_Cmpxchg width)
        [ addr, old, new ]

------------------------------------------------------------------------------
-- Helpers for emitting function calls

-- | Emit a call to @memcpy@.
emitMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemcpyCall CmmExpr
dst CmmExpr
src CmmExpr
n Alignment
align =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ {-no results-} ]
        (Int -> CallishMachOp
MO_Memcpy (Alignment -> Int
alignmentBytes Alignment
align))
        [ CmmExpr
dst, CmmExpr
src, CmmExpr
n ]

-- | Emit a call to @memcpy@, but check for range
-- overlap when -fcheck-prim-bounds is on.
emitCheckedMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitCheckedMemcpyCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitCheckedMemcpyCall CmmExpr
dst CmmExpr
src CmmExpr
n Alignment
align = do
    FCode () -> FCode ()
whenCheckBounds (FCode Platform
getPlatform FCode Platform -> (Platform -> FCode ()) -> FCode ()
forall a b. FCode a -> (a -> FCode b) -> FCode b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Platform -> FCode ()
doCheck)
    CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemcpyCall CmmExpr
dst CmmExpr
src CmmExpr
n Alignment
align
  where
    doCheck :: Platform -> FCode ()
doCheck Platform
platform = do
        overlapCheckFailed <- FCode () -> FCode CmmAGraph
forall a. FCode a -> FCode CmmAGraph
getCode (FCode () -> FCode CmmAGraph) -> FCode () -> FCode CmmAGraph
forall a b. (a -> b) -> a -> b
$
          [(LocalReg, ForeignHint)]
-> CmmExpr -> [(CmmExpr, ForeignHint)] -> FCode ()
emitCCallNeverReturns [] (CLabel -> CmmExpr
mkLblExpr CLabel
mkMemcpyRangeOverlapLabel) []
        emit =<< mkCmmIfThen' rangesOverlap overlapCheckFailed (Just False)
      where
        rangesOverlap :: CmmExpr
rangesOverlap = (CmmExpr -> CmmExpr -> CmmExpr
checkDiff CmmExpr
dst CmmExpr
src CmmExpr -> CmmExpr -> CmmExpr
`or` CmmExpr -> CmmExpr -> CmmExpr
checkDiff CmmExpr
src CmmExpr
dst) CmmExpr -> CmmExpr -> CmmExpr
`ne` CmmExpr
zero
        checkDiff :: CmmExpr -> CmmExpr -> CmmExpr
checkDiff CmmExpr
p CmmExpr
q = (CmmExpr
p CmmExpr -> CmmExpr -> CmmExpr
`minus` CmmExpr
q) CmmExpr -> CmmExpr -> CmmExpr
`uLT` CmmExpr
n
        or :: CmmExpr -> CmmExpr -> CmmExpr
or = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmOrWord Platform
platform
        minus :: CmmExpr -> CmmExpr -> CmmExpr
minus = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmSubWord Platform
platform
        uLT :: CmmExpr -> CmmExpr -> CmmExpr
uLT  = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmULtWord Platform
platform
        ne :: CmmExpr -> CmmExpr -> CmmExpr
ne   = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmNeWord Platform
platform
        zero :: CmmExpr
zero = Platform -> CmmExpr
zeroExpr Platform
platform

-- | Emit a call to @memmove@.
emitMemmoveCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemmoveCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemmoveCall CmmExpr
dst CmmExpr
src CmmExpr
n Alignment
align =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ {- no results -} ]
        (Int -> CallishMachOp
MO_Memmove (Alignment -> Int
alignmentBytes Alignment
align))
        [ CmmExpr
dst, CmmExpr
src, CmmExpr
n ]

-- | Emit a call to @memset@.  The second argument must fit inside an
-- unsigned char.
emitMemsetCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemsetCall :: CmmExpr -> CmmExpr -> CmmExpr -> Alignment -> FCode ()
emitMemsetCall CmmExpr
dst CmmExpr
c CmmExpr
n Alignment
align =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ {- no results -} ]
        (Int -> CallishMachOp
MO_Memset (Alignment -> Int
alignmentBytes Alignment
align))
        [ CmmExpr
dst, CmmExpr
c, CmmExpr
n ]

emitMemcmpCall :: LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitMemcmpCall :: LocalReg -> CmmExpr -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitMemcmpCall LocalReg
res CmmExpr
ptr1 CmmExpr
ptr2 CmmExpr
n Int
align = do
    -- 'MO_Memcmp' is assumed to return an 32bit 'CInt' because all
    -- code-gens currently call out to the @memcmp(3)@ C function.
    -- This was easier than moving the sign-extensions into
    -- all the code-gens.
    platform <- FCode Platform
getPlatform
    let is32Bit = CmmType -> Width
typeWidth (LocalReg -> CmmType
localRegType LocalReg
res) Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W32

    cres <- if is32Bit
              then return res
              else newTemp b32

    emitPrimCall
        [ cres ]
        (MO_Memcmp align)
        [ ptr1, ptr2, n ]

    unless is32Bit $
      emit $ mkAssign (CmmLocal res)
                      (CmmMachOp
                         (mo_s_32ToWord platform)
                         [(CmmReg (CmmLocal cres))])

emitBSwapCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitBSwapCall LocalReg
res CmmExpr
x Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_BSwap Width
width)
        [ CmmExpr
x ]

emitBRevCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitBRevCall LocalReg
res CmmExpr
x Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_BRev Width
width)
        [ CmmExpr
x ]

emitPopCntCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitPopCntCall LocalReg
res CmmExpr
x Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_PopCnt Width
width)
        [ CmmExpr
x ]

emitPdepCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPdepCall LocalReg
res CmmExpr
x CmmExpr
y Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_Pdep Width
width)
        [ CmmExpr
x, CmmExpr
y ]

emitPextCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall :: LocalReg -> CmmExpr -> CmmExpr -> Width -> FCode ()
emitPextCall LocalReg
res CmmExpr
x CmmExpr
y Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_Pext Width
width)
        [ CmmExpr
x, CmmExpr
y ]

emitClzCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitClzCall LocalReg
res CmmExpr
x Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_Clz Width
width)
        [ CmmExpr
x ]

emitCtzCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall :: LocalReg -> CmmExpr -> Width -> FCode ()
emitCtzCall LocalReg
res CmmExpr
x Width
width =
    [LocalReg] -> CallishMachOp -> [CmmExpr] -> FCode ()
emitPrimCall
        [ LocalReg
res ]
        (Width -> CallishMachOp
MO_Ctz Width
width)
        [ CmmExpr
x ]

---------------------------------------------------------------------------
-- Array bounds checking
---------------------------------------------------------------------------

whenCheckBounds :: FCode () -> FCode ()
whenCheckBounds :: FCode () -> FCode ()
whenCheckBounds FCode ()
a = do
  config <- FCode StgToCmmConfig
getStgToCmmConfig
  case stgToCmmDoBoundsCheck config of
    Bool
False -> () -> FCode ()
forall a. a -> FCode a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    Bool
True  -> FCode ()
a

emitBoundsCheck :: CmmExpr  -- ^ accessed index
                -> CmmExpr  -- ^ array size (in elements)
                -> FCode ()
emitBoundsCheck :: CmmExpr -> CmmExpr -> FCode ()
emitBoundsCheck CmmExpr
idx CmmExpr
sz = do
    FCode Bool -> FCode ()
forall (m :: * -> *). (HasCallStack, Monad m) => m Bool -> m ()
assertM (StgToCmmConfig -> Bool
stgToCmmDoBoundsCheck (StgToCmmConfig -> Bool) -> FCode StgToCmmConfig -> FCode Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FCode StgToCmmConfig
getStgToCmmConfig)
    platform <- FCode Platform
getPlatform
    boundsCheckFailed <- getCode $
      emitCCallNeverReturns [] (mkLblExpr mkOutOfBoundsAccessLabel) []
    let isOutOfBounds = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmUGeWord Platform
platform CmmExpr
idx CmmExpr
sz
    emit =<< mkCmmIfThen' isOutOfBounds boundsCheckFailed (Just False)

emitRangeBoundsCheck :: CmmExpr  -- ^ first accessed index
                     -> CmmExpr  -- ^ number of accessed indices (non-zero)
                     -> CmmExpr  -- ^ array size (in elements)
                     -> FCode ()
emitRangeBoundsCheck :: CmmExpr -> CmmExpr -> CmmExpr -> FCode ()
emitRangeBoundsCheck CmmExpr
idx CmmExpr
len CmmExpr
arrSizeExpr = do
    FCode Bool -> FCode ()
forall (m :: * -> *). (HasCallStack, Monad m) => m Bool -> m ()
assertM (StgToCmmConfig -> Bool
stgToCmmDoBoundsCheck (StgToCmmConfig -> Bool) -> FCode StgToCmmConfig -> FCode Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FCode StgToCmmConfig
getStgToCmmConfig)
    config <- FCode StgToCmmConfig
getStgToCmmConfig
    platform <- getPlatform
    arrSize <- assignTempE arrSizeExpr
    -- arrSizeExpr is probably a load we don't want to duplicate
    rangeTooLargeReg <- newTemp (bWord platform)
    lastSafeIndexReg <- newTemp (bWord platform)
    _ <- withSequel (AssignTo [lastSafeIndexReg, rangeTooLargeReg] False) $
      cmmPrimOpApp config WordSubCOp [arrSize, len] Nothing
    boundsCheckFailed <- getCode $
      emitCCallNeverReturns [] (mkLblExpr mkOutOfBoundsAccessLabel) []
    let
      rangeTooLarge = CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
rangeTooLargeReg)
      lastSafeIndex = CmmReg -> CmmExpr
CmmReg (LocalReg -> CmmReg
CmmLocal LocalReg
lastSafeIndexReg)
      badStartIndex = (CmmExpr
idx CmmExpr -> CmmExpr -> CmmExpr
`uGT` CmmExpr
lastSafeIndex)
      isOutOfBounds = (CmmExpr
rangeTooLarge CmmExpr -> CmmExpr -> CmmExpr
`or` CmmExpr
badStartIndex) CmmExpr -> CmmExpr -> CmmExpr
`neq` CmmExpr
zero
      uGT = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmUGtWord Platform
platform
      or = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmOrWord Platform
platform
      neq = Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmNeWord Platform
platform
      zero = Platform -> CmmExpr
zeroExpr Platform
platform
    emit =<< mkCmmIfThen' isOutOfBounds boundsCheckFailed (Just False)

doPtrArrayBoundsCheck
    :: CmmExpr  -- ^ accessed index (in bytes)
    -> CmmExpr  -- ^ pointer to @StgMutArrPtrs@
    -> FCode ()
doPtrArrayBoundsCheck :: CmmExpr -> CmmExpr -> FCode ()
doPtrArrayBoundsCheck CmmExpr
idx CmmExpr
arr = FCode () -> FCode ()
whenCheckBounds (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    emitBoundsCheck idx (ptrArraySize platform profile arr)

doSmallPtrArrayBoundsCheck
    :: CmmExpr  -- ^ accessed index (in bytes)
    -> CmmExpr  -- ^ pointer to @StgMutArrPtrs@
    -> FCode ()
doSmallPtrArrayBoundsCheck :: CmmExpr -> CmmExpr -> FCode ()
doSmallPtrArrayBoundsCheck CmmExpr
idx CmmExpr
arr = FCode () -> FCode ()
whenCheckBounds (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    emitBoundsCheck idx (smallPtrArraySize platform profile arr)

doByteArrayBoundsCheck
    :: CmmExpr  -- ^ accessed index (in elements)
    -> CmmExpr  -- ^ pointer to @StgArrBytes@
    -> CmmType  -- ^ indexing type
    -> CmmType  -- ^ element type
    -> FCode ()
doByteArrayBoundsCheck :: CmmExpr -> CmmExpr -> CmmType -> CmmType -> FCode ()
doByteArrayBoundsCheck CmmExpr
idx CmmExpr
arr CmmType
idx_ty CmmType
elem_ty = FCode () -> FCode ()
whenCheckBounds (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
    profile <- FCode Profile
getProfile
    platform <- getPlatform
    let elem_w = CmmType -> Width
typeWidth CmmType
elem_ty
        idx_w = CmmType -> Width
typeWidth CmmType
idx_ty
        elem_sz = Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (Int -> CmmExpr) -> Int -> CmmExpr
forall a b. (a -> b) -> a -> b
$ Width -> Int
widthInBytes Width
elem_w
        arr_sz = Platform -> Profile -> CmmExpr -> CmmExpr
byteArraySize Platform
platform Profile
profile CmmExpr
arr
        effective_arr_sz =
          Platform -> CmmExpr -> CmmExpr -> CmmExpr
cmmUShrWord Platform
platform CmmExpr
arr_sz (Platform -> Int -> CmmExpr
mkIntExpr Platform
platform (Width -> Int
widthInLog Width
idx_w))
    if elem_w == idx_w
      then emitBoundsCheck idx effective_arr_sz  -- aligned => simpler check
      else assert (idx_w == W8) (emitRangeBoundsCheck idx elem_sz arr_sz)

-- | Write barrier for @MUT_VAR@ modification.
emitDirtyMutVar :: CmmExpr -> CmmExpr -> FCode ()
emitDirtyMutVar :: CmmExpr -> CmmExpr -> FCode ()
emitDirtyMutVar CmmExpr
mutvar CmmExpr
old_val = do
    cfg <- FCode StgToCmmConfig
getStgToCmmConfig
    platform <- getPlatform
    mkdirtyMutVarCCall <- getCode $! emitCCall
      [{-no results-}]
      (CmmLit (CmmLabel mkDirty_MUT_VAR_Label))
      [(baseExpr platform, AddrHint), (mutvar, AddrHint), (old_val, AddrHint)]

    emit =<< mkCmmIfThen
      (cmmEqWord platform (mkLblExpr mkMUT_VAR_CLEAN_infoLabel)
       (closureInfoPtr platform (stgToCmmAlignCheck cfg) mutvar))
      mkdirtyMutVarCCall

---------------------------------------------------------------------------
-- Pushing to the update remembered set
---------------------------------------------------------------------------

-- | Push a range of pointer-array elements that are about to be copied over to
-- the update remembered set.
emitCopyUpdRemSetPush :: Platform
                      -> ByteOff    -- ^ array header size (in bytes)
                      -> CmmExpr    -- ^ destination array
                      -> CmmExpr    -- ^ offset in destination array (in words)
                      -> Int        -- ^ number of elements to copy
                      -> FCode ()
emitCopyUpdRemSetPush :: Platform -> Int -> CmmExpr -> CmmExpr -> Int -> FCode ()
emitCopyUpdRemSetPush Platform
_platform Int
_hdr_size CmmExpr
_dst CmmExpr
_dst_off Int
0 = () -> FCode ()
forall a. a -> FCode a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
emitCopyUpdRemSetPush Platform
platform Int
hdr_size CmmExpr
dst CmmExpr
dst_off Int
n =
    FCode () -> FCode ()
forall a. FCode a -> FCode ()
whenUpdRemSetEnabled (FCode () -> FCode ()) -> FCode () -> FCode ()
forall a b. (a -> b) -> a -> b
$ do
        updfr_off <- FCode Int
getUpdFrameOff
        graph <- mkCall lbl (NativeNodeCall,NativeReturn) [] args updfr_off []
        emit graph
  where
    lbl :: CmmExpr
lbl = CLabel -> CmmExpr
mkLblExpr (CLabel -> CmmExpr) -> CLabel -> CmmExpr
forall a b. (a -> b) -> a -> b
$ PrimCall -> CLabel
mkPrimCallLabel
          (PrimCall -> CLabel) -> PrimCall -> CLabel
forall a b. (a -> b) -> a -> b
$ FastString -> Unit -> PrimCall
PrimCall (String -> FastString
fsLit String
"stg_copyArray_barrier") Unit
rtsUnit
    args :: [CmmExpr]
args =
      [ Platform -> Int -> CmmExpr
mkIntExpr Platform
platform Int
hdr_size
      , CmmExpr
dst
      , CmmExpr
dst_off
      , Platform -> Int -> CmmExpr
mkIntExpr Platform
platform Int
n
      ]