8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use back:: lto;
11
+ use back:: bytecode:: { self , RLIB_BYTECODE_EXTENSION } ;
12
+ use back:: lto:: { self , ModuleBuffer , ThinBuffer } ;
12
13
use back:: link:: { self , get_linker, remove} ;
13
14
use back:: linker:: LinkerInfo ;
14
15
use back:: symbol_export:: ExportedSymbols ;
15
16
use base;
16
17
use consts;
17
18
use rustc_incremental:: { save_trans_partition, in_incr_comp_dir} ;
18
- use rustc:: dep_graph:: DepGraph ;
19
+ use rustc:: dep_graph:: { DepGraph , WorkProductFileKind } ;
19
20
use rustc:: middle:: cstore:: { LinkMeta , EncodedMetadata } ;
20
21
use rustc:: session:: config:: { self , OutputFilenames , OutputType , OutputTypes , Passes , SomePasses ,
21
22
AllPasses , Sanitizer } ;
@@ -44,7 +45,7 @@ use rustc_demangle;
44
45
45
46
use std:: any:: Any ;
46
47
use std:: ffi:: { CString , CStr } ;
47
- use std:: fs;
48
+ use std:: fs:: { self , File } ;
48
49
use std:: io;
49
50
use std:: io:: Write ;
50
51
use std:: mem;
@@ -228,6 +229,7 @@ pub struct ModuleConfig {
228
229
// Flags indicating which outputs to produce.
229
230
emit_no_opt_bc : bool ,
230
231
emit_bc : bool ,
232
+ emit_bc_compressed : bool ,
231
233
emit_lto_bc : bool ,
232
234
emit_ir : bool ,
233
235
emit_asm : bool ,
@@ -257,6 +259,7 @@ impl ModuleConfig {
257
259
258
260
emit_no_opt_bc : false ,
259
261
emit_bc : false ,
262
+ emit_bc_compressed : false ,
260
263
emit_lto_bc : false ,
261
264
emit_ir : false ,
262
265
emit_asm : false ,
@@ -627,20 +630,34 @@ unsafe fn codegen(cgcx: &CodegenContext,
627
630
let bc_out = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , module_name) ;
628
631
let obj_out = cgcx. output_filenames . temp_path ( OutputType :: Object , module_name) ;
629
632
630
- if write_bc {
631
- let bc_out_c = path2cstr ( & bc_out) ;
632
- if llvm:: LLVMRustThinLTOAvailable ( ) {
633
- with_codegen ( tm, llmod, config. no_builtins , |cpm| {
634
- llvm:: LLVMRustWriteThinBitcodeToFile (
635
- cpm,
636
- llmod,
637
- bc_out_c. as_ptr ( ) ,
638
- )
639
- } ) ;
633
+
634
+ if write_bc || config. emit_bc_compressed {
635
+ let thin;
636
+ let old;
637
+ let data = if llvm:: LLVMRustThinLTOAvailable ( ) {
638
+ thin = ThinBuffer :: new ( llmod) ;
639
+ thin. data ( )
640
640
} else {
641
- llvm:: LLVMWriteBitcodeToFile ( llmod, bc_out_c. as_ptr ( ) ) ;
641
+ old = ModuleBuffer :: new ( llmod) ;
642
+ old. data ( )
643
+ } ;
644
+ timeline. record ( "make-bc" ) ;
645
+
646
+ if write_bc {
647
+ if let Err ( e) = File :: create ( & bc_out) . and_then ( |mut f| f. write_all ( data) ) {
648
+ diag_handler. err ( & format ! ( "failed to write bytecode: {}" , e) ) ;
649
+ }
650
+ timeline. record ( "write-bc" ) ;
651
+ }
652
+
653
+ if config. emit_bc_compressed {
654
+ let dst = bc_out. with_extension ( RLIB_BYTECODE_EXTENSION ) ;
655
+ let data = bytecode:: encode ( & mtrans. llmod_id , data) ;
656
+ if let Err ( e) = File :: create ( & dst) . and_then ( |mut f| f. write_all ( & data) ) {
657
+ diag_handler. err ( & format ! ( "failed to write bytecode: {}" , e) ) ;
658
+ }
659
+ timeline. record ( "compress-bc" ) ;
642
660
}
643
- timeline. record ( "bc" ) ;
644
661
}
645
662
646
663
time ( config. time_passes , & format ! ( "codegen passes [{}]" , module_name. unwrap( ) ) ,
@@ -736,6 +753,7 @@ unsafe fn codegen(cgcx: &CodegenContext,
736
753
drop ( handlers) ;
737
754
Ok ( mtrans. into_compiled_module ( config. emit_obj ,
738
755
config. emit_bc ,
756
+ config. emit_bc_compressed ,
739
757
& cgcx. output_filenames ) )
740
758
}
741
759
@@ -822,11 +840,12 @@ pub fn start_async_translation(tcx: TyCtxt,
822
840
allocator_config. emit_bc = true ;
823
841
}
824
842
825
- // Emit bitcode files for the crate if we're emitting an rlib.
826
- // Whenever an rlib is created, the bitcode is inserted into the
827
- // archive in order to allow LTO against it.
843
+ // Emit compressed bitcode files for the crate if we're emitting an rlib.
844
+ // Whenever an rlib is created, the bitcode is inserted into the archive in
845
+ // order to allow LTO against it.
828
846
if need_crate_bitcode_for_rlib ( sess) {
829
- modules_config. emit_bc = true ;
847
+ modules_config. emit_bc_compressed = true ;
848
+ allocator_config. emit_bc_compressed = true ;
830
849
}
831
850
832
851
for output_type in output_types_override. keys ( ) {
@@ -906,29 +925,25 @@ pub fn start_async_translation(tcx: TyCtxt,
906
925
907
926
fn copy_module_artifacts_into_incr_comp_cache ( sess : & Session ,
908
927
dep_graph : & DepGraph ,
909
- compiled_modules : & CompiledModules ,
910
- crate_output : & OutputFilenames ) {
928
+ compiled_modules : & CompiledModules ) {
911
929
if sess. opts . incremental . is_none ( ) {
912
930
return ;
913
931
}
914
932
915
933
for module in compiled_modules. modules . iter ( ) {
916
934
let mut files = vec ! [ ] ;
917
935
918
- if module. emit_obj {
919
- let path = crate_output. temp_path ( OutputType :: Object , Some ( & module. name ) ) ;
920
- files. push ( ( OutputType :: Object , path) ) ;
936
+ if let Some ( ref path) = module. object {
937
+ files. push ( ( WorkProductFileKind :: Object , path. clone ( ) ) ) ;
921
938
}
922
-
923
- if module. emit_bc {
924
- let path = crate_output. temp_path ( OutputType :: Bitcode , Some ( & module. name ) ) ;
925
- files. push ( ( OutputType :: Bitcode , path) ) ;
939
+ if let Some ( ref path) = module. bytecode {
940
+ files. push ( ( WorkProductFileKind :: Bytecode , path. clone ( ) ) ) ;
941
+ }
942
+ if let Some ( ref path) = module. bytecode_compressed {
943
+ files. push ( ( WorkProductFileKind :: BytecodeCompressed , path. clone ( ) ) ) ;
926
944
}
927
945
928
- save_trans_partition ( sess,
929
- dep_graph,
930
- & module. name ,
931
- & files) ;
946
+ save_trans_partition ( sess, dep_graph, & module. name , & files) ;
932
947
}
933
948
}
934
949
@@ -1032,8 +1047,6 @@ fn produce_final_output_artifacts(sess: &Session,
1032
1047
// well.
1033
1048
1034
1049
// Specific rules for keeping .#module-name#.bc:
1035
- // - If we're building an rlib (`needs_crate_bitcode`), then keep
1036
- // it.
1037
1050
// - If the user requested bitcode (`user_wants_bitcode`), and
1038
1051
// codegen_units > 1, then keep it.
1039
1052
// - If the user requested bitcode but codegen_units == 1, then we
@@ -1043,41 +1056,37 @@ fn produce_final_output_artifacts(sess: &Session,
1043
1056
// If you change how this works, also update back::link::link_rlib,
1044
1057
// where .#module-name#.bc files are (maybe) deleted after making an
1045
1058
// rlib.
1046
- let needs_crate_bitcode = need_crate_bitcode_for_rlib ( sess) ;
1047
1059
let needs_crate_object = crate_output. outputs . contains_key ( & OutputType :: Exe ) ;
1048
1060
1049
- let keep_numbered_bitcode = needs_crate_bitcode ||
1050
- ( user_wants_bitcode && sess. codegen_units ( ) > 1 ) ;
1061
+ let keep_numbered_bitcode = user_wants_bitcode && sess. codegen_units ( ) > 1 ;
1051
1062
1052
1063
let keep_numbered_objects = needs_crate_object ||
1053
1064
( user_wants_objects && sess. codegen_units ( ) > 1 ) ;
1054
1065
1055
1066
for module in compiled_modules. modules . iter ( ) {
1056
- let module_name = Some ( & module. name [ ..] ) ;
1057
-
1058
- if module. emit_obj && !keep_numbered_objects {
1059
- let path = crate_output. temp_path ( OutputType :: Object , module_name) ;
1060
- remove ( sess, & path) ;
1067
+ if let Some ( ref path) = module. object {
1068
+ if !keep_numbered_objects {
1069
+ remove ( sess, path) ;
1070
+ }
1061
1071
}
1062
1072
1063
- if module. emit_bc && !keep_numbered_bitcode {
1064
- let path = crate_output. temp_path ( OutputType :: Bitcode , module_name) ;
1065
- remove ( sess, & path) ;
1073
+ if let Some ( ref path) = module. bytecode {
1074
+ if !keep_numbered_bitcode {
1075
+ remove ( sess, path) ;
1076
+ }
1066
1077
}
1067
1078
}
1068
1079
1069
- if compiled_modules. metadata_module . emit_bc && !user_wants_bitcode {
1070
- let path = crate_output. temp_path ( OutputType :: Bitcode ,
1071
- Some ( & compiled_modules. metadata_module . name ) ) ;
1072
- remove ( sess, & path) ;
1073
- }
1074
-
1075
- if let Some ( ref allocator_module) = compiled_modules. allocator_module {
1076
- if allocator_module. emit_bc && !user_wants_bitcode {
1077
- let path = crate_output. temp_path ( OutputType :: Bitcode ,
1078
- Some ( & allocator_module. name ) ) ;
1080
+ if !user_wants_bitcode {
1081
+ if let Some ( ref path) = compiled_modules. metadata_module . bytecode {
1079
1082
remove ( sess, & path) ;
1080
1083
}
1084
+
1085
+ if let Some ( ref allocator_module) = compiled_modules. allocator_module {
1086
+ if let Some ( ref path) = allocator_module. bytecode {
1087
+ remove ( sess, path) ;
1088
+ }
1089
+ }
1081
1090
}
1082
1091
}
1083
1092
@@ -1149,8 +1158,28 @@ fn execute_work_item(cgcx: &CodegenContext,
1149
1158
. as_ref ( )
1150
1159
. unwrap ( ) ;
1151
1160
let name = & mtrans. name ;
1161
+ let mut object = None ;
1162
+ let mut bytecode = None ;
1163
+ let mut bytecode_compressed = None ;
1152
1164
for ( kind, saved_file) in wp. saved_files {
1153
- let obj_out = cgcx. output_filenames . temp_path ( kind, Some ( name) ) ;
1165
+ let obj_out = match kind {
1166
+ WorkProductFileKind :: Object => {
1167
+ let path = cgcx. output_filenames . temp_path ( OutputType :: Object , Some ( name) ) ;
1168
+ object = Some ( path. clone ( ) ) ;
1169
+ path
1170
+ }
1171
+ WorkProductFileKind :: Bytecode => {
1172
+ let path = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , Some ( name) ) ;
1173
+ bytecode = Some ( path. clone ( ) ) ;
1174
+ path
1175
+ }
1176
+ WorkProductFileKind :: BytecodeCompressed => {
1177
+ let path = cgcx. output_filenames . temp_path ( OutputType :: Bitcode , Some ( name) )
1178
+ . with_extension ( RLIB_BYTECODE_EXTENSION ) ;
1179
+ bytecode_compressed = Some ( path. clone ( ) ) ;
1180
+ path
1181
+ }
1182
+ } ;
1154
1183
let source_file = in_incr_comp_dir ( & incr_comp_session_dir,
1155
1184
& saved_file) ;
1156
1185
debug ! ( "copying pre-existing module `{}` from {:?} to {}" ,
@@ -1167,16 +1196,18 @@ fn execute_work_item(cgcx: &CodegenContext,
1167
1196
}
1168
1197
}
1169
1198
}
1170
- let object = cgcx. output_filenames . temp_path ( OutputType :: Object , Some ( name) ) ;
1199
+ assert_eq ! ( object. is_some( ) , config. emit_obj) ;
1200
+ assert_eq ! ( bytecode. is_some( ) , config. emit_bc) ;
1201
+ assert_eq ! ( bytecode_compressed. is_some( ) , config. emit_bc_compressed) ;
1171
1202
1172
1203
Ok ( WorkItemResult :: Compiled ( CompiledModule {
1173
- object,
1174
1204
llmod_id : mtrans. llmod_id . clone ( ) ,
1175
1205
name : module_name,
1176
1206
kind : ModuleKind :: Regular ,
1177
1207
pre_existing : true ,
1178
- emit_bc : config. emit_bc ,
1179
- emit_obj : config. emit_obj ,
1208
+ object,
1209
+ bytecode,
1210
+ bytecode_compressed,
1180
1211
} ) )
1181
1212
} else {
1182
1213
debug ! ( "llvm-optimizing {:?}" , module_name) ;
@@ -2053,8 +2084,7 @@ impl OngoingCrateTranslation {
2053
2084
2054
2085
copy_module_artifacts_into_incr_comp_cache ( sess,
2055
2086
dep_graph,
2056
- & compiled_modules,
2057
- & self . output_filenames ) ;
2087
+ & compiled_modules) ;
2058
2088
produce_final_output_artifacts ( sess,
2059
2089
& compiled_modules,
2060
2090
& self . output_filenames ) ;
@@ -2075,6 +2105,7 @@ impl OngoingCrateTranslation {
2075
2105
2076
2106
modules : compiled_modules. modules ,
2077
2107
allocator_module : compiled_modules. allocator_module ,
2108
+ metadata_module : compiled_modules. metadata_module ,
2078
2109
} ;
2079
2110
2080
2111
if self . no_integrated_as {
0 commit comments