pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError {
match llvm::last_error() {
Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
- None => handler.fatal(&msg),
+ None => handler.fatal(msg),
}
}
None
};
let config = TargetMachineFactoryConfig { split_dwarf_file };
- target_machine_factory(&tcx.sess, tcx.backend_optimization_level(()))(config)
+ target_machine_factory(tcx.sess, tcx.backend_optimization_level(()))(config)
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
}
fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
match relocation_model {
RelocModel::Static => llvm::RelocModel::Static,
- RelocModel::Pic => llvm::RelocModel::PIC,
+ // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute.
+ RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
RelocModel::Ropi => llvm::RelocModel::ROPI,
RelocModel::Rwpi => llvm::RelocModel::RWPI,
.map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap())
}
-pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool {
- // The new pass manager is disabled by default.
- config.new_llvm_pass_manager.unwrap_or(false)
+fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
+ config
+ .pgo_sample_use
+ .as_ref()
+ .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap())
+}
+
+pub(crate) fn should_use_new_llvm_pass_manager(
+ _cgcx: &CodegenContext<LlvmCodegenBackend>,
+ config: &ModuleConfig,
+) -> bool {
+ // The new pass manager is causing significant performance issues such as #91128, and is
+ // therefore disabled in stable versions of rustc by default.
+ config
+ .new_llvm_pass_manager
+ .unwrap_or(false)
}
pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
let using_thin_buffers = opt_stage == llvm::OptStage::PreLinkThinLTO || config.bitcode_needed();
let pgo_gen_path = get_pgo_gen_path(config);
let pgo_use_path = get_pgo_use_path(config);
+ let pgo_sample_use_path = get_pgo_sample_use_path(config);
let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
// Sanitizer instrumentation is only inserted during the pre-link optimization stage.
let sanitizer_options = if !is_lto {
None
};
- let llvm_selfprofiler = if cgcx.prof.llvm_recording_enabled() {
- let mut llvm_profiler = LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap());
- &mut llvm_profiler as *mut _ as *mut c_void
+ let mut llvm_profiler = if cgcx.prof.llvm_recording_enabled() {
+ Some(LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()))
} else {
- std::ptr::null_mut()
+ None
};
+ let llvm_selfprofiler =
+ llvm_profiler.as_mut().map(|s| s as *mut _ as *mut c_void).unwrap_or(std::ptr::null_mut());
+
let extra_passes = config.passes.join(",");
// FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
config.instrument_coverage,
config.instrument_gcov,
+ pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
+ config.debug_info_for_profiling,
llvm_selfprofiler,
selfprofile_before_pass_callback,
selfprofile_after_pass_callback,
}
if let Some(opt_level) = config.opt_level {
- if should_use_new_llvm_pass_manager(config) {
+ if should_use_new_llvm_pass_manager(cgcx, config) {
let opt_stage = match cgcx.lto {
Lto::Fat => llvm::OptStage::PreLinkFatLTO,
Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
if config.instrument_coverage {
llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap());
}
+ if config.debug_info_for_profiling {
+ llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap());
+ }
add_sanitizer_passes(config, &mut extra_passes);
let prepare_for_thin_lto = cgcx.lto == Lto::Thin
|| cgcx.lto == Lto::ThinLocal
|| (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
- with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
+ with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| {
llvm::LLVMRustAddLastExtensionPasses(
b,
extra_passes.as_ptr(),
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name));
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
- linker.add(&buffer.data()).map_err(|()| {
+ linker.add(buffer.data()).map_err(|()| {
let msg = format!("failed to serialize module {:?}", module.name);
- llvm_err(&diag_handler, &msg)
+ llvm_err(diag_handler, &msg)
})?;
}
drop(linker);
let inline_threshold = config.inline_threshold;
let pgo_gen_path = get_pgo_gen_path(config);
let pgo_use_path = get_pgo_use_path(config);
+ let pgo_sample_use_path = get_pgo_sample_use_path(config);
llvm::LLVMRustConfigurePassManagerBuilder(
builder,
prepare_for_thin_lto,
pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
+ pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
);
llvm::LLVMPassManagerBuilderSetSizeLevel(builder, opt_size as u32);