1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use rustc
::session
::{self, config}
;
15 use llvm
::archive_ro
::ArchiveRO
;
16 use llvm
::{ModuleRef, TargetMachineRef, True, False}
;
17 use rustc
::metadata
::cstore
;
18 use rustc
::util
::common
::time
;
19 use back
::write
::{ModuleConfig, with_llvm_pmb}
;
24 use std
::ffi
::CString
;
26 pub fn run(sess
: &session
::Session
, llmod
: ModuleRef
,
27 tm
: TargetMachineRef
, reachable
: &[String
],
28 config
: &ModuleConfig
) {
29 if sess
.opts
.cg
.prefer_dynamic
{
30 sess
.err("cannot prefer dynamic linking when performing LTO");
31 sess
.note("only 'staticlib' and 'bin' outputs are supported with LTO");
32 sess
.abort_if_errors();
35 // Make sure we actually can run LTO
36 for crate_type
in sess
.crate_types
.borrow().iter() {
38 config
::CrateTypeExecutable
| config
::CrateTypeStaticlib
=> {}
40 sess
.fatal("lto can only be run for executables and \
41 static library outputs");
46 // For each of our upstream dependencies, find the corresponding rlib and
47 // load the bitcode from the archive. Then merge it into the current LLVM
48 // module that we've got.
49 let crates
= sess
.cstore
.get_used_crates(cstore
::RequireStatic
);
50 for (cnum
, path
) in crates
{
51 let name
= sess
.cstore
.get_crate_data(cnum
).name
.clone();
52 let path
= match path
{
55 sess
.fatal(&format
!("could not find rlib for: `{}`",
60 let archive
= ArchiveRO
::open(&path
).expect("wanted an rlib");
61 let bytecodes
= archive
.iter().filter_map(|child
| {
62 child
.name().map(|name
| (name
, child
))
63 }).filter(|&(name
, _
)| name
.ends_with("bytecode.deflate"));
64 for (name
, data
) in bytecodes
{
65 let bc_encoded
= data
.data();
67 let bc_decoded
= if is_versioned_bytecode_format(bc_encoded
) {
68 time(sess
.time_passes(), &format
!("decode {}", name
), (), |_
| {
70 let version
= extract_bytecode_format_version(bc_encoded
);
73 // The only version existing so far
74 let data_size
= extract_compressed_bytecode_size_v1(bc_encoded
);
75 let compressed_data
= &bc_encoded
[
76 link
::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
..
77 (link
::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET
+ data_size
as usize)];
79 match flate
::inflate_bytes(compressed_data
) {
80 Ok(inflated
) => inflated
,
82 sess
.fatal(&format
!("failed to decompress bc of `{}`",
87 sess
.fatal(&format
!("Unsupported bytecode format version {}",
92 time(sess
.time_passes(), &format
!("decode {}", name
), (), |_
| {
93 // the object must be in the old, pre-versioning format, so simply
94 // inflate everything and let LLVM decide if it can make sense of it
95 match flate
::inflate_bytes(bc_encoded
) {
98 sess
.fatal(&format
!("failed to decompress bc of `{}`",
105 let ptr
= bc_decoded
.as_ptr();
106 debug
!("linking {}", name
);
107 time(sess
.time_passes(), &format
!("ll link {}", name
), (),
109 if !llvm
::LLVMRustLinkInExternalBitcode(llmod
,
110 ptr
as *const libc
::c_char
,
111 bc_decoded
.len() as libc
::size_t
) {
112 write
::llvm_err(sess
.diagnostic().handler(),
113 format
!("failed to load bc of `{}`",
120 // Internalize everything but the reachable symbols of the current module
121 let cstrs
: Vec
<CString
> = reachable
.iter().map(|s
| {
122 CString
::new(s
.clone()).unwrap()
124 let arr
: Vec
<*const libc
::c_char
> = cstrs
.iter().map(|c
| c
.as_ptr()).collect();
125 let ptr
= arr
.as_ptr();
127 llvm
::LLVMRustRunRestrictionPass(llmod
,
128 ptr
as *const *const libc
::c_char
,
129 arr
.len() as libc
::size_t
);
132 if sess
.no_landing_pads() {
134 llvm
::LLVMRustMarkAllFunctionsNounwind(llmod
);
138 // Now we have one massive module inside of llmod. Time to run the
139 // LTO-specific optimization passes that LLVM provides.
141 // This code is based off the code found in llvm's LTO code generator:
142 // tools/lto/LTOCodeGenerator.cpp
143 debug
!("running the pass manager");
145 let pm
= llvm
::LLVMCreatePassManager();
146 llvm
::LLVMRustAddAnalysisPasses(tm
, pm
, llmod
);
147 llvm
::LLVMRustAddPass(pm
, "verify\0".as_ptr() as *const _
);
149 with_llvm_pmb(llmod
, config
, &mut |b
| {
150 llvm
::LLVMPassManagerBuilderPopulateLTOPassManager(b
, pm
,
151 /* Internalize = */ False
,
152 /* RunInliner = */ True
);
155 llvm
::LLVMRustAddPass(pm
, "verify\0".as_ptr() as *const _
);
157 time(sess
.time_passes(), "LTO passes", (), |()|
158 llvm
::LLVMRunPassManager(pm
, llmod
));
160 llvm
::LLVMDisposePassManager(pm
);
165 fn is_versioned_bytecode_format(bc
: &[u8]) -> bool
{
166 let magic_id_byte_count
= link
::RLIB_BYTECODE_OBJECT_MAGIC
.len();
167 return bc
.len() > magic_id_byte_count
&&
168 &bc
[..magic_id_byte_count
] == link
::RLIB_BYTECODE_OBJECT_MAGIC
;
171 fn extract_bytecode_format_version(bc
: &[u8]) -> u32 {
172 let pos
= link
::RLIB_BYTECODE_OBJECT_VERSION_OFFSET
;
173 let byte_data
= &bc
[pos
..pos
+ 4];
174 let data
= unsafe { *(byte_data.as_ptr() as *const u32) }
;
178 fn extract_compressed_bytecode_size_v1(bc
: &[u8]) -> u64 {
179 let pos
= link
::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET
;
180 let byte_data
= &bc
[pos
..pos
+ 8];
181 let data
= unsafe { *(byte_data.as_ptr() as *const u64) }
;