1 use std::any::Any; 2 3 use super::write::WriteBackendMethods; 4 use super::CodegenObject; 5 use crate::back::write::TargetMachineFactoryFn; 6 use crate::{CodegenResults, ModuleCodegen}; 7 8 use rustc_ast::expand::allocator::AllocatorKind; 9 use rustc_data_structures::fx::FxIndexMap; 10 use rustc_data_structures::sync::{DynSend, DynSync}; 11 use rustc_errors::ErrorGuaranteed; 12 use rustc_metadata::EncodedMetadata; 13 use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; 14 use rustc_middle::query::{ExternProviders, Providers}; 15 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; 16 use rustc_middle::ty::{Ty, TyCtxt}; 17 use rustc_session::{ 18 config::{self, OutputFilenames, PrintRequest}, 19 cstore::MetadataLoaderDyn, 20 Session, 21 }; 22 use rustc_span::symbol::Symbol; 23 use rustc_target::abi::call::FnAbi; 24 use rustc_target::spec::Target; 25 26 pub trait BackendTypes { 27 type Value: CodegenObject; 28 type Function: CodegenObject; 29 30 type BasicBlock: Copy; 31 type Type: CodegenObject; 32 type Funclet; 33 34 // FIXME(eddyb) find a common convention for all of the debuginfo-related 35 // names (choose between `Dbg`, `Debug`, `DebugInfo`, `DI` etc.). 36 type DIScope: Copy; 37 type DILocation: Copy; 38 type DIVariable: Copy; 39 } 40 41 pub trait Backend<'tcx>: 42 Sized 43 + BackendTypes 44 + HasTyCtxt<'tcx> 45 + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> 46 + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> 47 { 48 } 49 50 impl<'tcx, T> Backend<'tcx> for T where 51 Self: BackendTypes 52 + HasTyCtxt<'tcx> 53 + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> 54 + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> 55 { 56 } 57 58 pub trait CodegenBackend { 59 /// Locale resources for diagnostic messages - a string the content of the Fluent resource. 60 /// Called before `init` so that all other functions are able to emit translatable diagnostics. locale_resource(&self) -> &'static str61 fn locale_resource(&self) -> &'static str; 62 init(&self, _sess: &Session)63 fn init(&self, _sess: &Session) {} print(&self, _req: PrintRequest, _sess: &Session)64 fn print(&self, _req: PrintRequest, _sess: &Session) {} target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol>65 fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> { 66 vec![] 67 } print_passes(&self)68 fn print_passes(&self) {} print_version(&self)69 fn print_version(&self) {} 70 71 /// If this plugin provides additional builtin targets, provide the one enabled by the options here. 72 /// Be careful: this is called *before* init() is called. target_override(&self, _opts: &config::Options) -> Option<Target>73 fn target_override(&self, _opts: &config::Options) -> Option<Target> { 74 None 75 } 76 77 /// The metadata loader used to load rlib and dylib metadata. 78 /// 79 /// Alternative codegen backends may want to use different rlib or dylib formats than the 80 /// default native static archives and dynamic libraries. metadata_loader(&self) -> Box<MetadataLoaderDyn>81 fn metadata_loader(&self) -> Box<MetadataLoaderDyn> { 82 Box::new(crate::back::metadata::DefaultMetadataLoader) 83 } 84 provide(&self, _providers: &mut Providers)85 fn provide(&self, _providers: &mut Providers) {} provide_extern(&self, _providers: &mut ExternProviders)86 fn provide_extern(&self, _providers: &mut ExternProviders) {} codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box<dyn Any>87 fn codegen_crate<'tcx>( 88 &self, 89 tcx: TyCtxt<'tcx>, 90 metadata: EncodedMetadata, 91 need_metadata_module: bool, 92 ) -> Box<dyn Any>; 93 94 /// This is called on the returned `Box<dyn Any>` from `codegen_backend` 95 /// 96 /// # Panics 97 /// 98 /// Panics when the passed `Box<dyn Any>` was not returned by `codegen_backend`. join_codegen( &self, ongoing_codegen: Box<dyn Any>, sess: &Session, outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>99 fn join_codegen( 100 &self, 101 ongoing_codegen: Box<dyn Any>, 102 sess: &Session, 103 outputs: &OutputFilenames, 104 ) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>; 105 106 /// This is called on the returned `Box<dyn Any>` from `join_codegen` 107 /// 108 /// # Panics 109 /// 110 /// Panics when the passed `Box<dyn Any>` was not returned by `join_codegen`. link( &self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed>111 fn link( 112 &self, 113 sess: &Session, 114 codegen_results: CodegenResults, 115 outputs: &OutputFilenames, 116 ) -> Result<(), ErrorGuaranteed>; 117 } 118 119 pub trait ExtraBackendMethods: 120 CodegenBackend + WriteBackendMethods + Sized + Send + Sync + DynSend + DynSync 121 { codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, ) -> Self::Module122 fn codegen_allocator<'tcx>( 123 &self, 124 tcx: TyCtxt<'tcx>, 125 module_name: &str, 126 kind: AllocatorKind, 127 alloc_error_handler_kind: AllocatorKind, 128 ) -> Self::Module; 129 /// This generates the codegen unit and returns it along with 130 /// a `u64` giving an estimate of the unit's processing cost. compile_codegen_unit( &self, tcx: TyCtxt<'_>, cgu_name: Symbol, ) -> (ModuleCodegen<Self::Module>, u64)131 fn compile_codegen_unit( 132 &self, 133 tcx: TyCtxt<'_>, 134 cgu_name: Symbol, 135 ) -> (ModuleCodegen<Self::Module>, u64); target_machine_factory( &self, sess: &Session, opt_level: config::OptLevel, target_features: &[String], ) -> TargetMachineFactoryFn<Self>136 fn target_machine_factory( 137 &self, 138 sess: &Session, 139 opt_level: config::OptLevel, 140 target_features: &[String], 141 ) -> TargetMachineFactoryFn<Self>; 142 spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static,143 fn spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T> 144 where 145 F: FnOnce() -> T, 146 F: Send + 'static, 147 T: Send + 'static, 148 { 149 std::thread::spawn(f) 150 } 151 spawn_named_thread<F, T>( _time_trace: bool, name: String, f: F, ) -> std::io::Result<std::thread::JoinHandle<T>> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static,152 fn spawn_named_thread<F, T>( 153 _time_trace: bool, 154 name: String, 155 f: F, 156 ) -> std::io::Result<std::thread::JoinHandle<T>> 157 where 158 F: FnOnce() -> T, 159 F: Send + 'static, 160 T: Send + 'static, 161 { 162 std::thread::Builder::new().name(name).spawn(f) 163 } 164 } 165