@@ -27,10 +27,16 @@ use {ModuleCodegen, ModuleLlvm, ModuleKind, ModuleSource};
2727use libc;
2828
2929use std:: ffi:: { CString , CStr } ;
30+ use std:: fs:: File ;
31+ use std:: io;
32+ use std:: mem;
33+ use std:: path:: Path ;
3034use std:: ptr;
3135use std:: slice;
3236use std:: sync:: Arc ;
3337
38+ pub const THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME : & str = "thin-lto-imports.bin" ;
39+
3440pub fn crate_type_allows_lto ( crate_type : config:: CrateType ) -> bool {
3541 match crate_type {
3642 config:: CrateTypeExecutable |
@@ -194,7 +200,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
194200 }
195201 Lto :: Thin |
196202 Lto :: ThinLocal => {
197- thin_lto ( & diag_handler, modules, upstream_modules, & arr, timeline)
203+ thin_lto ( cgcx , & diag_handler, modules, upstream_modules, & arr, timeline)
198204 }
199205 Lto :: No => unreachable ! ( ) ,
200206 }
@@ -347,7 +353,8 @@ impl Drop for Linker {
347353/// calculating the *index* for ThinLTO. This index will then be shared amongst
348354/// all of the `LtoModuleCodegen` units returned below and destroyed once
349355/// they all go out of scope.
350- fn thin_lto ( diag_handler : & Handler ,
356+ fn thin_lto ( cgcx : & CodegenContext ,
357+ diag_handler : & Handler ,
351358 modules : Vec < ModuleCodegen > ,
352359 serialized_modules : Vec < ( SerializedModule , CString ) > ,
353360 symbol_white_list : & [ * const libc:: c_char ] ,
@@ -425,6 +432,18 @@ fn thin_lto(diag_handler: &Handler,
425432 let msg = format ! ( "failed to prepare thin LTO context" ) ;
426433 return Err ( write:: llvm_err ( & diag_handler, msg) )
427434 }
435+
436+ // Save the ThinLTO import information for incremental compilation.
437+ if let Some ( ref incr_comp_session_dir) = cgcx. incr_comp_session_dir {
438+ let path = incr_comp_session_dir. join ( THIN_LTO_IMPORTS_INCR_COMP_FILE_NAME ) ;
439+ let imports = ThinLTOImports :: from_thin_lto_data ( data) ;
440+ if let Err ( err) = imports. save_to_file ( & path) {
441+ let msg = format ! ( "Error while writing ThinLTO import data: {}" ,
442+ err) ;
443+ return Err ( write:: llvm_err ( & diag_handler, msg) ) ;
444+ }
445+ }
446+
428447 let data = ThinData ( data) ;
429448 info ! ( "thin LTO data created" ) ;
430449 timeline. record ( "data" ) ;
@@ -787,6 +806,12 @@ pub struct ThinLTOImports {
787806
788807impl ThinLTOImports {
789808
809+ pub fn new_empty ( ) -> ThinLTOImports {
810+ ThinLTOImports {
811+ imports : FxHashMap ( ) ,
812+ }
813+ }
814+
790815 /// Load the ThinLTO import map from ThinLTOData.
791816 unsafe fn from_thin_lto_data ( data : * const llvm:: ThinLTOData ) -> ThinLTOImports {
792817 let raw_data: * const llvm:: ThinLTOModuleImports =
@@ -842,4 +867,58 @@ impl ThinLTOImports {
842867 imports
843868 }
844869 }
870+
871+ pub fn save_to_file ( & self , path : & Path ) -> io:: Result < ( ) > {
872+ use std:: io:: Write ;
873+
874+ let file = File :: create ( path) ?;
875+ let mut writer = io:: BufWriter :: new ( file) ;
876+
877+ for ( importing_module_name, imported_modules) in & self . imports {
878+ writeln ! ( writer, "{}" , importing_module_name) ?;
879+
880+ for imported_module in imported_modules {
881+ writeln ! ( writer, " {}" , imported_module) ?;
882+ }
883+
884+ writeln ! ( writer) ?;
885+ }
886+
887+ Ok ( ( ) )
888+ }
889+
890+ pub fn load_from_file ( path : & Path ) -> io:: Result < ThinLTOImports > {
891+ use std:: io:: BufRead ;
892+
893+ let mut imports = FxHashMap ( ) ;
894+ let mut current_module = None ;
895+ let mut current_imports = vec ! [ ] ;
896+
897+ let file = File :: open ( path) ?;
898+
899+ for line in io:: BufReader :: new ( file) . lines ( ) {
900+ let line = line?;
901+
902+ if line. is_empty ( ) {
903+ let importing_module = current_module
904+ . take ( )
905+ . expect ( "Importing module not set" ) ;
906+
907+ imports. insert ( importing_module,
908+ mem:: replace ( & mut current_imports, vec ! [ ] ) ) ;
909+ } else if line. starts_with ( " " ) {
910+ // This is an imported module
911+ assert_ne ! ( current_module, None ) ;
912+ current_imports. push ( line. trim ( ) . to_string ( ) ) ;
913+ } else {
914+ // This is the beginning of a new module
915+ assert_eq ! ( current_module, None ) ;
916+ current_module = Some ( line. trim ( ) . to_string ( ) ) ;
917+ }
918+ }
919+
920+ Ok ( ThinLTOImports {
921+ imports
922+ } )
923+ }
845924}
0 commit comments