GHC/Platform/Regs.hs

    module GHC.Platform.Regs
           (callerSaves, activeStgRegs, haveRegBase, globalRegMaybe, freeReg)
           where

    import GHC.Prelude

    import GHC.Cmm.Expr
    import GHC.Platform
    import GHC.Platform.Reg

    import qualified GHC.Platform.ARM        as ARM
    import qualified GHC.Platform.AArch64    as AArch64
    import qualified GHC.Platform.PPC        as PPC
    import qualified GHC.Platform.S390X      as S390X
    import qualified GHC.Platform.SPARC      as SPARC
    import qualified GHC.Platform.X86        as X86
    import qualified GHC.Platform.X86_64     as X86_64
    import qualified GHC.Platform.RISCV64    as RISCV64
    import qualified GHC.Platform.NoRegs     as NoRegs

    -- | Returns 'True' if this global register is stored in a caller-saves
    -- machine register.

    callerSaves :: Platform -> GlobalReg -> Bool
    callerSaves platform
     | platformUnregisterised platform = NoRegs.callerSaves
     | otherwise
     = case platformArch platform of
       ArchX86     -> X86.callerSaves
       ArchX86_64  -> X86_64.callerSaves
       ArchS390X   -> S390X.callerSaves
       ArchSPARC   -> SPARC.callerSaves
       ArchARM {}  -> ARM.callerSaves
       ArchAArch64 -> AArch64.callerSaves
       ArchRISCV64 -> RISCV64.callerSaves
       arch
        | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
            PPC.callerSaves

        | otherwise -> NoRegs.callerSaves

    -- | Here is where the STG register map is defined for each target arch.
    -- The order matters (for the llvm backend anyway)! We must make sure to
    -- maintain the order here with the order used in the LLVM calling conventions.
    -- Note that also, this isn't all registers, just the ones that are currently
    -- possibly mapped to real registers.
    activeStgRegs :: Platform -> [GlobalReg]
    activeStgRegs platform
     | platformUnregisterised platform = NoRegs.activeStgRegs
     | otherwise
     = case platformArch platform of
       ArchX86     -> X86.activeStgRegs
       ArchX86_64  -> X86_64.activeStgRegs
       ArchS390X   -> S390X.activeStgRegs
       ArchSPARC   -> SPARC.activeStgRegs
       ArchARM {}  -> ARM.activeStgRegs
       ArchAArch64 -> AArch64.activeStgRegs
       ArchRISCV64 -> RISCV64.activeStgRegs
       arch
        | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
            PPC.activeStgRegs

        | otherwise -> NoRegs.activeStgRegs

    haveRegBase :: Platform -> Bool
    haveRegBase platform
     | platformUnregisterised platform = NoRegs.haveRegBase
     | otherwise
     = case platformArch platform of
       ArchX86     -> X86.haveRegBase
       ArchX86_64  -> X86_64.haveRegBase
       ArchS390X   -> S390X.haveRegBase
       ArchSPARC   -> SPARC.haveRegBase
       ArchARM {}  -> ARM.haveRegBase
       ArchAArch64 -> AArch64.haveRegBase
       ArchRISCV64 -> RISCV64.haveRegBase
       arch
        | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
            PPC.haveRegBase

        | otherwise -> NoRegs.haveRegBase

    globalRegMaybe :: Platform -> GlobalReg -> Maybe RealReg
    globalRegMaybe platform
     | platformUnregisterised platform = NoRegs.globalRegMaybe
     | otherwise
     = case platformArch platform of
       ArchX86     -> X86.globalRegMaybe
       ArchX86_64  -> X86_64.globalRegMaybe
       ArchS390X   -> S390X.globalRegMaybe
       ArchSPARC   -> SPARC.globalRegMaybe
       ArchARM {}  -> ARM.globalRegMaybe
       ArchAArch64 -> AArch64.globalRegMaybe
       ArchRISCV64 -> RISCV64.globalRegMaybe
       arch
        | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
            PPC.globalRegMaybe

        | otherwise -> NoRegs.globalRegMaybe

    freeReg :: Platform -> RegNo -> Bool
    freeReg platform
     | platformUnregisterised platform = NoRegs.freeReg
     | otherwise
     = case platformArch platform of
       ArchX86     -> X86.freeReg
       ArchX86_64  -> X86_64.freeReg
       ArchS390X   -> S390X.freeReg
       ArchSPARC   -> SPARC.freeReg
       ArchARM {}  -> ARM.freeReg
       ArchAArch64 -> AArch64.freeReg
       ArchRISCV64 -> RISCV64.freeReg
       arch
        | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
            PPC.freeReg

        | otherwise -> NoRegs.freeReg