]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | #![feature( |
2 | rustc_private, | |
3 | decl_macro, | |
4 | type_alias_impl_trait, | |
5 | associated_type_bounds, | |
6 | never_type, | |
7 | try_blocks, | |
6a06907d XL |
8 | box_patterns, |
9 | hash_drain_filter | |
29967ef6 XL |
10 | )] |
11 | #![warn(rust_2018_idioms)] | |
12 | #![warn(unused_lifetimes)] | |
13 | #![warn(unreachable_pub)] | |
14 | ||
29967ef6 XL |
15 | extern crate snap; |
16 | #[macro_use] | |
17 | extern crate rustc_middle; | |
18 | extern crate rustc_ast; | |
19 | extern crate rustc_codegen_ssa; | |
20 | extern crate rustc_data_structures; | |
21 | extern crate rustc_errors; | |
22 | extern crate rustc_fs_util; | |
23 | extern crate rustc_hir; | |
24 | extern crate rustc_incremental; | |
25 | extern crate rustc_index; | |
26 | extern crate rustc_session; | |
27 | extern crate rustc_span; | |
29967ef6 XL |
28 | extern crate rustc_target; |
29 | ||
30 | // This prevents duplicating functions and statics that are already part of the host rustc process. | |
31 | #[allow(unused_extern_crates)] | |
32 | extern crate rustc_driver; | |
33 | ||
34 | use std::any::Any; | |
5869c6ff | 35 | use std::str::FromStr; |
29967ef6 XL |
36 | |
37 | use rustc_codegen_ssa::traits::CodegenBackend; | |
38 | use rustc_codegen_ssa::CodegenResults; | |
39 | use rustc_errors::ErrorReported; | |
40 | use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; | |
41 | use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader}; | |
42 | use rustc_middle::ty::query::Providers; | |
43 | use rustc_session::config::OutputFilenames; | |
44 | use rustc_session::Session; | |
45 | ||
46 | use cranelift_codegen::settings::{self, Configurable}; | |
47 | ||
48 | use crate::constant::ConstantCx; | |
49 | use crate::prelude::*; | |
50 | ||
51 | mod abi; | |
52 | mod allocator; | |
53 | mod analyze; | |
54 | mod archive; | |
29967ef6 XL |
55 | mod backend; |
56 | mod base; | |
57 | mod cast; | |
58 | mod codegen_i128; | |
59 | mod common; | |
60 | mod constant; | |
61 | mod debuginfo; | |
62 | mod discriminant; | |
63 | mod driver; | |
64 | mod inline_asm; | |
65 | mod intrinsics; | |
66 | mod linkage; | |
67 | mod main_shim; | |
68 | mod metadata; | |
69 | mod num; | |
70 | mod optimize; | |
71 | mod pointer; | |
72 | mod pretty_clif; | |
73 | mod toolchain; | |
74 | mod trap; | |
75 | mod unsize; | |
76 | mod value_and_place; | |
77 | mod vtable; | |
78 | ||
79 | mod prelude { | |
80 | pub(crate) use std::convert::{TryFrom, TryInto}; | |
81 | ||
29967ef6 XL |
82 | pub(crate) use rustc_span::Span; |
83 | ||
84 | pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; | |
85 | pub(crate) use rustc_middle::bug; | |
86 | pub(crate) use rustc_middle::mir::{self, *}; | |
87 | pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout}; | |
88 | pub(crate) use rustc_middle::ty::{ | |
5869c6ff XL |
89 | self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, |
90 | TypeFoldable, UintTy, | |
29967ef6 XL |
91 | }; |
92 | pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx}; | |
93 | ||
94 | pub(crate) use rustc_data_structures::fx::FxHashMap; | |
95 | ||
96 | pub(crate) use rustc_index::vec::Idx; | |
97 | ||
98 | pub(crate) use cranelift_codegen::entity::EntitySet; | |
99 | pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; | |
100 | pub(crate) use cranelift_codegen::ir::function::Function; | |
101 | pub(crate) use cranelift_codegen::ir::types; | |
102 | pub(crate) use cranelift_codegen::ir::{ | |
103 | AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, | |
104 | StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value, | |
105 | }; | |
106 | pub(crate) use cranelift_codegen::isa::{self, CallConv}; | |
107 | pub(crate) use cranelift_codegen::Context; | |
108 | pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; | |
109 | pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module}; | |
110 | ||
111 | pub(crate) use crate::abi::*; | |
112 | pub(crate) use crate::base::{codegen_operand, codegen_place}; | |
113 | pub(crate) use crate::cast::*; | |
114 | pub(crate) use crate::common::*; | |
115 | pub(crate) use crate::debuginfo::{DebugContext, UnwindContext}; | |
116 | pub(crate) use crate::pointer::Pointer; | |
117 | pub(crate) use crate::trap::*; | |
118 | pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue}; | |
119 | } | |
120 | ||
121 | struct PrintOnPanic<F: Fn() -> String>(F); | |
122 | impl<F: Fn() -> String> Drop for PrintOnPanic<F> { | |
123 | fn drop(&mut self) { | |
124 | if ::std::thread::panicking() { | |
125 | println!("{}", (self.0)()); | |
126 | } | |
127 | } | |
128 | } | |
129 | ||
6a06907d | 130 | struct CodegenCx<'m, 'tcx: 'm> { |
29967ef6 | 131 | tcx: TyCtxt<'tcx>, |
6a06907d | 132 | module: &'m mut dyn Module, |
29967ef6 XL |
133 | global_asm: String, |
134 | constants_cx: ConstantCx, | |
135 | cached_context: Context, | |
136 | vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>, | |
137 | debug_context: Option<DebugContext<'tcx>>, | |
138 | unwind_context: UnwindContext<'tcx>, | |
139 | } | |
140 | ||
6a06907d XL |
141 | impl<'m, 'tcx> CodegenCx<'m, 'tcx> { |
142 | fn new( | |
143 | tcx: TyCtxt<'tcx>, | |
144 | backend_config: BackendConfig, | |
145 | module: &'m mut dyn Module, | |
146 | debug_info: bool, | |
147 | ) -> Self { | |
148 | let unwind_context = UnwindContext::new( | |
149 | tcx, | |
150 | module.isa(), | |
151 | matches!(backend_config.codegen_mode, CodegenMode::Aot), | |
152 | ); | |
153 | let debug_context = | |
154 | if debug_info { Some(DebugContext::new(tcx, module.isa())) } else { None }; | |
29967ef6 XL |
155 | CodegenCx { |
156 | tcx, | |
157 | module, | |
158 | global_asm: String::new(), | |
159 | constants_cx: ConstantCx::default(), | |
160 | cached_context: Context::new(), | |
161 | vtables: FxHashMap::default(), | |
162 | debug_context, | |
163 | unwind_context, | |
164 | } | |
165 | } | |
166 | ||
6a06907d XL |
167 | fn finalize(self) -> (String, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) { |
168 | self.constants_cx.finalize(self.tcx, self.module); | |
169 | (self.global_asm, self.debug_context, self.unwind_context) | |
29967ef6 XL |
170 | } |
171 | } | |
172 | ||
173 | #[derive(Copy, Clone, Debug)] | |
5869c6ff XL |
174 | pub enum CodegenMode { |
175 | Aot, | |
176 | Jit, | |
177 | JitLazy, | |
178 | } | |
179 | ||
180 | impl Default for CodegenMode { | |
181 | fn default() -> Self { | |
182 | CodegenMode::Aot | |
183 | } | |
184 | } | |
185 | ||
186 | impl FromStr for CodegenMode { | |
187 | type Err = String; | |
188 | ||
189 | fn from_str(s: &str) -> Result<Self, Self::Err> { | |
190 | match s { | |
191 | "aot" => Ok(CodegenMode::Aot), | |
192 | "jit" => Ok(CodegenMode::Jit), | |
193 | "jit-lazy" => Ok(CodegenMode::JitLazy), | |
194 | _ => Err(format!("Unknown codegen mode `{}`", s)), | |
195 | } | |
196 | } | |
197 | } | |
198 | ||
199 | #[derive(Copy, Clone, Debug, Default)] | |
29967ef6 | 200 | pub struct BackendConfig { |
5869c6ff XL |
201 | pub codegen_mode: CodegenMode, |
202 | } | |
203 | ||
204 | impl BackendConfig { | |
205 | fn from_opts(opts: &[String]) -> Result<Self, String> { | |
206 | let mut config = BackendConfig::default(); | |
207 | for opt in opts { | |
208 | if let Some((name, value)) = opt.split_once('=') { | |
209 | match name { | |
210 | "mode" => config.codegen_mode = value.parse()?, | |
211 | _ => return Err(format!("Unknown option `{}`", name)), | |
212 | } | |
213 | } else { | |
214 | return Err(format!("Invalid option `{}`", opt)); | |
215 | } | |
216 | } | |
217 | Ok(config) | |
218 | } | |
29967ef6 XL |
219 | } |
220 | ||
221 | pub struct CraneliftCodegenBackend { | |
5869c6ff | 222 | pub config: Option<BackendConfig>, |
29967ef6 XL |
223 | } |
224 | ||
225 | impl CodegenBackend for CraneliftCodegenBackend { | |
226 | fn init(&self, sess: &Session) { | |
227 | if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode { | |
228 | sess.warn("LTO is not supported. You may get a linker error."); | |
229 | } | |
230 | } | |
231 | ||
232 | fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> { | |
233 | Box::new(crate::metadata::CraneliftMetadataLoader) | |
234 | } | |
235 | ||
236 | fn provide(&self, _providers: &mut Providers) {} | |
237 | fn provide_extern(&self, _providers: &mut Providers) {} | |
238 | ||
239 | fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> { | |
240 | vec![] | |
241 | } | |
242 | ||
243 | fn codegen_crate<'tcx>( | |
244 | &self, | |
245 | tcx: TyCtxt<'tcx>, | |
246 | metadata: EncodedMetadata, | |
247 | need_metadata_module: bool, | |
248 | ) -> Box<dyn Any> { | |
5869c6ff XL |
249 | let config = if let Some(config) = self.config { |
250 | config | |
251 | } else { | |
252 | BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) | |
253 | .unwrap_or_else(|err| tcx.sess.fatal(&err)) | |
254 | }; | |
255 | let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config); | |
29967ef6 XL |
256 | |
257 | res | |
258 | } | |
259 | ||
260 | fn join_codegen( | |
261 | &self, | |
262 | ongoing_codegen: Box<dyn Any>, | |
263 | _sess: &Session, | |
264 | ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> { | |
265 | Ok(*ongoing_codegen | |
266 | .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>() | |
267 | .unwrap()) | |
268 | } | |
269 | ||
270 | fn link( | |
271 | &self, | |
272 | sess: &Session, | |
273 | codegen_results: CodegenResults, | |
274 | outputs: &OutputFilenames, | |
275 | ) -> Result<(), ErrorReported> { | |
276 | use rustc_codegen_ssa::back::link::link_binary; | |
277 | ||
5869c6ff XL |
278 | let target_cpu = crate::target_triple(sess).to_string(); |
279 | link_binary::<crate::archive::ArArchiveBuilder<'_>>( | |
280 | sess, | |
281 | &codegen_results, | |
282 | outputs, | |
283 | &codegen_results.crate_name.as_str(), | |
284 | &target_cpu, | |
285 | ); | |
29967ef6 XL |
286 | |
287 | Ok(()) | |
288 | } | |
289 | } | |
290 | ||
291 | fn target_triple(sess: &Session) -> target_lexicon::Triple { | |
292 | sess.target.llvm_target.parse().unwrap() | |
293 | } | |
294 | ||
5869c6ff | 295 | fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> { |
29967ef6 XL |
296 | use target_lexicon::BinaryFormat; |
297 | ||
298 | let target_triple = crate::target_triple(sess); | |
299 | ||
300 | let mut flags_builder = settings::builder(); | |
5869c6ff | 301 | flags_builder.enable("is_pic").unwrap(); |
29967ef6 XL |
302 | flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided |
303 | flags_builder | |
6a06907d | 304 | .set("enable_verifier", if cfg!(debug_assertions) { "true" } else { "false" }) |
29967ef6 XL |
305 | .unwrap(); |
306 | ||
307 | let tls_model = match target_triple.binary_format { | |
308 | BinaryFormat::Elf => "elf_gd", | |
309 | BinaryFormat::Macho => "macho", | |
310 | BinaryFormat::Coff => "coff", | |
311 | _ => "none", | |
312 | }; | |
313 | flags_builder.set("tls_model", tls_model).unwrap(); | |
314 | ||
315 | flags_builder.set("enable_simd", "true").unwrap(); | |
316 | ||
29967ef6 XL |
317 | use rustc_session::config::OptLevel; |
318 | match sess.opts.optimize { | |
319 | OptLevel::No => { | |
320 | flags_builder.set("opt_level", "none").unwrap(); | |
321 | } | |
322 | OptLevel::Less | OptLevel::Default => {} | |
323 | OptLevel::Aggressive => { | |
324 | flags_builder.set("opt_level", "speed_and_size").unwrap(); | |
325 | } | |
326 | OptLevel::Size | OptLevel::SizeMin => { | |
327 | sess.warn("Optimizing for size is not supported. Just ignoring the request"); | |
328 | } | |
5869c6ff | 329 | } |
29967ef6 XL |
330 | |
331 | let flags = settings::Flags::new(flags_builder); | |
332 | ||
6a06907d | 333 | let variant = cranelift_codegen::isa::BackendVariant::MachInst; |
5869c6ff | 334 | let mut isa_builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap(); |
29967ef6 XL |
335 | // Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt` |
336 | // is interpreted as `bsr`. | |
337 | isa_builder.enable("nehalem").unwrap(); | |
338 | isa_builder.finish(flags) | |
339 | } | |
340 | ||
341 | /// This is the entrypoint for a hot plugged rustc_codegen_cranelift | |
342 | #[no_mangle] | |
343 | pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { | |
5869c6ff | 344 | Box::new(CraneliftCodegenBackend { config: None }) |
29967ef6 | 345 | } |