diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 637d54dd06c65..38b34cb1485ef 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -796,6 +796,19 @@ impl<'a> Linker for GccLinker<'a> { } } + // On Apple, exporting LLVM symbols from rustc_driver allows the Enzyme + // submodule to find LLVM in rustc. Currently we only need this on + // Apple; keep the scope narrow to avoid exporting extra symbols on + // other targets. + // Related: https://github.com/rust-lang/enzyme/pull/31 + if crate_type == CrateType::Dylib + && self.sess.target.is_like_darwin + && self.sess.opts.unstable_opts.export_llvm_symbols + && self.sess.opts.crate_name.as_deref() == Some("rustc_driver") + { + return; + } + // We manually create a list of exported symbols to ensure we don't expose any more. // The object files have far more public symbols than we actually want to export, // so we hide them all here. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 99ab134038124..e126dcc64c020 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2365,6 +2365,8 @@ options! { "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], "export symbols from executables, as if they were dynamic libraries"), + export_llvm_symbols: bool = (false, parse_bool, [TRACKED], + "export LLVM symbols from rustc_driver on darwin"), external_clangrt: bool = (false, parse_bool, [UNTRACKED], "rely on user specified linker commands to find clangrt"), extra_const_ub_checks: bool = (false, parse_bool, [TRACKED], diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 4b13776bcf393..0702eea76e244 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1261,6 +1261,13 @@ pub fn rustc_cargo( cargo.rustflag("-Zdefault-visibility=protected"); } + // On Apple, Enzyme can hang if rustc and Enzyme each embed their own LLVM. + // Export LLVM symbols from rustc_driver so Enzyme reuses rustc's LLVM. + // Related: https://github.com/rust-lang/enzyme/pull/31 + if builder.config.llvm_enzyme && target.contains("apple") && build_compiler.stage != 0 { + cargo.rustflag("-Zexport-llvm-symbols"); + } + if is_lto_stage(build_compiler) { match builder.config.rust_lto { RustcLto::Thin | RustcLto::Fat => {