[Git][ghc/ghc][master] ghc-toolchain: implement llvm program versioning logic
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
d6d76a7a by David Eichmann at 2026-05-19T12:46:19-04:00
ghc-toolchain: implement llvm program versioning logic
- - - - -
3 changed files:
- m4/ghc_toolchain.m4
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
Changes:
=====================================
m4/ghc_toolchain.m4
=====================================
@@ -143,7 +143,17 @@ AC_DEFUN([FIND_GHC_TOOLCHAIN_BIN],[
GHC_TOOLCHAIN_BIN="bin/${CrossCompilePrefix}ghc-toolchain-bin"
;;
NO)
- # We're in the source tree, so compile ghc-toolchain
+ # We're in the source tree
+
+ # Check for consistency of LLVM versions
+ hs_min_llvm=$(sed -n 's/^minLlvmVersion = //p' utils/ghc-toolchain/src/GHC/Toolchain/Program.hs)
+ hs_max_llvm=$(sed -n 's/^maxLlvmVersionExcl = //p' utils/ghc-toolchain/src/GHC/Toolchain/Program.hs)
+ test "$hs_min_llvm" = "$LlvmMinVersion" || \
+ AC_MSG_ERROR([minLlvmVersion ($hs_min_llvm) in utils/ghc-toolchain/src/GHC/Toolchain/Program.hs must equal LlvmMinVersion ($LlvmMinVersion) in configure.ac])
+ test "$hs_max_llvm" = "$LlvmMaxVersion" || \
+ AC_MSG_ERROR([maxLlvmVersionExcl ($hs_max_llvm) in utils/ghc-toolchain/src/GHC/Toolchain/Program.hs must equal LlvmMaxVersion ($LlvmMaxVersion) in configure.ac])
+
+ # Compile ghc-toolchain
"$GHC" -v0 \
-ilibraries/ghc-platform/src -iutils/ghc-toolchain/src \
-XNoImplicitPrelude \
=====================================
utils/ghc-toolchain/exe/Main.hs
=====================================
@@ -289,13 +289,9 @@ formatOpts = [
validateOpts :: Opts -> [String]
validateOpts opts = mconcat
- [ assertJust _optTriple "missing --triple flag"
- , assertJust _optOutput "missing --output flag"
+ [ ["missing --triple flag" | isNothing (optTriple opts)]
+ , ["missing --output flag" | isNothing (optOutput opts)]
]
- where
- assertJust :: Lens Opts (Maybe a) -> String -> [String]
- assertJust lens msg =
- [ msg | Nothing <- pure $ view lens opts ]
main :: IO ()
main = do
@@ -480,13 +476,13 @@ mkTarget opts = do
throwE "Neither a object-merging tool (e.g. ld -r) nor an ar that supports -L is available"
-- LLVM toolchain
- llc <- optional $ findProgram "llc" (optLlc opts) ["llc"]
- opt <- optional $ findProgram "opt" (optOpt opts) ["opt"]
- llvmAs <- optional $ findProgram "llvm assembler" (optLlvmAs opts) ["clang"]
+ llc <- optional $ findLlvmProgram "llc" (optLlc opts) "llc" True
+ opt <- optional $ findLlvmProgram "opt" (optOpt opts) "opt" True
+ llvmAs <- optional $ findLlvmProgram "llvm assembler" (optLlvmAs opts) "clang" True
-- for windows, also used for cross compiling
windres <- optional $ findProgram "windres" (optWindres opts) ["windres"]
- dlltool <- optional $ findProgram "dlltool" (optDlltool opts) ["llvm-dlltool"]
+ dlltool <- optional $ findLlvmProgram "dlltool" (optDlltool opts) "llvm-dlltool" False
-- Darwin-specific utilities
(otool, installNameTool) <-
=====================================
utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
=====================================
@@ -16,6 +16,7 @@ module GHC.Toolchain.Program
, _poPath
, _poFlags
, findProgram
+ , findLlvmProgram
-- * Compiler programs
, compile
, supportsTarget
@@ -23,7 +24,8 @@ module GHC.Toolchain.Program
import Control.Monad
import Control.Monad.IO.Class
-import Data.List (intercalate, isPrefixOf)
+import Data.Char (isDigit)
+import Data.List (find, intercalate, isPrefixOf, tails)
import Data.Maybe
import System.FilePath
import System.Directory
@@ -131,17 +133,13 @@ programFromOpt userSpec path flags = Program { prgPath = fromMaybe path (poPath
-- in the given list of candidates.
--
-- If the 'ProgOpt' program flags are unspecified the program will have an empty list of flags.
-findProgram :: String
+findProgram :: String -- ^ The program description
-> ProgOpt -- ^ path provided by user
-> [FilePath] -- ^ candidate names
-> M Program
findProgram description userSpec candidates
- | Just path <- poPath userSpec = do
- let err =
- [ "Failed to find " ++ description ++ "."
- , "Looked for user-specified program '" ++ path ++ "' in the system search path."
- ]
- toProgram <$> find_it path <|> throwEs err
+ | Just findProgramFromProgOpts <- maybeFindProgramFromProgOpts description userSpec
+ = findProgramFromProgOpts
| otherwise = do
env <- getEnv
@@ -154,17 +152,91 @@ findProgram description userSpec candidates
[ "Failed to find " ++ description ++ "."
, "Looked for one of " ++ show candidates' ++ " in the system search path."
]
- toProgram <$> oneOf' err (map find_it candidates') <|> throwEs err
+ path <- oneOf' err (map findExecutableErr candidates')
+ return Program { prgPath = path, prgFlags = fromMaybe [] (poFlags userSpec) }
+
+-- Note that @configure.ac@ checks these llvm version constants (using @sed@) to
+-- ensure they are the same as the @$LlvmMinVersion@ and @$LlvmMaxVersion@
+-- defined in @configure.ac@.
+
+-- Min llvm version (inclusive)
+minLlvmVersion :: Int
+minLlvmVersion = 13
+
+-- Max llvm version (exclusive)
+maxLlvmVersionExcl :: Int
+maxLlvmVersionExcl = 23
+
+-- Max llvm version (inclusive)
+maxLlvmVersion :: Int
+maxLlvmVersion = maxLlvmVersionExcl - 1
+
+-- | Tries to find an llvm program with the highest supported llvm versions.
+-- This searches for an explicitly versioned executable (postfixed with the llvm version).
+-- If an explicitly versioned executable is not found, then this searches for a non-explicitly
+-- versioned executable. If supported, the llvm version is checked by passing @--version@ to
+-- the executable.
+--
+-- If the 'ProgOpt' program flags are unspecified the program will have an empty list of flags.
+findLlvmProgram :: String -- ^ The llvm program description
+ -> ProgOpt -- ^ path provided by user
+ -> FilePath -- ^ Candidate name
+ -> Bool -- ^ True if the program supports the @--version@ flag and the output
+ -- contains the llvm version number in the form @version
participants (1)
-
Marge Bot (@marge-bot)