1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use calculate_svh
::SvhCalculate
;
12 use rbml
::opaque
::Encoder
;
13 use rustc
::dep_graph
::DepNode
;
15 use rustc_serialize
::{Encodable as RustcEncodable}
;
16 use std
::io
::{self, Cursor, Write}
;
17 use std
::fs
::{self, File}
;
20 use super::directory
::*;
23 pub fn save_dep_graph
<'tcx
>(tcx
: &ty
::TyCtxt
<'tcx
>) {
24 let _ignore
= tcx
.dep_graph
.in_ignore();
26 if let Some(dep_graph
) = dep_graph_path(tcx
) {
27 // FIXME(#32754) lock file?
29 // delete the old dep-graph, if any
30 if dep_graph
.exists() {
31 match fs
::remove_file(&dep_graph
) {
35 &format
!("unable to delete old dep-graph at `{}`: {}",
36 dep_graph
.display(), err
));
42 // generate the data in a memory buffer
43 let mut wr
= Cursor
::new(Vec
::new());
44 match encode_dep_graph(tcx
, &mut Encoder
::new(&mut wr
)) {
48 &format
!("could not encode dep-graph to `{}`: {}",
49 dep_graph
.display(), err
));
55 let data
= wr
.into_inner();
57 File
::create(&dep_graph
)
58 .and_then(|mut file
| file
.write_all(&data
))
63 &format
!("failed to write dep-graph to `{}`: {}",
64 dep_graph
.display(), err
));
71 pub fn encode_dep_graph
<'tcx
>(tcx
: &ty
::TyCtxt
<'tcx
>,
72 encoder
: &mut Encoder
)
75 // Here we take advantage of how RBML allows us to skip around
76 // and encode the depgraph as a two-part structure:
79 // <dep-graph>[SerializedDepGraph]</dep-graph> // tag 0
80 // <directory>[DefIdDirectory]</directory> // tag 1
83 // Then later we can load the directory by skipping to find tag 1.
85 let query
= tcx
.dep_graph
.query();
87 let mut builder
= DefIdDirectoryBuilder
::new(tcx
);
89 // Create hashes for things we can persist.
93 .filter_map(|dep_node
| match dep_node
{
94 DepNode
::Hir(def_id
) => {
95 assert
!(def_id
.is_local());
98 // FIXME(#32753) -- should we use a distinct hash here
99 let hash
= tcx
.calculate_item_hash(def_id
);
100 SerializedHash { index: index, hash: hash }
107 // Create the serialized dep-graph, dropping nodes that are
108 // from other crates or from inlined items.
110 // FIXME(#32015) fix handling of other crates
111 let graph
= SerializedDepGraph
{
112 nodes
: query
.nodes().into_iter()
113 .flat_map(|node
| builder
.map(node
))
115 edges
: query
.edges().into_iter()
116 .flat_map(|(source_node
, target_node
)| {
117 builder
.map(source_node
)
119 builder
.map(target_node
)
120 .map(|target
| (source
, target
))
127 debug
!("graph = {:#?}", graph
);
129 // Encode the directory and then the graph data.
130 let directory
= builder
.into_directory();
131 try
!(directory
.encode(encoder
));
132 try
!(graph
.encode(encoder
));