Skip to main content

rustc_codegen_ssa/traits/
backend.rs

1use std::any::Any;
2use std::hash::Hash;
3
4use rustc_ast::expand::allocator::AllocatorMethod;
5use rustc_data_structures::fx::FxIndexMap;
6use rustc_data_structures::sync::{DynSend, DynSync};
7use rustc_metadata::EncodedMetadata;
8use rustc_metadata::creader::MetadataLoaderDyn;
9use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
10use rustc_middle::ty::TyCtxt;
11use rustc_middle::util::Providers;
12use rustc_session::Session;
13use rustc_session::config::{CrateType, OutputFilenames, PrintRequest};
14use rustc_span::Symbol;
15
16use super::CodegenObject;
17use crate::back::archive::ArArchiveBuilderBuilder;
18use crate::back::link::link_binary;
19use crate::{CompiledModules, CrateInfo, ModuleCodegen, TargetConfig};
20
21pub trait BackendTypes {
22    type Function: CodegenObject;
23    type BasicBlock: Copy;
24    type Funclet;
25
26    type Value: CodegenObject + PartialEq;
27    type Type: CodegenObject + PartialEq;
28    type FunctionSignature: CodegenObject + PartialEq;
29
30    // FIXME(eddyb) find a common convention for all of the debuginfo-related
31    // names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.).
32    type DIScope: Copy + Hash + PartialEq + Eq;
33    type DILocation: Copy;
34    type DIVariable: Copy;
35}
36
37pub trait CodegenBackend {
38    fn name(&self) -> &'static str;
39
40    fn init(&self, _sess: &Session) {}
41
42    fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
43
44    /// Collect target-specific options that should be set in `cfg(...)`, including
45    /// `target_feature` and support for unstable float types.
46    fn target_config(&self, _sess: &Session) -> TargetConfig {
47        TargetConfig {
48            target_features: ::alloc::vec::Vec::new()vec![],
49            unstable_target_features: ::alloc::vec::Vec::new()vec![],
50            // `true` is used as a default so backends need to acknowledge when they do not
51            // support the float types, rather than accidentally quietly skipping all tests.
52            has_reliable_f16: true,
53            has_reliable_f16_math: true,
54            has_reliable_f128: true,
55            has_reliable_f128_math: true,
56        }
57    }
58
59    fn supported_crate_types(&self, _sess: &Session) -> Vec<CrateType> {
60        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [CrateType::Executable, CrateType::Dylib, CrateType::Rlib,
                CrateType::StaticLib, CrateType::Cdylib, CrateType::ProcMacro,
                CrateType::Sdylib]))vec![
61            CrateType::Executable,
62            CrateType::Dylib,
63            CrateType::Rlib,
64            CrateType::StaticLib,
65            CrateType::Cdylib,
66            CrateType::ProcMacro,
67            CrateType::Sdylib,
68        ]
69    }
70
71    fn print_passes(&self) {}
72
73    fn print_version(&self) {}
74
75    /// Returns a list of all intrinsics that this backend definitely
76    /// replaces, which means their fallback bodies do not need to be monomorphized.
77    fn replaced_intrinsics(&self) -> Vec<Symbol> {
78        ::alloc::vec::Vec::new()vec![]
79    }
80
81    /// Returns a list of all intrinsics that this backend definitely
82    /// does *not* replace, which means their fallback bodies can be MIR-inlined.
83    fn fallback_intrinsics(&self) -> Vec<Symbol> {
84        ::alloc::vec::Vec::new()vec![]
85    }
86
87    /// Is ThinLTO supported by this backend?
88    fn thin_lto_supported(&self) -> bool {
89        true
90    }
91
92    /// Value printed by `--print=backend-has-zstd`.
93    ///
94    /// Used by compiletest to determine whether tests involving zstd compression
95    /// (e.g. `-Zdebuginfo-compression=zstd`) should be executed or skipped.
96    fn has_zstd(&self) -> bool {
97        false
98    }
99
100    /// Value printed by `--print=backend-has-mnemonic:...`.
101    ///
102    /// Used by compiletest to determine whether tests involving `asm!()` should
103    /// be executed or skipped.
104    fn has_mnemonic(&self, _sess: &Session, _mnemonic: &str) -> bool {
105        false
106    }
107
108    /// The metadata loader used to load rlib and dylib metadata.
109    ///
110    /// Alternative codegen backends may want to use different rlib or dylib formats than the
111    /// default native static archives and dynamic libraries.
112    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
113        Box::new(crate::back::metadata::DefaultMetadataLoader)
114    }
115
116    fn provide(&self, _providers: &mut Providers) {}
117
118    fn target_cpu(&self, sess: &Session) -> String;
119
120    fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box<dyn Any>;
121
122    /// This is called on the returned `Box<dyn Any>` from [`codegen_crate`](Self::codegen_crate)
123    ///
124    /// # Panics
125    ///
126    /// Panics when the passed `Box<dyn Any>` was not returned by [`codegen_crate`](Self::codegen_crate).
127    fn join_codegen(
128        &self,
129        ongoing_codegen: Box<dyn Any>,
130        sess: &Session,
131        outputs: &OutputFilenames,
132        crate_info: &CrateInfo,
133    ) -> (CompiledModules, FxIndexMap<WorkProductId, WorkProduct>);
134
135    fn print_pass_timings(&self) {}
136
137    fn print_statistics(&self) {}
138
139    fn print_statistics_json(&self) -> String {
140        String::new()
141    }
142
143    /// This is called on the returned [`CompiledModules`] from [`join_codegen`](Self::join_codegen).
144    fn link(
145        &self,
146        sess: &Session,
147        compiled_modules: CompiledModules,
148        crate_info: CrateInfo,
149        metadata: EncodedMetadata,
150        outputs: &OutputFilenames,
151    ) {
152        link_binary(
153            sess,
154            &ArArchiveBuilderBuilder,
155            compiled_modules,
156            crate_info,
157            metadata,
158            outputs,
159            self.name(),
160        );
161    }
162}
163
164pub trait ExtraBackendMethods: Send + Sync + DynSend + DynSync {
165    type Module;
166
167    fn codegen_allocator<'tcx>(
168        &self,
169        tcx: TyCtxt<'tcx>,
170        module_name: &str,
171        methods: &[AllocatorMethod],
172    ) -> Self::Module;
173
174    /// This generates the codegen unit and returns it along with
175    /// a `u64` giving an estimate of the unit's processing cost.
176    fn compile_codegen_unit(
177        &self,
178        tcx: TyCtxt<'_>,
179        cgu_name: Symbol,
180    ) -> (ModuleCodegen<Self::Module>, u64);
181}