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