-- | Llvm code generator configuration module GHC.CmmToLlvm.Config ( LlvmCgConfig(..) , LlvmConfig(..) , LlvmTarget(..) , initLlvmConfig ) where import GHC.Prelude import GHC.Platform import GHC.Utils.Outputable import GHC.Settings.Utils import GHC.Utils.Panic import GHC.CmmToLlvm.Version.Type (LlvmVersion) import System.FilePath data LlvmCgConfig = LlvmCgConfig { llvmCgPlatform :: !Platform -- ^ Target platform , llvmCgContext :: !SDocContext -- ^ Context for LLVM code generation , llvmCgFillUndefWithGarbage :: !Bool -- ^ Fill undefined literals with garbage values , llvmCgSplitSection :: !Bool -- ^ Split sections , llvmCgAvxEnabled :: !Bool , llvmCgBmiVersion :: Maybe BmiVersion -- ^ (x86) BMI instructions , llvmCgLlvmVersion :: Maybe LlvmVersion -- ^ version of Llvm we're using , llvmCgDoWarn :: !Bool -- ^ True ==> warn unsupported Llvm version , llvmCgLlvmTarget :: !String -- ^ target triple passed to LLVM , llvmCgLlvmConfig :: !LlvmConfig -- ^ Supported LLVM configurations. -- see Note [LLVM configuration] } data LlvmTarget = LlvmTarget { lDataLayout :: String , lCPU :: String , lAttributes :: [String] } -- Note [LLVM configuration] -- ~~~~~~~~~~~~~~~~~~~~~~~~~ -- The `llvm-targets` and `llvm-passes` files are shipped with GHC and contain -- information needed by the LLVM backend to invoke `llc` and `opt`. -- Specifically: -- -- * llvm-targets maps autoconf host triples to the corresponding LLVM -- `data-layout` declarations. This information is extracted from clang using -- the script in utils/llvm-targets/gen-data-layout.sh and should be updated -- whenever we target a new version of LLVM. -- -- * llvm-passes maps GHC optimization levels to sets of LLVM optimization -- flags that GHC should pass to `opt`. -- -- This information is contained in files rather the GHC source to allow users -- to add new targets to GHC without having to recompile the compiler. -- initLlvmConfig :: FilePath -> IO LlvmConfig initLlvmConfig top_dir = do targets <- readAndParse "llvm-targets" passes <- readAndParse "llvm-passes" return $ LlvmConfig { llvmTargets = fmap mkLlvmTarget <$> targets , llvmPasses = passes } where readAndParse :: Read a => String -> IO a readAndParse name = do let f = top_dir name llvmConfigStr <- readFile f case maybeReadFuzzy llvmConfigStr of Just s -> return s Nothing -> pgmError ("Can't parse LLVM config file: " ++ show f) mkLlvmTarget :: (String, String, String) -> LlvmTarget mkLlvmTarget (dl, cpu, attrs) = LlvmTarget dl cpu (words attrs) data LlvmConfig = LlvmConfig { llvmTargets :: [(String, LlvmTarget)] , llvmPasses :: [(Int, String)] }