Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • m4/ghc_toolchain.m4
    ... ... @@ -143,7 +143,17 @@ AC_DEFUN([FIND_GHC_TOOLCHAIN_BIN],[
    143 143
                 GHC_TOOLCHAIN_BIN="bin/${CrossCompilePrefix}ghc-toolchain-bin"
    
    144 144
                 ;;
    
    145 145
             NO)
    
    146
    -            # We're in the source tree, so compile ghc-toolchain
    
    146
    +            # We're in the source tree
    
    147
    +
    
    148
    +            # Check for consistency of LLVM versions
    
    149
    +            hs_min_llvm=$(sed -n 's/^minLlvmVersion = //p' utils/ghc-toolchain/src/GHC/Toolchain/Program.hs)
    
    150
    +            hs_max_llvm=$(sed -n 's/^maxLlvmVersionExcl = //p' utils/ghc-toolchain/src/GHC/Toolchain/Program.hs)
    
    151
    +            test "$hs_min_llvm" = "$LlvmMinVersion" || \
    
    152
    +                AC_MSG_ERROR([minLlvmVersion ($hs_min_llvm) in utils/ghc-toolchain/src/GHC/Toolchain/Program.hs must equal LlvmMinVersion ($LlvmMinVersion) in configure.ac])
    
    153
    +            test "$hs_max_llvm" = "$LlvmMaxVersion" || \
    
    154
    +                AC_MSG_ERROR([maxLlvmVersionExcl ($hs_max_llvm) in utils/ghc-toolchain/src/GHC/Toolchain/Program.hs must equal LlvmMaxVersion ($LlvmMaxVersion) in configure.ac])
    
    155
    +
    
    156
    +            # Compile ghc-toolchain
    
    147 157
                 "$GHC" -v0 \
    
    148 158
                     -ilibraries/ghc-platform/src -iutils/ghc-toolchain/src \
    
    149 159
                     -XNoImplicitPrelude \
    

  • utils/ghc-toolchain/exe/Main.hs
    ... ... @@ -289,13 +289,9 @@ formatOpts = [
    289 289
     
    
    290 290
     validateOpts :: Opts -> [String]
    
    291 291
     validateOpts opts = mconcat
    
    292
    -    [ assertJust _optTriple "missing --triple flag"
    
    293
    -    , assertJust _optOutput "missing --output flag"
    
    292
    +    [ ["missing --triple flag" | isNothing (optTriple opts)]
    
    293
    +    , ["missing --output flag" | isNothing (optOutput opts)]
    
    294 294
         ]
    
    295
    -  where
    
    296
    -    assertJust :: Lens Opts (Maybe a) -> String -> [String]
    
    297
    -    assertJust lens msg =
    
    298
    -      [ msg | Nothing <- pure $ view lens opts ]
    
    299 295
     
    
    300 296
     main :: IO ()
    
    301 297
     main = do
    
    ... ... @@ -480,13 +476,13 @@ mkTarget opts = do
    480 476
           throwE "Neither a object-merging tool (e.g. ld -r) nor an ar that supports -L is available"
    
    481 477
     
    
    482 478
         -- LLVM toolchain
    
    483
    -    llc <- optional $ findProgram "llc" (optLlc opts) ["llc"]
    
    484
    -    opt <- optional $ findProgram "opt" (optOpt opts) ["opt"]
    
    485
    -    llvmAs <- optional $ findProgram "llvm assembler" (optLlvmAs opts) ["clang"]
    
    479
    +    llc <- optional $ findLlvmProgram "llc" (optLlc opts) "llc" True
    
    480
    +    opt <- optional $ findLlvmProgram "opt" (optOpt opts) "opt" True
    
    481
    +    llvmAs <- optional $ findLlvmProgram "llvm assembler" (optLlvmAs opts) "clang" True
    
    486 482
     
    
    487 483
         -- for windows, also used for cross compiling
    
    488 484
         windres <- optional $ findProgram "windres" (optWindres opts) ["windres"]
    
    489
    -    dlltool <- optional $ findProgram "dlltool" (optDlltool opts) ["llvm-dlltool"]
    
    485
    +    dlltool <- optional $ findLlvmProgram "dlltool" (optDlltool opts) "llvm-dlltool" False
    
    490 486
     
    
    491 487
         -- Darwin-specific utilities
    
    492 488
         (otool, installNameTool) <-
    

  • utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
    ... ... @@ -16,6 +16,7 @@ module GHC.Toolchain.Program
    16 16
         , _poPath
    
    17 17
         , _poFlags
    
    18 18
         , findProgram
    
    19
    +    , findLlvmProgram
    
    19 20
          -- * Compiler programs
    
    20 21
         , compile
    
    21 22
         , supportsTarget
    
    ... ... @@ -23,7 +24,8 @@ module GHC.Toolchain.Program
    23 24
     
    
    24 25
     import Control.Monad
    
    25 26
     import Control.Monad.IO.Class
    
    26
    -import Data.List (intercalate, isPrefixOf)
    
    27
    +import Data.Char (isDigit)
    
    28
    +import Data.List (find, intercalate, isPrefixOf, tails)
    
    27 29
     import Data.Maybe
    
    28 30
     import System.FilePath
    
    29 31
     import System.Directory
    
    ... ... @@ -131,17 +133,13 @@ programFromOpt userSpec path flags = Program { prgPath = fromMaybe path (poPath
    131 133
     -- in the given list of candidates.
    
    132 134
     --
    
    133 135
     -- If the 'ProgOpt' program flags are unspecified the program will have an empty list of flags.
    
    134
    -findProgram :: String
    
    136
    +findProgram :: String      -- ^ The program description
    
    135 137
                 -> ProgOpt     -- ^ path provided by user
    
    136 138
                 -> [FilePath]  -- ^ candidate names
    
    137 139
                 -> M Program
    
    138 140
     findProgram description userSpec candidates
    
    139
    -  | Just path <- poPath userSpec = do
    
    140
    -      let err =
    
    141
    -            [ "Failed to find " ++ description ++ "."
    
    142
    -            , "Looked for user-specified program '" ++ path ++ "' in the system search path."
    
    143
    -            ]
    
    144
    -      toProgram <$> find_it path <|> throwEs err
    
    141
    +  | Just findProgramFromProgOpts <- maybeFindProgramFromProgOpts description userSpec
    
    142
    +  = findProgramFromProgOpts
    
    145 143
     
    
    146 144
       | otherwise = do
    
    147 145
           env <- getEnv
    
    ... ... @@ -154,17 +152,91 @@ findProgram description userSpec candidates
    154 152
                 [ "Failed to find " ++ description ++ "."
    
    155 153
                 , "Looked for one of " ++ show candidates' ++ " in the system search path."
    
    156 154
                 ]
    
    157
    -      toProgram <$> oneOf' err (map find_it candidates') <|> throwEs err
    
    155
    +      path <- oneOf' err (map findExecutableErr candidates')
    
    156
    +      return Program { prgPath = path, prgFlags = fromMaybe [] (poFlags userSpec) }
    
    157
    +
    
    158
    +-- Note that @configure.ac@ checks these llvm version constants (using @sed@) to
    
    159
    +-- ensure they are the same as the @$LlvmMinVersion@ and @$LlvmMaxVersion@
    
    160
    +-- defined in @configure.ac@.
    
    161
    +
    
    162
    +-- Min llvm version (inclusive)
    
    163
    +minLlvmVersion :: Int
    
    164
    +minLlvmVersion = 13
    
    165
    +
    
    166
    +-- Max llvm version (exclusive)
    
    167
    +maxLlvmVersionExcl :: Int
    
    168
    +maxLlvmVersionExcl = 23
    
    169
    +
    
    170
    +-- Max llvm version (inclusive)
    
    171
    +maxLlvmVersion :: Int
    
    172
    +maxLlvmVersion = maxLlvmVersionExcl - 1
    
    173
    +
    
    174
    +-- | Tries to find an llvm program with the highest supported llvm versions.
    
    175
    +-- This searches for an explicitly versioned executable (postfixed with the llvm version).
    
    176
    +-- If an explicitly versioned executable is not found, then this searches for a non-explicitly
    
    177
    +-- versioned executable. If supported, the llvm version is checked by passing @--version@ to
    
    178
    +-- the executable.
    
    179
    +--
    
    180
    +-- If the 'ProgOpt' program flags are unspecified the program will have an empty list of flags.
    
    181
    +findLlvmProgram :: String      -- ^ The llvm program description
    
    182
    +                -> ProgOpt     -- ^ path provided by user
    
    183
    +                -> FilePath    -- ^ Candidate name
    
    184
    +                -> Bool        -- ^ True if the program supports the @--version@ flag and the output
    
    185
    +                               --   contains the llvm version number in the form @version <LLVM_VERSION>@
    
    186
    +                -> M Program
    
    187
    +findLlvmProgram description userSpec candidate checkVersion
    
    188
    +  | Just findProgramFromProgOpts <- maybeFindProgramFromProgOpts description userSpec
    
    189
    +  = findProgramFromProgOpts
    
    190
    +
    
    191
    +  | otherwise = do
    
    192
    +      program <- findProgram description userSpec (versionedCandidates ++ [candidate])
    
    193
    +      when checkVersion $ do
    
    194
    +        -- Extract the version from the `--version` output
    
    195
    +        versionOutput <- readProgramStdout program ["--version"]
    
    196
    +        let versionStrPrefix = "version "
    
    197
    +
    
    198
    +            versionMay :: Maybe Int
    
    199
    +            versionMay = fmap (read . takeWhile isDigit . drop (length versionStrPrefix))
    
    200
    +              . find (versionStrPrefix `isPrefixOf`)
    
    201
    +              $ tails versionOutput
    
    202
    +
    
    203
    +            errSupportedVersions = prgPath program <> ": We only support llvm " <> show minLlvmVersion <> " upto " <> show maxLlvmVersion <> " (non-inclusive)"
    
    204
    +        case versionMay of
    
    205
    +          Nothing -> throwE (errSupportedVersions <> " (no version found).")
    
    206
    +          Just version -> when
    
    207
    +            (version < minLlvmVersion || version > maxLlvmVersion)
    
    208
    +            (throwE $ errSupportedVersions <> "  (found " <> show version <> ").")
    
    209
    +      return program
    
    158 210
       where
    
    159
    -      toProgram path = Program { prgPath = path, prgFlags = fromMaybe [] (poFlags userSpec) }
    
    160
    -
    
    161
    -      find_it name = do
    
    162
    -          r <- liftIO $ findExecutable name
    
    163
    -          case r of
    
    164
    -            Nothing -> throwE $ name ++ " not found in search path"
    
    165
    -            -- Use the given `prgPath` or candidate name rather than the
    
    166
    -            -- absolute path returned by `findExecutable`.
    
    167
    -            Just _x -> return name
    
    211
    +    versionedCandidates =
    
    212
    +      [ candidate <> postfix
    
    213
    +      | llvmVersion <- show <$> [maxLlvmVersion, maxLlvmVersion-1 .. minLlvmVersion]
    
    214
    +      , postfix <-
    
    215
    +        [ "-" <> llvmVersion
    
    216
    +        , "-" <> llvmVersion <> ".0"
    
    217
    +        , llvmVersion
    
    218
    +        ]
    
    219
    +      ]
    
    220
    +
    
    221
    +maybeFindProgramFromProgOpts :: String -> ProgOpt -> Maybe (M Program)
    
    222
    +maybeFindProgramFromProgOpts description userSpec = case poPath userSpec of
    
    223
    +  Nothing -> Nothing
    
    224
    +  Just path -> Just $ do
    
    225
    +    let err =
    
    226
    +          [ "Failed to find " ++ description ++ "."
    
    227
    +          , "Looked for user-specified program '" ++ path ++ "' in the system search path."
    
    228
    +          ]
    
    229
    +    path' <- findExecutableErr path <|> throwEs err
    
    230
    +    return Program { prgPath = path', prgFlags = fromMaybe [] (poFlags userSpec) }
    
    231
    +
    
    232
    +findExecutableErr :: String -> M FilePath
    
    233
    +findExecutableErr name = do
    
    234
    +    r <- liftIO $ findExecutable name
    
    235
    +    case r of
    
    236
    +      Nothing -> throwE $ name ++ " not found in search path"
    
    237
    +      -- Use the given `prgPath` or candidate name rather than the
    
    238
    +      -- absolute path returned by `findExecutable`.
    
    239
    +      Just _x -> return name
    
    168 240
     
    
    169 241
     -------------------- Compiling utilities --------------------
    
    170 242