|
1 | 1 | use std::ffi::CString;
|
| 2 | +use std::path::PathBuf; |
2 | 3 | use std::sync::Arc;
|
3 | 4 |
|
4 | 5 | use rustc_data_structures::memmap::Mmap;
|
5 |
| -use rustc_errors::{DiagCtxtHandle, FatalError}; |
6 |
| -use rustc_hir::def_id::LOCAL_CRATE; |
7 |
| -use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; |
| 6 | +use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; |
| 7 | +use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportLevel}; |
| 8 | +use rustc_middle::ty::TyCtxt; |
8 | 9 | use rustc_session::config::{CrateType, Lto};
|
9 | 10 | use tracing::info;
|
10 | 11 |
|
11 |
| -use crate::back::symbol_export; |
| 12 | +use crate::back::symbol_export::{self, symbol_name_for_instance_in_crate}; |
12 | 13 | use crate::back::write::CodegenContext;
|
13 | 14 | use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro};
|
14 | 15 | use crate::traits::*;
|
@@ -73,65 +74,73 @@ fn crate_type_allows_lto(crate_type: CrateType) -> bool {
|
73 | 74 | }
|
74 | 75 | }
|
75 | 76 |
|
76 |
| -pub fn exported_symbols_for_lto<'a, B: WriteBackendMethods>( |
77 |
| - cgcx: &'a CodegenContext<B>, |
78 |
| - dcx: DiagCtxtHandle<'_>, |
79 |
| -) -> Result<Vec<&'a str>, FatalError> { |
80 |
| - // FIXME move symbol filtering to cg_ssa |
81 |
| - let export_threshold = match cgcx.lto { |
| 77 | +pub(super) fn exported_symbols_for_lto( |
| 78 | + tcx: TyCtxt<'_>, |
| 79 | + each_linked_rlib_for_lto: &[(CrateNum, PathBuf)], |
| 80 | +) -> Vec<String> { |
| 81 | + let export_threshold = match tcx.sess.lto() { |
82 | 82 | // We're just doing LTO for our one crate
|
83 | 83 | Lto::ThinLocal => SymbolExportLevel::Rust,
|
84 | 84 |
|
85 | 85 | // We're doing LTO for the entire crate graph
|
86 |
| - Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&cgcx.crate_types), |
| 86 | + Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&tcx.crate_types()), |
87 | 87 |
|
88 |
| - Lto::No => panic!("didn't request LTO but we're doing LTO"), |
| 88 | + Lto::No => return vec![], |
89 | 89 | };
|
90 | 90 |
|
91 |
| - let symbol_filter = &|&(ref name, info): &'a (String, SymbolExportInfo)| { |
92 |
| - if info.level.is_below_threshold(export_threshold) || info.used { |
93 |
| - Some(name.as_str()) |
94 |
| - } else { |
95 |
| - None |
96 |
| - } |
| 91 | + let copy_symbols = |cnum| { |
| 92 | + tcx.exported_non_generic_symbols(cnum) |
| 93 | + .iter() |
| 94 | + .chain(tcx.exported_generic_symbols(cnum)) |
| 95 | + .filter_map(|&(s, info): &(ExportedSymbol<'_>, SymbolExportInfo)| { |
| 96 | + if info.level.is_below_threshold(export_threshold) || info.used { |
| 97 | + Some(symbol_name_for_instance_in_crate(tcx, s, cnum)) |
| 98 | + } else { |
| 99 | + None |
| 100 | + } |
| 101 | + }) |
| 102 | + .collect::<Vec<_>>() |
97 | 103 | };
|
98 |
| - let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); |
99 | 104 | let mut symbols_below_threshold = {
|
100 |
| - let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold"); |
101 |
| - exported_symbols[&LOCAL_CRATE].iter().filter_map(symbol_filter).collect::<Vec<&str>>() |
| 105 | + let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold"); |
| 106 | + copy_symbols(LOCAL_CRATE) |
102 | 107 | };
|
103 | 108 | info!("{} symbols to preserve in this crate", symbols_below_threshold.len());
|
104 | 109 |
|
105 | 110 | // If we're performing LTO for the entire crate graph, then for each of our
|
106 | 111 | // upstream dependencies, include their exported symbols.
|
107 |
| - if cgcx.lto != Lto::ThinLocal { |
108 |
| - // Make sure we actually can run LTO |
109 |
| - for crate_type in cgcx.crate_types.iter() { |
110 |
| - if !crate_type_allows_lto(*crate_type) { |
111 |
| - return Err(dcx.emit_almost_fatal(LtoDisallowed)); |
112 |
| - } else if *crate_type == CrateType::Dylib { |
113 |
| - if !cgcx.opts.unstable_opts.dylib_lto { |
114 |
| - return Err(dcx.emit_almost_fatal(LtoDylib)); |
115 |
| - } |
116 |
| - } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto { |
117 |
| - return Err(dcx.emit_almost_fatal(LtoProcMacro)); |
118 |
| - } |
| 112 | + if tcx.sess.lto() != Lto::ThinLocal { |
| 113 | + for &(cnum, ref _path) in each_linked_rlib_for_lto { |
| 114 | + let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold"); |
| 115 | + symbols_below_threshold.extend(copy_symbols(cnum)); |
119 | 116 | }
|
| 117 | + } |
120 | 118 |
|
121 |
| - if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { |
122 |
| - return Err(dcx.emit_almost_fatal(DynamicLinkingWithLTO)); |
123 |
| - } |
| 119 | + symbols_below_threshold |
| 120 | +} |
| 121 | + |
| 122 | +pub(super) fn check_lto_allowed<B: WriteBackendMethods>(cgcx: &CodegenContext<B>) { |
| 123 | + if cgcx.lto == Lto::ThinLocal { |
| 124 | + // Crate local LTO is always allowed |
| 125 | + return; |
| 126 | + } |
124 | 127 |
|
125 |
| - for &(cnum, ref _path) in cgcx.each_linked_rlib_for_lto.iter() { |
126 |
| - let exported_symbols = |
127 |
| - cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); |
128 |
| - { |
129 |
| - let _timer = cgcx.prof.generic_activity("lto_generate_symbols_below_threshold"); |
130 |
| - symbols_below_threshold |
131 |
| - .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter)); |
| 128 | + let dcx = cgcx.create_dcx(); |
| 129 | + |
| 130 | + // Make sure we actually can run LTO |
| 131 | + for crate_type in cgcx.crate_types.iter() { |
| 132 | + if !crate_type_allows_lto(*crate_type) { |
| 133 | + dcx.handle().emit_fatal(LtoDisallowed); |
| 134 | + } else if *crate_type == CrateType::Dylib { |
| 135 | + if !cgcx.opts.unstable_opts.dylib_lto { |
| 136 | + dcx.handle().emit_fatal(LtoDylib); |
132 | 137 | }
|
| 138 | + } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto { |
| 139 | + dcx.handle().emit_fatal(LtoProcMacro); |
133 | 140 | }
|
134 | 141 | }
|
135 | 142 |
|
136 |
| - Ok(symbols_below_threshold) |
| 143 | + if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { |
| 144 | + dcx.handle().emit_fatal(DynamicLinkingWithLTO); |
| 145 | + } |
137 | 146 | }
|
0 commit comments