11use rustc_data_structures:: fx:: FxHashMap ;
22use rustc_data_structures:: sync:: join;
3- use rustc_middle:: dep_graph:: { DepGraph , WorkProduct , WorkProductId } ;
3+ use rustc_middle:: dep_graph:: { DepGraph , PreviousDepGraph , WorkProduct , WorkProductId } ;
44use rustc_middle:: ty:: TyCtxt ;
55use rustc_serialize:: opaque:: { FileEncodeResult , FileEncoder } ;
66use rustc_serialize:: Encodable as RustcEncodable ;
@@ -15,6 +15,9 @@ use super::file_format;
1515use super :: fs:: * ;
1616use super :: work_product;
1717
18+ /// Save and dump the DepGraph.
19+ ///
20+ /// No query must be invoked after this function.
1821pub fn save_dep_graph ( tcx : TyCtxt < ' _ > ) {
1922 debug ! ( "save_dep_graph()" ) ;
2023 tcx. dep_graph . with_ignore ( || {
@@ -29,23 +32,43 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
2932
3033 let query_cache_path = query_cache_path ( sess) ;
3134 let dep_graph_path = dep_graph_path ( sess) ;
35+ let staging_dep_graph_path = staging_dep_graph_path ( sess) ;
36+
37+ join (
38+ || sess. time ( "assert_dep_graph" , || crate :: assert_dep_graph ( tcx) ) ,
39+ || sess. time ( "check_dirty_clean" , || dirty_clean:: check_dirty_clean_annotations ( tcx) ) ,
40+ ) ;
41+
42+ if sess. opts . debugging_opts . incremental_info {
43+ tcx. dep_graph . print_incremental_info ( )
44+ }
3245
3346 join (
3447 move || {
3548 sess. time ( "incr_comp_persist_result_cache" , || {
3649 save_in ( sess, query_cache_path, "query cache" , |e| encode_query_cache ( tcx, e) ) ;
3750 } ) ;
3851 } ,
39- || {
52+ move || {
4053 sess. time ( "incr_comp_persist_dep_graph" , || {
41- save_in ( sess, dep_graph_path, "dependency graph" , |e| {
42- sess. time ( "incr_comp_encode_dep_graph" , || encode_dep_graph ( tcx, e) )
43- } ) ;
54+ if let Err ( err) = tcx. dep_graph . encode ( ) {
55+ sess. err ( & format ! (
56+ "failed to write dependency graph to `{}`: {}" ,
57+ staging_dep_graph_path. display( ) ,
58+ err
59+ ) ) ;
60+ }
61+ if let Err ( err) = fs:: rename ( & staging_dep_graph_path, & dep_graph_path) {
62+ sess. err ( & format ! (
63+ "failed to move dependency graph from `{}` to `{}`: {}" ,
64+ staging_dep_graph_path. display( ) ,
65+ dep_graph_path. display( ) ,
66+ err
67+ ) ) ;
68+ }
4469 } ) ;
4570 } ,
4671 ) ;
47-
48- dirty_clean:: check_dirty_clean_annotations ( tcx) ;
4972 } )
5073}
5174
@@ -92,7 +115,7 @@ pub fn save_work_product_index(
92115 } ) ;
93116}
94117
95- fn save_in < F > ( sess : & Session , path_buf : PathBuf , name : & str , encode : F )
118+ pub ( crate ) fn save_in < F > ( sess : & Session , path_buf : PathBuf , name : & str , encode : F )
96119where
97120 F : FnOnce ( & mut FileEncoder ) -> FileEncodeResult ,
98121{
@@ -144,21 +167,6 @@ where
144167 debug ! ( "save: data written to disk successfully" ) ;
145168}
146169
147- fn encode_dep_graph ( tcx : TyCtxt < ' _ > , encoder : & mut FileEncoder ) -> FileEncodeResult {
148- // First encode the commandline arguments hash
149- tcx. sess . opts . dep_tracking_hash ( ) . encode ( encoder) ?;
150-
151- if tcx. sess . opts . debugging_opts . incremental_info {
152- tcx. dep_graph . print_incremental_info ( ) ;
153- }
154-
155- // There is a tiny window between printing the incremental info above and encoding the dep
156- // graph below in which the dep graph could change, thus making the printed incremental info
157- // slightly out of date. If this matters to you, please feel free to submit a patch. :)
158-
159- tcx. sess . time ( "incr_comp_encode_serialized_dep_graph" , || tcx. dep_graph . encode ( encoder) )
160- }
161-
162170fn encode_work_product_index (
163171 work_products : & FxHashMap < WorkProductId , WorkProduct > ,
164172 encoder : & mut FileEncoder ,
@@ -177,3 +185,56 @@ fn encode_work_product_index(
177185fn encode_query_cache ( tcx : TyCtxt < ' _ > , encoder : & mut FileEncoder ) -> FileEncodeResult {
178186 tcx. sess . time ( "incr_comp_serialize_result_cache" , || tcx. serialize_query_result_cache ( encoder) )
179187}
188+
189+ pub fn build_dep_graph (
190+ sess : & Session ,
191+ prev_graph : PreviousDepGraph ,
192+ prev_work_products : FxHashMap < WorkProductId , WorkProduct > ,
193+ ) -> Option < DepGraph > {
194+ if sess. opts . incremental . is_none ( ) {
195+ // No incremental compilation.
196+ return None ;
197+ }
198+
199+ // Stream the dep-graph to an alternate file, to avoid overwriting anything in case of errors.
200+ let path_buf = staging_dep_graph_path ( sess) ;
201+
202+ let mut encoder = match FileEncoder :: new ( & path_buf) {
203+ Ok ( encoder) => encoder,
204+ Err ( err) => {
205+ sess. err ( & format ! (
206+ "failed to create dependency graph at `{}`: {}" ,
207+ path_buf. display( ) ,
208+ err
209+ ) ) ;
210+ return None ;
211+ }
212+ } ;
213+
214+ if let Err ( err) = file_format:: write_file_header ( & mut encoder, sess. is_nightly_build ( ) ) {
215+ sess. err ( & format ! (
216+ "failed to write dependency graph header to `{}`: {}" ,
217+ path_buf. display( ) ,
218+ err
219+ ) ) ;
220+ return None ;
221+ }
222+
223+ // First encode the commandline arguments hash
224+ if let Err ( err) = sess. opts . dep_tracking_hash ( ) . encode ( & mut encoder) {
225+ sess. err ( & format ! (
226+ "failed to write dependency graph hash `{}`: {}" ,
227+ path_buf. display( ) ,
228+ err
229+ ) ) ;
230+ return None ;
231+ }
232+
233+ Some ( DepGraph :: new (
234+ prev_graph,
235+ prev_work_products,
236+ encoder,
237+ sess. opts . debugging_opts . query_dep_graph ,
238+ sess. opts . debugging_opts . incremental_info ,
239+ ) )
240+ }
0 commit comments