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

    import CmmExpr
    import FastBool
    import Platform
    import Reg

    import qualified CodeGen.Platform.ARM        as ARM
    import qualified CodeGen.Platform.ARM64      as ARM64
    import qualified CodeGen.Platform.PPC        as PPC
    import qualified CodeGen.Platform.PPC_Darwin as PPC_Darwin
    import qualified CodeGen.Platform.SPARC      as SPARC
    import qualified CodeGen.Platform.X86        as X86
    import qualified CodeGen.Platform.X86_64     as X86_64
    import qualified CodeGen.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
       ArchSPARC  -> SPARC.callerSaves
       ArchARM {} -> ARM.callerSaves
       ArchARM64  -> ARM64.callerSaves
       arch
        | arch `elem` [ArchPPC, ArchPPC_64] ->
           case platformOS platform of
           OSDarwin -> PPC_Darwin.callerSaves
           _        -> 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
    -- possbily 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
       ArchSPARC  -> SPARC.activeStgRegs
       ArchARM {} -> ARM.activeStgRegs
       ArchARM64  -> ARM64.activeStgRegs
       arch
        | arch `elem` [ArchPPC, ArchPPC_64] ->
           case platformOS platform of
           OSDarwin -> PPC_Darwin.activeStgRegs
           _        -> 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
       ArchSPARC  -> SPARC.haveRegBase
       ArchARM {} -> ARM.haveRegBase
       ArchARM64  -> ARM64.haveRegBase
       arch
        | arch `elem` [ArchPPC, ArchPPC_64] ->
           case platformOS platform of
           OSDarwin -> PPC_Darwin.haveRegBase
           _        -> 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
       ArchSPARC  -> SPARC.globalRegMaybe
       ArchARM {} -> ARM.globalRegMaybe
       ArchARM64  -> ARM64.globalRegMaybe
       arch
        | arch `elem` [ArchPPC, ArchPPC_64] ->
           case platformOS platform of
           OSDarwin -> PPC_Darwin.globalRegMaybe
           _        -> PPC.globalRegMaybe

        | otherwise -> NoRegs.globalRegMaybe

    freeReg :: Platform -> RegNo -> FastBool
    freeReg platform
     | platformUnregisterised platform = NoRegs.freeReg
     | otherwise
     = case platformArch platform of
       ArchX86    -> X86.freeReg
       ArchX86_64 -> X86_64.freeReg
       ArchSPARC  -> SPARC.freeReg
       ArchARM {} -> ARM.freeReg
       ArchARM64  -> ARM64.freeReg
       arch
        | arch `elem` [ArchPPC, ArchPPC_64] ->
           case platformOS platform of
           OSDarwin -> PPC_Darwin.freeReg
           _        -> PPC.freeReg

        | otherwise -> NoRegs.freeReg