Skip to content

Commit ad4d2f0

Browse files
committed
Check / emit annotations based on env vars
1 parent 2d83c89 commit ad4d2f0

11 files changed

+80
-49
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ To run:
33

44
`cargo run [FILENAME].rs`
55

6-
To view the visualization
6+
To view the visualization
77

8-
1. `PCS_VISUALIZATION=true cargo run [FILENAME.rs]`
8+
1. `PCG_VISUALIZATION=true cargo run [FILENAME.rs]`
99
2. `cd visualization && ./serve`
1010
3. Go to http://localhost:8080 and select the function you wish to view
1111

src/borrows/borrow_pcg_capabilities.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::collections::HashMap;
22

3-
use crate::free_pcs::CapabilityKind;
3+
use crate::{
4+
free_pcs::CapabilityKind,
5+
utils::{display::DisplayWithRepacker, PlaceRepacker},
6+
};
47

58
use super::borrow_pcg_edge::PCGNode;
69

@@ -16,9 +19,11 @@ impl<'tcx> BorrowPCGCapabilities<'tcx> {
1619
Self(HashMap::new())
1720
}
1821

19-
pub(crate) fn debug_capability_lines(&self) -> Vec<String> {
22+
pub(crate) fn debug_capability_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
2023
self.iter()
21-
.map(|(node, capability)| format!("{}: {:?}", node, capability))
24+
.map(|(node, capability)| {
25+
format!("{}: {:?}", node.to_short_string(repacker), capability)
26+
})
2227
.collect()
2328
}
2429

src/borrows/borrows_state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ impl<'tcx> Default for BorrowsState<'tcx> {
9191
}
9292

9393
impl<'tcx> BorrowsState<'tcx> {
94-
pub(crate) fn debug_capability_lines(&self) -> Vec<String> {
95-
self.capabilities.debug_capability_lines()
94+
pub(crate) fn debug_capability_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
95+
self.capabilities.debug_capability_lines(repacker)
9696
}
9797
pub(crate) fn insert(&mut self, edge: BorrowPCGEdge<'tcx>) -> bool {
9898
self.graph.insert(edge)

src/borrows/domain.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct LoopAbstraction<'tcx> {
1919
}
2020

2121
impl<'tcx> DisplayWithRepacker<'tcx> for LoopAbstraction<'tcx> {
22-
fn to_short_string(&self, repacker: PlaceRepacker<'_, 'tcx>) -> String {
22+
fn to_short_string(&self, _repacker: PlaceRepacker<'_, 'tcx>) -> String {
2323
format!("Loop({:?})", self.block)
2424
}
2525
}
@@ -73,7 +73,7 @@ pub struct FunctionCallAbstraction<'tcx> {
7373
}
7474

7575
impl<'tcx> DisplayWithRepacker<'tcx> for FunctionCallAbstraction<'tcx> {
76-
fn to_short_string(&self, repacker: PlaceRepacker<'_, 'tcx>) -> String {
76+
fn to_short_string(&self, _repacker: PlaceRepacker<'_, 'tcx>) -> String {
7777
format!("FunctionCall({:?}, {:?})", self.def_id, self.substs)
7878
}
7979
}

src/free_pcs/impl/fpcs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ impl<'tcx> Debug for CapabilitySummary<'tcx> {
150150
}
151151

152152
impl<'tcx> CapabilitySummary<'tcx> {
153-
pub(crate) fn debug_lines(&self) -> Vec<String> {
153+
pub(crate) fn debug_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
154154
self.0
155155
.iter()
156-
.map(|c| c.debug_lines())
156+
.map(|c| c.debug_lines(repacker))
157157
.collect::<Vec<_>>()
158158
.concat()
159159
}

src/free_pcs/impl/local.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_interface::{
1515
use crate::{
1616
free_pcs::{CapabilityKind, RelatedSet, RepackOp},
1717
rustc_interface,
18-
utils::{Place, PlaceOrdering, PlaceRepacker},
18+
utils::{display::DisplayWithRepacker, Place, PlaceOrdering, PlaceRepacker},
1919
};
2020

2121
#[derive(Clone, PartialEq, Eq)]
@@ -42,10 +42,10 @@ impl Default for CapabilityLocal<'_> {
4242
}
4343

4444
impl<'tcx> CapabilityLocal<'tcx> {
45-
pub(crate) fn debug_lines(&self) -> Vec<String> {
45+
pub(crate) fn debug_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
4646
match self {
4747
Self::Unallocated => vec![],
48-
Self::Allocated(cps) => cps.debug_lines(),
48+
Self::Allocated(cps) => cps.debug_lines(repacker),
4949
}
5050
}
5151

@@ -81,9 +81,9 @@ impl<'tcx> Debug for CapabilityProjections<'tcx> {
8181
}
8282

8383
impl<'tcx> CapabilityProjections<'tcx> {
84-
pub(crate) fn debug_lines(&self) -> Vec<String> {
84+
pub(crate) fn debug_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
8585
self.iter()
86-
.map(|(p, k)| format!("{p:?}: {k:?}"))
86+
.map(|(p, k)| format!("{}: {:?}", p.to_short_string(repacker), k))
8787
.collect()
8888
}
8989

src/free_pcs/results/cursor.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl<'mir, 'tcx, D: HasPcg<'mir, 'tcx>, E: Analysis<'tcx, Domain = D>>
140140
repacks_start: state.post_main().bridge(&to.post_main(), rp),
141141
repacks_middle: Vec::new(),
142142
borrows: entry_set.get_curr_borrow_pcg().states.clone(),
143+
// TODO: It seems like extra_start should be similar to repacks_start
143144
extra_start: BorrowsBridge::new(),
144145
extra_middle: BorrowsBridge::new(),
145146
}
@@ -171,11 +172,11 @@ pub struct FreePcsBasicBlock<'tcx> {
171172
}
172173

173174
impl<'tcx> FreePcsBasicBlock<'tcx> {
174-
pub fn debug_lines(&self) -> Vec<String> {
175+
pub fn debug_lines(&self, repacker: PlaceRepacker<'_, 'tcx>) -> Vec<String> {
175176
let mut result = Vec::new();
176177
for stmt in self.statements.iter() {
177178
for phase in EvalStmtPhase::phases() {
178-
for line in stmt.debug_lines(phase) {
179+
for line in stmt.debug_lines(phase, repacker) {
179180
result.push(format!("{:?} {}: {}", stmt.location, phase, line));
180181
}
181182
}
@@ -201,9 +202,16 @@ pub struct FreePcsLocation<'tcx> {
201202
}
202203

203204
impl<'tcx> FreePcsLocation<'tcx> {
204-
pub(crate) fn debug_lines(&self, phase: EvalStmtPhase) -> Vec<String> {
205-
let mut result = self.states[phase].debug_lines();
206-
result.extend(self.borrows[phase].debug_capability_lines());
205+
pub(crate) fn debug_lines(
206+
&self,
207+
phase: EvalStmtPhase,
208+
repacker: PlaceRepacker<'_, 'tcx>,
209+
) -> Vec<String> {
210+
let mut result = self.states[phase].debug_lines(repacker);
211+
for action in self.actions[phase].iter() {
212+
result.push(action.debug_line(repacker));
213+
}
214+
result.extend(self.borrows[phase].debug_capability_lines(repacker));
207215
result
208216
}
209217
}

src/main.rs

+42-25
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::fs::File;
44
use std::io::Write;
55

6+
use pcs::utils::PlaceRepacker;
67
use std::cell::RefCell;
78
use tracing::{debug, info, trace, warn};
89
use tracing_subscriber;
@@ -65,15 +66,22 @@ fn should_check_body(body: &BodyWithBorrowckFacts<'_>) -> bool {
6566
// true
6667
}
6768

68-
fn run_pcs_on_all_fns<'tcx>(tcx: TyCtxt<'tcx>) {
69+
fn env_feature_enabled(feature: &str) -> bool {
70+
["true", "1"].contains(&std::env::var(feature).unwrap_or_default().as_str())
71+
}
72+
73+
fn run_pcg_on_all_fns<'tcx>(tcx: TyCtxt<'tcx>) {
6974
let mut item_names = vec![];
7075

71-
let vis_dir = if std::env::var("PCS_VISUALIZATION").unwrap_or_default() == "true" {
76+
let vis_dir = if env_feature_enabled("PCG_VISUALIZATION") {
7277
Some("visualization/data")
7378
} else {
7479
None
7580
};
7681

82+
let emit_pcg_annotations = env_feature_enabled("PCG_EMIT_ANNOTATIONS");
83+
let check_pcg_annotations = env_feature_enabled("PCG_CHECK_ANNOTATIONS");
84+
7785
if let Some(path) = &vis_dir {
7886
if std::path::Path::new(path).exists() {
7987
std::fs::remove_dir_all(path)
@@ -109,30 +117,39 @@ fn run_pcs_on_all_fns<'tcx>(tcx: TyCtxt<'tcx>) {
109117
tcx,
110118
vis_dir.map(|dir| format!("{}/{}", dir, item_name)),
111119
);
112-
if let Ok(source) = tcx.sess.source_map().span_to_snippet(body.body.span) {
113-
let expected_annotations = source
114-
.lines()
115-
.flat_map(|l| l.split("// PCG: ").nth(1))
116-
.map(|l| l.trim())
117-
.collect::<Vec<_>>();
118-
if !expected_annotations.is_empty() {
119-
eprintln!("Expected annotations: {:?}", expected_annotations);
120-
let mut debug_lines = Vec::new();
121-
for (idx, _) in body.body.basic_blocks.iter_enumerated() {
122-
let block = output.get_all_for_bb(idx);
123-
debug_lines.extend(block.debug_lines());
120+
if emit_pcg_annotations || check_pcg_annotations {
121+
let mut debug_lines = Vec::new();
122+
for (idx, _) in body.body.basic_blocks.iter_enumerated() {
123+
let block = output.get_all_for_bb(idx);
124+
debug_lines
125+
.extend(block.debug_lines(PlaceRepacker::new(&body.body, tcx)));
126+
}
127+
if emit_pcg_annotations {
128+
for line in debug_lines.iter() {
129+
eprintln!("// PCG: {}", line);
124130
}
125-
let missing_annotations = expected_annotations
126-
.iter()
127-
.filter(|a| !debug_lines.contains(&a.to_string()))
128-
.collect::<Vec<_>>();
129-
if !missing_annotations.is_empty() {
130-
panic!("Missing annotations: {:?}", missing_annotations);
131+
}
132+
if check_pcg_annotations {
133+
if let Ok(source) =
134+
tcx.sess.source_map().span_to_snippet(body.body.span)
135+
{
136+
let expected_annotations = source
137+
.lines()
138+
.flat_map(|l| l.split("// PCG: ").nth(1))
139+
.map(|l| l.trim())
140+
.collect::<Vec<_>>();
141+
if !expected_annotations.is_empty() {
142+
let missing_annotations = expected_annotations
143+
.iter()
144+
.filter(|a| !debug_lines.contains(&a.to_string()))
145+
.collect::<Vec<_>>();
146+
if !missing_annotations.is_empty() {
147+
panic!("Missing annotations: {:?}", missing_annotations);
148+
}
149+
}
150+
} else {
151+
tracing::warn!("No source for function: {}", item_name);
131152
}
132-
// eprintln!("Debug lines:");
133-
// for line in debug_lines {
134-
// eprintln!("{}", line);
135-
// }
136153
}
137154
}
138155
}
@@ -175,7 +192,7 @@ impl driver::Callbacks for PcsCallbacks {
175192
_compiler: &Compiler,
176193
queries: &'tcx Queries<'tcx>,
177194
) -> Compilation {
178-
queries.global_ctxt().unwrap().enter(run_pcs_on_all_fns);
195+
queries.global_ctxt().unwrap().enter(run_pcg_on_all_fns);
179196
if std::env::var("CARGO").is_ok() {
180197
Compilation::Continue
181198
} else {

tests/19_lifetime_projection.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ struct S<'a> {
77
}
88

99
fn f<'a>(s: S<'a>) {
10-
let x = s.x; // PCG: bb0[1] pre_operands: _1.1: E
11-
// PCG: bb0[1] pre_operands: _1.1↓'?6: E
10+
let x = s.x; // PCG: bb0[1] pre_operands: s.y: E
11+
// PCG: bb0[1] pre_operands: s.y↓'?6: E
1212
let y = s.y.a;
1313

1414
}

tests/27_aurel.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
struct X<'a> { a: &'a mut i32 }
22
fn foo_ref_struct<'a>(x: X<'a>) {
3-
*x.a = 42;
3+
*x.a = 42; // PCG: bb0[0] pre_main: Weaken *x.a from E to W
44
}
55
fn main(){}

tests/run_all_tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fn run_all_tests() {
3636

3737
let status = Command::new(&pcs_exe)
3838
.arg(&test_file)
39+
.env("PCG_CHECK_ANNOTATIONS", "true")
3940
.status()
4041
.unwrap_or_else(|e| panic!("Failed to execute test {}: {}", test_file.display(), e));
4142

0 commit comments

Comments
 (0)