{-# LANGUAGE CPP #-}
module GHC.CmmToLlvm.Config
( LlvmCgConfig(..)
, LlvmConfig(..)
, LlvmTarget(..)
, initLlvmConfig
, LlvmVersion(..)
, supportedLlvmVersionLowerBound
, supportedLlvmVersionUpperBound
, parseLlvmVersion
, llvmVersionSupported
, llvmVersionStr
, llvmVersionList
)
where
#include "ghc-llvm-version.h"
import GHC.Prelude
import GHC.Platform
import GHC.Utils.Outputable
import GHC.Settings.Utils
import GHC.Utils.Panic
import Data.Char (isDigit)
import Data.List (intercalate)
import qualified Data.List.NonEmpty as NE
import System.FilePath
data LlvmCgConfig = LlvmCgConfig
{ LlvmCgConfig -> Platform
llvmCgPlatform :: !Platform
, LlvmCgConfig -> SDocContext
llvmCgContext :: !SDocContext
, LlvmCgConfig -> Bool
llvmCgFillUndefWithGarbage :: !Bool
, LlvmCgConfig -> Bool
llvmCgSplitSection :: !Bool
, LlvmCgConfig -> Maybe BmiVersion
llvmCgBmiVersion :: Maybe BmiVersion
, LlvmCgConfig -> Maybe LlvmVersion
llvmCgLlvmVersion :: Maybe LlvmVersion
, LlvmCgConfig -> Bool
llvmCgDoWarn :: !Bool
, LlvmCgConfig -> String
llvmCgLlvmTarget :: !String
, LlvmCgConfig -> LlvmConfig
llvmCgLlvmConfig :: !LlvmConfig
}
data LlvmTarget = LlvmTarget
{ LlvmTarget -> String
lDataLayout :: String
, LlvmTarget -> String
lCPU :: String
, LlvmTarget -> [String]
lAttributes :: [String]
}
initLlvmConfig :: FilePath -> IO LlvmConfig
initLlvmConfig :: String -> IO LlvmConfig
initLlvmConfig String
top_dir
= do
[(String, (String, String, String))]
targets <- forall a. Read a => String -> IO a
readAndParse String
"llvm-targets"
[(Int, String)]
passes <- forall a. Read a => String -> IO a
readAndParse String
"llvm-passes"
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ LlvmConfig
{ llvmTargets :: [(String, LlvmTarget)]
llvmTargets = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String, String, String) -> LlvmTarget
mkLlvmTarget forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(String, (String, String, String))]
targets
, llvmPasses :: [(Int, String)]
llvmPasses = [(Int, String)]
passes
}
where
readAndParse :: Read a => String -> IO a
readAndParse :: forall a. Read a => String -> IO a
readAndParse String
name = do
let f :: String
f = String
top_dir String -> String -> String
</> String
name
String
llvmConfigStr <- String -> IO String
readFile String
f
case forall a. Read a => String -> Maybe a
maybeReadFuzzy String
llvmConfigStr of
Just a
s -> forall (m :: * -> *) a. Monad m => a -> m a
return a
s
Maybe a
Nothing -> forall a. HasCallStack => String -> a
pgmError (String
"Can't parse LLVM config file: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show String
f)
mkLlvmTarget :: (String, String, String) -> LlvmTarget
mkLlvmTarget :: (String, String, String) -> LlvmTarget
mkLlvmTarget (String
dl, String
cpu, String
attrs) = String -> String -> [String] -> LlvmTarget
LlvmTarget String
dl String
cpu (String -> [String]
words String
attrs)
data LlvmConfig = LlvmConfig
{ LlvmConfig -> [(String, LlvmTarget)]
llvmTargets :: [(String, LlvmTarget)]
, LlvmConfig -> [(Int, String)]
llvmPasses :: [(Int, String)]
}
newtype LlvmVersion = LlvmVersion { LlvmVersion -> NonEmpty Int
llvmVersionNE :: NE.NonEmpty Int }
deriving (LlvmVersion -> LlvmVersion -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LlvmVersion -> LlvmVersion -> Bool
$c/= :: LlvmVersion -> LlvmVersion -> Bool
== :: LlvmVersion -> LlvmVersion -> Bool
$c== :: LlvmVersion -> LlvmVersion -> Bool
Eq, Eq LlvmVersion
LlvmVersion -> LlvmVersion -> Bool
LlvmVersion -> LlvmVersion -> Ordering
LlvmVersion -> LlvmVersion -> LlvmVersion
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
min :: LlvmVersion -> LlvmVersion -> LlvmVersion
$cmin :: LlvmVersion -> LlvmVersion -> LlvmVersion
max :: LlvmVersion -> LlvmVersion -> LlvmVersion
$cmax :: LlvmVersion -> LlvmVersion -> LlvmVersion
>= :: LlvmVersion -> LlvmVersion -> Bool
$c>= :: LlvmVersion -> LlvmVersion -> Bool
> :: LlvmVersion -> LlvmVersion -> Bool
$c> :: LlvmVersion -> LlvmVersion -> Bool
<= :: LlvmVersion -> LlvmVersion -> Bool
$c<= :: LlvmVersion -> LlvmVersion -> Bool
< :: LlvmVersion -> LlvmVersion -> Bool
$c< :: LlvmVersion -> LlvmVersion -> Bool
compare :: LlvmVersion -> LlvmVersion -> Ordering
$ccompare :: LlvmVersion -> LlvmVersion -> Ordering
Ord)
parseLlvmVersion :: String -> Maybe LlvmVersion
parseLlvmVersion :: String -> Maybe LlvmVersion
parseLlvmVersion =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap NonEmpty Int -> LlvmVersion
LlvmVersion forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. Read a => [a] -> String -> [a]
go [] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isDigit)
where
go :: [a] -> String -> [a]
go [a]
vs String
s
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
ver_str
= forall a. [a] -> [a]
reverse [a]
vs
| Char
'.' : String
rest' <- String
rest
= [a] -> String -> [a]
go (forall a. Read a => String -> a
read String
ver_str forall a. a -> [a] -> [a]
: [a]
vs) String
rest'
| Bool
otherwise
= forall a. [a] -> [a]
reverse (forall a. Read a => String -> a
read String
ver_str forall a. a -> [a] -> [a]
: [a]
vs)
where
(String
ver_str, String
rest) = forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit String
s
supportedLlvmVersionLowerBound :: LlvmVersion
supportedLlvmVersionLowerBound :: LlvmVersion
supportedLlvmVersionLowerBound = NonEmpty Int -> LlvmVersion
LlvmVersion (sUPPORTED_LLVM_VERSION_MIN NE.:| [])
supportedLlvmVersionUpperBound :: LlvmVersion
supportedLlvmVersionUpperBound :: LlvmVersion
supportedLlvmVersionUpperBound = NonEmpty Int -> LlvmVersion
LlvmVersion (sUPPORTED_LLVM_VERSION_MAX NE.:| [])
llvmVersionSupported :: LlvmVersion -> Bool
llvmVersionSupported :: LlvmVersion -> Bool
llvmVersionSupported LlvmVersion
v =
LlvmVersion
v forall a. Ord a => a -> a -> Bool
>= LlvmVersion
supportedLlvmVersionLowerBound Bool -> Bool -> Bool
&& LlvmVersion
v forall a. Ord a => a -> a -> Bool
< LlvmVersion
supportedLlvmVersionUpperBound
llvmVersionStr :: LlvmVersion -> String
llvmVersionStr :: LlvmVersion -> String
llvmVersionStr = forall a. [a] -> [[a]] -> [a]
intercalate String
"." forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a. Show a => a -> String
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. LlvmVersion -> [Int]
llvmVersionList
llvmVersionList :: LlvmVersion -> [Int]
llvmVersionList :: LlvmVersion -> [Int]
llvmVersionList = forall a. NonEmpty a -> [a]
NE.toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. LlvmVersion -> NonEmpty Int
llvmVersionNE