rustc_codegen_ssa/
lib.rs

1// tidy-alphabetical-start
2#![allow(internal_features)]
3#![allow(rustc::diagnostic_outside_of_impl)]
4#![allow(rustc::untranslatable_diagnostic)]
5#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
6#![doc(rust_logo)]
7#![feature(assert_matches)]
8#![feature(box_patterns)]
9#![feature(file_buffered)]
10#![feature(if_let_guard)]
11#![feature(negative_impls)]
12#![feature(rustdoc_internals)]
13#![feature(string_from_utf8_lossy_owned)]
14#![feature(trait_alias)]
15#![feature(try_blocks)]
16#![recursion_limit = "256"]
17// tidy-alphabetical-end
18
19//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
20//! The backend-agnostic functions of this crate use functions defined in various traits that
21//! have to be implemented by each backend.
22
23use std::collections::BTreeSet;
24use std::io;
25use std::path::{Path, PathBuf};
26use std::sync::Arc;
27
28use rustc_ast as ast;
29use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
30use rustc_data_structures::unord::UnordMap;
31use rustc_hir::CRATE_HIR_ID;
32use rustc_hir::def_id::CrateNum;
33use rustc_macros::{Decodable, Encodable, HashStable};
34use rustc_metadata::EncodedMetadata;
35use rustc_middle::dep_graph::WorkProduct;
36use rustc_middle::lint::LevelAndSource;
37use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
38use rustc_middle::middle::dependency_format::Dependencies;
39use rustc_middle::middle::exported_symbols::SymbolExportKind;
40use rustc_middle::ty::TyCtxt;
41use rustc_middle::util::Providers;
42use rustc_serialize::opaque::{FileEncoder, MemDecoder};
43use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
44use rustc_session::Session;
45use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
46use rustc_session::cstore::{self, CrateSource};
47use rustc_session::lint::builtin::LINKER_MESSAGES;
48use rustc_session::utils::NativeLibKind;
49use rustc_span::Symbol;
50
51pub mod assert_module_sources;
52pub mod back;
53pub mod base;
54pub mod codegen_attrs;
55pub mod common;
56pub mod debuginfo;
57pub mod errors;
58pub mod meth;
59pub mod mir;
60pub mod mono_item;
61pub mod size_of_val;
62pub mod target_features;
63pub mod traits;
64
65rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
66
67pub struct ModuleCodegen<M> {
68    /// The name of the module. When the crate may be saved between
69    /// compilations, incremental compilation requires that name be
70    /// unique amongst **all** crates. Therefore, it should contain
71    /// something unique to this crate (e.g., a module path) as well
72    /// as the crate name and disambiguator.
73    /// We currently generate these names via CodegenUnit::build_cgu_name().
74    pub name: String,
75    pub module_llvm: M,
76    pub kind: ModuleKind,
77    /// Saving the ThinLTO buffer for embedding in the object file.
78    pub thin_lto_buffer: Option<Vec<u8>>,
79}
80
81impl<M> ModuleCodegen<M> {
82    pub fn new_regular(name: impl Into<String>, module: M) -> Self {
83        Self {
84            name: name.into(),
85            module_llvm: module,
86            kind: ModuleKind::Regular,
87            thin_lto_buffer: None,
88        }
89    }
90
91    pub fn new_allocator(name: impl Into<String>, module: M) -> Self {
92        Self {
93            name: name.into(),
94            module_llvm: module,
95            kind: ModuleKind::Allocator,
96            thin_lto_buffer: None,
97        }
98    }
99
100    pub fn into_compiled_module(
101        self,
102        emit_obj: bool,
103        emit_dwarf_obj: bool,
104        emit_bc: bool,
105        emit_asm: bool,
106        emit_ir: bool,
107        outputs: &OutputFilenames,
108        invocation_temp: Option<&str>,
109    ) -> CompiledModule {
110        let object = emit_obj
111            .then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp));
112        let dwarf_object =
113            emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp));
114        let bytecode = emit_bc
115            .then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp));
116        let assembly = emit_asm
117            .then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp));
118        let llvm_ir = emit_ir.then(|| {
119            outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp)
120        });
121
122        CompiledModule {
123            name: self.name.clone(),
124            kind: self.kind,
125            object,
126            dwarf_object,
127            bytecode,
128            assembly,
129            llvm_ir,
130            links_from_incr_cache: Vec::new(),
131        }
132    }
133}
134
135#[derive(Debug, Encodable, Decodable)]
136pub struct CompiledModule {
137    pub name: String,
138    pub kind: ModuleKind,
139    pub object: Option<PathBuf>,
140    pub dwarf_object: Option<PathBuf>,
141    pub bytecode: Option<PathBuf>,
142    pub assembly: Option<PathBuf>, // --emit=asm
143    pub llvm_ir: Option<PathBuf>,  // --emit=llvm-ir, llvm-bc is in bytecode
144    pub links_from_incr_cache: Vec<PathBuf>,
145}
146
147impl CompiledModule {
148    /// Call `emit` function with every artifact type currently compiled
149    pub fn for_each_output(&self, mut emit: impl FnMut(&Path, OutputType)) {
150        if let Some(path) = self.object.as_deref() {
151            emit(path, OutputType::Object);
152        }
153        if let Some(path) = self.bytecode.as_deref() {
154            emit(path, OutputType::Bitcode);
155        }
156        if let Some(path) = self.llvm_ir.as_deref() {
157            emit(path, OutputType::LlvmAssembly);
158        }
159        if let Some(path) = self.assembly.as_deref() {
160            emit(path, OutputType::Assembly);
161        }
162    }
163}
164
165pub(crate) struct CachedModuleCodegen {
166    pub name: String,
167    pub source: WorkProduct,
168}
169
170#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)]
171pub enum ModuleKind {
172    Regular,
173    Allocator,
174}
175
176bitflags::bitflags! {
177    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
178    pub struct MemFlags: u8 {
179        const VOLATILE = 1 << 0;
180        const NONTEMPORAL = 1 << 1;
181        const UNALIGNED = 1 << 2;
182    }
183}
184
185#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
186pub struct NativeLib {
187    pub kind: NativeLibKind,
188    pub name: Symbol,
189    pub filename: Option<Symbol>,
190    pub cfg: Option<ast::MetaItemInner>,
191    pub verbatim: bool,
192    pub dll_imports: Vec<cstore::DllImport>,
193}
194
195impl From<&cstore::NativeLib> for NativeLib {
196    fn from(lib: &cstore::NativeLib) -> Self {
197        NativeLib {
198            kind: lib.kind,
199            filename: lib.filename,
200            name: lib.name,
201            cfg: lib.cfg.clone(),
202            verbatim: lib.verbatim.unwrap_or(false),
203            dll_imports: lib.dll_imports.clone(),
204        }
205    }
206}
207
208/// Misc info we load from metadata to persist beyond the tcx.
209///
210/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
211/// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where
212/// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from
213/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
214/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
215/// and the corresponding properties without referencing information outside of a `CrateInfo`.
216#[derive(Debug, Encodable, Decodable)]
217pub struct CrateInfo {
218    pub target_cpu: String,
219    pub target_features: Vec<String>,
220    pub crate_types: Vec<CrateType>,
221    pub exported_symbols: UnordMap<CrateType, Vec<String>>,
222    pub linked_symbols: FxIndexMap<CrateType, Vec<(String, SymbolExportKind)>>,
223    pub local_crate_name: Symbol,
224    pub compiler_builtins: Option<CrateNum>,
225    pub profiler_runtime: Option<CrateNum>,
226    pub is_no_builtins: FxHashSet<CrateNum>,
227    pub native_libraries: FxIndexMap<CrateNum, Vec<NativeLib>>,
228    pub crate_name: UnordMap<CrateNum, Symbol>,
229    pub used_libraries: Vec<NativeLib>,
230    pub used_crate_source: UnordMap<CrateNum, Arc<CrateSource>>,
231    pub used_crates: Vec<CrateNum>,
232    pub dependency_formats: Arc<Dependencies>,
233    pub windows_subsystem: Option<String>,
234    pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
235    pub lint_levels: CodegenLintLevels,
236    pub metadata_symbol: String,
237}
238
239/// Target-specific options that get set in `cfg(...)`.
240///
241/// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
242pub struct TargetConfig {
243    /// Options to be set in `cfg(target_features)`.
244    pub target_features: Vec<Symbol>,
245    /// Options to be set in `cfg(target_features)`, but including unstable features.
246    pub unstable_target_features: Vec<Symbol>,
247    /// Option for `cfg(target_has_reliable_f16)`, true if `f16` basic arithmetic works.
248    pub has_reliable_f16: bool,
249    /// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work.
250    pub has_reliable_f16_math: bool,
251    /// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works.
252    pub has_reliable_f128: bool,
253    /// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work.
254    pub has_reliable_f128_math: bool,
255}
256
257#[derive(Encodable, Decodable)]
258pub struct CodegenResults {
259    pub modules: Vec<CompiledModule>,
260    pub allocator_module: Option<CompiledModule>,
261    pub crate_info: CrateInfo,
262}
263
264pub enum CodegenErrors {
265    WrongFileType,
266    EmptyVersionNumber,
267    EncodingVersionMismatch { version_array: String, rlink_version: u32 },
268    RustcVersionMismatch { rustc_version: String },
269    CorruptFile,
270}
271
272pub fn provide(providers: &mut Providers) {
273    crate::back::symbol_export::provide(providers);
274    crate::base::provide(providers);
275    crate::target_features::provide(providers);
276    crate::codegen_attrs::provide(providers);
277    providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![];
278}
279
280/// Checks if the given filename ends with the `.rcgu.o` extension that `rustc`
281/// uses for the object files it generates.
282pub fn looks_like_rust_object_file(filename: &str) -> bool {
283    let path = Path::new(filename);
284    let ext = path.extension().and_then(|s| s.to_str());
285    if ext != Some(OutputType::Object.extension()) {
286        // The file name does not end with ".o", so it can't be an object file.
287        return false;
288    }
289
290    // Strip the ".o" at the end
291    let ext2 = path.file_stem().and_then(|s| Path::new(s).extension()).and_then(|s| s.to_str());
292
293    // Check if the "inner" extension
294    ext2 == Some(RUST_CGU_EXT)
295}
296
297const RLINK_VERSION: u32 = 1;
298const RLINK_MAGIC: &[u8] = b"rustlink";
299
300impl CodegenResults {
301    pub fn serialize_rlink(
302        sess: &Session,
303        rlink_file: &Path,
304        codegen_results: &CodegenResults,
305        metadata: &EncodedMetadata,
306        outputs: &OutputFilenames,
307    ) -> Result<usize, io::Error> {
308        let mut encoder = FileEncoder::new(rlink_file)?;
309        encoder.emit_raw_bytes(RLINK_MAGIC);
310        // `emit_raw_bytes` is used to make sure that the version representation does not depend on
311        // Encoder's inner representation of `u32`.
312        encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
313        encoder.emit_str(sess.cfg_version);
314        Encodable::encode(codegen_results, &mut encoder);
315        Encodable::encode(metadata, &mut encoder);
316        Encodable::encode(outputs, &mut encoder);
317        encoder.finish().map_err(|(_path, err)| err)
318    }
319
320    pub fn deserialize_rlink(
321        sess: &Session,
322        data: Vec<u8>,
323    ) -> Result<(Self, EncodedMetadata, OutputFilenames), CodegenErrors> {
324        // The Decodable machinery is not used here because it panics if the input data is invalid
325        // and because its internal representation may change.
326        if !data.starts_with(RLINK_MAGIC) {
327            return Err(CodegenErrors::WrongFileType);
328        }
329        let data = &data[RLINK_MAGIC.len()..];
330        if data.len() < 4 {
331            return Err(CodegenErrors::EmptyVersionNumber);
332        }
333
334        let mut version_array: [u8; 4] = Default::default();
335        version_array.copy_from_slice(&data[..4]);
336        if u32::from_be_bytes(version_array) != RLINK_VERSION {
337            return Err(CodegenErrors::EncodingVersionMismatch {
338                version_array: String::from_utf8_lossy(&version_array).to_string(),
339                rlink_version: RLINK_VERSION,
340            });
341        }
342
343        let Ok(mut decoder) = MemDecoder::new(&data[4..], 0) else {
344            return Err(CodegenErrors::CorruptFile);
345        };
346        let rustc_version = decoder.read_str();
347        if rustc_version != sess.cfg_version {
348            return Err(CodegenErrors::RustcVersionMismatch {
349                rustc_version: rustc_version.to_string(),
350            });
351        }
352
353        let codegen_results = CodegenResults::decode(&mut decoder);
354        let metadata = EncodedMetadata::decode(&mut decoder);
355        let outputs = OutputFilenames::decode(&mut decoder);
356        Ok((codegen_results, metadata, outputs))
357    }
358}
359
360/// A list of lint levels used in codegen.
361///
362/// When using `-Z link-only`, we don't have access to the tcx and must work
363/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable.
364/// Instead, encode exactly the information we need.
365#[derive(Copy, Clone, Debug, Encodable, Decodable)]
366pub struct CodegenLintLevels {
367    linker_messages: LevelAndSource,
368}
369
370impl CodegenLintLevels {
371    pub fn from_tcx(tcx: TyCtxt<'_>) -> Self {
372        Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) }
373    }
374}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy