    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE UndecidableInstances #-}

    module GHC.Cmm.Expr
        ( CmmExpr(..), cmmExprType, cmmExprWidth, cmmExprAlignment, maybeInvertCmmExpr
        , CmmReg(..), cmmRegType, cmmRegWidth
        , CmmLit(..), cmmLitType
        , AlignmentSpec(..)
          -- TODO: Remove:
        , LocalReg(..), localRegType
        , GlobalReg(..), isArgReg, globalRegSpillType
        , GlobalRegUse(..)
        , spReg, hpReg, spLimReg, hpLimReg, nodeReg
        , currentTSOReg, currentNurseryReg, hpAllocReg, cccsReg
        , node, baseReg

        , DefinerOfRegs, UserOfRegs
        , foldRegsDefd, foldRegsUsed
        , foldLocalRegsDefd, foldLocalRegsUsed

        , RegSet, LocalRegSet, GlobalRegSet
        , emptyRegSet, elemRegSet, extendRegSet, deleteFromRegSet, mkRegSet
        , plusRegSet, minusRegSet, timesRegSet, sizeRegSet, nullRegSet
        , regSetToList

        , isTrivialCmmExpr
        , hasNoGlobalRegs
        , isLit
        , isComparisonExpr

        , Area(..)
        , module GHC.Cmm.MachOp
        , module GHC.Cmm.Type
        )
    where

    import GHC.Prelude

    import GHC.Platform
    import GHC.Cmm.BlockId
    import GHC.Cmm.CLabel
    import GHC.Cmm.MachOp
    import GHC.Cmm.Type
    import GHC.Cmm.Reg
    import GHC.Utils.Panic (panic)
    import GHC.Utils.Outputable

    import Data.Maybe
    import Data.Set (Set)
    import qualified Data.Set as Set
    import Numeric ( fromRat )

    import GHC.Types.Basic (Alignment, mkAlignment, alignmentOf)

    -----------------------------------------------------------------------------
    --              CmmExpr
    -- An expression.  Expressions have no side effects.
    -----------------------------------------------------------------------------

    data CmmExpr
      = CmmLit !CmmLit              -- Literal
      | CmmLoad !CmmExpr !CmmType !AlignmentSpec
                                    -- Read memory location
      | CmmReg !CmmReg              -- Contents of register
      | CmmMachOp MachOp [CmmExpr]  -- Machine operation (+, -, *, etc.)
      | CmmStackSlot Area {-# UNPACK #-} !Int
                                    -- Addressing expression of a stack slot
                                    -- See Note [CmmStackSlot aliasing]
      | CmmRegOff !CmmReg !Int
            -- CmmRegOff reg i
            --        ** is shorthand only, meaning **
            -- CmmMachOp (MO_Add rep) [x, CmmLit (CmmInt (fromIntegral i) rep)]
            --      where rep = typeWidth (cmmRegType reg)
      deriving Int -> CmmExpr -> ShowS
    [CmmExpr] -> ShowS
    CmmExpr -> String
    (Int -> CmmExpr -> ShowS)
    -> (CmmExpr -> String) -> ([CmmExpr] -> ShowS) -> Show CmmExpr
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CmmExpr -> ShowS
    showsPrec :: Int -> CmmExpr -> ShowS
    $cshow :: CmmExpr -> String
    show :: CmmExpr -> String
    $cshowList :: [CmmExpr] -> ShowS
    showList :: [CmmExpr] -> ShowS
    Show

    instance Eq CmmExpr where       -- Equality ignores the types
      CmmLit CmmLit
    l1          == :: CmmExpr -> CmmExpr -> Bool
    == CmmLit CmmLit
    l2          = CmmLit
    l1CmmLit -> CmmLit -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CmmLit
    l2
      CmmLoad CmmExpr
    e1 CmmType
    _ AlignmentSpec
    _     == CmmLoad CmmExpr
    e2 CmmType
    _ AlignmentSpec
    _     = CmmExpr
    e1CmmExpr -> CmmExpr -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CmmExpr
    e2
      CmmReg CmmReg
    r1          == CmmReg CmmReg
    r2          = CmmReg
    r1CmmReg -> CmmReg -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CmmReg
    r2
      CmmRegOff CmmReg
    r1 Int
    i1    == CmmRegOff CmmReg
    r2 Int
    i2    = CmmReg
    r1CmmReg -> CmmReg -> Bool
    forall a. Eq a => a -> a -> Bool
    ==CmmReg
    r2 Bool -> Bool -> Bool
    && Int
    i1Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Int
    i2
      CmmMachOp MachOp
    op1 [CmmExpr]
    es1  == CmmMachOp MachOp
    op2 [CmmExpr]
    es2  = MachOp
    op1MachOp -> MachOp -> Bool
    forall a. Eq a => a -> a -> Bool
    ==MachOp
    op2 Bool -> Bool -> Bool
    && [CmmExpr]
    es1[CmmExpr] -> [CmmExpr] -> Bool
    forall a. Eq a => a -> a -> Bool
    ==[CmmExpr]
    es2
      CmmStackSlot Area
    a1 Int
    i1 == CmmStackSlot Area
    a2 Int
    i2 = Area
    a1Area -> Area -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Area
    a2 Bool -> Bool -> Bool
    && Int
    i1Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Int
    i2
      CmmExpr
    _e1                == CmmExpr
    _e2                = Bool
    False

    instance OutputableP Platform CmmExpr where
        pdoc :: Platform -> CmmExpr -> SDoc
    pdoc = Platform -> CmmExpr -> SDoc
    pprExpr

    data AlignmentSpec = NaturallyAligned | Unaligned
      deriving (AlignmentSpec -> AlignmentSpec -> Bool
    (AlignmentSpec -> AlignmentSpec -> Bool)
    -> (AlignmentSpec -> AlignmentSpec -> Bool) -> Eq AlignmentSpec
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: AlignmentSpec -> AlignmentSpec -> Bool
    == :: AlignmentSpec -> AlignmentSpec -> Bool
    $c/= :: AlignmentSpec -> AlignmentSpec -> Bool
    /= :: AlignmentSpec -> AlignmentSpec -> Bool
    Eq, Eq AlignmentSpec
    Eq AlignmentSpec =>
    (AlignmentSpec -> AlignmentSpec -> Ordering)
    -> (AlignmentSpec -> AlignmentSpec -> Bool)
    -> (AlignmentSpec -> AlignmentSpec -> Bool)
    -> (AlignmentSpec -> AlignmentSpec -> Bool)
    -> (AlignmentSpec -> AlignmentSpec -> Bool)
    -> (AlignmentSpec -> AlignmentSpec -> AlignmentSpec)
    -> (AlignmentSpec -> AlignmentSpec -> AlignmentSpec)
    -> Ord AlignmentSpec
    AlignmentSpec -> AlignmentSpec -> Bool
    AlignmentSpec -> AlignmentSpec -> Ordering
    AlignmentSpec -> AlignmentSpec -> AlignmentSpec
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: AlignmentSpec -> AlignmentSpec -> Ordering
    compare :: AlignmentSpec -> AlignmentSpec -> Ordering
    $c< :: AlignmentSpec -> AlignmentSpec -> Bool
    < :: AlignmentSpec -> AlignmentSpec -> Bool
    $c<= :: AlignmentSpec -> AlignmentSpec -> Bool
    <= :: AlignmentSpec -> AlignmentSpec -> Bool
    $c> :: AlignmentSpec -> AlignmentSpec -> Bool
    > :: AlignmentSpec -> AlignmentSpec -> Bool
    $c>= :: AlignmentSpec -> AlignmentSpec -> Bool
    >= :: AlignmentSpec -> AlignmentSpec -> Bool
    $cmax :: AlignmentSpec -> AlignmentSpec -> AlignmentSpec
    max :: AlignmentSpec -> AlignmentSpec -> AlignmentSpec
    $cmin :: AlignmentSpec -> AlignmentSpec -> AlignmentSpec
    min :: AlignmentSpec -> AlignmentSpec -> AlignmentSpec
    Ord, Int -> AlignmentSpec -> ShowS
    [AlignmentSpec] -> ShowS
    AlignmentSpec -> String
    (Int -> AlignmentSpec -> ShowS)
    -> (AlignmentSpec -> String)
    -> ([AlignmentSpec] -> ShowS)
    -> Show AlignmentSpec
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> AlignmentSpec -> ShowS
    showsPrec :: Int -> AlignmentSpec -> ShowS
    $cshow :: AlignmentSpec -> String
    show :: AlignmentSpec -> String
    $cshowList :: [AlignmentSpec] -> ShowS
    showList :: [AlignmentSpec] -> ShowS
    Show)

    -- | A stack area is either the stack slot where a variable is spilled
    -- or the stack space where function arguments and results are passed.
    data Area
      = Old            -- See Note [Old Area]
      | Young {-# UNPACK #-} !BlockId  -- Invariant: must be a continuation BlockId
                       -- See Note [Continuation BlockIds] in GHC.Cmm.Node.
      deriving (Area -> Area -> Bool
    (Area -> Area -> Bool) -> (Area -> Area -> Bool) -> Eq Area
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Area -> Area -> Bool
    == :: Area -> Area -> Bool
    $c/= :: Area -> Area -> Bool
    /= :: Area -> Area -> Bool
    Eq, Eq Area
    Eq Area =>
    (Area -> Area -> Ordering)
    -> (Area -> Area -> Bool)
    -> (Area -> Area -> Bool)
    -> (Area -> Area -> Bool)
    -> (Area -> Area -> Bool)
    -> (Area -> Area -> Area)
    -> (Area -> Area -> Area)
    -> Ord Area
    Area -> Area -> Bool
    Area -> Area -> Ordering
    Area -> Area -> Area
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: Area -> Area -> Ordering
    compare :: Area -> Area -> Ordering
    $c< :: Area -> Area -> Bool
    < :: Area -> Area -> Bool
    $c<= :: Area -> Area -> Bool
    <= :: Area -> Area -> Bool
    $c> :: Area -> Area -> Bool
    > :: Area -> Area -> Bool
    $c>= :: Area -> Area -> Bool
    >= :: Area -> Area -> Bool
    $cmax :: Area -> Area -> Area
    max :: Area -> Area -> Area
    $cmin :: Area -> Area -> Area
    min :: Area -> Area -> Area
    Ord, Int -> Area -> ShowS
    [Area] -> ShowS
    Area -> String
    (Int -> Area -> ShowS)
    -> (Area -> String) -> ([Area] -> ShowS) -> Show Area
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Area -> ShowS
    showsPrec :: Int -> Area -> ShowS
    $cshow :: Area -> String
    show :: Area -> String
    $cshowList :: [Area] -> ShowS
    showList :: [Area] -> ShowS
    Show)

    instance Outputable Area where
        ppr :: Area -> SDoc
    ppr Area
    e = Area -> SDoc
    pprArea Area
    e

    pprArea :: Area -> SDoc
    pprArea :: Area -> SDoc
    pprArea Area
    Old        = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "old"
    pprArea (Young BlockId
    id) = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hcat [ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "young<", BlockId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr BlockId
    id, String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    ">" ]

    {- Note [Old Area]
    ~~~~~~~~~~~~~~~~~~
    There is a single call area 'Old', allocated at the extreme old
    end of the stack frame (ie just younger than the return address)
    which holds:
      * incoming (overflow) parameters,
      * outgoing (overflow) parameter to tail calls,
      * outgoing (overflow) result values
      * the update frame (if any)

    Its size is the max of all these requirements.  On entry, the stack
    pointer will point to the youngest incoming parameter, which is not
    necessarily at the young end of the Old area.

    End of note -}

    {- Note [CmmStackSlot aliasing]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    When do two CmmStackSlots alias?

     - T[old+N] aliases with U[young(L)+M] for all T, U, L, N and M
     - T[old+N] aliases with U[old+M] only if the areas actually overlap

    Or more informally, different Areas may overlap with each other.

    An alternative semantics, that we previously had, was that different
    Areas do not overlap.  The problem that lead to redefining the
    semantics of stack areas is described below.

    e.g. if we had

        x = Sp[old + 8]
        y = Sp[old + 16]

        Sp[young(L) + 8]  = L
        Sp[young(L) + 16] = y
        Sp[young(L) + 24] = x
        call f() returns to L

    if areas semantically do not overlap, then we might optimise this to

        Sp[young(L) + 8]  = L
        Sp[young(L) + 16] = Sp[old + 8]
        Sp[young(L) + 24] = Sp[old + 16]
        call f() returns to L

    and now young(L) cannot be allocated at the same place as old, and we
    are doomed to use more stack.

      - old+8  conflicts with young(L)+8
      - old+16 conflicts with young(L)+16 and young(L)+8

    so young(L)+8 == old+24 and we get

        Sp[-8]  = L
        Sp[-16] = Sp[8]
        Sp[-24] = Sp[0]
        Sp -= 24
        call f() returns to L

    However, if areas are defined to be "possibly overlapping" in the
    semantics, then we cannot commute any loads/stores of old with
    young(L), and we will be able to re-use both old+8 and old+16 for
    young(L).

        x = Sp[8]
        y = Sp[0]

        Sp[8] = L
        Sp[0] = y
        Sp[-8] = x
        Sp = Sp - 8
        call f() returns to L

    Now, the assignments of y go away,

        x = Sp[8]
        Sp[8] = L
        Sp[-8] = x
        Sp = Sp - 8
        call f() returns to L
    -}

    data CmmLit
      = CmmInt !Integer  !Width
            -- Interpretation: the 2's complement representation of the value
            -- is truncated to the specified size.  This is easier than trying
            -- to keep the value within range, because we don't know whether
            -- it will be used as a signed or unsigned value (the CmmType doesn't
            -- distinguish between signed & unsigned).
      | CmmFloat  Rational !Width
      | CmmVec [CmmLit]                     -- Vector literal
      | CmmLabel    CLabel                  -- Address of label
      | CmmLabelOff CLabel !Int              -- Address of label + byte offset

            -- Due to limitations in the C backend, the following
            -- MUST ONLY be used inside the info table indicated by label2
            -- (label2 must be the info label), and label1 must be an
            -- SRT, a slow entrypoint or a large bitmap (see the Mangler)
            -- Don't use it at all unless tablesNextToCode.
            -- It is also used inside the NCG during when generating
            -- position-independent code.
      | CmmLabelDiffOff CLabel CLabel !Int !Width -- label1 - label2 + offset
            -- In an expression, the width just has the effect of MO_SS_Conv
            -- from wordWidth to the desired width.
            --
            -- In a static literal, the supported Widths depend on the
            -- architecture: wordWidth is supported on all
            -- architectures. Additionally W32 is supported on x86_64 when
            -- using the small memory model.

      | CmmBlock {-# UNPACK #-} !BlockId     -- Code label
            -- Invariant: must be a continuation BlockId
            -- See Note [Continuation BlockIds] in GHC.Cmm.Node.

      | CmmHighStackMark -- A late-bound constant that stands for the max
                         -- #bytes of stack space used during a procedure.
                         -- During the stack-layout pass, CmmHighStackMark
                         -- is replaced by a CmmInt for the actual number
                         -- of bytes used
      deriving (CmmLit -> CmmLit -> Bool
    (CmmLit -> CmmLit -> Bool)
    -> (CmmLit -> CmmLit -> Bool) -> Eq CmmLit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CmmLit -> CmmLit -> Bool
    == :: CmmLit -> CmmLit -> Bool
    $c/= :: CmmLit -> CmmLit -> Bool
    /= :: CmmLit -> CmmLit -> Bool
    Eq, Int -> CmmLit -> ShowS
    [CmmLit] -> ShowS
    CmmLit -> String
    (Int -> CmmLit -> ShowS)
    -> (CmmLit -> String) -> ([CmmLit] -> ShowS) -> Show CmmLit
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CmmLit -> ShowS
    showsPrec :: Int -> CmmLit -> ShowS
    $cshow :: CmmLit -> String
    show :: CmmLit -> String
    $cshowList :: [CmmLit] -> ShowS
    showList :: [CmmLit] -> ShowS
    Show)

    instance OutputableP Platform CmmLit where
        pdoc :: Platform -> CmmLit -> SDoc
    pdoc = Platform -> CmmLit -> SDoc
    pprLit

    instance Outputable CmmLit where
      ppr :: CmmLit -> SDoc
    ppr (CmmInt Integer
    n Width
    w) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmInt" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Integer -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Integer
    n SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    w
      ppr (CmmFloat Rational
    n Width
    w) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmFloat" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text (Rational -> String
    forall a. Show a => a -> String
    show Rational
    n) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    w
      ppr (CmmVec [CmmLit]
    xs) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmVec" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> [CmmLit] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [CmmLit]
    xs
      ppr (CmmLabel CLabel
    _) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmLabel"
      ppr (CmmLabelOff CLabel
    _ Int
    _) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmLabelOff"
      ppr (CmmLabelDiffOff CLabel
    _ CLabel
    _ Int
    _ Width
    _) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmLabelDiffOff"
      ppr (CmmBlock BlockId
    blk) = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmBlock" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> BlockId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr BlockId
    blk
      ppr CmmLit
    CmmHighStackMark = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "CmmHighStackMark"

    cmmExprType :: Platform -> CmmExpr -> CmmType
    cmmExprType :: Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform = \case
       (CmmLit CmmLit
    lit)        -> Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform CmmLit
    lit
       (CmmLoad CmmExpr
    _ CmmType
    rep AlignmentSpec
    _)   -> CmmType
    rep
       (CmmReg CmmReg
    reg)        -> CmmReg -> CmmType
    cmmRegType CmmReg
    reg
       (CmmMachOp MachOp
    op [CmmExpr]
    args) -> Platform -> MachOp -> [CmmType] -> CmmType
    machOpResultType Platform
    platform MachOp
    op ((CmmExpr -> CmmType) -> [CmmExpr] -> [CmmType]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform) [CmmExpr]
    args)
       (CmmRegOff CmmReg
    reg Int
    _)   -> CmmReg -> CmmType
    cmmRegType CmmReg
    reg
       (CmmStackSlot Area
    _ Int
    _)  -> Platform -> CmmType
    bWord Platform
    platform -- an address
       -- Careful though: what is stored at the stack slot may be bigger than
       -- an address

    cmmLitType :: Platform -> CmmLit -> CmmType
    cmmLitType :: Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform = \case
       (CmmInt Integer
    _ Width
    width)     -> Width -> CmmType
    cmmBits  Width
    width
       (CmmFloat Rational
    _ Width
    width)   -> Width -> CmmType
    cmmFloat Width
    width
       (CmmVec [])          -> String -> CmmType
    forall a. HasCallStack => String -> a
    panic String
    "cmmLitType: CmmVec []"
       (CmmVec (CmmLit
    l:[CmmLit]
    ls))      -> let ty :: CmmType
    ty = Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform CmmLit
    l
                              in if (CmmType -> Bool) -> [CmmType] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (CmmType -> CmmType -> Bool
    `cmmEqType` CmmType
    ty) ((CmmLit -> CmmType) -> [CmmLit] -> [CmmType]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform) [CmmLit]
    ls)
                                   then Int -> CmmType -> CmmType
    cmmVec (Int
    1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +[CmmLit] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [CmmLit]
    ls) CmmType
    ty
                                   else String -> CmmType
    forall a. HasCallStack => String -> a
    panic String
    "cmmLitType: CmmVec"
       (CmmLabel CLabel
    lbl)       -> Platform -> CLabel -> CmmType
    cmmLabelType Platform
    platform CLabel
    lbl
       (CmmLabelOff CLabel
    lbl Int
    _)  -> Platform -> CLabel -> CmmType
    cmmLabelType Platform
    platform CLabel
    lbl
       (CmmLabelDiffOff CLabel
    _ CLabel
    _ Int
    _ Width
    width) -> Width -> CmmType
    cmmBits Width
    width
       (CmmBlock BlockId
    _)         -> Platform -> CmmType
    bWord Platform
    platform
       (CmmLit
    CmmHighStackMark)   -> Platform -> CmmType
    bWord Platform
    platform

    cmmLabelType :: Platform -> CLabel -> CmmType
    cmmLabelType :: Platform -> CLabel -> CmmType
    cmmLabelType Platform
    platform CLabel
    lbl
     | CLabel -> Bool
    isGcPtrLabel CLabel
    lbl = Platform -> CmmType
    gcWord Platform
    platform
     | Bool
    otherwise        = Platform -> CmmType
    bWord Platform
    platform

    cmmExprWidth :: Platform -> CmmExpr -> Width
    cmmExprWidth :: Platform -> CmmExpr -> Width
    cmmExprWidth Platform
    platform CmmExpr
    e = CmmType -> Width
    typeWidth (Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform CmmExpr
    e)

    -- | Returns an alignment in bytes of a CmmExpr when it's a statically
    -- known integer constant, otherwise returns an alignment of 1 byte.
    -- The caller is responsible for using with a sensible CmmExpr
    -- argument.
    cmmExprAlignment :: CmmExpr -> Alignment
    cmmExprAlignment :: CmmExpr -> Alignment
    cmmExprAlignment (CmmLit (CmmInt Integer
    intOff Width
    _)) = Int -> Alignment
    alignmentOf (Integer -> Int
    forall a. Num a => Integer -> a
    fromInteger Integer
    intOff)
    cmmExprAlignment CmmExpr
    _                          = Int -> Alignment
    mkAlignment Int
    1
    --------
    --- Negation for conditional branches

    maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
    maybeInvertCmmExpr :: CmmExpr -> Maybe CmmExpr
    maybeInvertCmmExpr (CmmMachOp MachOp
    op [CmmExpr]
    args) = do op' <- MachOp -> Maybe MachOp
    maybeInvertComparison MachOp
    op
                                                return (CmmMachOp op' args)
    maybeInvertCmmExpr CmmExpr
    _ = Maybe CmmExpr
    forall a. Maybe a
    Nothing

    ---------------------------------------------------
    --         CmmExpr predicates
    ---------------------------------------------------

    isTrivialCmmExpr :: CmmExpr -> Bool
    isTrivialCmmExpr :: CmmExpr -> Bool
    isTrivialCmmExpr (CmmLoad CmmExpr
    _ CmmType
    _ AlignmentSpec
    _)    = Bool
    False
    isTrivialCmmExpr (CmmMachOp MachOp
    _ [CmmExpr]
    _)    = Bool
    False
    isTrivialCmmExpr (CmmLit CmmLit
    _)         = Bool
    True
    isTrivialCmmExpr (CmmReg CmmReg
    _)         = Bool
    True
    isTrivialCmmExpr (CmmRegOff CmmReg
    _ Int
    _)    = Bool
    True
    isTrivialCmmExpr (CmmStackSlot Area
    _ Int
    _) = String -> Bool
    forall a. HasCallStack => String -> a
    panic String
    "isTrivialCmmExpr CmmStackSlot"

    hasNoGlobalRegs :: CmmExpr -> Bool
    hasNoGlobalRegs :: CmmExpr -> Bool
    hasNoGlobalRegs (CmmLoad CmmExpr
    e CmmType
    _ AlignmentSpec
    _)            = CmmExpr -> Bool
    hasNoGlobalRegs CmmExpr
    e
    hasNoGlobalRegs (CmmMachOp MachOp
    _ [CmmExpr]
    es)           = (CmmExpr -> Bool) -> [CmmExpr] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all CmmExpr -> Bool
    hasNoGlobalRegs [CmmExpr]
    es
    hasNoGlobalRegs (CmmLit CmmLit
    _)                 = Bool
    True
    hasNoGlobalRegs (CmmReg (CmmLocal LocalReg
    _))      = Bool
    True
    hasNoGlobalRegs (CmmRegOff (CmmLocal LocalReg
    _) Int
    _) = Bool
    True
    hasNoGlobalRegs CmmExpr
    _                          = Bool
    False

    isLit :: CmmExpr -> Bool
    isLit :: CmmExpr -> Bool
    isLit (CmmLit CmmLit
    _) = Bool
    True
    isLit CmmExpr
    _          = Bool
    False

    isComparisonExpr :: CmmExpr -> Bool
    isComparisonExpr :: CmmExpr -> Bool
    isComparisonExpr (CmmMachOp MachOp
    op [CmmExpr]
    _) = MachOp -> Bool
    isComparisonMachOp MachOp
    op
    isComparisonExpr CmmExpr
    _                = Bool
    False

    -----------------------------------------------------------------------------
    --    Register-use information for expressions and other types
    -----------------------------------------------------------------------------

    -- | Sets of registers

    -- These are used for dataflow facts, and a common operation is taking
    -- the union of two RegSets and then asking whether the union is the
    -- same as one of the inputs.  UniqSet isn't good here, because
    -- sizeUniqSet is O(n) whereas Set.size is O(1), so we use ordinary
    -- Sets.

    type RegSet r     = Set r
    type LocalRegSet  = RegSet LocalReg
    type GlobalRegSet = RegSet GlobalReg

    emptyRegSet             :: RegSet r
    nullRegSet              :: RegSet r -> Bool
    elemRegSet              :: Ord r => r -> RegSet r -> Bool
    extendRegSet            :: Ord r => RegSet r -> r -> RegSet r
    deleteFromRegSet        :: Ord r => RegSet r -> r -> RegSet r
    mkRegSet                :: Ord r => [r] -> RegSet r
    minusRegSet, plusRegSet, timesRegSet :: Ord r => RegSet r -> RegSet r -> RegSet r
    sizeRegSet              :: RegSet r -> Int
    regSetToList            :: RegSet r -> [r]

    emptyRegSet :: forall r. RegSet r
    emptyRegSet      = Set r
    forall r. RegSet r
    Set.empty
    nullRegSet :: forall r. RegSet r -> Bool
    nullRegSet       = Set r -> Bool
    forall r. RegSet r -> Bool
    Set.null
    elemRegSet :: forall r. Ord r => r -> RegSet r -> Bool
    elemRegSet       = r -> Set r -> Bool
    forall r. Ord r => r -> RegSet r -> Bool
    Set.member
    extendRegSet :: forall r. Ord r => RegSet r -> r -> RegSet r
    extendRegSet     = (r -> RegSet r -> RegSet r) -> RegSet r -> r -> RegSet r
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip r -> RegSet r -> RegSet r
    forall a. Ord a => a -> Set a -> Set a
    Set.insert
    deleteFromRegSet :: forall r. Ord r => RegSet r -> r -> RegSet r
    deleteFromRegSet = (r -> RegSet r -> RegSet r) -> RegSet r -> r -> RegSet r
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip r -> RegSet r -> RegSet r
    forall a. Ord a => a -> Set a -> Set a
    Set.delete
    mkRegSet :: forall r. Ord r => [r] -> RegSet r
    mkRegSet         = [r] -> Set r
    forall r. Ord r => [r] -> RegSet r
    Set.fromList
    minusRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    minusRegSet      = Set r -> Set r -> Set r
    forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.difference
    plusRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    plusRegSet       = Set r -> Set r -> Set r
    forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.union
    timesRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    timesRegSet      = Set r -> Set r -> Set r
    forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.intersection
    sizeRegSet :: forall r. RegSet r -> Int
    sizeRegSet       = Set r -> Int
    forall r. RegSet r -> Int
    Set.size
    regSetToList :: forall r. RegSet r -> [r]
    regSetToList     = Set r -> [r]
    forall r. RegSet r -> [r]
    Set.toList

    class Ord r => UserOfRegs r a where
      foldRegsUsed :: Platform -> (b -> r -> b) -> b -> a -> b

    foldLocalRegsUsed :: UserOfRegs LocalReg a
                      => Platform -> (b -> LocalReg -> b) -> b -> a -> b
    foldLocalRegsUsed :: forall a b.
    UserOfRegs LocalReg a =>
    Platform -> (b -> LocalReg -> b) -> b -> a -> b
    foldLocalRegsUsed = Platform -> (b -> LocalReg -> b) -> b -> a -> b
    forall b. Platform -> (b -> LocalReg -> b) -> b -> a -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed

    class Ord r => DefinerOfRegs r a where
      foldRegsDefd :: Platform -> (b -> r -> b) -> b -> a -> b

    foldLocalRegsDefd :: DefinerOfRegs LocalReg a
                      => Platform -> (b -> LocalReg -> b) -> b -> a -> b
    foldLocalRegsDefd :: forall a b.
    DefinerOfRegs LocalReg a =>
    Platform -> (b -> LocalReg -> b) -> b -> a -> b
    foldLocalRegsDefd = Platform -> (b -> LocalReg -> b) -> b -> a -> b
    forall b. Platform -> (b -> LocalReg -> b) -> b -> a -> b
    forall r a b.
    DefinerOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsDefd

    instance UserOfRegs LocalReg CmmReg where
        foldRegsUsed :: forall b. Platform -> (b -> LocalReg -> b) -> b -> CmmReg -> b
    foldRegsUsed Platform
    _ b -> LocalReg -> b
    f b
    z (CmmLocal LocalReg
    reg) = b -> LocalReg -> b
    f b
    z LocalReg
    reg
        foldRegsUsed Platform
    _ b -> LocalReg -> b
    _ b
    z (CmmGlobal GlobalRegUse
    _)  = b
    z

    instance DefinerOfRegs LocalReg CmmReg where
        foldRegsDefd :: forall b. Platform -> (b -> LocalReg -> b) -> b -> CmmReg -> b
    foldRegsDefd Platform
    _ b -> LocalReg -> b
    f b
    z (CmmLocal LocalReg
    reg) = b -> LocalReg -> b
    f b
    z LocalReg
    reg
        foldRegsDefd Platform
    _ b -> LocalReg -> b
    _ b
    z (CmmGlobal GlobalRegUse
    _)  = b
    z

    instance UserOfRegs GlobalReg CmmReg where
        {-# INLINEABLE foldRegsUsed #-}
        foldRegsUsed :: forall b. Platform -> (b -> GlobalReg -> b) -> b -> CmmReg -> b
    foldRegsUsed Platform
    _ b -> GlobalReg -> b
    _ b
    z (CmmLocal LocalReg
    _)    = b
    z
        foldRegsUsed Platform
    _ b -> GlobalReg -> b
    f b
    z (CmmGlobal (GlobalRegUse GlobalReg
    reg CmmType
    _)) = b -> GlobalReg -> b
    f b
    z GlobalReg
    reg

    instance UserOfRegs GlobalRegUse CmmReg where
        {-# INLINEABLE foldRegsUsed #-}
        foldRegsUsed :: forall b. Platform -> (b -> GlobalRegUse -> b) -> b -> CmmReg -> b
    foldRegsUsed Platform
    _ b -> GlobalRegUse -> b
    _ b
    z (CmmLocal LocalReg
    _)    = b
    z
        foldRegsUsed Platform
    _ b -> GlobalRegUse -> b
    f b
    z (CmmGlobal GlobalRegUse
    reg) = b -> GlobalRegUse -> b
    f b
    z GlobalRegUse
    reg
    instance DefinerOfRegs GlobalReg CmmReg where
        foldRegsDefd :: forall b. Platform -> (b -> GlobalReg -> b) -> b -> CmmReg -> b
    foldRegsDefd Platform
    _ b -> GlobalReg -> b
    _ b
    z (CmmLocal LocalReg
    _)    = b
    z
        foldRegsDefd Platform
    _ b -> GlobalReg -> b
    f b
    z (CmmGlobal (GlobalRegUse GlobalReg
    reg CmmType
    _)) = b -> GlobalReg -> b
    f b
    z GlobalReg
    reg

    instance DefinerOfRegs GlobalRegUse CmmReg where
        foldRegsDefd :: forall b. Platform -> (b -> GlobalRegUse -> b) -> b -> CmmReg -> b
    foldRegsDefd Platform
    _ b -> GlobalRegUse -> b
    _ b
    z (CmmLocal LocalReg
    _)    = b
    z
        foldRegsDefd Platform
    _ b -> GlobalRegUse -> b
    f b
    z (CmmGlobal GlobalRegUse
    reg) = b -> GlobalRegUse -> b
    f b
    z GlobalRegUse
    reg

    instance Ord r => UserOfRegs r r where
        foldRegsUsed :: forall b. Platform -> (b -> r -> b) -> b -> r -> b
    foldRegsUsed Platform
    _ b -> r -> b
    f b
    z r
    r = b -> r -> b
    f b
    z r
    r

    instance Ord r => DefinerOfRegs r r where
        foldRegsDefd :: forall b. Platform -> (b -> r -> b) -> b -> r -> b
    foldRegsDefd Platform
    _ b -> r -> b
    f b
    z r
    r = b -> r -> b
    f b
    z r
    r

    instance (Ord r, UserOfRegs r CmmReg) => UserOfRegs r CmmExpr where
      -- The (Ord r) in the context is necessary here
      -- See Note [Recursive superclasses] in GHC.Tc.TyCl.Instance
      {-# INLINEABLE foldRegsUsed #-}
      foldRegsUsed :: forall b. Platform -> (b -> r -> b) -> b -> CmmExpr -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f !b
    z CmmExpr
    e = b -> CmmExpr -> b
    expr b
    z CmmExpr
    e
        where expr :: b -> CmmExpr -> b
    expr b
    z (CmmLit CmmLit
    _)          = b
    z
              expr b
    z (CmmLoad CmmExpr
    addr CmmType
    _ AlignmentSpec
    _)  = Platform -> (b -> r -> b) -> b -> CmmExpr -> b
    forall b. Platform -> (b -> r -> b) -> b -> CmmExpr -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f b
    z CmmExpr
    addr
              expr b
    z (CmmReg CmmReg
    r)          = Platform -> (b -> r -> b) -> b -> CmmReg -> b
    forall b. Platform -> (b -> r -> b) -> b -> CmmReg -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f b
    z CmmReg
    r
              expr b
    z (CmmMachOp MachOp
    _ [CmmExpr]
    exprs) = Platform -> (b -> r -> b) -> b -> [CmmExpr] -> b
    forall b. Platform -> (b -> r -> b) -> b -> [CmmExpr] -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f b
    z [CmmExpr]
    exprs
              expr b
    z (CmmRegOff CmmReg
    r Int
    _)     = Platform -> (b -> r -> b) -> b -> CmmReg -> b
    forall b. Platform -> (b -> r -> b) -> b -> CmmReg -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f b
    z CmmReg
    r
              expr b
    z (CmmStackSlot Area
    _ Int
    _)  = b
    z

    instance UserOfRegs r a => UserOfRegs r [a] where
      foldRegsUsed :: forall b. Platform -> (b -> r -> b) -> b -> [a] -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f b
    set [a]
    as = (b -> a -> b) -> b -> [a] -> b
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (Platform -> (b -> r -> b) -> b -> a -> b
    forall b. Platform -> (b -> r -> b) -> b -> a -> b
    forall r a b.
    UserOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsUsed Platform
    platform b -> r -> b
    f) b
    set [a]
    as
      {-# INLINABLE foldRegsUsed #-}

    instance DefinerOfRegs r a => DefinerOfRegs r [a] where
      foldRegsDefd :: forall b. Platform -> (b -> r -> b) -> b -> [a] -> b
    foldRegsDefd Platform
    platform b -> r -> b
    f b
    set [a]
    as = (b -> a -> b) -> b -> [a] -> b
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (Platform -> (b -> r -> b) -> b -> a -> b
    forall b. Platform -> (b -> r -> b) -> b -> a -> b
    forall r a b.
    DefinerOfRegs r a =>
    Platform -> (b -> r -> b) -> b -> a -> b
    foldRegsDefd Platform
    platform b -> r -> b
    f) b
    set [a]
    as
      {-# INLINABLE foldRegsDefd #-}

    -- --------------------------------------------------------------------------
    -- Pretty-printing expressions
    -- --------------------------------------------------------------------------

    pprExpr :: Platform -> CmmExpr -> SDoc
    pprExpr :: Platform -> CmmExpr -> SDoc
    pprExpr Platform
    platform CmmExpr
    e
        = case CmmExpr
    e of
            CmmRegOff CmmReg
    reg Int
    i ->
                    Platform -> CmmExpr -> SDoc
    pprExpr Platform
    platform (MachOp -> [CmmExpr] -> CmmExpr
    CmmMachOp (Width -> MachOp
    MO_Add Width
    rep)
                               [CmmReg -> CmmExpr
    CmmReg CmmReg
    reg, CmmLit -> CmmExpr
    CmmLit (Integer -> Width -> CmmLit
    CmmInt (Int -> Integer
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    i) Width
    rep)])
                    where rep :: Width
    rep = CmmType -> Width
    typeWidth (CmmReg -> CmmType
    cmmRegType CmmReg
    reg)
            CmmLit CmmLit
    lit -> Platform -> CmmLit -> SDoc
    pprLit Platform
    platform CmmLit
    lit
            CmmExpr
    _other     -> Platform -> CmmExpr -> SDoc
    pprExpr1 Platform
    platform CmmExpr
    e

    -- Here's the precedence table from GHC.Cmm.Parser:
    -- %nonassoc '>=' '>' '<=' '<' '!=' '=='
    -- %left '|'
    -- %left '^'
    -- %left '&'
    -- %left '>>' '<<'
    -- %left '-' '+'
    -- %left '/' '*' '%'
    -- %right '~'

    -- We just cope with the common operators for now, the rest will get
    -- a default conservative behaviour.

    -- %nonassoc '>=' '>' '<=' '<' '!=' '=='
    pprExpr1, pprExpr7, pprExpr8 :: Platform -> CmmExpr -> SDoc
    pprExpr1 :: Platform -> CmmExpr -> SDoc
    pprExpr1 Platform
    platform (CmmMachOp MachOp
    op [CmmExpr
    x,CmmExpr
    y])
       | Just SDoc
    doc <- MachOp -> Maybe SDoc
    infixMachOp1 MachOp
    op
       = Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform CmmExpr
    x SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform CmmExpr
    y
    pprExpr1 Platform
    platform CmmExpr
    e = Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform CmmExpr
    e

    infixMachOp1, infixMachOp7, infixMachOp8 :: MachOp -> Maybe SDoc

    infixMachOp1 :: MachOp -> Maybe SDoc
    infixMachOp1 (MO_Eq     Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "==")
    infixMachOp1 (MO_Ne     Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "!=")
    infixMachOp1 (MO_Shl    Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "<<")
    infixMachOp1 (MO_U_Shr  Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    ">>")
    infixMachOp1 (MO_U_Ge   Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    ">=")
    infixMachOp1 (MO_U_Le   Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "<=")
    infixMachOp1 (MO_U_Gt   Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '>')
    infixMachOp1 (MO_U_Lt   Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '<')
    infixMachOp1 MachOp
    _             = Maybe SDoc
    forall a. Maybe a
    Nothing

    -- %left '-' '+'
    pprExpr7 :: Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform (CmmMachOp (MO_Add Width
    rep1) [CmmExpr
    x, CmmLit (CmmInt Integer
    i Width
    rep2)]) | Integer
    i Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    < Integer
    0
       = Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform (MachOp -> [CmmExpr] -> CmmExpr
    CmmMachOp (Width -> MachOp
    MO_Sub Width
    rep1) [CmmExpr
    x, CmmLit -> CmmExpr
    CmmLit (Integer -> Width -> CmmLit
    CmmInt (Integer -> Integer
    forall a. Num a => a -> a
    negate Integer
    i) Width
    rep2)])
    pprExpr7 Platform
    platform (CmmMachOp MachOp
    op [CmmExpr
    x,CmmExpr
    y])
       | Just SDoc
    doc <- MachOp -> Maybe SDoc
    infixMachOp7 MachOp
    op
       = Platform -> CmmExpr -> SDoc
    pprExpr7 Platform
    platform CmmExpr
    x SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CmmExpr -> SDoc
    pprExpr8 Platform
    platform CmmExpr
    y
    pprExpr7 Platform
    platform CmmExpr
    e = Platform -> CmmExpr -> SDoc
    pprExpr8 Platform
    platform CmmExpr
    e

    infixMachOp7 :: MachOp -> Maybe SDoc
    infixMachOp7 (MO_Add Width
    _)  = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+')
    infixMachOp7 (MO_Sub Width
    _)  = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-')
    infixMachOp7 MachOp
    _           = Maybe SDoc
    forall a. Maybe a
    Nothing

    -- %left '/' '*' '%'
    pprExpr8 :: Platform -> CmmExpr -> SDoc
    pprExpr8 Platform
    platform (CmmMachOp MachOp
    op [CmmExpr
    x,CmmExpr
    y])
       | Just SDoc
    doc <- MachOp -> Maybe SDoc
    infixMachOp8 MachOp
    op
       = Platform -> CmmExpr -> SDoc
    pprExpr8 Platform
    platform CmmExpr
    x SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    y
    pprExpr8 Platform
    platform CmmExpr
    e = Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    e

    infixMachOp8 :: MachOp -> Maybe SDoc
    infixMachOp8 (MO_U_Quot Width
    _) = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '/')
    infixMachOp8 (MO_Mul Width
    _)    = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '*')
    infixMachOp8 (MO_U_Rem Width
    _)  = SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '%')
    infixMachOp8 MachOp
    _             = Maybe SDoc
    forall a. Maybe a
    Nothing

    pprExpr9 :: Platform -> CmmExpr -> SDoc
    pprExpr9 :: Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    e =
       case CmmExpr
    e of
            CmmLit    CmmLit
    lit       -> Platform -> CmmLit -> SDoc
    pprLit1 Platform
    platform CmmLit
    lit
            CmmLoad   CmmExpr
    expr CmmType
    rep AlignmentSpec
    align
                                -> let align_mark :: SDoc
    align_mark =
                                           case AlignmentSpec
    align of
                                             AlignmentSpec
    NaturallyAligned -> SDoc
    forall doc. IsOutput doc => doc
    empty
                                             AlignmentSpec
    Unaligned        -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "^"
                                    in CmmType -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CmmType
    rep SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    align_mark SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    brackets (Platform -> CmmExpr -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CmmExpr
    expr)
            CmmReg    CmmReg
    reg       -> CmmReg -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CmmReg
    reg
            CmmRegOff  CmmReg
    reg Int
    off  -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (CmmReg -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CmmReg
    reg SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int Int
    off)
            CmmStackSlot Area
    a Int
    off  -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (Area -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Area
    a   SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int Int
    off)
            CmmMachOp MachOp
    mop [CmmExpr]
    args  -> Platform -> MachOp -> [CmmExpr] -> SDoc
    genMachOp Platform
    platform MachOp
    mop [CmmExpr]
    args

    genMachOp :: Platform -> MachOp -> [CmmExpr] -> SDoc
    genMachOp :: Platform -> MachOp -> [CmmExpr] -> SDoc
    genMachOp Platform
    platform (MO_RelaxedRead Width
    w) [CmmExpr
    x] =
        CmmType -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Width -> CmmType
    cmmBits Width
    w) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "!" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    brackets (Platform -> CmmExpr -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CmmExpr
    x)
    genMachOp Platform
    platform MachOp
    mop [CmmExpr]
    args
       | Just SDoc
    doc <- MachOp -> Maybe SDoc
    infixMachOp MachOp
    mop = case [CmmExpr]
    args of
            -- dyadic
            [CmmExpr
    x,CmmExpr
    y] -> Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    x SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    y

            -- unary
            [CmmExpr
    x]   -> SDoc
    doc SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CmmExpr -> SDoc
    pprExpr9 Platform
    platform CmmExpr
    x

            [CmmExpr]
    _     -> String -> SDoc -> SDoc -> SDoc
    forall a. String -> SDoc -> a -> a
    pprTrace String
    "GHC.Cmm.Expr.genMachOp: machop with strange number of args"
                              (MachOp -> SDoc
    pprMachOp MachOp
    mop SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+>
                                SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens ([SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hcat ([SDoc] -> SDoc) -> [SDoc] -> SDoc
    forall a b. (a -> b) -> a -> b
    $ SDoc -> [SDoc] -> [SDoc]
    forall doc. IsLine doc => doc -> [doc] -> [doc]
    punctuate SDoc
    forall doc. IsLine doc => doc
    comma ((CmmExpr -> SDoc) -> [CmmExpr] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmExpr -> SDoc
    pprExpr Platform
    platform) [CmmExpr]
    args)))
                              SDoc
    forall doc. IsOutput doc => doc
    empty

       | Maybe SDoc -> Bool
    forall a. Maybe a -> Bool
    isJust (MachOp -> Maybe SDoc
    infixMachOp1 MachOp
    mop)
       Bool -> Bool -> Bool
    || Maybe SDoc -> Bool
    forall a. Maybe a -> Bool
    isJust (MachOp -> Maybe SDoc
    infixMachOp7 MachOp
    mop)
       Bool -> Bool -> Bool
    || Maybe SDoc -> Bool
    forall a. Maybe a -> Bool
    isJust (MachOp -> Maybe SDoc
    infixMachOp8 MachOp
    mop)  = SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (Platform -> CmmExpr -> SDoc
    pprExpr Platform
    platform (MachOp -> [CmmExpr] -> CmmExpr
    CmmMachOp MachOp
    mop [CmmExpr]
    args))

       | Bool
    otherwise = Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '%' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    ppr_op SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens ([SDoc] -> SDoc
    commafy ((CmmExpr -> SDoc) -> [CmmExpr] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmExpr -> SDoc
    pprExpr Platform
    platform) [CmmExpr]
    args))
            where ppr_op :: SDoc
    ppr_op = String -> SDoc
    forall doc. IsLine doc => String -> doc
    text ((Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    map (\Char
    c -> if Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    ' ' then Char
    '_' else Char
    c)
                                     (MachOp -> String
    forall a. Show a => a -> String
    show MachOp
    mop))
                    -- replace spaces in (show mop) with underscores,

    --
    -- Unsigned ops on the word size of the machine get nice symbols.
    -- All else get dumped in their ugly format.
    --
    infixMachOp :: MachOp -> Maybe SDoc
    infixMachOp :: MachOp -> Maybe SDoc
    infixMachOp MachOp
    mop
            = case MachOp
    mop of
                MO_And    Width
    _ -> SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
    forall a b. (a -> b) -> a -> b
    $ Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '&'
                MO_Or     Width
    _ -> SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
    forall a b. (a -> b) -> a -> b
    $ Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '|'
                MO_Xor    Width
    _ -> SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
    forall a b. (a -> b) -> a -> b
    $ Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '^'
                MO_Not    Width
    _ -> SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
    forall a b. (a -> b) -> a -> b
    $ Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '~'
                MO_S_Neg  Width
    _ -> SDoc -> Maybe SDoc
    forall a. a -> Maybe a
    Just (SDoc -> Maybe SDoc) -> SDoc -> Maybe SDoc
    forall a b. (a -> b) -> a -> b
    $ Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-' -- there is no unsigned neg :)
                MachOp
    _ -> Maybe SDoc
    forall a. Maybe a
    Nothing

    -- --------------------------------------------------------------------------
    -- Pretty-printing literals
    --
    --  To minimise line noise we adopt the convention that if the literal
    --  has the natural machine word size, we do not append the type
    -- --------------------------------------------------------------------------

    pprLit :: Platform -> CmmLit -> SDoc
    pprLit :: Platform -> CmmLit -> SDoc
    pprLit Platform
    platform CmmLit
    lit = case CmmLit
    lit of
        CmmInt Integer
    i Width
    rep ->
            [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hcat [ (if Integer
    i Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    < Integer
    0 then SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens else SDoc -> SDoc
    forall a. a -> a
    id)(Integer -> SDoc
    forall doc. IsLine doc => Integer -> doc
    integer Integer
    i)
                 , Bool -> SDoc -> SDoc
    forall doc. IsOutput doc => Bool -> doc -> doc
    ppUnless (Width
    rep Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Platform -> Width
    wordWidth Platform
    platform) (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $
                   SDoc
    forall doc. IsLine doc => doc
    space SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> SDoc
    dcolon SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    rep ]

        CmmFloat Rational
    f Width
    rep     -> [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    hsep [ Double -> SDoc
    forall doc. IsLine doc => Double -> doc
    double (Rational -> Double
    forall a. RealFloat a => Rational -> a
    fromRat Rational
    f), SDoc
    dcolon, Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    rep ]
        CmmVec [CmmLit]
    lits        -> Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '<' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> [SDoc] -> SDoc
    commafy ((CmmLit -> SDoc) -> [CmmLit] -> [SDoc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmLit -> SDoc
    pprLit Platform
    platform) [CmmLit]
    lits) SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '>'
        CmmLabel CLabel
    clbl      -> Platform -> CLabel -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    clbl
        CmmLabelOff CLabel
    clbl Int
    i -> Platform -> CLabel -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    clbl SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> SDoc
    ppr_offset Int
    i
        CmmLabelDiffOff CLabel
    clbl1 CLabel
    clbl2 Int
    i Width
    _ -> Platform -> CLabel -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    clbl1 SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-'
                                           SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> SDoc
    forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    clbl2 SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> SDoc
    ppr_offset Int
    i
        CmmBlock BlockId
    id        -> BlockId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr BlockId
    id
        CmmLit
    CmmHighStackMark -> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "<highSp>"

    pprLit1 :: Platform -> CmmLit -> SDoc
    pprLit1 :: Platform -> CmmLit -> SDoc
    pprLit1 Platform
    platform lit :: CmmLit
    lit@(CmmLabelOff {}) = SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens (Platform -> CmmLit -> SDoc
    pprLit Platform
    platform CmmLit
    lit)
    pprLit1 Platform
    platform CmmLit
    lit                  = Platform -> CmmLit -> SDoc
    pprLit Platform
    platform CmmLit
    lit

    ppr_offset :: Int -> SDoc
    ppr_offset :: Int -> SDoc
    ppr_offset Int
    i
        | Int
    iInt -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Int
    0      = SDoc
    forall doc. IsOutput doc => doc
    empty
        | Int
    iInt -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >=Int
    0      = Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int Int
    i
        | Bool
    otherwise = Char -> SDoc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-' SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> SDoc
    forall doc. IsLine doc => Int -> doc
    int (-Int
    i)

    commafy :: [SDoc] -> SDoc
    commafy :: [SDoc] -> SDoc
    commafy [SDoc]
    xs = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    fsep ([SDoc] -> SDoc) -> [SDoc] -> SDoc
    forall a b. (a -> b) -> a -> b
    $ SDoc -> [SDoc] -> [SDoc]
    forall doc. IsLine doc => doc -> [doc] -> [doc]
    punctuate SDoc
    forall doc. IsLine doc => doc
    comma [SDoc]
    xs