5 //! This API is completely unstable and subject to change.
7 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
9 #![feature(box_patterns)]
10 #![feature(box_syntax)]
11 #![feature(const_cstr_unchecked)]
12 #![feature(crate_visibility_modifier)]
13 #![feature(extern_types)]
14 #![feature(in_band_lifetimes)]
17 #![feature(optin_builtin_traits)]
18 #![feature(concat_idents)]
19 #![feature(link_args)]
20 #![feature(static_nobundle)]
21 #![feature(trusted_len)]
24 use back
::write
::{create_target_machine, create_informational_target_machine}
;
25 use syntax_pos
::symbol
::Symbol
;
27 extern crate rustc_demangle
;
29 #[macro_use] extern crate bitflags;
31 #[macro_use] extern crate rustc;
32 extern crate rustc_target
;
33 #[macro_use] extern crate rustc_data_structures;
34 extern crate rustc_incremental
;
35 extern crate rustc_codegen_utils
;
36 extern crate rustc_codegen_ssa
;
37 extern crate rustc_fs_util
;
38 extern crate rustc_driver
as _
;
40 #[macro_use] extern crate log;
41 #[macro_use] extern crate syntax;
42 extern crate syntax_pos
;
43 extern crate rustc_errors
as errors
;
45 use rustc_codegen_ssa
::traits
::*;
46 use rustc_codegen_ssa
::back
::write
::{CodegenContext, ModuleConfig, FatLTOInput}
;
47 use rustc_codegen_ssa
::back
::lto
::{SerializedModule, LtoModuleCodegen, ThinModule}
;
48 use rustc_codegen_ssa
::CompiledModule
;
49 use errors
::{FatalError, Handler}
;
50 use rustc
::dep_graph
::WorkProduct
;
51 use syntax
::ext
::allocator
::AllocatorKind
;
52 use syntax_pos
::symbol
::InternedString
;
53 pub use llvm_util
::target_features
;
55 use std
::sync
::{mpsc, Arc}
;
58 use rustc
::dep_graph
::DepGraph
;
59 use rustc
::middle
::cstore
::{EncodedMetadata, MetadataLoader}
;
60 use rustc
::session
::Session
;
61 use rustc
::session
::config
::{OutputFilenames, OutputType, PrintRequest, OptLevel}
;
62 use rustc
::ty
::{self, TyCtxt}
;
63 use rustc
::util
::common
::ErrorReported
;
64 use rustc_codegen_ssa
::ModuleCodegen
;
65 use rustc_codegen_utils
::codegen_backend
::CodegenBackend
;
90 // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
91 #[path = "llvm/mod.rs"] mod llvm_; pub mod llvm { pub use super::llvm_::*; }
102 pub struct LlvmCodegenBackend(());
104 impl ExtraBackendMethods
for LlvmCodegenBackend
{
105 fn new_metadata(&self, tcx
: TyCtxt
<'_
>, mod_name
: &str) -> ModuleLlvm
{
106 ModuleLlvm
::new_metadata(tcx
, mod_name
)
109 fn write_compressed_metadata
<'tcx
>(
112 metadata
: &EncodedMetadata
,
113 llvm_module
: &mut ModuleLlvm
,
115 base
::write_compressed_metadata(tcx
, metadata
, llvm_module
)
117 fn codegen_allocator
<'tcx
>(
120 mods
: &mut ModuleLlvm
,
123 unsafe { allocator::codegen(tcx, mods, kind) }
125 fn compile_codegen_unit(&self, tcx
: TyCtxt
<'_
>, cgu_name
: InternedString
) {
126 base
::compile_codegen_unit(tcx
, cgu_name
);
128 fn target_machine_factory(
134 Result
<&'
static mut llvm
::TargetMachine
, String
> + Send
+ Sync
> {
135 back
::write
::target_machine_factory(sess
, optlvl
, find_features
)
137 fn target_cpu
<'b
>(&self, sess
: &'b Session
) -> &'b
str {
138 llvm_util
::target_cpu(sess
)
142 impl WriteBackendMethods
for LlvmCodegenBackend
{
143 type Module
= ModuleLlvm
;
144 type ModuleBuffer
= back
::lto
::ModuleBuffer
;
145 type Context
= llvm
::Context
;
146 type TargetMachine
= &'
static mut llvm
::TargetMachine
;
147 type ThinData
= back
::lto
::ThinData
;
148 type ThinBuffer
= back
::lto
::ThinBuffer
;
149 fn print_pass_timings(&self) {
150 unsafe { llvm::LLVMRustPrintPassTimings(); }
153 cgcx
: &CodegenContext
<Self>,
154 modules
: Vec
<FatLTOInput
<Self>>,
155 cached_modules
: Vec
<(SerializedModule
<Self::ModuleBuffer
>, WorkProduct
)>,
156 ) -> Result
<LtoModuleCodegen
<Self>, FatalError
> {
157 back
::lto
::run_fat(cgcx
, modules
, cached_modules
)
160 cgcx
: &CodegenContext
<Self>,
161 modules
: Vec
<(String
, Self::ThinBuffer
)>,
162 cached_modules
: Vec
<(SerializedModule
<Self::ModuleBuffer
>, WorkProduct
)>,
163 ) -> Result
<(Vec
<LtoModuleCodegen
<Self>>, Vec
<WorkProduct
>), FatalError
> {
164 back
::lto
::run_thin(cgcx
, modules
, cached_modules
)
167 cgcx
: &CodegenContext
<Self>,
168 diag_handler
: &Handler
,
169 module
: &ModuleCodegen
<Self::Module
>,
170 config
: &ModuleConfig
,
171 ) -> Result
<(), FatalError
> {
172 back
::write
::optimize(cgcx
, diag_handler
, module
, config
)
174 unsafe fn optimize_thin(
175 cgcx
: &CodegenContext
<Self>,
176 thin
: &mut ThinModule
<Self>,
177 ) -> Result
<ModuleCodegen
<Self::Module
>, FatalError
> {
178 back
::lto
::optimize_thin_module(thin
, cgcx
)
181 cgcx
: &CodegenContext
<Self>,
182 diag_handler
: &Handler
,
183 module
: ModuleCodegen
<Self::Module
>,
184 config
: &ModuleConfig
,
185 ) -> Result
<CompiledModule
, FatalError
> {
186 back
::write
::codegen(cgcx
, diag_handler
, module
, config
)
189 module
: ModuleCodegen
<Self::Module
>
190 ) -> (String
, Self::ThinBuffer
) {
191 back
::lto
::prepare_thin(module
)
194 module
: ModuleCodegen
<Self::Module
>
195 ) -> (String
, Self::ModuleBuffer
) {
196 (module
.name
, back
::lto
::ModuleBuffer
::new(module
.module_llvm
.llmod()))
198 fn run_lto_pass_manager(
199 cgcx
: &CodegenContext
<Self>,
200 module
: &ModuleCodegen
<Self::Module
>,
201 config
: &ModuleConfig
,
204 back
::lto
::run_pass_manager(cgcx
, module
, config
, thin
)
208 unsafe impl Send
for LlvmCodegenBackend {}
// Llvm is on a per-thread basis
209 unsafe impl Sync
for LlvmCodegenBackend {}
211 impl LlvmCodegenBackend
{
212 pub fn new() -> Box
<dyn CodegenBackend
> {
213 box LlvmCodegenBackend(())
217 impl CodegenBackend
for LlvmCodegenBackend
{
218 fn init(&self, sess
: &Session
) {
219 llvm_util
::init(sess
); // Make sure llvm is inited
222 fn print(&self, req
: PrintRequest
, sess
: &Session
) {
224 PrintRequest
::RelocationModels
=> {
225 println
!("Available relocation models:");
226 for &(name
, _
) in back
::write
::RELOC_MODEL_ARGS
.iter() {
227 println
!(" {}", name
);
231 PrintRequest
::CodeModels
=> {
232 println
!("Available code models:");
233 for &(name
, _
) in back
::write
::CODE_GEN_MODEL_ARGS
.iter(){
234 println
!(" {}", name
);
238 PrintRequest
::TlsModels
=> {
239 println
!("Available TLS models:");
240 for &(name
, _
) in back
::write
::TLS_MODEL_ARGS
.iter(){
241 println
!(" {}", name
);
245 req
=> llvm_util
::print(req
, sess
),
249 fn print_passes(&self) {
250 llvm_util
::print_passes();
253 fn print_version(&self) {
254 llvm_util
::print_version();
257 fn diagnostics(&self) -> &[(&'
static str, &'
static str)] {
258 &error_codes
::DIAGNOSTICS
261 fn target_features(&self, sess
: &Session
) -> Vec
<Symbol
> {
262 target_features(sess
)
265 fn metadata_loader(&self) -> Box
<dyn MetadataLoader
+ Sync
> {
266 box metadata
::LlvmMetadataLoader
269 fn provide(&self, providers
: &mut ty
::query
::Providers
<'_
>) {
270 rustc_codegen_utils
::symbol_names
::provide(providers
);
271 rustc_codegen_ssa
::back
::symbol_export
::provide(providers
);
272 rustc_codegen_ssa
::base
::provide_both(providers
);
273 attributes
::provide(providers
);
276 fn provide_extern(&self, providers
: &mut ty
::query
::Providers
<'_
>) {
277 rustc_codegen_ssa
::back
::symbol_export
::provide_extern(providers
);
278 rustc_codegen_ssa
::base
::provide_both(providers
);
279 attributes
::provide_extern(providers
);
282 fn codegen_crate
<'tcx
>(
285 metadata
: EncodedMetadata
,
286 need_metadata_module
: bool
,
287 rx
: mpsc
::Receiver
<Box
<dyn Any
+ Send
>>,
289 box rustc_codegen_ssa
::base
::codegen_crate(
290 LlvmCodegenBackend(()), tcx
, metadata
, need_metadata_module
, rx
)
293 fn join_codegen_and_link(
295 ongoing_codegen
: Box
<dyn Any
>,
297 dep_graph
: &DepGraph
,
298 outputs
: &OutputFilenames
,
299 ) -> Result
<(), ErrorReported
> {
300 use rustc
::util
::common
::time
;
301 let (codegen_results
, work_products
) =
302 ongoing_codegen
.downcast
::
303 <rustc_codegen_ssa
::back
::write
::OngoingCodegen
<LlvmCodegenBackend
>>()
304 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
306 if sess
.opts
.debugging_opts
.incremental_info
{
307 rustc_codegen_ssa
::back
::write
::dump_incremental_data(&codegen_results
);
311 "serialize work products",
312 move || rustc_incremental
::save_work_product_index(sess
, &dep_graph
, work_products
));
314 sess
.compile_status()?
;
316 if !sess
.opts
.output_types
.keys().any(|&i
| i
== OutputType
::Exe
||
317 i
== OutputType
::Metadata
) {
321 // Run the linker on any artifacts that resulted from the LLVM run.
322 // This should produce either a finished executable or library.
323 sess
.profiler(|p
| p
.start_activity("link_crate"));
324 time(sess
, "linking", || {
325 use rustc_codegen_ssa
::back
::link
::link_binary
;
326 use crate::back
::archive
::LlvmArchiveBuilder
;
328 let target_cpu
= crate::llvm_util
::target_cpu(sess
);
329 link_binary
::<LlvmArchiveBuilder
<'_
>>(
333 &codegen_results
.crate_name
.as_str(),
337 sess
.profiler(|p
| p
.end_activity("link_crate"));
339 // Now that we won't touch anything in the incremental compilation directory
340 // any more, we can finalize it (which involves renaming it)
341 rustc_incremental
::finalize_session_directory(sess
, codegen_results
.crate_hash
);
347 /// This is the entrypoint for a hot plugged rustc_codegen_llvm
349 pub fn __rustc_codegen_backend() -> Box
<dyn CodegenBackend
> {
350 LlvmCodegenBackend
::new()
353 pub struct ModuleLlvm
{
354 llcx
: &'
static mut llvm
::Context
,
355 llmod_raw
: *const llvm
::Module
,
356 tm
: &'
static mut llvm
::TargetMachine
,
359 unsafe impl Send
for ModuleLlvm { }
360 unsafe impl Sync
for ModuleLlvm { }
363 fn new(tcx
: TyCtxt
<'_
>, mod_name
: &str) -> Self {
365 let llcx
= llvm
::LLVMRustContextCreate(tcx
.sess
.fewer_names());
366 let llmod_raw
= context
::create_module(tcx
, llcx
, mod_name
) as *const _
;
370 tm
: create_target_machine(tcx
, false),
375 fn new_metadata(tcx
: TyCtxt
<'_
>, mod_name
: &str) -> Self {
377 let llcx
= llvm
::LLVMRustContextCreate(tcx
.sess
.fewer_names());
378 let llmod_raw
= context
::create_module(tcx
, llcx
, mod_name
) as *const _
;
382 tm
: create_informational_target_machine(&tcx
.sess
, false),
388 cgcx
: &CodegenContext
<LlvmCodegenBackend
>,
392 ) -> Result
<Self, FatalError
> {
394 let llcx
= llvm
::LLVMRustContextCreate(cgcx
.fewer_names
);
395 let llmod_raw
= back
::lto
::parse_module(llcx
, name
, buffer
, handler
)?
;
396 let tm
= match (cgcx
.tm_factory
.0)() {
399 handler
.struct_err(&e
).emit();
400 return Err(FatalError
)
412 fn llmod(&self) -> &llvm
::Module
{
419 impl Drop
for ModuleLlvm
{
422 llvm
::LLVMContextDispose(&mut *(self.llcx
as *mut _
));
423 llvm
::LLVMRustDisposeTargetMachine(&mut *(self.tm
as *mut _
));