]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] |
a1dfa0c6 | 2 | #![feature(box_patterns)] |
532ac7d7 | 3 | #![feature(try_blocks)] |
c295e0f8 | 4 | #![feature(once_cell)] |
416331ca | 5 | #![feature(associated_type_bounds)] |
5e7ed085 | 6 | #![feature(strict_provenance)] |
04454e1e | 7 | #![feature(int_roundings)] |
064997fb | 8 | #![feature(if_let_guard)] |
2b03887a | 9 | #![feature(never_type)] |
dfeec247 | 10 | #![recursion_limit = "256"] |
5e7ed085 | 11 | #![allow(rustc::potential_query_instability)] |
0731742a | 12 | |
a1dfa0c6 XL |
13 | //! This crate contains codegen code that is used by all codegen backends (LLVM and others). |
14 | //! The backend-agnostic functions of this crate use functions defined in various traits that | |
15 | //! have to be implemented by each backends. | |
16 | ||
dfeec247 | 17 | #[macro_use] |
3dfed10e XL |
18 | extern crate rustc_macros; |
19 | #[macro_use] | |
20 | extern crate tracing; | |
dfeec247 | 21 | #[macro_use] |
ba9703b0 | 22 | extern crate rustc_middle; |
a1dfa0c6 | 23 | |
fc512014 | 24 | use rustc_ast as ast; |
a1dfa0c6 | 25 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
dfeec247 XL |
26 | use rustc_data_structures::sync::Lrc; |
27 | use rustc_hir::def_id::CrateNum; | |
ba9703b0 | 28 | use rustc_middle::dep_graph::WorkProduct; |
ba9703b0 | 29 | use rustc_middle::middle::dependency_format::Dependencies; |
04454e1e | 30 | use rustc_middle::middle::exported_symbols::SymbolExportKind; |
3c0e092e | 31 | use rustc_middle::ty::query::{ExternProviders, Providers}; |
923072b8 FG |
32 | use rustc_serialize::opaque::{MemDecoder, MemEncoder}; |
33 | use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; | |
136023e0 | 34 | use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; |
c295e0f8 | 35 | use rustc_session::cstore::{self, CrateSource}; |
fc512014 | 36 | use rustc_session::utils::NativeLibKind; |
dfeec247 | 37 | use rustc_span::symbol::Symbol; |
04454e1e | 38 | use rustc_span::DebuggerVisualizerFile; |
923072b8 | 39 | use std::collections::BTreeSet; |
dfeec247 | 40 | use std::path::{Path, PathBuf}; |
a1dfa0c6 | 41 | |
dfeec247 XL |
42 | pub mod back; |
43 | pub mod base; | |
a1dfa0c6 | 44 | pub mod common; |
f035d41b | 45 | pub mod coverageinfo; |
a1dfa0c6 | 46 | pub mod debuginfo; |
2b03887a | 47 | pub mod errors; |
a1dfa0c6 XL |
48 | pub mod glue; |
49 | pub mod meth; | |
dfeec247 | 50 | pub mod mir; |
a1dfa0c6 | 51 | pub mod mono_item; |
29967ef6 | 52 | pub mod target_features; |
dfeec247 | 53 | pub mod traits; |
a1dfa0c6 XL |
54 | |
55 | pub struct ModuleCodegen<M> { | |
56 | /// The name of the module. When the crate may be saved between | |
57 | /// compilations, incremental compilation requires that name be | |
9fa01778 | 58 | /// unique amongst **all** crates. Therefore, it should contain |
a1dfa0c6 XL |
59 | /// something unique to this crate (e.g., a module path) as well |
60 | /// as the crate name and disambiguator. | |
61 | /// We currently generate these names via CodegenUnit::build_cgu_name(). | |
62 | pub name: String, | |
63 | pub module_llvm: M, | |
64 | pub kind: ModuleKind, | |
65 | } | |
66 | ||
a1dfa0c6 | 67 | impl<M> ModuleCodegen<M> { |
dfeec247 XL |
68 | pub fn into_compiled_module( |
69 | self, | |
70 | emit_obj: bool, | |
fc512014 | 71 | emit_dwarf_obj: bool, |
dfeec247 | 72 | emit_bc: bool, |
dfeec247 XL |
73 | outputs: &OutputFilenames, |
74 | ) -> CompiledModule { | |
75 | let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); | |
fc512014 | 76 | let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name))); |
dfeec247 | 77 | let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); |
a1dfa0c6 | 78 | |
fc512014 | 79 | CompiledModule { name: self.name.clone(), kind: self.kind, object, dwarf_object, bytecode } |
a1dfa0c6 XL |
80 | } |
81 | } | |
82 | ||
3dfed10e | 83 | #[derive(Debug, Encodable, Decodable)] |
a1dfa0c6 XL |
84 | pub struct CompiledModule { |
85 | pub name: String, | |
86 | pub kind: ModuleKind, | |
87 | pub object: Option<PathBuf>, | |
fc512014 | 88 | pub dwarf_object: Option<PathBuf>, |
a1dfa0c6 | 89 | pub bytecode: Option<PathBuf>, |
a1dfa0c6 XL |
90 | } |
91 | ||
92 | pub struct CachedModuleCodegen { | |
93 | pub name: String, | |
94 | pub source: WorkProduct, | |
95 | } | |
96 | ||
3dfed10e | 97 | #[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)] |
a1dfa0c6 XL |
98 | pub enum ModuleKind { |
99 | Regular, | |
100 | Metadata, | |
101 | Allocator, | |
102 | } | |
103 | ||
9fa01778 | 104 | bitflags::bitflags! { |
a1dfa0c6 XL |
105 | pub struct MemFlags: u8 { |
106 | const VOLATILE = 1 << 0; | |
107 | const NONTEMPORAL = 1 << 1; | |
108 | const UNALIGNED = 1 << 2; | |
109 | } | |
110 | } | |
111 | ||
fc512014 XL |
112 | #[derive(Clone, Debug, Encodable, Decodable, HashStable)] |
113 | pub struct NativeLib { | |
114 | pub kind: NativeLibKind, | |
115 | pub name: Option<Symbol>, | |
f2b60f7d | 116 | pub filename: Option<Symbol>, |
fc512014 | 117 | pub cfg: Option<ast::MetaItem>, |
17df50a5 XL |
118 | pub verbatim: Option<bool>, |
119 | pub dll_imports: Vec<cstore::DllImport>, | |
fc512014 XL |
120 | } |
121 | ||
122 | impl From<&cstore::NativeLib> for NativeLib { | |
123 | fn from(lib: &cstore::NativeLib) -> Self { | |
17df50a5 XL |
124 | NativeLib { |
125 | kind: lib.kind, | |
f2b60f7d | 126 | filename: lib.filename, |
17df50a5 XL |
127 | name: lib.name, |
128 | cfg: lib.cfg.clone(), | |
129 | verbatim: lib.verbatim, | |
130 | dll_imports: lib.dll_imports.clone(), | |
131 | } | |
fc512014 XL |
132 | } |
133 | } | |
134 | ||
9fa01778 | 135 | /// Misc info we load from metadata to persist beyond the tcx. |
dfeec247 XL |
136 | /// |
137 | /// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo` | |
138 | /// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where | |
139 | /// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from | |
140 | /// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own | |
141 | /// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource` | |
142 | /// and the corresponding properties without referencing information outside of a `CrateInfo`. | |
3dfed10e | 143 | #[derive(Debug, Encodable, Decodable)] |
a1dfa0c6 | 144 | pub struct CrateInfo { |
136023e0 XL |
145 | pub target_cpu: String, |
146 | pub exported_symbols: FxHashMap<CrateType, Vec<String>>, | |
04454e1e | 147 | pub linked_symbols: FxHashMap<CrateType, Vec<(String, SymbolExportKind)>>, |
17df50a5 | 148 | pub local_crate_name: Symbol, |
a1dfa0c6 XL |
149 | pub compiler_builtins: Option<CrateNum>, |
150 | pub profiler_runtime: Option<CrateNum>, | |
a1dfa0c6 | 151 | pub is_no_builtins: FxHashSet<CrateNum>, |
fc512014 | 152 | pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>, |
04454e1e | 153 | pub crate_name: FxHashMap<CrateNum, Symbol>, |
fc512014 | 154 | pub used_libraries: Vec<NativeLib>, |
a1dfa0c6 | 155 | pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>, |
136023e0 | 156 | pub used_crates: Vec<CrateNum>, |
e74abb32 | 157 | pub dependency_formats: Lrc<Dependencies>, |
17df50a5 | 158 | pub windows_subsystem: Option<String>, |
923072b8 | 159 | pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>, |
a1dfa0c6 XL |
160 | } |
161 | ||
3dfed10e | 162 | #[derive(Encodable, Decodable)] |
a1dfa0c6 | 163 | pub struct CodegenResults { |
a1dfa0c6 XL |
164 | pub modules: Vec<CompiledModule>, |
165 | pub allocator_module: Option<CompiledModule>, | |
48663c56 | 166 | pub metadata_module: Option<CompiledModule>, |
c295e0f8 | 167 | pub metadata: rustc_metadata::EncodedMetadata, |
a1dfa0c6 XL |
168 | pub crate_info: CrateInfo, |
169 | } | |
e74abb32 | 170 | |
f2b60f7d FG |
171 | pub enum CodegenErrors<'a> { |
172 | WrongFileType, | |
173 | EmptyVersionNumber, | |
174 | EncodingVersionMismatch { version_array: String, rlink_version: u32 }, | |
175 | RustcVersionMismatch { rustc_version: String, current_version: &'a str }, | |
176 | } | |
177 | ||
f035d41b | 178 | pub fn provide(providers: &mut Providers) { |
e74abb32 | 179 | crate::back::symbol_export::provide(providers); |
5869c6ff | 180 | crate::base::provide(providers); |
29967ef6 | 181 | crate::target_features::provide(providers); |
e74abb32 XL |
182 | } |
183 | ||
3c0e092e | 184 | pub fn provide_extern(providers: &mut ExternProviders) { |
e74abb32 | 185 | crate::back::symbol_export::provide_extern(providers); |
e74abb32 XL |
186 | } |
187 | ||
188 | /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc` | |
189 | /// uses for the object files it generates. | |
190 | pub fn looks_like_rust_object_file(filename: &str) -> bool { | |
191 | let path = Path::new(filename); | |
192 | let ext = path.extension().and_then(|s| s.to_str()); | |
193 | if ext != Some(OutputType::Object.extension()) { | |
194 | // The file name does not end with ".o", so it can't be an object file. | |
dfeec247 | 195 | return false; |
e74abb32 XL |
196 | } |
197 | ||
198 | // Strip the ".o" at the end | |
dfeec247 | 199 | let ext2 = path.file_stem().and_then(|s| Path::new(s).extension()).and_then(|s| s.to_str()); |
e74abb32 XL |
200 | |
201 | // Check if the "inner" extension | |
202 | ext2 == Some(RUST_CGU_EXT) | |
203 | } | |
5e7ed085 FG |
204 | |
205 | const RLINK_VERSION: u32 = 1; | |
206 | const RLINK_MAGIC: &[u8] = b"rustlink"; | |
207 | ||
208 | const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION"); | |
209 | ||
210 | impl CodegenResults { | |
211 | pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> { | |
923072b8 FG |
212 | let mut encoder = MemEncoder::new(); |
213 | encoder.emit_raw_bytes(RLINK_MAGIC); | |
5e7ed085 FG |
214 | // `emit_raw_bytes` is used to make sure that the version representation does not depend on |
215 | // Encoder's inner representation of `u32`. | |
923072b8 FG |
216 | encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); |
217 | encoder.emit_str(RUSTC_VERSION.unwrap()); | |
218 | Encodable::encode(codegen_results, &mut encoder); | |
219 | encoder.finish() | |
5e7ed085 FG |
220 | } |
221 | ||
f2b60f7d | 222 | pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> { |
5e7ed085 FG |
223 | // The Decodable machinery is not used here because it panics if the input data is invalid |
224 | // and because its internal representation may change. | |
225 | if !data.starts_with(RLINK_MAGIC) { | |
f2b60f7d | 226 | return Err(CodegenErrors::WrongFileType); |
5e7ed085 FG |
227 | } |
228 | let data = &data[RLINK_MAGIC.len()..]; | |
229 | if data.len() < 4 { | |
f2b60f7d | 230 | return Err(CodegenErrors::EmptyVersionNumber); |
5e7ed085 FG |
231 | } |
232 | ||
233 | let mut version_array: [u8; 4] = Default::default(); | |
234 | version_array.copy_from_slice(&data[..4]); | |
235 | if u32::from_be_bytes(version_array) != RLINK_VERSION { | |
f2b60f7d FG |
236 | return Err(CodegenErrors::EncodingVersionMismatch { |
237 | version_array: String::from_utf8_lossy(&version_array).to_string(), | |
238 | rlink_version: RLINK_VERSION, | |
239 | }); | |
5e7ed085 FG |
240 | } |
241 | ||
923072b8 | 242 | let mut decoder = MemDecoder::new(&data[4..], 0); |
5e7ed085 FG |
243 | let rustc_version = decoder.read_str(); |
244 | let current_version = RUSTC_VERSION.unwrap(); | |
245 | if rustc_version != current_version { | |
f2b60f7d FG |
246 | return Err(CodegenErrors::RustcVersionMismatch { |
247 | rustc_version: rustc_version.to_string(), | |
248 | current_version, | |
249 | }); | |
5e7ed085 FG |
250 | } |
251 | ||
252 | let codegen_results = CodegenResults::decode(&mut decoder); | |
253 | Ok(codegen_results) | |
254 | } | |
255 | } |