5 //! This API is completely unstable and subject to change.
7 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
8 #![feature(bool_to_option)]
9 #![feature(const_cstr_unchecked)]
10 #![feature(crate_visibility_modifier)]
11 #![feature(extern_types)]
12 #![feature(in_band_lifetimes)]
14 #![feature(trusted_len)]
15 #![recursion_limit = "256"]
17 use back
::write
::{create_informational_target_machine, create_target_machine}
;
18 use rustc_span
::symbol
::Symbol
;
20 pub use llvm_util
::target_features
;
21 use rustc
::dep_graph
::WorkProduct
;
22 use rustc_ast
::expand
::allocator
::AllocatorKind
;
23 use rustc_codegen_ssa
::back
::lto
::{LtoModuleCodegen, SerializedModule, ThinModule}
;
24 use rustc_codegen_ssa
::back
::write
::{CodegenContext, FatLTOInput, ModuleConfig}
;
25 use rustc_codegen_ssa
::traits
::*;
26 use rustc_codegen_ssa
::{CodegenResults, CompiledModule}
;
27 use rustc_errors
::{FatalError, Handler}
;
33 use rustc
::dep_graph
::DepGraph
;
34 use rustc
::middle
::cstore
::{EncodedMetadata, MetadataLoaderDyn}
;
35 use rustc
::session
::config
::{self, OptLevel, OutputFilenames, PrintRequest}
;
36 use rustc
::session
::Session
;
37 use rustc
::ty
::{self, TyCtxt}
;
38 use rustc
::util
::common
::ErrorReported
;
39 use rustc_codegen_ssa
::ModuleCodegen
;
40 use rustc_codegen_utils
::codegen_backend
::CodegenBackend
;
41 use rustc_serialize
::json
;
65 // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
66 #[path = "llvm/mod.rs"]
69 pub use super::llvm_
::*;
81 pub struct LlvmCodegenBackend(());
83 impl ExtraBackendMethods
for LlvmCodegenBackend
{
84 fn new_metadata(&self, tcx
: TyCtxt
<'_
>, mod_name
: &str) -> ModuleLlvm
{
85 ModuleLlvm
::new_metadata(tcx
, mod_name
)
88 fn write_compressed_metadata
<'tcx
>(
91 metadata
: &EncodedMetadata
,
92 llvm_module
: &mut ModuleLlvm
,
94 base
::write_compressed_metadata(tcx
, metadata
, llvm_module
)
96 fn codegen_allocator
<'tcx
>(
99 mods
: &mut ModuleLlvm
,
102 unsafe { allocator::codegen(tcx, mods, kind) }
104 fn compile_codegen_unit(
108 ) -> (ModuleCodegen
<ModuleLlvm
>, u64) {
109 base
::compile_codegen_unit(tcx
, cgu_name
)
111 fn target_machine_factory(
116 ) -> Arc
<dyn Fn() -> Result
<&'
static mut llvm
::TargetMachine
, String
> + Send
+ Sync
> {
117 back
::write
::target_machine_factory(sess
, optlvl
, find_features
)
119 fn target_cpu
<'b
>(&self, sess
: &'b Session
) -> &'b
str {
120 llvm_util
::target_cpu(sess
)
124 impl WriteBackendMethods
for LlvmCodegenBackend
{
125 type Module
= ModuleLlvm
;
126 type ModuleBuffer
= back
::lto
::ModuleBuffer
;
127 type Context
= llvm
::Context
;
128 type TargetMachine
= &'
static mut llvm
::TargetMachine
;
129 type ThinData
= back
::lto
::ThinData
;
130 type ThinBuffer
= back
::lto
::ThinBuffer
;
131 fn print_pass_timings(&self) {
133 llvm
::LLVMRustPrintPassTimings();
137 cgcx
: &CodegenContext
<Self>,
138 modules
: Vec
<FatLTOInput
<Self>>,
139 cached_modules
: Vec
<(SerializedModule
<Self::ModuleBuffer
>, WorkProduct
)>,
140 ) -> Result
<LtoModuleCodegen
<Self>, FatalError
> {
141 back
::lto
::run_fat(cgcx
, modules
, cached_modules
)
144 cgcx
: &CodegenContext
<Self>,
145 modules
: Vec
<(String
, Self::ThinBuffer
)>,
146 cached_modules
: Vec
<(SerializedModule
<Self::ModuleBuffer
>, WorkProduct
)>,
147 ) -> Result
<(Vec
<LtoModuleCodegen
<Self>>, Vec
<WorkProduct
>), FatalError
> {
148 back
::lto
::run_thin(cgcx
, modules
, cached_modules
)
151 cgcx
: &CodegenContext
<Self>,
152 diag_handler
: &Handler
,
153 module
: &ModuleCodegen
<Self::Module
>,
154 config
: &ModuleConfig
,
155 ) -> Result
<(), FatalError
> {
156 back
::write
::optimize(cgcx
, diag_handler
, module
, config
)
158 unsafe fn optimize_thin(
159 cgcx
: &CodegenContext
<Self>,
160 thin
: &mut ThinModule
<Self>,
161 ) -> Result
<ModuleCodegen
<Self::Module
>, FatalError
> {
162 back
::lto
::optimize_thin_module(thin
, cgcx
)
165 cgcx
: &CodegenContext
<Self>,
166 diag_handler
: &Handler
,
167 module
: ModuleCodegen
<Self::Module
>,
168 config
: &ModuleConfig
,
169 ) -> Result
<CompiledModule
, FatalError
> {
170 back
::write
::codegen(cgcx
, diag_handler
, module
, config
)
172 fn prepare_thin(module
: ModuleCodegen
<Self::Module
>) -> (String
, Self::ThinBuffer
) {
173 back
::lto
::prepare_thin(module
)
175 fn serialize_module(module
: ModuleCodegen
<Self::Module
>) -> (String
, Self::ModuleBuffer
) {
176 (module
.name
, back
::lto
::ModuleBuffer
::new(module
.module_llvm
.llmod()))
178 fn run_lto_pass_manager(
179 cgcx
: &CodegenContext
<Self>,
180 module
: &ModuleCodegen
<Self::Module
>,
181 config
: &ModuleConfig
,
184 back
::lto
::run_pass_manager(cgcx
, module
, config
, thin
)
188 unsafe impl Send
for LlvmCodegenBackend {}
// Llvm is on a per-thread basis
189 unsafe impl Sync
for LlvmCodegenBackend {}
191 impl LlvmCodegenBackend
{
192 pub fn new() -> Box
<dyn CodegenBackend
> {
193 Box
::new(LlvmCodegenBackend(()))
197 impl CodegenBackend
for LlvmCodegenBackend
{
198 fn init(&self, sess
: &Session
) {
199 llvm_util
::init(sess
); // Make sure llvm is inited
202 fn print(&self, req
: PrintRequest
, sess
: &Session
) {
204 PrintRequest
::RelocationModels
=> {
205 println
!("Available relocation models:");
206 for &(name
, _
) in back
::write
::RELOC_MODEL_ARGS
.iter() {
207 println
!(" {}", name
);
211 PrintRequest
::CodeModels
=> {
212 println
!("Available code models:");
213 for &(name
, _
) in back
::write
::CODE_GEN_MODEL_ARGS
.iter() {
214 println
!(" {}", name
);
218 PrintRequest
::TlsModels
=> {
219 println
!("Available TLS models:");
220 for &(name
, _
) in back
::write
::TLS_MODEL_ARGS
.iter() {
221 println
!(" {}", name
);
225 req
=> llvm_util
::print(req
, sess
),
229 fn print_passes(&self) {
230 llvm_util
::print_passes();
233 fn print_version(&self) {
234 llvm_util
::print_version();
237 fn target_features(&self, sess
: &Session
) -> Vec
<Symbol
> {
238 target_features(sess
)
241 fn metadata_loader(&self) -> Box
<MetadataLoaderDyn
> {
242 Box
::new(metadata
::LlvmMetadataLoader
)
245 fn provide(&self, providers
: &mut ty
::query
::Providers
<'_
>) {
246 attributes
::provide(providers
);
249 fn provide_extern(&self, providers
: &mut ty
::query
::Providers
<'_
>) {
250 attributes
::provide_extern(providers
);
253 fn codegen_crate
<'tcx
>(
256 metadata
: EncodedMetadata
,
257 need_metadata_module
: bool
,
259 Box
::new(rustc_codegen_ssa
::base
::codegen_crate(
260 LlvmCodegenBackend(()),
263 need_metadata_module
,
269 ongoing_codegen
: Box
<dyn Any
>,
271 dep_graph
: &DepGraph
,
272 ) -> Result
<Box
<dyn Any
>, ErrorReported
> {
273 let (codegen_results
, work_products
) = ongoing_codegen
274 .downcast
::<rustc_codegen_ssa
::back
::write
::OngoingCodegen
<LlvmCodegenBackend
>>()
275 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
277 if sess
.opts
.debugging_opts
.incremental_info
{
278 rustc_codegen_ssa
::back
::write
::dump_incremental_data(&codegen_results
);
281 sess
.time("serialize_work_products", move || {
282 rustc_incremental
::save_work_product_index(sess
, &dep_graph
, work_products
)
285 sess
.compile_status()?
;
287 Ok(Box
::new(codegen_results
))
293 codegen_results
: Box
<dyn Any
>,
294 outputs
: &OutputFilenames
,
295 ) -> Result
<(), ErrorReported
> {
296 let codegen_results
= codegen_results
297 .downcast
::<CodegenResults
>()
298 .expect("Expected CodegenResults, found Box<Any>");
300 if sess
.opts
.debugging_opts
.no_link
{
301 // FIXME: use a binary format to encode the `.rlink` file
302 let rlink_data
= json
::encode(&codegen_results
).map_err(|err
| {
303 sess
.fatal(&format
!("failed to encode rlink: {}", err
));
305 let rlink_file
= outputs
.with_extension(config
::RLINK_EXT
);
306 fs
::write(&rlink_file
, rlink_data
).map_err(|err
| {
307 sess
.fatal(&format
!("failed to write file {}: {}", rlink_file
.display(), err
));
312 // Run the linker on any artifacts that resulted from the LLVM run.
313 // This should produce either a finished executable or library.
314 sess
.time("link_crate", || {
315 use crate::back
::archive
::LlvmArchiveBuilder
;
316 use rustc_codegen_ssa
::back
::link
::link_binary
;
318 let target_cpu
= crate::llvm_util
::target_cpu(sess
);
319 link_binary
::<LlvmArchiveBuilder
<'_
>>(
323 &codegen_results
.crate_name
.as_str(),
328 // Now that we won't touch anything in the incremental compilation directory
329 // any more, we can finalize it (which involves renaming it)
330 rustc_incremental
::finalize_session_directory(sess
, codegen_results
.crate_hash
);
332 sess
.time("llvm_dump_timing_file", || {
333 if sess
.opts
.debugging_opts
.llvm_time_trace
{
334 llvm_util
::time_trace_profiler_finish("llvm_timings.json");
342 pub struct ModuleLlvm
{
343 llcx
: &'
static mut llvm
::Context
,
344 llmod_raw
: *const llvm
::Module
,
345 tm
: &'
static mut llvm
::TargetMachine
,
348 unsafe impl Send
for ModuleLlvm {}
349 unsafe impl Sync
for ModuleLlvm {}
352 fn new(tcx
: TyCtxt
<'_
>, mod_name
: &str) -> Self {
354 let llcx
= llvm
::LLVMRustContextCreate(tcx
.sess
.fewer_names());
355 let llmod_raw
= context
::create_module(tcx
, llcx
, mod_name
) as *const _
;
356 ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, false) }
360 fn new_metadata(tcx
: TyCtxt
<'_
>, mod_name
: &str) -> Self {
362 let llcx
= llvm
::LLVMRustContextCreate(tcx
.sess
.fewer_names());
363 let llmod_raw
= context
::create_module(tcx
, llcx
, mod_name
) as *const _
;
367 tm
: create_informational_target_machine(&tcx
.sess
, false),
373 cgcx
: &CodegenContext
<LlvmCodegenBackend
>,
377 ) -> Result
<Self, FatalError
> {
379 let llcx
= llvm
::LLVMRustContextCreate(cgcx
.fewer_names
);
380 let llmod_raw
= back
::lto
::parse_module(llcx
, name
, buffer
, handler
)?
;
381 let tm
= match (cgcx
.tm_factory
.0)() {
384 handler
.struct_err(&e
).emit();
385 return Err(FatalError
);
389 Ok(ModuleLlvm { llmod_raw, llcx, tm }
)
393 fn llmod(&self) -> &llvm
::Module
{
394 unsafe { &*self.llmod_raw }
398 impl Drop
for ModuleLlvm
{
401 llvm
::LLVMContextDispose(&mut *(self.llcx
as *mut _
));
402 llvm
::LLVMRustDisposeTargetMachine(&mut *(self.tm
as *mut _
));