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::util::common::time;
18 use rustc::util::common::path2cstr;
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,
30 output_names: &config::OutputFilenames) {
31 if sess.opts.cg.prefer_dynamic {
32 sess.struct_err("cannot prefer dynamic linking when performing LTO")
33 .note("only 'staticlib' and 'bin' outputs are supported with LTO")
35 sess.abort_if_errors();
38 // Make sure we actually can run LTO
39 for crate_type in sess.crate_types.borrow().iter() {
41 config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
43 sess.fatal("lto can only be run for executables and \
44 static library outputs");
49 // For each of our upstream dependencies, find the corresponding rlib and
50 // load the bitcode from the archive. Then merge it into the current LLVM
51 // module that we've got.
52 link::each_linked_rlib(sess, &mut |_, path| {
53 let archive = ArchiveRO::open(&path).expect("wanted an rlib");
54 let bytecodes = archive.iter().filter_map(|child| {
55 child.name().map(|name| (name, child))
56 }).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
57 for (name, data) in bytecodes {
58 let bc_encoded = data.data();
60 let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
61 time(sess.time_passes(), &format!("decode {}", name), || {
63 let version = extract_bytecode_format_version(bc_encoded);
66 // The only version existing so far
67 let data_size = extract_compressed_bytecode_size_v1(bc_encoded);
68 let compressed_data = &bc_encoded[
69 link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET..
70 (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as usize)];
72 match flate::inflate_bytes(compressed_data) {
73 Ok(inflated) => inflated,
75 sess.fatal(&format!("failed to decompress bc of `{}`",
80 sess.fatal(&format!("Unsupported bytecode format version {}",
85 time(sess.time_passes(), &format!("decode {}", name), || {
86 // the object must be in the old, pre-versioning format, so
87 // simply inflate everything and let LLVM decide if it can
89 match flate::inflate_bytes(bc_encoded) {
92 sess.fatal(&format!("failed to decompress bc of `{}`",
99 let ptr = bc_decoded.as_ptr();
100 debug!("linking {}", name);
101 time(sess.time_passes(), &format!("ll link {}", name), || unsafe {
102 if !llvm::LLVMRustLinkInExternalBitcode(llmod,
103 ptr as *const libc::c_char,
104 bc_decoded.len() as libc::size_t) {
105 write::llvm_err(sess.diagnostic(),
106 format!("failed to load bc of `{}`",
113 // Internalize everything but the reachable symbols of the current module
114 let cstrs: Vec<CString> = reachable.iter().map(|s| {
115 CString::new(s.clone()).unwrap()
117 let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
118 let ptr = arr.as_ptr();
120 llvm::LLVMRustRunRestrictionPass(llmod,
121 ptr as *const *const libc::c_char,
122 arr.len() as libc::size_t);
125 if sess.no_landing_pads() {
127 llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
131 if sess.opts.cg.save_temps {
132 let path = output_names.with_extension(&format!("{}.no-opt.lto.bc", name_extra));
133 let cstr = path2cstr(&path);
135 llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
139 // Now we have one massive module inside of llmod. Time to run the
140 // LTO-specific optimization passes that LLVM provides.
142 // This code is based off the code found in llvm's LTO code generator:
143 // tools/lto/LTOCodeGenerator.cpp
144 debug!("running the pass manager");
146 let pm = llvm::LLVMCreatePassManager();
147 llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
148 llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
150 with_llvm_pmb(llmod, config, &mut |b| {
151 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm,
152 /* Internalize = */ False,
153 /* RunInliner = */ True);
156 llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
158 time(sess.time_passes(), "LTO passes", ||
159 llvm::LLVMRunPassManager(pm, llmod));
161 llvm::LLVMDisposePassManager(pm);
166 fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
167 let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
168 return bc.len() > magic_id_byte_count &&
169 &bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
172 fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
173 let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET;
174 let byte_data = &bc[pos..pos + 4];
175 let data = unsafe { *(byte_data.as_ptr() as *const u32) };
179 fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
180 let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET;
181 let byte_data = &bc[pos..pos + 8];
182 let data = unsafe { *(byte_data.as_ptr() as *const u64) };