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;
23 use std::ffi::CString;
28 pub fn run(sess: &session::Session, llmod: ModuleRef,
29 tm: TargetMachineRef, reachable: &[String]) {
30 if sess.opts.cg.prefer_dynamic {
31 sess.err("cannot prefer dynamic linking when performing LTO");
32 sess.note("only 'staticlib' and 'bin' outputs are supported with LTO");
33 sess.abort_if_errors();
36 // Make sure we actually can run LTO
37 for crate_type in &*sess.crate_types.borrow() {
39 config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
41 sess.fatal("lto can only be run for executables and \
42 static library outputs");
47 // For each of our upstream dependencies, find the corresponding rlib and
48 // load the bitcode from the archive. Then merge it into the current LLVM
49 // module that we've got.
50 let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
51 for (cnum, path) in crates {
52 let name = sess.cstore.get_crate_data(cnum).name.clone();
53 let path = match path {
56 sess.fatal(&format!("could not find rlib for: `{}`",
61 let archive = ArchiveRO::open(&path).expect("wanted an rlib");
62 let file = path.filename_str().unwrap();
63 let file = &file[3..file.len() - 5]; // chop off lib/.rlib
64 debug!("reading {}", file);
65 for i in iter::count(0, 1) {
66 let bc_encoded = time(sess.time_passes(),
67 &format!("check for {}.{}.bytecode.deflate", name, i),
70 archive.read(&format!("{}.{}.bytecode.deflate",
73 let bc_encoded = match bc_encoded {
77 // No bitcode was found at all.
78 sess.fatal(&format!("missing compressed bytecode in {}",
81 // No more bitcode files to read.
86 let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
87 time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
89 let version = extract_bytecode_format_version(bc_encoded);
92 // The only version existing so far
93 let data_size = extract_compressed_bytecode_size_v1(bc_encoded);
94 let compressed_data = &bc_encoded[
95 link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET..
96 (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as uint)];
98 match flate::inflate_bytes(compressed_data) {
99 Some(inflated) => inflated,
101 sess.fatal(&format!("failed to decompress bc of `{}`",
106 sess.fatal(&format!("Unsupported bytecode format version {}",
111 time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
112 // the object must be in the old, pre-versioning format, so simply
113 // inflate everything and let LLVM decide if it can make sense of it
114 match flate::inflate_bytes(bc_encoded) {
117 sess.fatal(&format!("failed to decompress bc of `{}`",
124 let ptr = bc_decoded.as_ptr();
125 debug!("linking {}, part {}", name, i);
126 time(sess.time_passes(),
127 &format!("ll link {}.{}", name, i)[],
130 if !llvm::LLVMRustLinkInExternalBitcode(llmod,
131 ptr as *const libc::c_char,
132 bc_decoded.len() as libc::size_t) {
133 write::llvm_err(sess.diagnostic().handler(),
134 format!("failed to load bc of `{}`",
141 // Internalize everything but the reachable symbols of the current module
142 let cstrs: Vec<CString> = reachable.iter().map(|s| {
143 CString::from_slice(s.as_bytes())
145 let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
146 let ptr = arr.as_ptr();
148 llvm::LLVMRustRunRestrictionPass(llmod,
149 ptr as *const *const libc::c_char,
150 arr.len() as libc::size_t);
153 if sess.no_landing_pads() {
155 llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
159 // Now we have one massive module inside of llmod. Time to run the
160 // LTO-specific optimization passes that LLVM provides.
162 // This code is based off the code found in llvm's LTO code generator:
163 // tools/lto/LTOCodeGenerator.cpp
164 debug!("running the pass manager");
166 let pm = llvm::LLVMCreatePassManager();
167 llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
168 llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
170 let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;
172 let builder = llvm::LLVMPassManagerBuilderCreate();
173 llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
174 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
175 /* Internalize = */ False,
176 /* RunInliner = */ True);
177 llvm::LLVMPassManagerBuilderDispose(builder);
179 llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
181 time(sess.time_passes(), "LTO passes", (), |()|
182 llvm::LLVMRunPassManager(pm, llmod));
184 llvm::LLVMDisposePassManager(pm);
189 fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
190 let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
191 return bc.len() > magic_id_byte_count &&
192 &bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
195 fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
196 return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
199 fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
200 return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
203 fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: uint) -> T {
204 let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::<T>()];
206 *(byte_data.as_ptr() as *const T)