10
10
11
11
use back:: link;
12
12
use back:: write;
13
- use back:: symbol_export:: { self , ExportedSymbols } ;
14
- use rustc:: session:: { self , config} ;
13
+ use back:: symbol_export;
14
+ use rustc:: session:: config;
15
+ use errors:: FatalError ;
15
16
use llvm;
16
17
use llvm:: archive_ro:: ArchiveRO ;
17
18
use llvm:: { ModuleRef , TargetMachineRef , True , False } ;
18
19
use rustc:: util:: common:: time;
19
20
use rustc:: util:: common:: path2cstr;
20
21
use rustc:: hir:: def_id:: LOCAL_CRATE ;
21
- use back:: write:: { ModuleConfig , with_llvm_pmb} ;
22
+ use back:: write:: { ModuleConfig , with_llvm_pmb, CodegenContext } ;
22
23
23
24
use libc;
24
25
use flate2:: read:: ZlibDecoder ;
@@ -39,30 +40,31 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
39
40
}
40
41
}
41
42
42
- pub fn run ( sess : & session :: Session ,
43
+ pub fn run ( cgcx : & CodegenContext ,
43
44
llmod : ModuleRef ,
44
45
tm : TargetMachineRef ,
45
- exported_symbols : & ExportedSymbols ,
46
46
config : & ModuleConfig ,
47
- temp_no_opt_bc_filename : & Path ) {
48
- if sess. opts . cg . prefer_dynamic {
49
- sess. struct_err ( "cannot prefer dynamic linking when performing LTO" )
47
+ temp_no_opt_bc_filename : & Path ) -> Result < ( ) , FatalError > {
48
+ let handler = cgcx. handler ;
49
+ if cgcx. opts . cg . prefer_dynamic {
50
+ handler. struct_err ( "cannot prefer dynamic linking when performing LTO" )
50
51
. note ( "only 'staticlib', 'bin', and 'cdylib' outputs are \
51
52
supported with LTO")
52
53
. emit ( ) ;
53
- sess . abort_if_errors ( ) ;
54
+ return Err ( FatalError )
54
55
}
55
56
56
57
// Make sure we actually can run LTO
57
- for crate_type in sess . crate_types . borrow ( ) . iter ( ) {
58
+ for crate_type in cgcx . crate_types . iter ( ) {
58
59
if !crate_type_allows_lto ( * crate_type) {
59
- sess. fatal ( "lto can only be run for executables, cdylibs and \
60
- static library outputs") ;
60
+ let e = handler. fatal ( "lto can only be run for executables, cdylibs and \
61
+ static library outputs") ;
62
+ return Err ( e)
61
63
}
62
64
}
63
65
64
66
let export_threshold =
65
- symbol_export:: crates_export_threshold ( & sess . crate_types . borrow ( ) ) ;
67
+ symbol_export:: crates_export_threshold ( & cgcx . crate_types ) ;
66
68
67
69
let symbol_filter = & |& ( ref name, level) : & ( String , _ ) | {
68
70
if symbol_export:: is_below_threshold ( level, export_threshold) {
@@ -74,7 +76,7 @@ pub fn run(sess: &session::Session,
74
76
}
75
77
} ;
76
78
77
- let mut symbol_white_list: Vec < CString > = exported_symbols
79
+ let mut symbol_white_list: Vec < CString > = cgcx . exported_symbols
78
80
. exported_symbols ( LOCAL_CRATE )
79
81
. iter ( )
80
82
. filter_map ( symbol_filter)
@@ -83,16 +85,11 @@ pub fn run(sess: &session::Session,
83
85
// For each of our upstream dependencies, find the corresponding rlib and
84
86
// load the bitcode from the archive. Then merge it into the current LLVM
85
87
// module that we've got.
86
- link:: each_linked_rlib ( sess, & mut |cnum, path| {
87
- // `#![no_builtins]` crates don't participate in LTO.
88
- if sess. cstore . is_no_builtins ( cnum) {
89
- return ;
90
- }
91
-
88
+ for & ( cnum, ref path) in cgcx. each_linked_rlib_for_lto . iter ( ) {
92
89
symbol_white_list. extend (
93
- exported_symbols. exported_symbols ( cnum)
94
- . iter ( )
95
- . filter_map ( symbol_filter) ) ;
90
+ cgcx . exported_symbols . exported_symbols ( cnum)
91
+ . iter ( )
92
+ . filter_map ( symbol_filter) ) ;
96
93
97
94
let archive = ArchiveRO :: open ( & path) . expect ( "wanted an rlib" ) ;
98
95
let bytecodes = archive. iter ( ) . filter_map ( |child| {
@@ -102,7 +99,7 @@ pub fn run(sess: &session::Session,
102
99
let bc_encoded = data. data ( ) ;
103
100
104
101
let bc_decoded = if is_versioned_bytecode_format ( bc_encoded) {
105
- time ( sess . time_passes ( ) , & format ! ( "decode {}" , name) , || {
102
+ time ( cgcx . time_passes , & format ! ( "decode {}" , name) , || {
106
103
// Read the version
107
104
let version = extract_bytecode_format_version ( bc_encoded) ;
108
105
@@ -117,44 +114,49 @@ pub fn run(sess: &session::Session,
117
114
let res = ZlibDecoder :: new ( compressed_data)
118
115
. read_to_end ( & mut inflated) ;
119
116
if res. is_err ( ) {
120
- sess. fatal ( & format ! ( "failed to decompress bc of `{}`" ,
121
- name) )
117
+ let msg = format ! ( "failed to decompress bc of `{}`" ,
118
+ name) ;
119
+ Err ( handler. fatal ( & msg) )
120
+ } else {
121
+ Ok ( inflated)
122
122
}
123
- inflated
124
123
} else {
125
- sess . fatal ( & format ! ( "Unsupported bytecode format version {}" ,
126
- version) )
124
+ Err ( handler . fatal ( & format ! ( "Unsupported bytecode format version {}" ,
125
+ version) ) )
127
126
}
128
- } )
127
+ } ) ?
129
128
} else {
130
- time ( sess . time_passes ( ) , & format ! ( "decode {}" , name) , || {
129
+ time ( cgcx . time_passes , & format ! ( "decode {}" , name) , || {
131
130
// the object must be in the old, pre-versioning format, so
132
131
// simply inflate everything and let LLVM decide if it can
133
132
// make sense of it
134
133
let mut inflated = Vec :: new ( ) ;
135
134
let res = ZlibDecoder :: new ( bc_encoded)
136
135
. read_to_end ( & mut inflated) ;
137
136
if res. is_err ( ) {
138
- sess. fatal ( & format ! ( "failed to decompress bc of `{}`" ,
139
- name) )
137
+ let msg = format ! ( "failed to decompress bc of `{}`" ,
138
+ name) ;
139
+ Err ( handler. fatal ( & msg) )
140
+ } else {
141
+ Ok ( inflated)
140
142
}
141
- inflated
142
- } )
143
+ } ) ?
143
144
} ;
144
145
145
146
let ptr = bc_decoded. as_ptr ( ) ;
146
147
debug ! ( "linking {}" , name) ;
147
- time ( sess. time_passes ( ) , & format ! ( "ll link {}" , name) , || unsafe {
148
- if !llvm:: LLVMRustLinkInExternalBitcode ( llmod,
149
- ptr as * const libc:: c_char ,
150
- bc_decoded. len ( ) as libc:: size_t ) {
151
- write:: llvm_err ( sess. diagnostic ( ) ,
152
- format ! ( "failed to load bc of `{}`" ,
153
- name) ) ;
148
+ time ( cgcx. time_passes , & format ! ( "ll link {}" , name) , || unsafe {
149
+ if llvm:: LLVMRustLinkInExternalBitcode ( llmod,
150
+ ptr as * const libc:: c_char ,
151
+ bc_decoded. len ( ) as libc:: size_t ) {
152
+ Ok ( ( ) )
153
+ } else {
154
+ let msg = format ! ( "failed to load bc of `{}`" , name) ;
155
+ Err ( write:: llvm_err ( handler, msg) )
154
156
}
155
- } ) ;
157
+ } ) ? ;
156
158
}
157
- } ) ;
159
+ }
158
160
159
161
// Internalize everything but the exported symbols of the current module
160
162
let arr: Vec < * const libc:: c_char > = symbol_white_list. iter ( )
@@ -167,13 +169,13 @@ pub fn run(sess: &session::Session,
167
169
arr. len ( ) as libc:: size_t ) ;
168
170
}
169
171
170
- if sess . no_landing_pads ( ) {
172
+ if cgcx . no_landing_pads {
171
173
unsafe {
172
174
llvm:: LLVMRustMarkAllFunctionsNounwind ( llmod) ;
173
175
}
174
176
}
175
177
176
- if sess . opts . cg . save_temps {
178
+ if cgcx . opts . cg . save_temps {
177
179
let cstr = path2cstr ( temp_no_opt_bc_filename) ;
178
180
unsafe {
179
181
llvm:: LLVMWriteBitcodeToFile ( llmod, cstr. as_ptr ( ) ) ;
@@ -203,12 +205,13 @@ pub fn run(sess: &session::Session,
203
205
assert ! ( !pass. is_null( ) ) ;
204
206
llvm:: LLVMRustAddPass ( pm, pass) ;
205
207
206
- time ( sess . time_passes ( ) , "LTO passes" , ||
208
+ time ( cgcx . time_passes , "LTO passes" , ||
207
209
llvm:: LLVMRunPassManager ( pm, llmod) ) ;
208
210
209
211
llvm:: LLVMDisposePassManager ( pm) ;
210
212
}
211
213
debug ! ( "lto done" ) ;
214
+ Ok ( ( ) )
212
215
}
213
216
214
217
fn is_versioned_bytecode_format ( bc : & [ u8 ] ) -> bool {
0 commit comments