    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE UndecidableInstances #-}

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

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

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

        , 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.Utils.Panic (panic)
    import GHC.Utils.Outputable
    import GHC.Types.Unique

    import Data.Set (Set)
    import qualified Data.Set as Set

    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
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [CmmExpr] -> ShowS
    $cshowList :: [CmmExpr] -> ShowS
    show :: CmmExpr -> String
    $cshow :: CmmExpr -> String
    showsPrec :: Int -> CmmExpr -> ShowS
    $cshowsPrec :: Int -> CmmExpr -> ShowS
    Show

    instance Eq CmmExpr where       -- Equality ignores the types
      CmmLit CmmLit
    l1          == :: CmmExpr -> CmmExpr -> Bool
    == CmmLit CmmLit
    l2          = CmmLit
    l1forall a. Eq a => a -> a -> Bool
    ==CmmLit
    l2
      CmmLoad CmmExpr
    e1 CmmType
    _ AlignmentSpec
    _     == CmmLoad CmmExpr
    e2 CmmType
    _ AlignmentSpec
    _     = CmmExpr
    e1forall a. Eq a => a -> a -> Bool
    ==CmmExpr
    e2
      CmmReg CmmReg
    r1          == CmmReg CmmReg
    r2          = CmmReg
    r1forall a. Eq a => a -> a -> Bool
    ==CmmReg
    r2
      CmmRegOff CmmReg
    r1 Int
    i1    == CmmRegOff CmmReg
    r2 Int
    i2    = CmmReg
    r1forall a. Eq a => a -> a -> Bool
    ==CmmReg
    r2 Bool -> Bool -> Bool
    && Int
    i1forall a. Eq a => a -> a -> Bool
    ==Int
    i2
      CmmMachOp MachOp
    op1 [CmmExpr]
    es1  == CmmMachOp MachOp
    op2 [CmmExpr]
    es2  = MachOp
    op1forall a. Eq a => a -> a -> Bool
    ==MachOp
    op2 Bool -> Bool -> Bool
    && [CmmExpr]
    es1forall a. Eq a => a -> a -> Bool
    ==[CmmExpr]
    es2
      CmmStackSlot Area
    a1 Int
    i1 == CmmStackSlot Area
    a2 Int
    i2 = Area
    a1forall a. Eq a => a -> a -> Bool
    ==Area
    a2 Bool -> Bool -> Bool
    && Int
    i1forall a. Eq a => a -> a -> Bool
    ==Int
    i2
      CmmExpr
    _e1                == CmmExpr
    _e2                = Bool
    False

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

    data CmmReg
      = CmmLocal  {-# UNPACK #-} !LocalReg
      | CmmGlobal GlobalReg
      deriving( CmmReg -> CmmReg -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: CmmReg -> CmmReg -> Bool
    $c/= :: CmmReg -> CmmReg -> Bool
    == :: CmmReg -> CmmReg -> Bool
    $c== :: CmmReg -> CmmReg -> Bool
    Eq, Eq CmmReg
    CmmReg -> CmmReg -> Bool
    CmmReg -> CmmReg -> Ordering
    CmmReg -> CmmReg -> CmmReg
    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
    min :: CmmReg -> CmmReg -> CmmReg
    $cmin :: CmmReg -> CmmReg -> CmmReg
    max :: CmmReg -> CmmReg -> CmmReg
    $cmax :: CmmReg -> CmmReg -> CmmReg
    >= :: CmmReg -> CmmReg -> Bool
    $c>= :: CmmReg -> CmmReg -> Bool
    > :: CmmReg -> CmmReg -> Bool
    $c> :: CmmReg -> CmmReg -> Bool
    <= :: CmmReg -> CmmReg -> Bool
    $c<= :: CmmReg -> CmmReg -> Bool
    < :: CmmReg -> CmmReg -> Bool
    $c< :: CmmReg -> CmmReg -> Bool
    compare :: CmmReg -> CmmReg -> Ordering
    $ccompare :: CmmReg -> CmmReg -> Ordering
    Ord, Int -> CmmReg -> ShowS
    [CmmReg] -> ShowS
    CmmReg -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [CmmReg] -> ShowS
    $cshowList :: [CmmReg] -> ShowS
    show :: CmmReg -> String
    $cshow :: CmmReg -> String
    showsPrec :: Int -> CmmReg -> ShowS
    $cshowsPrec :: Int -> CmmReg -> 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 BlockId] in GHC.Cmm.Node.
      deriving (Area -> Area -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Area -> Area -> Bool
    $c/= :: Area -> Area -> Bool
    == :: Area -> Area -> Bool
    $c== :: Area -> Area -> Bool
    Eq, Eq 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
    min :: Area -> Area -> Area
    $cmin :: Area -> Area -> Area
    max :: Area -> Area -> Area
    $cmax :: Area -> Area -> Area
    >= :: Area -> Area -> Bool
    $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
    compare :: Area -> Area -> Ordering
    $ccompare :: Area -> Area -> Ordering
    Ord, Int -> Area -> ShowS
    [Area] -> ShowS
    Area -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [Area] -> ShowS
    $cshowList :: [Area] -> ShowS
    show :: Area -> String
    $cshow :: Area -> String
    showsPrec :: Int -> Area -> ShowS
    $cshowsPrec :: Int -> Area -> ShowS
    Show)

    {- 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 BlockId] 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
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: CmmLit -> CmmLit -> Bool
    $c/= :: CmmLit -> CmmLit -> Bool
    == :: CmmLit -> CmmLit -> Bool
    $c== :: CmmLit -> CmmLit -> Bool
    Eq, Int -> CmmLit -> ShowS
    [CmmLit] -> ShowS
    CmmLit -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [CmmLit] -> ShowS
    $cshowList :: [CmmLit] -> ShowS
    show :: CmmLit -> String
    $cshow :: CmmLit -> String
    showsPrec :: Int -> CmmLit -> ShowS
    $cshowsPrec :: Int -> CmmLit -> ShowS
    Show)

    instance Outputable CmmLit where
      ppr :: CmmLit -> SDoc
    ppr (CmmInt Integer
    n Width
    w) = String -> SDoc
    text String
    "CmmInt" SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr Integer
    n SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr Width
    w
      ppr (CmmFloat Rational
    n Width
    w) = String -> SDoc
    text String
    "CmmFloat" SDoc -> SDoc -> SDoc
    <+> String -> SDoc
    text (forall a. Show a => a -> String
    show Rational
    n) SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr Width
    w
      ppr (CmmVec [CmmLit]
    xs) = String -> SDoc
    text String
    "CmmVec" SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr [CmmLit]
    xs
      ppr (CmmLabel CLabel
    _) = String -> SDoc
    text String
    "CmmLabel"
      ppr (CmmLabelOff CLabel
    _ Int
    _) = String -> SDoc
    text String
    "CmmLabelOff"
      ppr (CmmLabelDiffOff CLabel
    _ CLabel
    _ Int
    _ Width
    _) = String -> SDoc
    text String
    "CmmLabelDiffOff"
      ppr (CmmBlock BlockId
    blk) = String -> SDoc
    text String
    "CmmBlock" SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr BlockId
    blk
      ppr CmmLit
    CmmHighStackMark = String -> SDoc
    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)        -> Platform -> CmmReg -> CmmType
    cmmRegType Platform
    platform CmmReg
    reg
       (CmmMachOp MachOp
    op [CmmExpr]
    args) -> Platform -> MachOp -> [CmmType] -> CmmType
    machOpResultType Platform
    platform MachOp
    op (forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform) [CmmExpr]
    args)
       (CmmRegOff CmmReg
    reg Int
    _)   -> Platform -> CmmReg -> CmmType
    cmmRegType Platform
    platform 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 [])          -> forall a. 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 forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (CmmType -> CmmType -> Bool
    `cmmEqType` CmmType
    ty) (forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform) [CmmLit]
    ls)
                                   then Int -> CmmType -> CmmType
    cmmVec (Int
    1forall a. Num a => a -> a -> a
    +forall (t :: * -> *) a. Foldable t => t a -> Int
    length [CmmLit]
    ls) CmmType
    ty
                                   else forall a. 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 (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 MachOp
    op' <- MachOp -> Maybe MachOp
    maybeInvertComparison MachOp
    op
                                                forall (m :: * -> *) a. Monad m => a -> m a
    return (MachOp -> [CmmExpr] -> CmmExpr
    CmmMachOp MachOp
    op' [CmmExpr]
    args)
    maybeInvertCmmExpr CmmExpr
    _ = forall a. Maybe a
    Nothing

    -----------------------------------------------------------------------------
    --              Local registers
    -----------------------------------------------------------------------------

    data LocalReg
      = LocalReg {-# UNPACK #-} !Unique !CmmType
        -- ^ Parameters:
        --   1. Identifier
        --   2. Type
      deriving Int -> LocalReg -> ShowS
    [LocalReg] -> ShowS
    LocalReg -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [LocalReg] -> ShowS
    $cshowList :: [LocalReg] -> ShowS
    show :: LocalReg -> String
    $cshow :: LocalReg -> String
    showsPrec :: Int -> LocalReg -> ShowS
    $cshowsPrec :: Int -> LocalReg -> ShowS
    Show

    instance Eq LocalReg where
      (LocalReg Unique
    u1 CmmType
    _) == :: LocalReg -> LocalReg -> Bool
    == (LocalReg Unique
    u2 CmmType
    _) = Unique
    u1 forall a. Eq a => a -> a -> Bool
    == Unique
    u2

    -- This is non-deterministic but we do not currently support deterministic
    -- code-generation. See Note [Unique Determinism and code generation]
    -- See Note [No Ord for Unique]
    instance Ord LocalReg where
      compare :: LocalReg -> LocalReg -> Ordering
    compare (LocalReg Unique
    u1 CmmType
    _) (LocalReg Unique
    u2 CmmType
    _) = Unique -> Unique -> Ordering
    nonDetCmpUnique Unique
    u1 Unique
    u2

    instance Uniquable LocalReg where
      getUnique :: LocalReg -> Unique
    getUnique (LocalReg Unique
    uniq CmmType
    _) = Unique
    uniq

    cmmRegType :: Platform -> CmmReg -> CmmType
    cmmRegType :: Platform -> CmmReg -> CmmType
    cmmRegType Platform
    _        (CmmLocal  LocalReg
    reg) = LocalReg -> CmmType
    localRegType LocalReg
    reg
    cmmRegType Platform
    platform (CmmGlobal GlobalReg
    reg) = Platform -> GlobalReg -> CmmType
    globalRegType Platform
    platform GlobalReg
    reg

    cmmRegWidth :: Platform -> CmmReg -> Width
    cmmRegWidth :: Platform -> CmmReg -> Width
    cmmRegWidth Platform
    platform = CmmType -> Width
    typeWidth forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Platform -> CmmReg -> CmmType
    cmmRegType Platform
    platform

    localRegType :: LocalReg -> CmmType
    localRegType :: LocalReg -> CmmType
    localRegType (LocalReg Unique
    _ CmmType
    rep) = CmmType
    rep

    -----------------------------------------------------------------------------
    --    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      = forall r. RegSet r
    Set.empty
    nullRegSet :: forall r. RegSet r -> Bool
    nullRegSet       = forall r. RegSet r -> Bool
    Set.null
    elemRegSet :: forall r. Ord r => r -> RegSet r -> Bool
    elemRegSet       = forall r. Ord r => r -> RegSet r -> Bool
    Set.member
    extendRegSet :: forall r. Ord r => RegSet r -> r -> RegSet r
    extendRegSet     = forall a b c. (a -> b -> c) -> b -> a -> c
    flip forall a. Ord a => a -> Set a -> Set a
    Set.insert
    deleteFromRegSet :: forall r. Ord r => RegSet r -> r -> RegSet r
    deleteFromRegSet = forall a b c. (a -> b -> c) -> b -> a -> c
    flip forall a. Ord a => a -> Set a -> Set a
    Set.delete
    mkRegSet :: forall r. Ord r => [r] -> RegSet r
    mkRegSet         = forall r. Ord r => [r] -> RegSet r
    Set.fromList
    minusRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    minusRegSet      = forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.difference
    plusRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    plusRegSet       = forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.union
    timesRegSet :: forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    timesRegSet      = forall r. Ord r => RegSet r -> RegSet r -> RegSet r
    Set.intersection
    sizeRegSet :: forall r. RegSet r -> Int
    sizeRegSet       = forall r. RegSet r -> Int
    Set.size
    regSetToList :: forall r. RegSet r -> [r]
    regSetToList     = 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 = 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 = 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 GlobalReg
    _)  = 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 GlobalReg
    _)  = 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 GlobalReg
    reg) = b -> GlobalReg -> b
    f b
    z GlobalReg
    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 GlobalReg
    reg) = b -> GlobalReg -> b
    f b
    z GlobalReg
    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
    _)  = 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)          = 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) = 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
    _)     = 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 = forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (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 = forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (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 #-}

    -----------------------------------------------------------------------------
    --              Global STG registers
    -----------------------------------------------------------------------------

    data VGcPtr = VGcPtr | VNonGcPtr deriving( VGcPtr -> VGcPtr -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: VGcPtr -> VGcPtr -> Bool
    $c/= :: VGcPtr -> VGcPtr -> Bool
    == :: VGcPtr -> VGcPtr -> Bool
    $c== :: VGcPtr -> VGcPtr -> Bool
    Eq, Int -> VGcPtr -> ShowS
    [VGcPtr] -> ShowS
    VGcPtr -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [VGcPtr] -> ShowS
    $cshowList :: [VGcPtr] -> ShowS
    show :: VGcPtr -> String
    $cshow :: VGcPtr -> String
    showsPrec :: Int -> VGcPtr -> ShowS
    $cshowsPrec :: Int -> VGcPtr -> ShowS
    Show )

    -----------------------------------------------------------------------------
    --              Global STG registers
    -----------------------------------------------------------------------------
    {-
    Note [Overlapping global registers]

    The backend might not faithfully implement the abstraction of the STG
    machine with independent registers for different values of type
    GlobalReg. Specifically, certain pairs of registers (r1, r2) may
    overlap in the sense that a store to r1 invalidates the value in r2,
    and vice versa.

    Currently this occurs only on the x86_64 architecture where FloatReg n
    and DoubleReg n are assigned the same microarchitectural register, in
    order to allow functions to receive more Float# or Double# arguments
    in registers (as opposed to on the stack).

    There are no specific rules about which registers might overlap with
    which other registers, but presumably it's safe to assume that nothing
    will overlap with special registers like Sp or BaseReg.

    Use GHC.Cmm.Utils.regsOverlap to determine whether two GlobalRegs overlap
    on a particular platform. The instance Eq GlobalReg is syntactic
    equality of STG registers and does not take overlap into
    account. However it is still used in UserOfRegs/DefinerOfRegs and
    there are likely still bugs there, beware!
    -}

    data GlobalReg
      -- Argument and return registers
      = VanillaReg                  -- pointers, unboxed ints and chars
            {-# UNPACK #-} !Int     -- its number
            VGcPtr

      | FloatReg            -- single-precision floating-point registers
            {-# UNPACK #-} !Int     -- its number

      | DoubleReg           -- double-precision floating-point registers
            {-# UNPACK #-} !Int     -- its number

      | LongReg             -- long int registers (64-bit, really)
            {-# UNPACK #-} !Int     -- its number

      | XmmReg                      -- 128-bit SIMD vector register
            {-# UNPACK #-} !Int     -- its number

      | YmmReg                      -- 256-bit SIMD vector register
            {-# UNPACK #-} !Int     -- its number

      | ZmmReg                      -- 512-bit SIMD vector register
            {-# UNPACK #-} !Int     -- its number

      -- STG registers
      | Sp                  -- Stack ptr; points to last occupied stack location.
      | SpLim               -- Stack limit
      | Hp                  -- Heap ptr; points to last occupied heap location.
      | HpLim               -- Heap limit register
      | CCCS                -- Current cost-centre stack
      | CurrentTSO          -- pointer to current thread's TSO
      | CurrentNursery      -- pointer to allocation area
      | HpAlloc             -- allocation count for heap check failure

                    -- We keep the address of some commonly-called
                    -- functions in the register table, to keep code
                    -- size down:
      | EagerBlackholeInfo  -- stg_EAGER_BLACKHOLE_info
      | GCEnter1            -- stg_gc_enter_1
      | GCFun               -- stg_gc_fun

      -- Base offset for the register table, used for accessing registers
      -- which do not have real registers assigned to them.  This register
      -- will only appear after we have expanded GlobalReg into memory accesses
      -- (where necessary) in the native code generator.
      | BaseReg

      -- The register used by the platform for the C stack pointer. This is
      -- a break in the STG abstraction used exclusively to setup stack unwinding
      -- information.
      | MachSp

      -- The is a dummy register used to indicate to the stack unwinder where
      -- a routine would return to.
      | UnwindReturnReg

      -- Base Register for PIC (position-independent code) calculations
      -- Only used inside the native code generator. It's exact meaning differs
      -- from platform to platform (see module PositionIndependentCode).
      | PicBaseReg

      deriving( Int -> GlobalReg -> ShowS
    [GlobalReg] -> ShowS
    GlobalReg -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [GlobalReg] -> ShowS
    $cshowList :: [GlobalReg] -> ShowS
    show :: GlobalReg -> String
    $cshow :: GlobalReg -> String
    showsPrec :: Int -> GlobalReg -> ShowS
    $cshowsPrec :: Int -> GlobalReg -> ShowS
    Show )

    instance Eq GlobalReg where
       VanillaReg Int
    i VGcPtr
    _ == :: GlobalReg -> GlobalReg -> Bool
    == VanillaReg Int
    j VGcPtr
    _ = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j -- Ignore type when seeking clashes
       FloatReg Int
    i == FloatReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       DoubleReg Int
    i == DoubleReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       LongReg Int
    i == LongReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       -- NOTE: XMM, YMM, ZMM registers actually are the same registers
       -- at least with respect to store at YMM i and then read from XMM i
       -- and similarly for ZMM etc.
       XmmReg Int
    i == XmmReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       YmmReg Int
    i == YmmReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       ZmmReg Int
    i == ZmmReg Int
    j = Int
    iforall a. Eq a => a -> a -> Bool
    ==Int
    j
       GlobalReg
    Sp == GlobalReg
    Sp = Bool
    True
       GlobalReg
    SpLim == GlobalReg
    SpLim = Bool
    True
       GlobalReg
    Hp == GlobalReg
    Hp = Bool
    True
       GlobalReg
    HpLim == GlobalReg
    HpLim = Bool
    True
       GlobalReg
    CCCS == GlobalReg
    CCCS = Bool
    True
       GlobalReg
    CurrentTSO == GlobalReg
    CurrentTSO = Bool
    True
       GlobalReg
    CurrentNursery == GlobalReg
    CurrentNursery = Bool
    True
       GlobalReg
    HpAlloc == GlobalReg
    HpAlloc = Bool
    True
       GlobalReg
    EagerBlackholeInfo == GlobalReg
    EagerBlackholeInfo = Bool
    True
       GlobalReg
    GCEnter1 == GlobalReg
    GCEnter1 = Bool
    True
       GlobalReg
    GCFun == GlobalReg
    GCFun = Bool
    True
       GlobalReg
    BaseReg == GlobalReg
    BaseReg = Bool
    True
       GlobalReg
    MachSp == GlobalReg
    MachSp = Bool
    True
       GlobalReg
    UnwindReturnReg == GlobalReg
    UnwindReturnReg = Bool
    True
       GlobalReg
    PicBaseReg == GlobalReg
    PicBaseReg = Bool
    True
       GlobalReg
    _r1 == GlobalReg
    _r2 = Bool
    False

    -- NOTE: this Ord instance affects the tuple layout in GHCi, see
    --       Note [GHCi tuple layout]
    instance Ord GlobalReg where
       compare :: GlobalReg -> GlobalReg -> Ordering
    compare (VanillaReg Int
    i VGcPtr
    _) (VanillaReg Int
    j VGcPtr
    _) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
         -- Ignore type when seeking clashes
       compare (FloatReg Int
    i)  (FloatReg  Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare (DoubleReg Int
    i) (DoubleReg Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare (LongReg Int
    i)   (LongReg   Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare (XmmReg Int
    i)    (XmmReg    Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare (YmmReg Int
    i)    (YmmReg    Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare (ZmmReg Int
    i)    (ZmmReg    Int
    j) = forall a. Ord a => a -> a -> Ordering
    compare Int
    i Int
    j
       compare GlobalReg
    Sp GlobalReg
    Sp = Ordering
    EQ
       compare GlobalReg
    SpLim GlobalReg
    SpLim = Ordering
    EQ
       compare GlobalReg
    Hp GlobalReg
    Hp = Ordering
    EQ
       compare GlobalReg
    HpLim GlobalReg
    HpLim = Ordering
    EQ
       compare GlobalReg
    CCCS GlobalReg
    CCCS = Ordering
    EQ
       compare GlobalReg
    CurrentTSO GlobalReg
    CurrentTSO = Ordering
    EQ
       compare GlobalReg
    CurrentNursery GlobalReg
    CurrentNursery = Ordering
    EQ
       compare GlobalReg
    HpAlloc GlobalReg
    HpAlloc = Ordering
    EQ
       compare GlobalReg
    EagerBlackholeInfo GlobalReg
    EagerBlackholeInfo = Ordering
    EQ
       compare GlobalReg
    GCEnter1 GlobalReg
    GCEnter1 = Ordering
    EQ
       compare GlobalReg
    GCFun GlobalReg
    GCFun = Ordering
    EQ
       compare GlobalReg
    BaseReg GlobalReg
    BaseReg = Ordering
    EQ
       compare GlobalReg
    MachSp GlobalReg
    MachSp = Ordering
    EQ
       compare GlobalReg
    UnwindReturnReg GlobalReg
    UnwindReturnReg = Ordering
    EQ
       compare GlobalReg
    PicBaseReg GlobalReg
    PicBaseReg = Ordering
    EQ
       compare (VanillaReg Int
    _ VGcPtr
    _) GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ (VanillaReg Int
    _ VGcPtr
    _) = Ordering
    GT
       compare (FloatReg Int
    _) GlobalReg
    _     = Ordering
    LT
       compare GlobalReg
    _ (FloatReg Int
    _)     = Ordering
    GT
       compare (DoubleReg Int
    _) GlobalReg
    _    = Ordering
    LT
       compare GlobalReg
    _ (DoubleReg Int
    _)    = Ordering
    GT
       compare (LongReg Int
    _) GlobalReg
    _      = Ordering
    LT
       compare GlobalReg
    _ (LongReg Int
    _)      = Ordering
    GT
       compare (XmmReg Int
    _) GlobalReg
    _       = Ordering
    LT
       compare GlobalReg
    _ (XmmReg Int
    _)       = Ordering
    GT
       compare (YmmReg Int
    _) GlobalReg
    _       = Ordering
    LT
       compare GlobalReg
    _ (YmmReg Int
    _)       = Ordering
    GT
       compare (ZmmReg Int
    _) GlobalReg
    _       = Ordering
    LT
       compare GlobalReg
    _ (ZmmReg Int
    _)       = Ordering
    GT
       compare GlobalReg
    Sp GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    Sp = Ordering
    GT
       compare GlobalReg
    SpLim GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    SpLim = Ordering
    GT
       compare GlobalReg
    Hp GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    Hp = Ordering
    GT
       compare GlobalReg
    HpLim GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    HpLim = Ordering
    GT
       compare GlobalReg
    CCCS GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    CCCS = Ordering
    GT
       compare GlobalReg
    CurrentTSO GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    CurrentTSO = Ordering
    GT
       compare GlobalReg
    CurrentNursery GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    CurrentNursery = Ordering
    GT
       compare GlobalReg
    HpAlloc GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    HpAlloc = Ordering
    GT
       compare GlobalReg
    GCEnter1 GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    GCEnter1 = Ordering
    GT
       compare GlobalReg
    GCFun GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    GCFun = Ordering
    GT
       compare GlobalReg
    BaseReg GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    BaseReg = Ordering
    GT
       compare GlobalReg
    MachSp GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    MachSp = Ordering
    GT
       compare GlobalReg
    UnwindReturnReg GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    UnwindReturnReg = Ordering
    GT
       compare GlobalReg
    EagerBlackholeInfo GlobalReg
    _ = Ordering
    LT
       compare GlobalReg
    _ GlobalReg
    EagerBlackholeInfo = Ordering
    GT

    -- convenient aliases
    baseReg, spReg, hpReg, spLimReg, hpLimReg, nodeReg,
      currentTSOReg, currentNurseryReg, hpAllocReg, cccsReg  :: CmmReg
    baseReg :: CmmReg
    baseReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    BaseReg
    spReg :: CmmReg
    spReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    Sp
    hpReg :: CmmReg
    hpReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    Hp
    hpLimReg :: CmmReg
    hpLimReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    HpLim
    spLimReg :: CmmReg
    spLimReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    SpLim
    nodeReg :: CmmReg
    nodeReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    node
    currentTSOReg :: CmmReg
    currentTSOReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    CurrentTSO
    currentNurseryReg :: CmmReg
    currentNurseryReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    CurrentNursery
    hpAllocReg :: CmmReg
    hpAllocReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    HpAlloc
    cccsReg :: CmmReg
    cccsReg = GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    CCCS

    node :: GlobalReg
    node :: GlobalReg
    node = Int -> VGcPtr -> GlobalReg
    VanillaReg Int
    1 VGcPtr
    VGcPtr

    globalRegType :: Platform -> GlobalReg -> CmmType
    globalRegType :: Platform -> GlobalReg -> CmmType
    globalRegType Platform
    platform = \case
       (VanillaReg Int
    _ VGcPtr
    VGcPtr)    -> Platform -> CmmType
    gcWord Platform
    platform
       (VanillaReg Int
    _ VGcPtr
    VNonGcPtr) -> Platform -> CmmType
    bWord Platform
    platform
       (FloatReg Int
    _)             -> Width -> CmmType
    cmmFloat Width
    W32
       (DoubleReg Int
    _)            -> Width -> CmmType
    cmmFloat Width
    W64
       (LongReg Int
    _)              -> Width -> CmmType
    cmmBits Width
    W64
       -- TODO: improve the internal model of SIMD/vectorized registers
       -- the right design SHOULd improve handling of float and double code too.
       -- see remarks in "NOTE [SIMD Design for the future]"" in GHC.StgToCmm.Prim
       (XmmReg Int
    _) -> Int -> CmmType -> CmmType
    cmmVec Int
    4 (Width -> CmmType
    cmmBits Width
    W32)
       (YmmReg Int
    _) -> Int -> CmmType -> CmmType
    cmmVec Int
    8 (Width -> CmmType
    cmmBits Width
    W32)
       (ZmmReg Int
    _) -> Int -> CmmType -> CmmType
    cmmVec Int
    16 (Width -> CmmType
    cmmBits Width
    W32)

       GlobalReg
    Hp         -> Platform -> CmmType
    gcWord Platform
    platform -- The initialiser for all
                                     -- dynamically allocated closures
       GlobalReg
    _          -> Platform -> CmmType
    bWord Platform
    platform

    isArgReg :: GlobalReg -> Bool
    isArgReg :: GlobalReg -> Bool
    isArgReg (VanillaReg {}) = Bool
    True
    isArgReg (FloatReg {})   = Bool
    True
    isArgReg (DoubleReg {})  = Bool
    True
    isArgReg (LongReg {})    = Bool
    True
    isArgReg (XmmReg {})     = Bool
    True
    isArgReg (YmmReg {})     = Bool
    True
    isArgReg (ZmmReg {})     = Bool
    True
    isArgReg GlobalReg
    _               = Bool
    False