1 #![feature(rustc_private)]
2 // Note: please avoid adding other feature gates where possible
3 #![warn(rust_2018_idioms)]
4 #![warn(unused_lifetimes)]
5 #![warn(unreachable_pub)]
8 extern crate rustc_middle
;
9 extern crate rustc_ast
;
10 extern crate rustc_codegen_ssa
;
11 extern crate rustc_data_structures
;
12 extern crate rustc_errors
;
13 extern crate rustc_fs_util
;
14 extern crate rustc_hir
;
15 extern crate rustc_incremental
;
16 extern crate rustc_index
;
17 extern crate rustc_interface
;
18 extern crate rustc_metadata
;
19 extern crate rustc_session
;
20 extern crate rustc_span
;
21 extern crate rustc_target
;
23 // This prevents duplicating functions and statics that are already part of the host rustc process.
24 #[allow(unused_extern_crates)]
25 extern crate rustc_driver
;
30 use rustc_codegen_ssa
::traits
::CodegenBackend
;
31 use rustc_codegen_ssa
::CodegenResults
;
32 use rustc_errors
::ErrorGuaranteed
;
33 use rustc_metadata
::EncodedMetadata
;
34 use rustc_middle
::dep_graph
::{WorkProduct, WorkProductId}
;
35 use rustc_session
::config
::OutputFilenames
;
36 use rustc_session
::Session
;
37 use rustc_span
::Symbol
;
39 use cranelift_codegen
::isa
::TargetIsa
;
40 use cranelift_codegen
::settings
::{self, Configurable}
;
42 pub use crate::config
::*;
43 use crate::prelude
::*;
53 mod compiler_builtins
;
74 pub(crate) use rustc_span
::{FileNameDisplayPreference, Span}
;
76 pub(crate) use rustc_hir
::def_id
::{DefId, LOCAL_CRATE}
;
77 pub(crate) use rustc_middle
::bug
;
78 pub(crate) use rustc_middle
::mir
::{self, *}
;
79 pub(crate) use rustc_middle
::ty
::layout
::{self, LayoutOf, TyAndLayout}
;
80 pub(crate) use rustc_middle
::ty
::{
81 self, FloatTy
, Instance
, InstanceDef
, IntTy
, ParamEnv
, Ty
, TyCtxt
, TypeAndMut
,
82 TypeFoldable
, TypeVisitable
, UintTy
,
84 pub(crate) use rustc_target
::abi
::{Abi, Scalar, Size, VariantIdx}
;
86 pub(crate) use rustc_data_structures
::fx
::FxHashMap
;
88 pub(crate) use rustc_index
::vec
::Idx
;
90 pub(crate) use cranelift_codegen
::ir
::condcodes
::{FloatCC, IntCC}
;
91 pub(crate) use cranelift_codegen
::ir
::function
::Function
;
92 pub(crate) use cranelift_codegen
::ir
::types
;
93 pub(crate) use cranelift_codegen
::ir
::{
94 AbiParam
, Block
, ExternalName
, FuncRef
, Inst
, InstBuilder
, MemFlags
, Signature
, SourceLoc
,
95 StackSlot
, StackSlotData
, StackSlotKind
, TrapCode
, Type
, Value
,
97 pub(crate) use cranelift_codegen
::isa
::{self, CallConv}
;
98 pub(crate) use cranelift_codegen
::Context
;
99 pub(crate) use cranelift_frontend
::{FunctionBuilder, FunctionBuilderContext, Variable}
;
100 pub(crate) use cranelift_module
::{self, DataContext, FuncId, Linkage, Module}
;
102 pub(crate) use crate::abi
::*;
103 pub(crate) use crate::base
::{codegen_operand, codegen_place}
;
104 pub(crate) use crate::cast
::*;
105 pub(crate) use crate::common
::*;
106 pub(crate) use crate::debuginfo
::{DebugContext, UnwindContext}
;
107 pub(crate) use crate::pointer
::Pointer
;
108 pub(crate) use crate::value_and_place
::{CPlace, CPlaceInner, CValue}
;
111 struct PrintOnPanic
<F
: Fn() -> String
>(F
);
112 impl<F
: Fn() -> String
> Drop
for PrintOnPanic
<F
> {
114 if ::std
::thread
::panicking() {
115 println
!("{}", (self.0)());
120 /// The codegen context holds any information shared between the codegen of individual functions
121 /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
122 struct CodegenCx
<'tcx
> {
125 inline_asm_index
: Cell
<usize>,
126 cached_context
: Context
,
127 debug_context
: Option
<DebugContext
<'tcx
>>,
128 unwind_context
: UnwindContext
,
132 impl<'tcx
> CodegenCx
<'tcx
> {
135 backend_config
: BackendConfig
,
140 assert_eq
!(pointer_ty(tcx
), isa
.pointer_type());
143 UnwindContext
::new(isa
, matches
!(backend_config
.codegen_mode
, CodegenMode
::Aot
));
144 let debug_context
= if debug_info
&& !tcx
.sess
.target
.options
.is_like_windows
{
145 Some(DebugContext
::new(tcx
, isa
))
151 global_asm
: String
::new(),
152 inline_asm_index
: Cell
::new(0),
153 cached_context
: Context
::new(),
161 pub struct CraneliftCodegenBackend
{
162 pub config
: Option
<BackendConfig
>,
165 impl CodegenBackend
for CraneliftCodegenBackend
{
166 fn init(&self, sess
: &Session
) {
167 use rustc_session
::config
::Lto
;
169 Lto
::No
| Lto
::ThinLocal
=> {}
170 Lto
::Thin
| Lto
::Fat
=> sess
.warn("LTO is not supported. You may get a linker error."),
174 fn target_features(&self, _sess
: &Session
, _allow_unstable
: bool
) -> Vec
<rustc_span
::Symbol
> {
178 fn print_version(&self) {
179 println
!("Cranelift version: {}", cranelift_codegen
::VERSION
);
185 metadata
: EncodedMetadata
,
186 need_metadata_module
: bool
,
188 tcx
.sess
.abort_if_errors();
189 let config
= if let Some(config
) = self.config
.clone() {
192 if !tcx
.sess
.unstable_options() && !tcx
.sess
.opts
.cg
.llvm_args
.is_empty() {
193 tcx
.sess
.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif");
195 BackendConfig
::from_opts(&tcx
.sess
.opts
.cg
.llvm_args
)
196 .unwrap_or_else(|err
| tcx
.sess
.fatal(&err
))
198 match config
.codegen_mode
{
199 CodegenMode
::Aot
=> driver
::aot
::run_aot(tcx
, config
, metadata
, need_metadata_module
),
200 CodegenMode
::Jit
| CodegenMode
::JitLazy
=> {
201 #[cfg(feature = "jit")]
202 driver
::jit
::run_jit(tcx
, config
);
204 #[cfg(not(feature = "jit"))]
205 tcx
.sess
.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
212 ongoing_codegen
: Box
<dyn Any
>,
214 _outputs
: &OutputFilenames
,
215 ) -> Result
<(CodegenResults
, FxHashMap
<WorkProductId
, WorkProduct
>), ErrorGuaranteed
> {
217 .downcast
::<(CodegenResults
, FxHashMap
<WorkProductId
, WorkProduct
>)>()
224 codegen_results
: CodegenResults
,
225 outputs
: &OutputFilenames
,
226 ) -> Result
<(), ErrorGuaranteed
> {
227 use rustc_codegen_ssa
::back
::link
::link_binary
;
229 link_binary(sess
, &crate::archive
::ArArchiveBuilderBuilder
, &codegen_results
, outputs
)
233 fn target_triple(sess
: &Session
) -> target_lexicon
::Triple
{
234 match sess
.target
.llvm_target
.parse() {
235 Ok(triple
) => triple
,
236 Err(err
) => sess
.fatal(&format
!("target not recognized: {}", err
)),
240 fn build_isa(sess
: &Session
, backend_config
: &BackendConfig
) -> Box
<dyn isa
::TargetIsa
+ '
static> {
241 use target_lexicon
::BinaryFormat
;
243 let target_triple
= crate::target_triple(sess
);
245 let mut flags_builder
= settings
::builder();
246 flags_builder
.enable("is_pic").unwrap();
247 flags_builder
.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
248 let enable_verifier
= if backend_config
.enable_verifier { "true" }
else { "false" }
;
249 flags_builder
.set("enable_verifier", enable_verifier
).unwrap();
250 flags_builder
.set("regalloc_checker", enable_verifier
).unwrap();
252 let tls_model
= match target_triple
.binary_format
{
253 BinaryFormat
::Elf
=> "elf_gd",
254 BinaryFormat
::Macho
=> "macho",
255 BinaryFormat
::Coff
=> "coff",
258 flags_builder
.set("tls_model", tls_model
).unwrap();
260 flags_builder
.set("enable_simd", "true").unwrap();
262 flags_builder
.set("enable_llvm_abi_extensions", "true").unwrap();
264 use rustc_session
::config
::OptLevel
;
265 match sess
.opts
.optimize
{
267 flags_builder
.set("opt_level", "none").unwrap();
269 OptLevel
::Less
| OptLevel
::Default
=> {}
270 OptLevel
::Size
| OptLevel
::SizeMin
| OptLevel
::Aggressive
=> {
271 flags_builder
.set("opt_level", "speed_and_size").unwrap();
275 let flags
= settings
::Flags
::new(flags_builder
);
277 let isa_builder
= match sess
.opts
.cg
.target_cpu
.as_deref() {
279 let builder
= cranelift_native
::builder_with_options(true).unwrap();
284 cranelift_codegen
::isa
::lookup(target_triple
.clone()).unwrap_or_else(|err
| {
285 sess
.fatal(&format
!("can't compile for {}: {}", target_triple
, err
));
287 if let Err(_
) = builder
.enable(value
) {
288 sess
.fatal("the specified target cpu isn't currently supported by Cranelift.");
294 cranelift_codegen
::isa
::lookup(target_triple
.clone()).unwrap_or_else(|err
| {
295 sess
.fatal(&format
!("can't compile for {}: {}", target_triple
, err
));
297 if target_triple
.architecture
== target_lexicon
::Architecture
::X86_64
{
298 // Don't use "haswell" as the default, as it implies `has_lzcnt`.
299 // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
300 builder
.enable("nehalem").unwrap();
306 match isa_builder
.finish(flags
) {
307 Ok(target_isa
) => target_isa
,
308 Err(err
) => sess
.fatal(&format
!("failed to build TargetIsa: {}", err
)),
312 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
314 pub fn __rustc_codegen_backend() -> Box
<dyn CodegenBackend
> {
315 Box
::new(CraneliftCodegenBackend { config: None }
)