doAtomicReadByteArray
    :: LocalReg  -- ^ Result reg
    -> CmmExpr   -- ^ MutableByteArray#
    -> CmmExpr   -- ^ Index
    -> CmmType   -- ^ Type of element by which we are indexing
    -> FCode ()
doAtomicReadByteArray res mba idx idx_ty = do
    dflags <- getDynFlags
    let width = typeWidth idx_ty
        addr  = cmmIndexOffExpr dflags (arrWordsHdrSize dflags)
                width mba idx
    emitPrimCall
        [ res ]
        (MO_AtomicRead width)
        [ addr ]

-- | Emit an atomic write 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 res mba idx idx_ty = do
    dflags <- getDynFlags
    let width = typeWidth idx_ty
        addr  = cmmIndexOffExpr dflags (arrWordsHdrSize dflags)
                width mba idx
    emitPrimCall
        [ res ]
        (MO_AtomicRead width)
        [ addr ]

-- | Emit an atomic write to a byte array that acts as a memory barrier.
doAtomicReadByteArray res mba idx idx_ty = do
    dflags <- getDynFlags
    let width = typeWidth idx_ty
        addr  = cmmIndexOffExpr dflags (arrWordsHdrSize dflags)
                width mba idx
    emitPrimCall
        [ res ]
        (MO_AtomicRead width)
        [ addr ]

-- | Emit an atomic write to a byte array that acts as a memory barrier.