rapx/analysis/core/range_analysis/
PassRunner.rs

1#![allow(unused_imports)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4#![allow(unused_assignments)]
5#![allow(unused_parens)]
6#![allow(non_snake_case)]
7use crate::{rap_info, rap_warn};
8
9use super::SSA::SSATransformer::SSATransformer;
10use rustc_hir::def_id::DefId;
11use rustc_hir::def_id::LocalDefId;
12use rustc_middle::mir::pretty::{write_mir_fn, PrettyPrintMirOptions};
13use rustc_middle::mir::*;
14use rustc_middle::ty::TyCtxt;
15use std::collections::HashMap;
16use std::collections::HashSet;
17use std::fs;
18use std::fs::File;
19use std::io;
20use std::io::Cursor;
21
22use super::SSA::Replacer::*;
23pub struct PassRunner<'tcx> {
24    tcx: TyCtxt<'tcx>,
25    pub locals_map: HashMap<Local, HashSet<Local>>,
26}
27pub fn lvalue_check(mir_string: &str) -> bool {
28    let re = regex::Regex::new(r"_(\d+)\s*=").unwrap();
29    let mut counts = HashMap::new();
30    let mut has_duplicate = false;
31
32    for cap in re.captures_iter(mir_string) {
33        let var = cap[1].parse::<u32>().unwrap();
34        let counter = counts.entry(var).or_insert(0);
35        *counter += 1;
36        if *counter > 1 {
37            has_duplicate = true;
38        }
39    }
40
41    for (var, count) in counts {
42        if count > 1 {
43            rap_warn!("Variable _ {} is used {} times", var, count);
44        }
45    }
46
47    !has_duplicate
48}
49pub fn print_diff<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
50    let dir_path = "passrunner_mir";
51    fs::create_dir_all(dir_path).unwrap();
52    // PassRunner::new(self.tcx);
53    let mir_file_path = format!("{}/origin_mir.txt", dir_path);
54    let phi_mir_file_path = format!("{}/after_rename_mir.txt", dir_path);
55    let mut file = File::create(&mir_file_path).unwrap();
56    let mut w = io::BufWriter::new(&mut file);
57    write_mir_pretty(tcx, None, &mut w).unwrap();
58    let mut file2 = File::create(&phi_mir_file_path).unwrap();
59    let mut w2 = io::BufWriter::new(&mut file2);
60    let options = PrettyPrintMirOptions::from_cli(tcx);
61    write_mir_fn(tcx, body, &mut |_, _| Ok(()), &mut w2, options).unwrap();
62}
63impl<'tcx> PassRunner<'tcx> {
64    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
65        Self {
66            tcx,
67            locals_map: HashMap::default(),
68        }
69    }
70
71    pub fn get_final_ssa_as_string(&self, body: &Body<'tcx>) -> String {
72        let mut buffer2 = Cursor::new(Vec::new());
73        let options = PrettyPrintMirOptions::from_cli(self.tcx);
74        write_mir_fn(self.tcx, body, &mut |_, _| Ok(()), &mut buffer2, options).unwrap();
75        let after_mir = String::from_utf8(buffer2.into_inner()).unwrap();
76        after_mir
77    }
78
79    pub fn run_pass(&mut self, body: &mut Body<'tcx>, ssa_def_id: DefId, essa_def_id: DefId) {
80        let ssatransformer = SSATransformer::new(self.tcx, body, ssa_def_id, essa_def_id);
81        ssatransformer.print_ssatransformer();
82        let mut replacer = Replacer {
83            tcx: self.tcx,
84            ssatransformer,
85            new_local_collection: HashSet::default(),
86        };
87        replacer.insert_phi_statment(body);
88        replacer.insert_essa_statement(body);
89        replacer.rename_variables(body);
90        self.locals_map = replacer.ssatransformer.locals_map.clone();
91        print_diff(self.tcx, body);
92    }
93}