rapx/analysis/core/range_analysis/
PassRunner.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use rustc_middle::mir::pretty::{write_mir_fn, PrettyPrintMirOptions};
use std::collections::HashMap;
#[allow(unused)]
use std::collections::HashSet;
use std::io::Cursor;
// use std::fs::File;
// use std::io::{self, Write};
// use rustc_index::bit_set::BitSet;
// use rustc_index::IndexSlice;
// use rustc_middle::mir::visit::Visitor;
// use rustc_middle::mir::visit::*;
// use rustc_middle::mir::visit::*;
// use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
// use rustc_middle::mir::{visit::MutVisitor, Body};
use crate::{rap_info, rap_warn};
use rustc_middle::ty::TyCtxt;

// use crate::domain::ConstraintGraph::ConstraintGraph;
use super::SSA::SSATransformer::SSATransformer;

use super::SSA::Replacer::*;
pub struct PassRunner<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl<'tcx> PassRunner<'tcx> {
    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx }
    }
    // pub fn print_diff(&self, body: &Body<'tcx>) {
    //     let dir_path = "passrunner_mir";
    //     // PassRunner::new(self.tcx);
    //     let mir_file_path = format!("{}/origin_mir.txt", dir_path);
    //     let phi_mir_file_path = format!("{}/after_rename_mir.txt", dir_path);
    //     let mut file = File::create(&mir_file_path).unwrap();
    //     let mut w = io::BufWriter::new(&mut file);
    //     write_mir_pretty(self.tcx, None, &mut w).unwrap();
    //     let mut file2 = File::create(&phi_mir_file_path).unwrap();
    //     let mut w2 = io::BufWriter::new(&mut file2);
    //     let options = PrettyPrintMirOptions::from_cli(self.tcx);
    //     write_mir_fn(self.tcx, body, &mut |_, _| Ok(()), &mut w2, options).unwrap();
    // }
    pub fn get_final_ssa_as_string(&self, body: &Body<'tcx>) -> String {
        // origin_mir
        // let mut buffer1 = Cursor::new(Vec::new());
        // write_mir_pretty(self.tcx, None, &mut buffer1).unwrap();
        // let origin_mir = String::from_utf8(buffer1.into_inner()).unwrap();
        // after_rename_mir
        let mut buffer2 = Cursor::new(Vec::new());
        let options = PrettyPrintMirOptions::from_cli(self.tcx);
        write_mir_fn(self.tcx, body, &mut |_, _| Ok(()), &mut buffer2, options).unwrap();
        let after_mir = String::from_utf8(buffer2.into_inner()).unwrap();
        after_mir
    }
    pub fn lvalue_check(mir_string: &str) -> bool {
        let re = regex::Regex::new(r"_(\d+)\s*=").unwrap();
        let mut counts = HashMap::new();
        let mut has_duplicate = false;

        for cap in re.captures_iter(mir_string) {
            let var = cap[1].parse::<u32>().unwrap();
            let counter = counts.entry(var).or_insert(0);
            *counter += 1;
            if *counter > 1 {
                has_duplicate = true;
            }
        }

        for (var, count) in counts {
            if count > 1 {
                rap_warn!("Variable _{} is used {} times", var, count);
            }
        }

        !has_duplicate
    }
    pub fn run_pass(&self, body: &mut Body<'tcx>) {
        let ssatransformer =
            SSATransformer::new(self.tcx, body, body.source.def_id().expect_local());
        let mut replacer = Replacer {
            tcx: self.tcx,

            ssatransformer,
            new_local_collection: HashSet::default(),
        };
        replacer.insert_phi_statment(body);
        replacer.insert_essa_statement(body);
        replacer.rename_variables(body);
        let essa_mir_string = self.get_final_ssa_as_string(body);
        rap_info!("final SSA {:?}\n", &essa_mir_string);
        rap_info!(
            "ssa lvalue check true{:?}",
            PassRunner::lvalue_check(&essa_mir_string)
        );
    }
}