    {-# LANGUAGE RecordWildCards #-}
    {-# LANGUAGE NamedFieldPuns #-}
    module GHC.Toolchain.Target where

    import GHC.Platform.ArchOS

    import GHC.Toolchain.Prelude
    import GHC.Toolchain.Program

    import GHC.Toolchain.Tools.Cc
    import GHC.Toolchain.Tools.Cxx
    import GHC.Toolchain.Tools.Cpp
    import GHC.Toolchain.Tools.Ar
    import GHC.Toolchain.Tools.Ranlib
    import GHC.Toolchain.Tools.Link
    import GHC.Toolchain.Tools.Nm
    import GHC.Toolchain.Tools.MergeObjs

    data WordSize = WS4 | WS8
        deriving (Int -> WordSize -> ShowS
    [WordSize] -> ShowS
    WordSize -> String
    (Int -> WordSize -> ShowS)
    -> (WordSize -> String) -> ([WordSize] -> ShowS) -> Show WordSize
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> WordSize -> ShowS
    showsPrec :: Int -> WordSize -> ShowS
    $cshow :: WordSize -> String
    show :: WordSize -> String
    $cshowList :: [WordSize] -> ShowS
    showList :: [WordSize] -> ShowS
    Show, ReadPrec [WordSize]
    ReadPrec WordSize
    Int -> ReadS WordSize
    ReadS [WordSize]
    (Int -> ReadS WordSize)
    -> ReadS [WordSize]
    -> ReadPrec WordSize
    -> ReadPrec [WordSize]
    -> Read WordSize
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS WordSize
    readsPrec :: Int -> ReadS WordSize
    $creadList :: ReadS [WordSize]
    readList :: ReadS [WordSize]
    $creadPrec :: ReadPrec WordSize
    readPrec :: ReadPrec WordSize
    $creadListPrec :: ReadPrec [WordSize]
    readListPrec :: ReadPrec [WordSize]
    Read, WordSize -> WordSize -> Bool
    (WordSize -> WordSize -> Bool)
    -> (WordSize -> WordSize -> Bool) -> Eq WordSize
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: WordSize -> WordSize -> Bool
    == :: WordSize -> WordSize -> Bool
    $c/= :: WordSize -> WordSize -> Bool
    /= :: WordSize -> WordSize -> Bool
    Eq, Eq WordSize
    Eq WordSize =>
    (WordSize -> WordSize -> Ordering)
    -> (WordSize -> WordSize -> Bool)
    -> (WordSize -> WordSize -> Bool)
    -> (WordSize -> WordSize -> Bool)
    -> (WordSize -> WordSize -> Bool)
    -> (WordSize -> WordSize -> WordSize)
    -> (WordSize -> WordSize -> WordSize)
    -> Ord WordSize
    WordSize -> WordSize -> Bool
    WordSize -> WordSize -> Ordering
    WordSize -> WordSize -> WordSize
    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 :: WordSize -> WordSize -> Ordering
    compare :: WordSize -> WordSize -> Ordering
    $c< :: WordSize -> WordSize -> Bool
    < :: WordSize -> WordSize -> Bool
    $c<= :: WordSize -> WordSize -> Bool
    <= :: WordSize -> WordSize -> Bool
    $c> :: WordSize -> WordSize -> Bool
    > :: WordSize -> WordSize -> Bool
    $c>= :: WordSize -> WordSize -> Bool
    >= :: WordSize -> WordSize -> Bool
    $cmax :: WordSize -> WordSize -> WordSize
    max :: WordSize -> WordSize -> WordSize
    $cmin :: WordSize -> WordSize -> WordSize
    min :: WordSize -> WordSize -> WordSize
    Ord)

    data Endianness = LittleEndian | BigEndian
        deriving (Int -> Endianness -> ShowS
    [Endianness] -> ShowS
    Endianness -> String
    (Int -> Endianness -> ShowS)
    -> (Endianness -> String)
    -> ([Endianness] -> ShowS)
    -> Show Endianness
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Endianness -> ShowS
    showsPrec :: Int -> Endianness -> ShowS
    $cshow :: Endianness -> String
    show :: Endianness -> String
    $cshowList :: [Endianness] -> ShowS
    showList :: [Endianness] -> ShowS
    Show, ReadPrec [Endianness]
    ReadPrec Endianness
    Int -> ReadS Endianness
    ReadS [Endianness]
    (Int -> ReadS Endianness)
    -> ReadS [Endianness]
    -> ReadPrec Endianness
    -> ReadPrec [Endianness]
    -> Read Endianness
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Endianness
    readsPrec :: Int -> ReadS Endianness
    $creadList :: ReadS [Endianness]
    readList :: ReadS [Endianness]
    $creadPrec :: ReadPrec Endianness
    readPrec :: ReadPrec Endianness
    $creadListPrec :: ReadPrec [Endianness]
    readListPrec :: ReadPrec [Endianness]
    Read, Endianness -> Endianness -> Bool
    (Endianness -> Endianness -> Bool)
    -> (Endianness -> Endianness -> Bool) -> Eq Endianness
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Endianness -> Endianness -> Bool
    == :: Endianness -> Endianness -> Bool
    $c/= :: Endianness -> Endianness -> Bool
    /= :: Endianness -> Endianness -> Bool
    Eq, Eq Endianness
    Eq Endianness =>
    (Endianness -> Endianness -> Ordering)
    -> (Endianness -> Endianness -> Bool)
    -> (Endianness -> Endianness -> Bool)
    -> (Endianness -> Endianness -> Bool)
    -> (Endianness -> Endianness -> Bool)
    -> (Endianness -> Endianness -> Endianness)
    -> (Endianness -> Endianness -> Endianness)
    -> Ord Endianness
    Endianness -> Endianness -> Bool
    Endianness -> Endianness -> Ordering
    Endianness -> Endianness -> Endianness
    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 :: Endianness -> Endianness -> Ordering
    compare :: Endianness -> Endianness -> Ordering
    $c< :: Endianness -> Endianness -> Bool
    < :: Endianness -> Endianness -> Bool
    $c<= :: Endianness -> Endianness -> Bool
    <= :: Endianness -> Endianness -> Bool
    $c> :: Endianness -> Endianness -> Bool
    > :: Endianness -> Endianness -> Bool
    $c>= :: Endianness -> Endianness -> Bool
    >= :: Endianness -> Endianness -> Bool
    $cmax :: Endianness -> Endianness -> Endianness
    max :: Endianness -> Endianness -> Endianness
    $cmin :: Endianness -> Endianness -> Endianness
    min :: Endianness -> Endianness -> Endianness
    Ord)

    -- TODO(#23674): Move the remaining relevant `settings-xxx` to Target:
    -- * llc command
    -- * opt command
    -- * install_name_tool
    -- * otool command
    --
    -- Those are all things that are put into GHC's settings, and that might be
    -- different across targets

    -- | A 'Target' consists of:
    --
    -- * a target architecture and operating system
    -- * various bits of information about the platform
    -- * various toolchain components targetting that platform
    data Target = Target
        { -- Platform
          Target -> ArchOS
    tgtArchOs :: ArchOS
        , Target -> Maybe String
    tgtVendor :: Maybe String -- ^ This is the vendor component of the triple, the other two components are found in @'tgtArchOs'@
        , Target -> Bool
    tgtLocallyExecutable :: Bool
        , Target -> Bool
    tgtSupportsGnuNonexecStack :: Bool
        , Target -> Bool
    tgtSupportsSubsectionsViaSymbols :: Bool
        , Target -> Bool
    tgtSupportsIdentDirective :: Bool
        , Target -> WordSize
    tgtWordSize :: WordSize
        , Target -> Endianness
    tgtEndianness :: Endianness
        , Target -> Bool
    tgtSymbolsHaveLeadingUnderscore :: Bool
        , Target -> String
    tgtLlvmTarget :: String

          -- GHC capabilities
        , Target -> Bool
    tgtUnregisterised :: Bool
        , Target -> Bool
    tgtTablesNextToCode :: Bool
        -- , tgtHasThreadedRts :: Bool -- We likely just need this when bootstrapping
        , Target -> Bool
    tgtUseLibffiForAdjustors :: Bool
        -- ^ We need to know whether or not to include libffi headers, and generate additional code for it

          -- C toolchain
        , Target -> Cc
    tgtCCompiler :: Cc
        , Target -> Cxx
    tgtCxxCompiler :: Cxx
        , Target -> Cpp
    tgtCPreprocessor :: Cpp
        , Target -> HsCpp
    tgtHsCPreprocessor :: HsCpp
        , Target -> CcLink
    tgtCCompilerLink :: CcLink
        , Target -> Ar
    tgtAr :: Ar
        , Target -> Maybe Ranlib
    tgtRanlib :: Maybe Ranlib
        -- ^ N.B. Most @ar@ implementations will add an index by default without @ranlib@ so this is often optional
        , Target -> Nm
    tgtNm :: Nm
        , Target -> Maybe MergeObjs
    tgtMergeObjs :: Maybe MergeObjs
        -- ^ We don't need a merge objects tool if we @Ar@ supports @-L@

          -- Windows-specific tools
        , Target -> Maybe Program
    tgtWindres :: Maybe Program
        }
        deriving (ReadPrec [Target]
    ReadPrec Target
    Int -> ReadS Target
    ReadS [Target]
    (Int -> ReadS Target)
    -> ReadS [Target]
    -> ReadPrec Target
    -> ReadPrec [Target]
    -> Read Target
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS Target
    readsPrec :: Int -> ReadS Target
    $creadList :: ReadS [Target]
    readList :: ReadS [Target]
    $creadPrec :: ReadPrec Target
    readPrec :: ReadPrec Target
    $creadListPrec :: ReadPrec [Target]
    readListPrec :: ReadPrec [Target]
    Read, Target -> Target -> Bool
    (Target -> Target -> Bool)
    -> (Target -> Target -> Bool) -> Eq Target
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Target -> Target -> Bool
    == :: Target -> Target -> Bool
    $c/= :: Target -> Target -> Bool
    /= :: Target -> Target -> Bool
    Eq, Eq Target
    Eq Target =>
    (Target -> Target -> Ordering)
    -> (Target -> Target -> Bool)
    -> (Target -> Target -> Bool)
    -> (Target -> Target -> Bool)
    -> (Target -> Target -> Bool)
    -> (Target -> Target -> Target)
    -> (Target -> Target -> Target)
    -> Ord Target
    Target -> Target -> Bool
    Target -> Target -> Ordering
    Target -> Target -> Target
    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 :: Target -> Target -> Ordering
    compare :: Target -> Target -> Ordering
    $c< :: Target -> Target -> Bool
    < :: Target -> Target -> Bool
    $c<= :: Target -> Target -> Bool
    <= :: Target -> Target -> Bool
    $c> :: Target -> Target -> Bool
    > :: Target -> Target -> Bool
    $c>= :: Target -> Target -> Bool
    >= :: Target -> Target -> Bool
    $cmax :: Target -> Target -> Target
    max :: Target -> Target -> Target
    $cmin :: Target -> Target -> Target
    min :: Target -> Target -> Target
    Ord)

    -- | The word size as an integer representing the number of bytes
    wordSize2Bytes :: WordSize -> Int
    wordSize2Bytes :: WordSize -> Int
    wordSize2Bytes WordSize
    WS4 = Int
    4
    wordSize2Bytes WordSize
    WS8 = Int
    8

    -- | Reconstruct the platform triple from a toolchain target
    -- (specifically from tgtArchOs and tgtVendor)
    targetPlatformTriple :: Target -> String
    targetPlatformTriple :: Target -> String
    targetPlatformTriple Target{ArchOS
    tgtArchOs :: Target -> ArchOS
    tgtArchOs :: ArchOS
    tgtArchOs, Maybe String
    tgtVendor :: Target -> Maybe String
    tgtVendor :: Maybe String
    tgtVendor} =
      let archStr :: String
    archStr = Arch -> String
    stringEncodeArch (Arch -> String) -> Arch -> String
    forall a b. (a -> b) -> a -> b
    $ ArchOS -> Arch
    archOS_arch ArchOS
    tgtArchOs
          osStr :: String
    osStr   = OS -> String
    stringEncodeOS (OS -> String) -> OS -> String
    forall a b. (a -> b) -> a -> b
    $ ArchOS -> OS
    archOS_OS ArchOS
    tgtArchOs
       in case Maybe String
    tgtVendor of
            Maybe String
    Nothing -> String
    archStr String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "-" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    osStr
            Just String
    vendor -> String
    archStr String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "-" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    vendor String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "-" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    osStr

    -- | Handwritten Show instance to have have better diffs against the toolchain
    -- targets generated by configure
    instance Show Target where
      show :: Target -> String
    show Target{Bool
    String
    Maybe String
    Maybe Program
    Maybe Ranlib
    Maybe MergeObjs
    ArchOS
    Nm
    Cxx
    Cc
    CcLink
    HsCpp
    Cpp
    Ar
    Endianness
    WordSize
    tgtArchOs :: Target -> ArchOS
    tgtVendor :: Target -> Maybe String
    tgtLocallyExecutable :: Target -> Bool
    tgtSupportsGnuNonexecStack :: Target -> Bool
    tgtSupportsSubsectionsViaSymbols :: Target -> Bool
    tgtSupportsIdentDirective :: Target -> Bool
    tgtWordSize :: Target -> WordSize
    tgtEndianness :: Target -> Endianness
    tgtSymbolsHaveLeadingUnderscore :: Target -> Bool
    tgtLlvmTarget :: Target -> String
    tgtUnregisterised :: Target -> Bool
    tgtTablesNextToCode :: Target -> Bool
    tgtUseLibffiForAdjustors :: Target -> Bool
    tgtCCompiler :: Target -> Cc
    tgtCxxCompiler :: Target -> Cxx
    tgtCPreprocessor :: Target -> Cpp
    tgtHsCPreprocessor :: Target -> HsCpp
    tgtCCompilerLink :: Target -> CcLink
    tgtAr :: Target -> Ar
    tgtRanlib :: Target -> Maybe Ranlib
    tgtNm :: Target -> Nm
    tgtMergeObjs :: Target -> Maybe MergeObjs
    tgtWindres :: Target -> Maybe Program
    tgtArchOs :: ArchOS
    tgtVendor :: Maybe String
    tgtLocallyExecutable :: Bool
    tgtSupportsGnuNonexecStack :: Bool
    tgtSupportsSubsectionsViaSymbols :: Bool
    tgtSupportsIdentDirective :: Bool
    tgtWordSize :: WordSize
    tgtEndianness :: Endianness
    tgtSymbolsHaveLeadingUnderscore :: Bool
    tgtLlvmTarget :: String
    tgtUnregisterised :: Bool
    tgtTablesNextToCode :: Bool
    tgtUseLibffiForAdjustors :: Bool
    tgtCCompiler :: Cc
    tgtCxxCompiler :: Cxx
    tgtCPreprocessor :: Cpp
    tgtHsCPreprocessor :: HsCpp
    tgtCCompilerLink :: CcLink
    tgtAr :: Ar
    tgtRanlib :: Maybe Ranlib
    tgtNm :: Nm
    tgtMergeObjs :: Maybe MergeObjs
    tgtWindres :: Maybe Program
    ..} = [String] -> String
    unlines
        [ String
    "Target"
        , String
    "{ tgtArchOs = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ArchOS -> String
    forall a. Show a => a -> String
    show ArchOS
    tgtArchOs
        , String
    ", tgtVendor = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Maybe String -> String
    forall a. Show a => a -> String
    show Maybe String
    tgtVendor
        , String
    ", tgtLocallyExecutable = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtLocallyExecutable
        , String
    ", tgtSupportsGnuNonexecStack = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtSupportsGnuNonexecStack
        , String
    ", tgtSupportsSubsectionsViaSymbols = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtSupportsSubsectionsViaSymbols
        , String
    ", tgtSupportsIdentDirective = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtSupportsIdentDirective
        , String
    ", tgtWordSize = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ WordSize -> String
    forall a. Show a => a -> String
    show WordSize
    tgtWordSize
        , String
    ", tgtEndianness = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Endianness -> String
    forall a. Show a => a -> String
    show Endianness
    tgtEndianness
        , String
    ", tgtSymbolsHaveLeadingUnderscore = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtSymbolsHaveLeadingUnderscore
        , String
    ", tgtLlvmTarget = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    forall a. Show a => a -> String
    show String
    tgtLlvmTarget
        , String
    ", tgtUnregisterised = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtUnregisterised
        , String
    ", tgtTablesNextToCode = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtTablesNextToCode
        , String
    ", tgtUseLibffiForAdjustors = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Bool -> String
    forall a. Show a => a -> String
    show Bool
    tgtUseLibffiForAdjustors
        , String
    ", tgtCCompiler = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Cc -> String
    forall a. Show a => a -> String
    show Cc
    tgtCCompiler
        , String
    ", tgtCxxCompiler = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Cxx -> String
    forall a. Show a => a -> String
    show Cxx
    tgtCxxCompiler
        , String
    ", tgtCPreprocessor = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Cpp -> String
    forall a. Show a => a -> String
    show Cpp
    tgtCPreprocessor
        , String
    ", tgtHsCPreprocessor = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ HsCpp -> String
    forall a. Show a => a -> String
    show HsCpp
    tgtHsCPreprocessor
        , String
    ", tgtCCompilerLink = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ CcLink -> String
    forall a. Show a => a -> String
    show CcLink
    tgtCCompilerLink
        , String
    ", tgtAr = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Ar -> String
    forall a. Show a => a -> String
    show Ar
    tgtAr
        , String
    ", tgtRanlib = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Maybe Ranlib -> String
    forall a. Show a => a -> String
    show Maybe Ranlib
    tgtRanlib
        , String
    ", tgtNm = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Nm -> String
    forall a. Show a => a -> String
    show Nm
    tgtNm
        , String
    ", tgtMergeObjs = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Maybe MergeObjs -> String
    forall a. Show a => a -> String
    show Maybe MergeObjs
    tgtMergeObjs
        , String
    ", tgtWindres = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ Maybe Program -> String
    forall a. Show a => a -> String
    show Maybe Program
    tgtWindres
        , String
    "}"
        ]