summaryrefslogtreecommitdiff
path: root/compiler/main/SysTools.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/main/SysTools.hs')
-rw-r--r--compiler/main/SysTools.hs32
1 files changed, 27 insertions, 5 deletions
diff --git a/compiler/main/SysTools.hs b/compiler/main/SysTools.hs
index fa339bbb87..b3312b0dae 100644
--- a/compiler/main/SysTools.hs
+++ b/compiler/main/SysTools.hs
@@ -13,7 +13,7 @@
module SysTools (
-- * Initialisation
initSysTools,
- initLlvmConfig,
+ lazyInitLlvmConfig,
-- * Interface to system tools
module SysTools.Tasks,
@@ -52,6 +52,7 @@ import DynFlags
import Control.Monad.Trans.Except (runExceptT)
import System.FilePath
import System.IO
+import System.IO.Unsafe (unsafeInterleaveIO)
import SysTools.ExtraObj
import SysTools.Info
import SysTools.Tasks
@@ -110,13 +111,34 @@ stuff.
************************************************************************
-}
-initLlvmConfig :: 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.
+--
+-- Since this information is only needed by the LLVM backend we load it lazily
+-- with unsafeInterleaveIO. Consequently it is important that we lazily pattern
+-- match on LlvmConfig until we actually need its contents.
+
+lazyInitLlvmConfig :: String
-> IO LlvmConfig
-initLlvmConfig top_dir
- = do
+lazyInitLlvmConfig top_dir
+ = unsafeInterleaveIO $ do -- see Note [LLVM configuration]
targets <- readAndParse "llvm-targets" mkLlvmTarget
passes <- readAndParse "llvm-passes" id
- return (targets, passes)
+ return $ LlvmConfig { llvmTargets = targets, llvmPasses = passes }
where
readAndParse name builder =
do let llvmConfigFile = top_dir </> name