]>
Commit | Line | Data |
---|---|---|
5e7ed085 FG |
1 | #![feature(rustc_private)] |
2 | // Note: please avoid adding other feature gates where possible | |
29967ef6 XL |
3 | #![warn(rust_2018_idioms)] |
4 | #![warn(unused_lifetimes)] | |
5 | #![warn(unreachable_pub)] | |
6 | ||
f2b60f7d | 7 | extern crate jobserver; |
29967ef6 XL |
8 | #[macro_use] |
9 | extern crate rustc_middle; | |
10 | extern crate rustc_ast; | |
11 | extern crate rustc_codegen_ssa; | |
12 | extern crate rustc_data_structures; | |
13 | extern crate rustc_errors; | |
14 | extern crate rustc_fs_util; | |
15 | extern crate rustc_hir; | |
16 | extern crate rustc_incremental; | |
17 | extern crate rustc_index; | |
136023e0 | 18 | extern crate rustc_interface; |
17df50a5 | 19 | extern crate rustc_metadata; |
29967ef6 XL |
20 | extern crate rustc_session; |
21 | extern crate rustc_span; | |
29967ef6 XL |
22 | extern crate rustc_target; |
23 | ||
24 | // This prevents duplicating functions and statics that are already part of the host rustc process. | |
25 | #[allow(unused_extern_crates)] | |
26 | extern crate rustc_driver; | |
27 | ||
28 | use std::any::Any; | |
f2b60f7d FG |
29 | use std::cell::{Cell, RefCell}; |
30 | use std::sync::Arc; | |
29967ef6 XL |
31 | |
32 | use rustc_codegen_ssa::traits::CodegenBackend; | |
33 | use rustc_codegen_ssa::CodegenResults; | |
f2b60f7d | 34 | use rustc_data_structures::profiling::SelfProfilerRef; |
5e7ed085 | 35 | use rustc_errors::ErrorGuaranteed; |
c295e0f8 | 36 | use rustc_metadata::EncodedMetadata; |
29967ef6 | 37 | use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; |
29967ef6 XL |
38 | use rustc_session::config::OutputFilenames; |
39 | use rustc_session::Session; | |
a2a8927a | 40 | use rustc_span::Symbol; |
29967ef6 | 41 | |
17df50a5 | 42 | use cranelift_codegen::isa::TargetIsa; |
29967ef6 XL |
43 | use cranelift_codegen::settings::{self, Configurable}; |
44 | ||
17df50a5 | 45 | pub use crate::config::*; |
29967ef6 XL |
46 | use crate::prelude::*; |
47 | ||
48 | mod abi; | |
49 | mod allocator; | |
50 | mod analyze; | |
51 | mod archive; | |
29967ef6 XL |
52 | mod base; |
53 | mod cast; | |
54 | mod codegen_i128; | |
55 | mod common; | |
cdc7bbd5 | 56 | mod compiler_builtins; |
f2b60f7d | 57 | mod concurrency_limiter; |
17df50a5 | 58 | mod config; |
29967ef6 XL |
59 | mod constant; |
60 | mod debuginfo; | |
61 | mod discriminant; | |
62 | mod driver; | |
f2b60f7d | 63 | mod global_asm; |
29967ef6 XL |
64 | mod inline_asm; |
65 | mod intrinsics; | |
66 | mod linkage; | |
67 | mod main_shim; | |
29967ef6 XL |
68 | mod num; |
69 | mod optimize; | |
70 | mod pointer; | |
71 | mod pretty_clif; | |
72 | mod toolchain; | |
73 | mod trap; | |
74 | mod unsize; | |
75 | mod value_and_place; | |
76 | mod vtable; | |
77 | ||
78 | mod prelude { | |
a2a8927a | 79 | pub(crate) use rustc_span::{FileNameDisplayPreference, Span}; |
29967ef6 XL |
80 | |
81 | pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; | |
82 | pub(crate) use rustc_middle::bug; | |
83 | pub(crate) use rustc_middle::mir::{self, *}; | |
c295e0f8 | 84 | pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout}; |
29967ef6 | 85 | pub(crate) use rustc_middle::ty::{ |
5869c6ff | 86 | self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, |
064997fb | 87 | TypeFoldable, TypeVisitable, UintTy, |
29967ef6 | 88 | }; |
c295e0f8 | 89 | pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx}; |
29967ef6 XL |
90 | |
91 | pub(crate) use rustc_data_structures::fx::FxHashMap; | |
92 | ||
93 | pub(crate) use rustc_index::vec::Idx; | |
94 | ||
29967ef6 XL |
95 | pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; |
96 | pub(crate) use cranelift_codegen::ir::function::Function; | |
97 | pub(crate) use cranelift_codegen::ir::types; | |
98 | pub(crate) use cranelift_codegen::ir::{ | |
2b03887a FG |
99 | AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, |
100 | StackSlotData, StackSlotKind, TrapCode, Type, Value, | |
29967ef6 XL |
101 | }; |
102 | pub(crate) use cranelift_codegen::isa::{self, CallConv}; | |
103 | pub(crate) use cranelift_codegen::Context; | |
104 | pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; | |
136023e0 | 105 | pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module}; |
29967ef6 XL |
106 | |
107 | pub(crate) use crate::abi::*; | |
108 | pub(crate) use crate::base::{codegen_operand, codegen_place}; | |
109 | pub(crate) use crate::cast::*; | |
110 | pub(crate) use crate::common::*; | |
111 | pub(crate) use crate::debuginfo::{DebugContext, UnwindContext}; | |
112 | pub(crate) use crate::pointer::Pointer; | |
29967ef6 XL |
113 | pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue}; |
114 | } | |
115 | ||
116 | struct PrintOnPanic<F: Fn() -> String>(F); | |
117 | impl<F: Fn() -> String> Drop for PrintOnPanic<F> { | |
118 | fn drop(&mut self) { | |
119 | if ::std::thread::panicking() { | |
120 | println!("{}", (self.0)()); | |
121 | } | |
122 | } | |
123 | } | |
124 | ||
17df50a5 XL |
125 | /// The codegen context holds any information shared between the codegen of individual functions |
126 | /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). | |
f2b60f7d FG |
127 | struct CodegenCx { |
128 | profiler: SelfProfilerRef, | |
129 | output_filenames: Arc<OutputFilenames>, | |
130 | should_write_ir: bool, | |
29967ef6 | 131 | global_asm: String, |
a2a8927a | 132 | inline_asm_index: Cell<usize>, |
f2b60f7d | 133 | debug_context: Option<DebugContext>, |
17df50a5 | 134 | unwind_context: UnwindContext, |
a2a8927a | 135 | cgu_name: Symbol, |
29967ef6 XL |
136 | } |
137 | ||
f2b60f7d | 138 | impl CodegenCx { |
6a06907d | 139 | fn new( |
f2b60f7d | 140 | tcx: TyCtxt<'_>, |
6a06907d | 141 | backend_config: BackendConfig, |
17df50a5 | 142 | isa: &dyn TargetIsa, |
6a06907d | 143 | debug_info: bool, |
a2a8927a | 144 | cgu_name: Symbol, |
6a06907d | 145 | ) -> Self { |
17df50a5 XL |
146 | assert_eq!(pointer_ty(tcx), isa.pointer_type()); |
147 | ||
148 | let unwind_context = | |
a2a8927a | 149 | UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); |
064997fb FG |
150 | let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows { |
151 | Some(DebugContext::new(tcx, isa)) | |
152 | } else { | |
153 | None | |
154 | }; | |
29967ef6 | 155 | CodegenCx { |
f2b60f7d FG |
156 | profiler: tcx.prof.clone(), |
157 | output_filenames: tcx.output_filenames(()).clone(), | |
158 | should_write_ir: crate::pretty_clif::should_write_ir(tcx), | |
29967ef6 | 159 | global_asm: String::new(), |
a2a8927a | 160 | inline_asm_index: Cell::new(0), |
29967ef6 XL |
161 | debug_context, |
162 | unwind_context, | |
a2a8927a | 163 | cgu_name, |
29967ef6 XL |
164 | } |
165 | } | |
29967ef6 XL |
166 | } |
167 | ||
168 | pub struct CraneliftCodegenBackend { | |
f2b60f7d | 169 | pub config: RefCell<Option<BackendConfig>>, |
29967ef6 XL |
170 | } |
171 | ||
172 | impl CodegenBackend for CraneliftCodegenBackend { | |
173 | fn init(&self, sess: &Session) { | |
cdc7bbd5 XL |
174 | use rustc_session::config::Lto; |
175 | match sess.lto() { | |
176 | Lto::No | Lto::ThinLocal => {} | |
177 | Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."), | |
29967ef6 | 178 | } |
f2b60f7d FG |
179 | |
180 | let mut config = self.config.borrow_mut(); | |
181 | if config.is_none() { | |
182 | let new_config = BackendConfig::from_opts(&sess.opts.cg.llvm_args) | |
183 | .unwrap_or_else(|err| sess.fatal(&err)); | |
184 | *config = Some(new_config); | |
185 | } | |
29967ef6 XL |
186 | } |
187 | ||
064997fb | 188 | fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> { |
29967ef6 XL |
189 | vec![] |
190 | } | |
191 | ||
17df50a5 XL |
192 | fn print_version(&self) { |
193 | println!("Cranelift version: {}", cranelift_codegen::VERSION); | |
194 | } | |
195 | ||
cdc7bbd5 | 196 | fn codegen_crate( |
29967ef6 | 197 | &self, |
cdc7bbd5 | 198 | tcx: TyCtxt<'_>, |
29967ef6 XL |
199 | metadata: EncodedMetadata, |
200 | need_metadata_module: bool, | |
201 | ) -> Box<dyn Any> { | |
17df50a5 | 202 | tcx.sess.abort_if_errors(); |
f2b60f7d | 203 | let config = self.config.borrow().clone().unwrap(); |
17df50a5 XL |
204 | match config.codegen_mode { |
205 | CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module), | |
206 | CodegenMode::Jit | CodegenMode::JitLazy => { | |
207 | #[cfg(feature = "jit")] | |
5e7ed085 | 208 | driver::jit::run_jit(tcx, config); |
17df50a5 XL |
209 | |
210 | #[cfg(not(feature = "jit"))] | |
211 | tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift"); | |
212 | } | |
213 | } | |
29967ef6 XL |
214 | } |
215 | ||
216 | fn join_codegen( | |
217 | &self, | |
218 | ongoing_codegen: Box<dyn Any>, | |
f2b60f7d | 219 | sess: &Session, |
a2a8927a | 220 | _outputs: &OutputFilenames, |
5e7ed085 | 221 | ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { |
f2b60f7d FG |
222 | Ok(ongoing_codegen |
223 | .downcast::<driver::aot::OngoingCodegen>() | |
224 | .unwrap() | |
225 | .join(sess, self.config.borrow().as_ref().unwrap())) | |
29967ef6 XL |
226 | } |
227 | ||
228 | fn link( | |
229 | &self, | |
230 | sess: &Session, | |
231 | codegen_results: CodegenResults, | |
232 | outputs: &OutputFilenames, | |
5e7ed085 | 233 | ) -> Result<(), ErrorGuaranteed> { |
29967ef6 XL |
234 | use rustc_codegen_ssa::back::link::link_binary; |
235 | ||
064997fb | 236 | link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) |
29967ef6 XL |
237 | } |
238 | } | |
239 | ||
240 | fn target_triple(sess: &Session) -> target_lexicon::Triple { | |
94222f64 XL |
241 | match sess.target.llvm_target.parse() { |
242 | Ok(triple) => triple, | |
243 | Err(err) => sess.fatal(&format!("target not recognized: {}", err)), | |
244 | } | |
29967ef6 XL |
245 | } |
246 | ||
17df50a5 | 247 | fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::TargetIsa + 'static> { |
29967ef6 XL |
248 | use target_lexicon::BinaryFormat; |
249 | ||
250 | let target_triple = crate::target_triple(sess); | |
251 | ||
252 | let mut flags_builder = settings::builder(); | |
5869c6ff | 253 | flags_builder.enable("is_pic").unwrap(); |
17df50a5 XL |
254 | let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" }; |
255 | flags_builder.set("enable_verifier", enable_verifier).unwrap(); | |
064997fb | 256 | flags_builder.set("regalloc_checker", enable_verifier).unwrap(); |
29967ef6 XL |
257 | |
258 | let tls_model = match target_triple.binary_format { | |
259 | BinaryFormat::Elf => "elf_gd", | |
260 | BinaryFormat::Macho => "macho", | |
261 | BinaryFormat::Coff => "coff", | |
262 | _ => "none", | |
263 | }; | |
264 | flags_builder.set("tls_model", tls_model).unwrap(); | |
265 | ||
266 | flags_builder.set("enable_simd", "true").unwrap(); | |
267 | ||
cdc7bbd5 XL |
268 | flags_builder.set("enable_llvm_abi_extensions", "true").unwrap(); |
269 | ||
29967ef6 XL |
270 | use rustc_session::config::OptLevel; |
271 | match sess.opts.optimize { | |
272 | OptLevel::No => { | |
273 | flags_builder.set("opt_level", "none").unwrap(); | |
274 | } | |
275 | OptLevel::Less | OptLevel::Default => {} | |
cdc7bbd5 | 276 | OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { |
29967ef6 XL |
277 | flags_builder.set("opt_level", "speed_and_size").unwrap(); |
278 | } | |
5869c6ff | 279 | } |
29967ef6 | 280 | |
2b03887a FG |
281 | if target_triple.architecture == target_lexicon::Architecture::X86_64 { |
282 | // Windows depends on stack probes to grow the committed part of the stack | |
283 | flags_builder.enable("enable_probestack").unwrap(); | |
284 | flags_builder.set("probestack_strategy", "inline").unwrap(); | |
285 | } else { | |
286 | // __cranelift_probestack is not provided and inline stack probes are only supported on x86_64 | |
287 | flags_builder.set("enable_probestack", "false").unwrap(); | |
288 | } | |
289 | ||
29967ef6 XL |
290 | let flags = settings::Flags::new(flags_builder); |
291 | ||
17df50a5 XL |
292 | let isa_builder = match sess.opts.cg.target_cpu.as_deref() { |
293 | Some("native") => { | |
a2a8927a | 294 | let builder = cranelift_native::builder_with_options(true).unwrap(); |
17df50a5 XL |
295 | builder |
296 | } | |
297 | Some(value) => { | |
298 | let mut builder = | |
a2a8927a XL |
299 | cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { |
300 | sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); | |
301 | }); | |
17df50a5 | 302 | if let Err(_) = builder.enable(value) { |
94222f64 | 303 | sess.fatal("the specified target cpu isn't currently supported by Cranelift."); |
17df50a5 XL |
304 | } |
305 | builder | |
306 | } | |
307 | None => { | |
308 | let mut builder = | |
a2a8927a XL |
309 | cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { |
310 | sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); | |
311 | }); | |
136023e0 XL |
312 | if target_triple.architecture == target_lexicon::Architecture::X86_64 { |
313 | // Don't use "haswell" as the default, as it implies `has_lzcnt`. | |
314 | // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. | |
315 | builder.enable("nehalem").unwrap(); | |
316 | } | |
17df50a5 XL |
317 | builder |
318 | } | |
319 | }; | |
320 | ||
5e7ed085 FG |
321 | match isa_builder.finish(flags) { |
322 | Ok(target_isa) => target_isa, | |
323 | Err(err) => sess.fatal(&format!("failed to build TargetIsa: {}", err)), | |
324 | } | |
29967ef6 XL |
325 | } |
326 | ||
327 | /// This is the entrypoint for a hot plugged rustc_codegen_cranelift | |
328 | #[no_mangle] | |
329 | pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { | |
f2b60f7d | 330 | Box::new(CraneliftCodegenBackend { config: RefCell::new(None) }) |
29967ef6 | 331 | } |