    module GHC.CmmToAsm.SPARC.CodeGen.Base (
            InstrBlock,
            CondCode(..),
            ChildCode64(..),
            Amode(..),

            Register(..),
            setFormatOfRegister,

            getRegisterReg,
            mangleIndexTree
    )

    where

    import GHC.Prelude

    import GHC.CmmToAsm.SPARC.Instr
    import GHC.CmmToAsm.SPARC.Cond
    import GHC.CmmToAsm.SPARC.AddrMode
    import GHC.CmmToAsm.SPARC.Regs
    import GHC.CmmToAsm.Format
    import GHC.Platform.Reg

    import GHC.Platform.Regs
    import GHC.Cmm
    import GHC.Cmm.Ppr.Expr () -- For Outputable instances
    import GHC.Platform

    import GHC.Utils.Outputable
    import GHC.Utils.Panic
    import GHC.Data.OrdList

    --------------------------------------------------------------------------------
    -- | 'InstrBlock's are the insn sequences generated by the insn selectors.
    --      They are really trees of insns to facilitate fast appending, where a
    --      left-to-right traversal yields the insns in the correct order.
    --
    type InstrBlock
            = OrdList Instr

    -- | Condition codes passed up the tree.
    --
    data CondCode
            = CondCode Bool Cond InstrBlock

    -- | a.k.a \"Register64\"
    --      Reg is the lower 32-bit temporary which contains the result.
    --      Use getHiVRegFromLo to find the other VRegUnique.
    --
    --      Rules of this simplified insn selection game are therefore that
    --      the returned Reg may be modified
    --
    data ChildCode64
       = ChildCode64
            InstrBlock
            Reg

    -- | Holds code that references a memory address.
    data Amode
            = Amode
                    -- the AddrMode we can use in the instruction
                    --      that does the real load\/store.
                    AddrMode

                    -- other setup code we have to run first before we can use the
                    --      above AddrMode.
                    InstrBlock

    --------------------------------------------------------------------------------
    -- | Code to produce a result into a register.
    --      If the result must go in a specific register, it comes out as Fixed.
    --      Otherwise, the parent can decide which register to put it in.
    --
    data Register
            = Fixed Format Reg InstrBlock
            | Any   Format (Reg -> InstrBlock)

    -- | Change the format field in a Register.
    setFormatOfRegister
            :: Register -> Format -> Register

    setFormatOfRegister :: Register -> Format -> Register
    setFormatOfRegister Register
    reg Format
    format
     = case Register
    reg of
            Fixed Format
    _ Reg
    reg InstrBlock
    code        -> Format -> Reg -> InstrBlock -> Register
    Fixed Format
    format Reg
    reg InstrBlock
    code
            Any Format
    _ Reg -> InstrBlock
    codefn            -> Format -> (Reg -> InstrBlock) -> Register
    Any   Format
    format Reg -> InstrBlock
    codefn

    --------------------------------------------------------------------------------
    -- | Grab the Reg for a CmmReg
    getRegisterReg :: Platform -> CmmReg -> Reg

    getRegisterReg :: Platform -> CmmReg -> Reg
    getRegisterReg Platform
    _ (CmmLocal (LocalReg Unique
    u CmmType
    pk))
            = VirtualReg -> Reg
    RegVirtual forall a b. (a -> b) -> a -> b
    $ Unique -> Format -> VirtualReg
    mkVirtualReg Unique
    u (CmmType -> Format
    cmmTypeFormat CmmType
    pk)

    getRegisterReg Platform
    platform (CmmGlobal GlobalReg
    mid)
      = case Platform -> GlobalReg -> Maybe RealReg
    globalRegMaybe Platform
    platform GlobalReg
    mid of
            Just RealReg
    reg -> RealReg -> Reg
    RegReal RealReg
    reg
            Maybe RealReg
    Nothing  -> forall a. HasCallStack => String -> SDoc -> a
    pprPanic
                            String
    "SPARC.CodeGen.Base.getRegisterReg: global is in memory"
                            (forall a. Outputable a => a -> SDoc
    ppr forall a b. (a -> b) -> a -> b
    $ GlobalReg -> CmmReg
    CmmGlobal GlobalReg
    mid)

    -- Expand CmmRegOff.  ToDo: should we do it this way around, or convert
    -- CmmExprs into CmmRegOff?
    mangleIndexTree :: Platform -> CmmExpr -> CmmExpr

    mangleIndexTree :: Platform -> CmmExpr -> CmmExpr
    mangleIndexTree Platform
    platform (CmmRegOff CmmReg
    reg Int
    off)
            = MachOp -> [CmmExpr] -> CmmExpr
    CmmMachOp (Width -> MachOp
    MO_Add Width
    width) [CmmReg -> CmmExpr
    CmmReg CmmReg
    reg, CmmLit -> CmmExpr
    CmmLit (Integer -> Width -> CmmLit
    CmmInt (forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    off) Width
    width)]
            where width :: Width
    width = CmmType -> Width
    typeWidth (Platform -> CmmReg -> CmmType
    cmmRegType Platform
    platform CmmReg
    reg)

    mangleIndexTree Platform
    _ CmmExpr
    _
            = forall a. String -> a
    panic String
    "SPARC.CodeGen.Base.mangleIndexTree: no match"