{-# 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
"}"
    ]