]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_gcc/src/lib.rs
Rollup merge of #91209 - camelid:snapshot, r=jyn514
[rust.git] / compiler / rustc_codegen_gcc / src / lib.rs
1 /*
2  * TODO(antoyo): support #[inline] attributes.
3  * TODO(antoyo): support LTO.
4  *
5  * TODO(antoyo): remove the patches.
6  */
7
8 #![feature(rustc_private, decl_macro, associated_type_bounds, never_type, trusted_len)]
9 #![allow(broken_intra_doc_links)]
10 #![recursion_limit="256"]
11 #![warn(rust_2018_idioms)]
12 #![warn(unused_lifetimes)]
13
14 extern crate rustc_ast;
15 extern crate rustc_codegen_ssa;
16 extern crate rustc_data_structures;
17 extern crate rustc_errors;
18 extern crate rustc_hir;
19 extern crate rustc_metadata;
20 extern crate rustc_middle;
21 extern crate rustc_session;
22 extern crate rustc_span;
23 extern crate rustc_symbol_mangling;
24 extern crate rustc_target;
25 extern crate snap;
26
27 // This prevents duplicating functions and statics that are already part of the host rustc process.
28 #[allow(unused_extern_crates)]
29 extern crate rustc_driver;
30
31 mod abi;
32 mod allocator;
33 mod archive;
34 mod asm;
35 mod back;
36 mod base;
37 mod builder;
38 mod callee;
39 mod common;
40 mod consts;
41 mod context;
42 mod coverageinfo;
43 mod debuginfo;
44 mod declare;
45 mod intrinsic;
46 mod mono_item;
47 mod type_;
48 mod type_of;
49
50 use std::any::Any;
51 use std::sync::Arc;
52
53 use gccjit::{Context, OptimizationLevel};
54 use rustc_ast::expand::allocator::AllocatorKind;
55 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
56 use rustc_codegen_ssa::base::codegen_crate;
57 use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryFn};
58 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
59 use rustc_codegen_ssa::target_features::supported_target_features;
60 use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
61 use rustc_data_structures::fx::FxHashMap;
62 use rustc_errors::{ErrorReported, Handler};
63 use rustc_metadata::EncodedMetadata;
64 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
65 use rustc_middle::ty::TyCtxt;
66 use rustc_session::config::{Lto, OptLevel, OutputFilenames};
67 use rustc_session::Session;
68 use rustc_span::Symbol;
69 use rustc_span::fatal_error::FatalError;
70
71 pub struct PrintOnPanic<F: Fn() -> String>(pub F);
72
73 impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
74     fn drop(&mut self) {
75         if ::std::thread::panicking() {
76             println!("{}", (self.0)());
77         }
78     }
79 }
80
81 #[derive(Clone)]
82 pub struct GccCodegenBackend;
83
84 impl CodegenBackend for GccCodegenBackend {
85     fn init(&self, sess: &Session) {
86         if sess.lto() != Lto::No {
87             sess.warn("LTO is not supported. You may get a linker error.");
88         }
89     }
90
91     fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
92         let target_cpu = target_cpu(tcx.sess);
93         let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module);
94
95         rustc_symbol_mangling::test::report_symbol_names(tcx);
96
97         Box::new(res)
98     }
99
100     fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
101         let (codegen_results, work_products) = ongoing_codegen
102             .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
103             .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
104             .join(sess);
105
106         Ok((codegen_results, work_products))
107     }
108
109     fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorReported> {
110         use rustc_codegen_ssa::back::link::link_binary;
111
112         link_binary::<crate::archive::ArArchiveBuilder<'_>>(
113             sess,
114             &codegen_results,
115             outputs,
116         )
117     }
118
119     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
120         target_features(sess)
121     }
122 }
123
124 impl ExtraBackendMethods for GccCodegenBackend {
125     fn new_metadata<'tcx>(&self, _tcx: TyCtxt<'tcx>, _mod_name: &str) -> Self::Module {
126         GccContext {
127             context: Context::default(),
128         }
129     }
130
131     fn write_compressed_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut Self::Module) {
132         base::write_compressed_metadata(tcx, metadata, gcc_module)
133     }
134
135     fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, mods: &mut Self::Module, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) {
136         unsafe { allocator::codegen(tcx, mods, module_name, kind, has_alloc_error_handler) }
137     }
138
139     fn compile_codegen_unit<'tcx>(&self, tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
140         base::compile_codegen_unit(tcx, cgu_name)
141     }
142
143     fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel) -> TargetMachineFactoryFn<Self> {
144         // TODO(antoyo): set opt level.
145         Arc::new(|_| {
146             Ok(())
147         })
148     }
149
150     fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str {
151         unimplemented!();
152     }
153
154     fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> {
155         None
156         // TODO(antoyo)
157     }
158 }
159
160 pub struct ModuleBuffer;
161
162 impl ModuleBufferMethods for ModuleBuffer {
163     fn data(&self) -> &[u8] {
164         unimplemented!();
165     }
166 }
167
168 pub struct ThinBuffer;
169
170 impl ThinBufferMethods for ThinBuffer {
171     fn data(&self) -> &[u8] {
172         unimplemented!();
173     }
174 }
175
176 pub struct GccContext {
177     context: Context<'static>,
178 }
179
180 unsafe impl Send for GccContext {}
181 // FIXME(antoyo): that shouldn't be Sync. Parallel compilation is currently disabled with "-Zno-parallel-llvm". Try to disable it here.
182 unsafe impl Sync for GccContext {}
183
184 impl WriteBackendMethods for GccCodegenBackend {
185     type Module = GccContext;
186     type TargetMachine = ();
187     type ModuleBuffer = ModuleBuffer;
188     type Context = ();
189     type ThinData = ();
190     type ThinBuffer = ThinBuffer;
191
192     fn run_fat_lto(_cgcx: &CodegenContext<Self>, mut modules: Vec<FatLTOInput<Self>>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
193         // TODO(antoyo): implement LTO by sending -flto to libgccjit and adding the appropriate gcc linker plugins.
194         // NOTE: implemented elsewhere.
195         // TODO: what is implemented elsewhere ^ ?
196         let module =
197             match modules.remove(0) {
198                 FatLTOInput::InMemory(module) => module,
199                 FatLTOInput::Serialized { .. } => {
200                     unimplemented!();
201                 }
202             };
203         Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: vec![] })
204     }
205
206     fn run_thin_lto(_cgcx: &CodegenContext<Self>, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
207         unimplemented!();
208     }
209
210     fn print_pass_timings(&self) {
211         unimplemented!();
212     }
213
214     unsafe fn optimize(_cgcx: &CodegenContext<Self>, _diag_handler: &Handler, module: &ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<(), FatalError> {
215         module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
216         Ok(())
217     }
218
219     unsafe fn optimize_thin(_cgcx: &CodegenContext<Self>, _thin: &mut ThinModule<Self>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
220         unimplemented!();
221     }
222
223     unsafe fn codegen(cgcx: &CodegenContext<Self>, diag_handler: &Handler, module: ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
224         back::write::codegen(cgcx, diag_handler, module, config)
225     }
226
227     fn prepare_thin(_module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
228         unimplemented!();
229     }
230
231     fn serialize_module(_module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
232         unimplemented!();
233     }
234
235     fn run_lto_pass_manager(_cgcx: &CodegenContext<Self>, _module: &ModuleCodegen<Self::Module>, _config: &ModuleConfig, _thin: bool) -> Result<(), FatalError> {
236         // TODO(antoyo)
237         Ok(())
238     }
239
240     fn run_link(cgcx: &CodegenContext<Self>, diag_handler: &Handler, modules: Vec<ModuleCodegen<Self::Module>>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
241         back::write::link(cgcx, diag_handler, modules)
242     }
243 }
244
245 /// This is the entrypoint for a hot plugged rustc_codegen_gccjit
246 #[no_mangle]
247 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
248     Box::new(GccCodegenBackend)
249 }
250
251 fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
252     match optlevel {
253         None => OptimizationLevel::None,
254         Some(level) => {
255             match level {
256                 OptLevel::No => OptimizationLevel::None,
257                 OptLevel::Less => OptimizationLevel::Limited,
258                 OptLevel::Default => OptimizationLevel::Standard,
259                 OptLevel::Aggressive => OptimizationLevel::Aggressive,
260                 OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
261             }
262         },
263     }
264 }
265
266 fn handle_native(name: &str) -> &str {
267     if name != "native" {
268         return name;
269     }
270
271     unimplemented!();
272 }
273
274 pub fn target_cpu(sess: &Session) -> &str {
275     let name = sess.opts.cg.target_cpu.as_ref().unwrap_or(&sess.target.cpu);
276     handle_native(name)
277 }
278
279 pub fn target_features(sess: &Session) -> Vec<Symbol> {
280     supported_target_features(sess)
281         .iter()
282         .filter_map(
283             |&(feature, gate)| {
284                 if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None }
285             },
286         )
287         .filter(|_feature| {
288             // TODO(antoyo): implement a way to get enabled feature in libgccjit.
289             false
290         })
291         .map(|feature| Symbol::intern(feature))
292         .collect()
293 }