]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/back/lto.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / librustc_trans / back / lto.rs
CommitLineData
1a4d82fc
JJ
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.
4//
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.
10
11use super::link;
12use super::write;
13use rustc::session::{self, config};
14use llvm;
15use llvm::archive_ro::ArchiveRO;
16use llvm::{ModuleRef, TargetMachineRef, True, False};
1a4d82fc 17use rustc::util::common::time;
b039eaaf 18use rustc::util::common::path2cstr;
c1a9b12d 19use back::write::{ModuleConfig, with_llvm_pmb};
1a4d82fc
JJ
20
21use libc;
22use flate;
23
24use std::ffi::CString;
5bcae85e 25use std::path::Path;
1a4d82fc
JJ
26
27pub fn run(sess: &session::Session, llmod: ModuleRef,
c1a9b12d 28 tm: TargetMachineRef, reachable: &[String],
b039eaaf 29 config: &ModuleConfig,
5bcae85e 30 temp_no_opt_bc_filename: &Path) {
1a4d82fc 31 if sess.opts.cg.prefer_dynamic {
9cc50fc6 32 sess.struct_err("cannot prefer dynamic linking when performing LTO")
a7813a04
XL
33 .note("only 'staticlib', 'bin', and 'cdylib' outputs are \
34 supported with LTO")
9cc50fc6 35 .emit();
1a4d82fc
JJ
36 sess.abort_if_errors();
37 }
38
39 // Make sure we actually can run LTO
62682a34 40 for crate_type in sess.crate_types.borrow().iter() {
1a4d82fc 41 match *crate_type {
a7813a04
XL
42 config::CrateTypeExecutable |
43 config::CrateTypeCdylib |
44 config::CrateTypeStaticlib => {}
1a4d82fc
JJ
45 _ => {
46 sess.fatal("lto can only be run for executables and \
47 static library outputs");
48 }
49 }
50 }
51
52 // For each of our upstream dependencies, find the corresponding rlib and
53 // load the bitcode from the archive. Then merge it into the current LLVM
54 // module that we've got.
9e0c209e
SL
55 link::each_linked_rlib(sess, &mut |cnum, path| {
56 // `#![no_builtins]` crates don't participate in LTO.
57 if sess.cstore.is_no_builtins(cnum) {
58 return;
59 }
60
1a4d82fc 61 let archive = ArchiveRO::open(&path).expect("wanted an rlib");
c1a9b12d 62 let bytecodes = archive.iter().filter_map(|child| {
7453a54e 63 child.ok().and_then(|c| c.name().map(|name| (name, c)))
c1a9b12d
SL
64 }).filter(|&(name, _)| name.ends_with("bytecode.deflate"));
65 for (name, data) in bytecodes {
66 let bc_encoded = data.data();
1a4d82fc
JJ
67
68 let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
e9174d1e 69 time(sess.time_passes(), &format!("decode {}", name), || {
1a4d82fc
JJ
70 // Read the version
71 let version = extract_bytecode_format_version(bc_encoded);
72
73 if version == 1 {
74 // The only version existing so far
75 let data_size = extract_compressed_bytecode_size_v1(bc_encoded);
76 let compressed_data = &bc_encoded[
77 link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET..
c34b1796 78 (link::RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET + data_size as usize)];
1a4d82fc
JJ
79
80 match flate::inflate_bytes(compressed_data) {
c34b1796
AL
81 Ok(inflated) => inflated,
82 Err(_) => {
1a4d82fc 83 sess.fatal(&format!("failed to decompress bc of `{}`",
c34b1796 84 name))
1a4d82fc
JJ
85 }
86 }
87 } else {
88 sess.fatal(&format!("Unsupported bytecode format version {}",
c34b1796 89 version))
1a4d82fc
JJ
90 }
91 })
92 } else {
e9174d1e
SL
93 time(sess.time_passes(), &format!("decode {}", name), || {
94 // the object must be in the old, pre-versioning format, so
95 // simply inflate everything and let LLVM decide if it can
96 // make sense of it
1a4d82fc 97 match flate::inflate_bytes(bc_encoded) {
c34b1796
AL
98 Ok(bc) => bc,
99 Err(_) => {
1a4d82fc 100 sess.fatal(&format!("failed to decompress bc of `{}`",
c34b1796 101 name))
1a4d82fc
JJ
102 }
103 }
104 })
105 };
106
85aaf69f 107 let ptr = bc_decoded.as_ptr();
c1a9b12d 108 debug!("linking {}", name);
e9174d1e 109 time(sess.time_passes(), &format!("ll link {}", name), || unsafe {
1a4d82fc
JJ
110 if !llvm::LLVMRustLinkInExternalBitcode(llmod,
111 ptr as *const libc::c_char,
112 bc_decoded.len() as libc::size_t) {
9cc50fc6 113 write::llvm_err(sess.diagnostic(),
1a4d82fc 114 format!("failed to load bc of `{}`",
85aaf69f 115 &name[..]));
1a4d82fc
JJ
116 }
117 });
118 }
e9174d1e 119 });
1a4d82fc
JJ
120
121 // Internalize everything but the reachable symbols of the current module
122 let cstrs: Vec<CString> = reachable.iter().map(|s| {
85aaf69f 123 CString::new(s.clone()).unwrap()
1a4d82fc
JJ
124 }).collect();
125 let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
126 let ptr = arr.as_ptr();
127 unsafe {
128 llvm::LLVMRustRunRestrictionPass(llmod,
129 ptr as *const *const libc::c_char,
130 arr.len() as libc::size_t);
131 }
132
133 if sess.no_landing_pads() {
134 unsafe {
135 llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
136 }
137 }
138
b039eaaf 139 if sess.opts.cg.save_temps {
5bcae85e 140 let cstr = path2cstr(temp_no_opt_bc_filename);
b039eaaf
SL
141 unsafe {
142 llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
143 }
144 }
145
1a4d82fc
JJ
146 // Now we have one massive module inside of llmod. Time to run the
147 // LTO-specific optimization passes that LLVM provides.
148 //
149 // This code is based off the code found in llvm's LTO code generator:
150 // tools/lto/LTOCodeGenerator.cpp
151 debug!("running the pass manager");
152 unsafe {
153 let pm = llvm::LLVMCreatePassManager();
154 llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
7453a54e
SL
155 let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
156 assert!(!pass.is_null());
157 llvm::LLVMRustAddPass(pm, pass);
1a4d82fc 158
c1a9b12d
SL
159 with_llvm_pmb(llmod, config, &mut |b| {
160 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm,
161 /* Internalize = */ False,
162 /* RunInliner = */ True);
163 });
1a4d82fc 164
7453a54e
SL
165 let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _);
166 assert!(!pass.is_null());
167 llvm::LLVMRustAddPass(pm, pass);
1a4d82fc 168
e9174d1e 169 time(sess.time_passes(), "LTO passes", ||
1a4d82fc
JJ
170 llvm::LLVMRunPassManager(pm, llmod));
171
172 llvm::LLVMDisposePassManager(pm);
173 }
174 debug!("lto done");
175}
176
177fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
178 let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
179 return bc.len() > magic_id_byte_count &&
85aaf69f 180 &bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
1a4d82fc
JJ
181}
182
183fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
9346a6ac
AL
184 let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET;
185 let byte_data = &bc[pos..pos + 4];
186 let data = unsafe { *(byte_data.as_ptr() as *const u32) };
187 u32::from_le(data)
1a4d82fc
JJ
188}
189
190fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
9346a6ac
AL
191 let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET;
192 let byte_data = &bc[pos..pos + 8];
193 let data = unsafe { *(byte_data.as_ptr() as *const u64) };
194 u64::from_le(data)
1a4d82fc 195}