haskell.compiler.ghc91{0,2}: provide LLVM compatible assembler (#440761)

This commit is contained in:
sternenseemann
2025-09-12 10:43:13 +00:00
committed by GitHub
4 changed files with 47 additions and 23 deletions
@@ -433,7 +433,10 @@ let
}
.${name};
in
"${tools}/bin/${tools.targetPrefix}${name}";
getToolExe tools name;
# targetPrefix aware lib.getExe'
getToolExe = drv: name: lib.getExe' drv "${drv.targetPrefix or ""}${name}";
# Use gold either following the default, or to avoid the BFD linker due to some bugs / perf issues.
# But we cannot avoid BFD when using musl libc due to https://sourceware.org/bugzilla/show_bug.cgi?id=23856
@@ -530,8 +533,15 @@ stdenv.mkDerivation (
export INSTALL_NAME_TOOL="${toolPath "install_name_tool" targetCC}"
''
+ lib.optionalString useLLVM ''
export LLC="${lib.getBin buildTargetLlvmPackages.llvm}/bin/llc"
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
export LLC="${getToolExe buildTargetLlvmPackages.llvm "llc"}"
export OPT="${getToolExe buildTargetLlvmPackages.llvm "opt"}"
''
# LLVMAS should be a "specific LLVM compatible assembler" which needs to understand
# assembly produced by LLVM. The easiest way to be sure is to use clang from the same
# version as llc and opt. Note that the naming chosen by GHC is misleading, clang can
# be used as an assembler, llvm-as converts IR into machine code.
+ lib.optionalString (useLLVM && lib.versionAtLeast version "9.10") ''
export LLVMAS="${getToolExe buildTargetLlvmPackages.clang "clang"}"
''
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
# LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
@@ -541,11 +551,12 @@ stdenv.mkDerivation (
# the assembly it is given, we need to make sure that it matches the LLVM version of $CC if possible.
# It is unclear (at the time of writing 2024-09-01) whether $CC should match the LLVM version we use
# for llc and opt which would require using a custom darwin stdenv for targetCC.
# 2025-09-06: The existence of LLVMAS suggests that matching $CC is fine (correct?) here.
export CLANG="${
if targetCC.isClang then
toolPath "clang" targetCC
else
"${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang"
getToolExe buildTargetLlvmPackages.clang "clang"
}"
''
+ lib.optionalString (stdenv.buildPlatform.libc == "glibc") ''
@@ -826,17 +837,19 @@ stdenv.mkDerivation (
''
+ lib.optionalString useLLVM ''
ghc-settings-edit "$settingsFile" \
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
"LLVM llc command" "${getToolExe llvmPackages.llvm "llc"}" \
"LLVM opt command" "${getToolExe llvmPackages.llvm "opt"}"
''
# See comment for LLVMAS in preConfigure
+ lib.optionalString (useLLVM && lib.versionAtLeast version "9.10") ''
ghc-settings-edit "$settingsFile" \
"LLVM llvm-as command" "${getToolExe llvmPackages.clang "clang"}"
''
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
ghc-settings-edit "$settingsFile" \
"LLVM clang command" "${
# See comment for CLANG in preConfigure
if installCC.isClang then
toolPath "clang" installCC
else
"${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang"
if installCC.isClang then toolPath "clang" installCC else getToolExe llvmPackages.clang "clang"
}"
''
+ lib.optionalString stdenv.targetPlatform.isWindows ''
@@ -225,7 +225,10 @@ let
}
.${name};
in
"${tools}/bin/${tools.targetPrefix}${name}";
getToolExe tools name;
# targetPrefix aware lib.getExe'
getToolExe = drv: name: lib.getExe' drv "${drv.targetPrefix or ""}${name}";
# Use gold either following the default, or to avoid the BFD linker due to some bugs / perf issues.
# But we cannot avoid BFD when using musl libc due to https://sourceware.org/bugzilla/show_bug.cgi?id=23856
@@ -408,8 +411,8 @@ stdenv.mkDerivation (
export INSTALL_NAME_TOOL="${toolPath "install_name_tool" targetCC}"
''
+ lib.optionalString useLLVM ''
export LLC="${lib.getBin buildTargetLlvmPackages.llvm}/bin/llc"
export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt"
export LLC="${getToolExe buildTargetLlvmPackages.llvm "llc"}"
export OPT="${getToolExe buildTargetLlvmPackages.llvm "opt"}"
''
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
# LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
@@ -423,7 +426,7 @@ stdenv.mkDerivation (
if targetCC.isClang then
toolPath "clang" targetCC
else
"${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang"
getToolExe buildTargetLlvmPackages.clang "clang"
}"
''
+ ''
@@ -624,17 +627,14 @@ stdenv.mkDerivation (
''
+ lib.optionalString useLLVM ''
ghc-settings-edit "$settingsFile" \
"LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \
"LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt"
"LLVM llc command" "${getToolExe llvmPackages.llvm "llc"}" \
"LLVM opt command" "${getToolExe llvmPackages.llvm "opt"}"
''
+ lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) ''
ghc-settings-edit "$settingsFile" \
"LLVM clang command" "${
# See comment for CLANG in preConfigure
if installCC.isClang then
toolPath "clang" installCC
else
"${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang"
if installCC.isClang then toolPath "clang" installCC else getToolExe llvmPackages.clang "clang"
}"
''
+ ''
@@ -734,6 +734,13 @@ package-set { inherit pkgs lib callPackage; } self
*/
forceLlvmCodegenBackend = overrideCabal (drv: {
configureFlags = drv.configureFlags or [ ] ++ [ "--ghc-option=-fllvm" ];
buildTools = drv.buildTools or [ ] ++ [ self.ghc.llvmPackages.llvm ];
buildTools =
drv.buildTools or [ ]
++ [ self.ghc.llvmPackages.llvm ]
# GHC >= 9.10 needs LLVM specific assembler, i.e. clang
# On Darwin clang is always required
++ lib.optionals (lib.versionAtLeast self.ghc.version "9.10" || stdenv.hostPlatform.isDarwin) [
self.ghc.llvmPackages.clang
];
});
}
@@ -68,10 +68,14 @@ let
)
);
hasLibraries = lib.any (x: x.isHaskellLibrary) paths;
# CLang is needed on Darwin for -fllvm to work:
# Clang is needed on Darwin for -fllvm to work.
# GHC >= 9.10 needs an LLVM specific assembler which we use clang for.
# https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm
llvm = lib.makeBinPath (
[ ghc.llvmPackages.llvm ] ++ lib.optional stdenv.targetPlatform.isDarwin ghc.llvmPackages.clang
[ ghc.llvmPackages.llvm ]
++ lib.optionals (lib.versionAtLeast ghc.version "9.10" || stdenv.targetPlatform.isDarwin) [
ghc.llvmPackages.clang
]
);
in