doNewArrayOp :: CmmFormal             -- ^ return register
             -> SMRep                 -- ^ representation of the array
             -> CLabel                -- ^ info pointer
             -> [(CmmExpr, ByteOff)]  -- ^ header payload
             -> WordOff               -- ^ array size
             -> CmmExpr               -- ^ initial element
             -> FCode ()
doNewArrayOp res_r rep info payload n init = do
    dflags <- getDynFlags

    let info_ptr = mkLblExpr info

    tickyAllocPrim (mkIntExpr dflags (hdrSize dflags rep))
        (mkIntExpr dflags (nonHdrSize dflags rep))
        (zeroExpr dflags)

    base <- allocHeapClosure rep info_ptr curCCS payload

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

    -- Initialise all elements of the the array
    p <- assignTemp $ cmmOffsetB dflags (CmmReg arr) (hdrSize dflags rep)
    for <- newLabelC
    emitLabel for
    let loopBody =
            [ mkStore (CmmReg (CmmLocal p)) init
            , mkAssign (CmmLocal p) (cmmOffsetW dflags (CmmReg (CmmLocal p)) 1)
            , mkBranch for ]
    emit =<< mkCmmIfThen
        (cmmULtWord dflags (CmmReg (CmmLocal p))
         (cmmOffsetW dflags (CmmReg arr)
          (hdrSizeW dflags rep + n)))
        (catAGraphs loopBody)

    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.
doNewArrayOp :: CmmFormal             -- ^ return register
             -> SMRep                 -- ^ representation of the array
             -> CLabel                -- ^ info pointer
             -> [(CmmExpr, ByteOff)]  -- ^ header payload
             -> WordOff               -- ^ array size
             -> CmmExpr               -- ^ initial element
             -> FCode ()
doNewArrayOp res_r rep info payload n init = do
    dflags <- getDynFlags

    let info_ptr = mkLblExpr info

    tickyAllocPrim (mkIntExpr dflags (hdrSize dflags rep))
        (mkIntExpr dflags (nonHdrSize dflags rep))
        (zeroExpr dflags)

    base <- allocHeapClosure rep info_ptr curCCS payload

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

    -- Initialise all elements of the the array
    p <- assignTemp $ cmmOffsetB dflags (CmmReg arr) (hdrSize dflags rep)
    for <- newLabelC
    emitLabel for
    let loopBody =
            [ mkStore (CmmReg (CmmLocal p)) init
            , mkAssign (CmmLocal p) (cmmOffsetW dflags (CmmReg (CmmLocal p)) 1)
            , mkBranch for ]
    emit =<< mkCmmIfThen
        (cmmULtWord dflags (CmmReg (CmmLocal p))
         (cmmOffsetW dflags (CmmReg arr)
          (hdrSizeW dflags rep + n)))
        (catAGraphs loopBody)

    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.
doNewArrayOp res_r rep info payload n init = do
    dflags <- getDynFlags

    let info_ptr = mkLblExpr info

    tickyAllocPrim (mkIntExpr dflags (hdrSize dflags rep))
        (mkIntExpr dflags (nonHdrSize dflags rep))
        (zeroExpr dflags)

    base <- allocHeapClosure rep info_ptr curCCS payload

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

    -- Initialise all elements of the the array
    p <- assignTemp $ cmmOffsetB dflags (CmmReg arr) (hdrSize dflags rep)
    for <- newLabelC
    emitLabel for
    let loopBody =
            [ mkStore (CmmReg (CmmLocal p)) init
            , mkAssign (CmmLocal p) (cmmOffsetW dflags (CmmReg (CmmLocal p)) 1)
            , mkBranch for ]
    emit =<< mkCmmIfThen
        (cmmULtWord dflags (CmmReg (CmmLocal p))
         (cmmOffsetW dflags (CmmReg arr)
          (hdrSizeW dflags rep + n)))
        (catAGraphs loopBody)

    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.