1010
1111use back:: link;
1212use 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 ;
1516use llvm;
1617use llvm:: archive_ro:: ArchiveRO ;
1718use llvm:: { ModuleRef , TargetMachineRef , True , False } ;
1819use rustc:: util:: common:: time;
1920use rustc:: util:: common:: path2cstr;
2021use rustc:: hir:: def_id:: LOCAL_CRATE ;
21- use back:: write:: { ModuleConfig , with_llvm_pmb} ;
22+ use back:: write:: { ModuleConfig , with_llvm_pmb, CodegenContext } ;
2223
2324use libc;
2425use flate2:: read:: ZlibDecoder ;
@@ -39,30 +40,31 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
3940 }
4041}
4142
42- pub fn run ( sess : & session :: Session ,
43+ pub fn run ( cgcx : & CodegenContext ,
4344 llmod : ModuleRef ,
4445 tm : TargetMachineRef ,
45- exported_symbols : & ExportedSymbols ,
4646 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" )
5051 . note ( "only 'staticlib', 'bin', and 'cdylib' outputs are \
5152 supported with LTO")
5253 . emit ( ) ;
53- sess . abort_if_errors ( ) ;
54+ return Err ( FatalError )
5455 }
5556
5657 // 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 ( ) {
5859 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)
6163 }
6264 }
6365
6466 let export_threshold =
65- symbol_export:: crates_export_threshold ( & sess . crate_types . borrow ( ) ) ;
67+ symbol_export:: crates_export_threshold ( & cgcx . crate_types ) ;
6668
6769 let symbol_filter = & |& ( ref name, level) : & ( String , _ ) | {
6870 if symbol_export:: is_below_threshold ( level, export_threshold) {
@@ -74,7 +76,7 @@ pub fn run(sess: &session::Session,
7476 }
7577 } ;
7678
77- let mut symbol_white_list: Vec < CString > = exported_symbols
79+ let mut symbol_white_list: Vec < CString > = cgcx . exported_symbols
7880 . exported_symbols ( LOCAL_CRATE )
7981 . iter ( )
8082 . filter_map ( symbol_filter)
@@ -83,16 +85,11 @@ pub fn run(sess: &session::Session,
8385 // For each of our upstream dependencies, find the corresponding rlib and
8486 // load the bitcode from the archive. Then merge it into the current LLVM
8587 // 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 ( ) {
9289 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) ) ;
9693
9794 let archive = ArchiveRO :: open ( & path) . expect ( "wanted an rlib" ) ;
9895 let bytecodes = archive. iter ( ) . filter_map ( |child| {
@@ -102,7 +99,7 @@ pub fn run(sess: &session::Session,
10299 let bc_encoded = data. data ( ) ;
103100
104101 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) , || {
106103 // Read the version
107104 let version = extract_bytecode_format_version ( bc_encoded) ;
108105
@@ -117,44 +114,49 @@ pub fn run(sess: &session::Session,
117114 let res = ZlibDecoder :: new ( compressed_data)
118115 . read_to_end ( & mut inflated) ;
119116 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)
122122 }
123- inflated
124123 } else {
125- sess . fatal ( & format ! ( "Unsupported bytecode format version {}" ,
126- version) )
124+ Err ( handler . fatal ( & format ! ( "Unsupported bytecode format version {}" ,
125+ version) ) )
127126 }
128- } )
127+ } ) ?
129128 } else {
130- time ( sess . time_passes ( ) , & format ! ( "decode {}" , name) , || {
129+ time ( cgcx . time_passes , & format ! ( "decode {}" , name) , || {
131130 // the object must be in the old, pre-versioning format, so
132131 // simply inflate everything and let LLVM decide if it can
133132 // make sense of it
134133 let mut inflated = Vec :: new ( ) ;
135134 let res = ZlibDecoder :: new ( bc_encoded)
136135 . read_to_end ( & mut inflated) ;
137136 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)
140142 }
141- inflated
142- } )
143+ } ) ?
143144 } ;
144145
145146 let ptr = bc_decoded. as_ptr ( ) ;
146147 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) )
154156 }
155- } ) ;
157+ } ) ? ;
156158 }
157- } ) ;
159+ }
158160
159161 // Internalize everything but the exported symbols of the current module
160162 let arr: Vec < * const libc:: c_char > = symbol_white_list. iter ( )
@@ -167,13 +169,13 @@ pub fn run(sess: &session::Session,
167169 arr. len ( ) as libc:: size_t ) ;
168170 }
169171
170- if sess . no_landing_pads ( ) {
172+ if cgcx . no_landing_pads {
171173 unsafe {
172174 llvm:: LLVMRustMarkAllFunctionsNounwind ( llmod) ;
173175 }
174176 }
175177
176- if sess . opts . cg . save_temps {
178+ if cgcx . opts . cg . save_temps {
177179 let cstr = path2cstr ( temp_no_opt_bc_filename) ;
178180 unsafe {
179181 llvm:: LLVMWriteBitcodeToFile ( llmod, cstr. as_ptr ( ) ) ;
@@ -203,12 +205,13 @@ pub fn run(sess: &session::Session,
203205 assert ! ( !pass. is_null( ) ) ;
204206 llvm:: LLVMRustAddPass ( pm, pass) ;
205207
206- time ( sess . time_passes ( ) , "LTO passes" , ||
208+ time ( cgcx . time_passes , "LTO passes" , ||
207209 llvm:: LLVMRunPassManager ( pm, llmod) ) ;
208210
209211 llvm:: LLVMDisposePassManager ( pm) ;
210212 }
211213 debug ! ( "lto done" ) ;
214+ Ok ( ( ) )
212215}
213216
214217fn is_versioned_bytecode_format ( bc : & [ u8 ] ) -> bool {
0 commit comments