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