rapx/analysis/core/range_analysis/SSA/
Replacer.rs

1#![allow(non_snake_case)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4use super::SSATransformer::SSATransformer;
5use rustc_abi::FieldIdx;
6use rustc_index::IndexVec;
7use rustc_middle::ty::TyCtxt;
8use rustc_middle::{mir::*, ty::GenericArgs};
9use std::collections::{HashMap, HashSet, VecDeque};
10// use stable_mir::mir::FieldIdx;
11// use stable_mir::ty::ConstantKind;
12// // use rustc_middle::mir::visit::*;
13// // use rustc_index::IndexSlice;
14
15pub struct Replacer<'tcx> {
16    pub(crate) tcx: TyCtxt<'tcx>,
17    pub(crate) ssatransformer: super::SSATransformer::SSATransformer<'tcx>,
18    pub(crate) new_local_collection: HashSet<Local>,
19}
20impl<'tcx> Replacer<'tcx> {
21    pub fn insert_phi_statment(&mut self, body: &mut Body<'tcx>) {
22        for (block_index, blockdata) in body.basic_blocks.iter_enumerated() {}
23        let mut phi_functions: HashMap<BasicBlock, HashSet<Local>> = HashMap::new();
24        for bb in body.basic_blocks.indices() {
25            phi_functions.insert(bb, HashSet::new());
26        }
27        let variables: Vec<Local> = self
28            .ssatransformer
29            .local_assign_blocks
30            .iter()
31            .filter(|(_, blocks)| blocks.len() >= 2)
32            .map(|(&local, _)| local)
33            .collect();
34        for var in &variables {
35            if let Some(def_blocks) = self.ssatransformer.local_assign_blocks.get(var) {
36                let mut worklist: VecDeque<BasicBlock> = def_blocks.iter().cloned().collect();
37                let mut processed: HashSet<BasicBlock> = HashSet::new();
38
39                while let Some(block) = worklist.pop_front() {
40                    if let Some(df_blocks) = self.ssatransformer.df.get(&block) {
41                        for &df_block in df_blocks {
42                            if !processed.contains(&df_block) {
43                                phi_functions.get_mut(&df_block).unwrap().insert(*var);
44                                processed.insert(df_block);
45                                if self.ssatransformer.local_assign_blocks[var].contains(&df_block)
46                                {
47                                    worklist.push_back(df_block);
48                                }
49                            }
50                        }
51                    }
52                }
53            }
54        }
55
56        for (block, vars) in phi_functions {
57            for var in vars.clone() {
58                let decl = body.local_decls[var].clone();
59                // let new_var = body.local_decls.push(decl);
60
61                // print!("body.local_decls.len():{:?}\n", body.local_decls.len());
62                let predecessors = body.basic_blocks.predecessors()[block].clone();
63
64                let mut operands = IndexVec::with_capacity(predecessors.len());
65                for _ in 0..predecessors.len() {
66                    operands.push(Operand::Copy(Place::from(var)));
67                }
68                let phi_stmt: Statement<'_> = Statement {
69                    source_info: SourceInfo::outermost(body.span),
70                    kind: StatementKind::Assign(Box::new((
71                        Place::from(var),
72                        Rvalue::Aggregate(
73                            Box::new(AggregateKind::Adt(
74                                self.ssatransformer.phi_def_id.clone(),
75                                rustc_abi::VariantIdx::from_u32(0),
76                                GenericArgs::empty(),
77                                None,
78                                None,
79                            )),
80                            operands,
81                        ),
82                    ))),
83                };
84                // let phi_stmt = Statement {
85                //     source_info: SourceInfo::outermost(body.span),
86                //     kind: StatementKind::Assign(Box::new((
87                //         Place::from(var),
88                //         Rvalue::Aggregate(Box::new(AggregateKind::Tuple), operands),
89                //     ))),
90                // };
91                body.basic_blocks_mut()[block]
92                    .statements
93                    .insert(0, phi_stmt);
94            }
95
96            for i in 0..vars.len() {
97                let phi_in_body = body.basic_blocks.as_mut()[block]
98                    .statements
99                    .get_mut(i)
100                    .unwrap();
101                let phi_ptr = phi_in_body as *const _;
102                self.ssatransformer.phi_statements.insert(phi_ptr, true);
103            }
104        }
105    }
106    pub fn insert_essa_statement(&mut self, body: &mut Body<'tcx>) {
107        let order = SSATransformer::depth_first_search_preorder(
108            &self.ssatransformer.dom_tree,
109            body.basic_blocks.indices().next().unwrap(),
110        );
111
112        for &bb in &order {
113            self.essa_process_basic_block(bb, body);
114        }
115    }
116
117    fn essa_process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
118        let switch_block_data = body.basic_blocks[bb].clone();
119
120        if let Some(terminator) = &switch_block_data.terminator {
121            if let TerminatorKind::SwitchInt { discr, targets, .. } = &terminator.kind {
122                {
123                    for (value, target) in targets.iter() {
124                        self.essa_assign_statement(&target, &bb, value, discr, body);
125                    }
126                    let otherwise = targets.otherwise();
127
128                    self.essa_assign_statement(&otherwise, &bb, 1, discr, body);
129                }
130            }
131        }
132    }
133    fn extract_condition(
134        &self,
135        place: &Place<'tcx>,
136        switch_block: &BasicBlockData<'tcx>,
137    ) -> Option<(Operand<'tcx>, Operand<'tcx>, BinOp)> {
138        for stmt in &switch_block.statements {
139            if let StatementKind::Assign(box (lhs, Rvalue::BinaryOp(bin_op, box (op1, op2)))) =
140                &stmt.kind
141            {
142                if lhs == place {
143                    let mut return_op1: &Operand<'tcx> = &op1;
144                    let mut return_op2: &Operand<'tcx> = &op2;
145                    for stmt_original in &switch_block.statements {
146                        if let StatementKind::Assign(box (lhs, Rvalue::Use(OP1))) =
147                            &stmt_original.kind
148                        {
149                            if lhs.clone() == op1.place().unwrap() {
150                                return_op1 = OP1;
151                            }
152                        }
153                    }
154                    if op2.constant().is_none() {
155                        for stmt_original in &switch_block.statements {
156                            if let StatementKind::Assign(box (lhs, Rvalue::Use(OP2))) =
157                                &stmt_original.kind
158                            {
159                                if lhs.clone() == op2.place().unwrap() {
160                                    return_op2 = OP2;
161                                }
162                            }
163                        }
164                    }
165                    return Some((return_op1.clone(), return_op2.clone(), *bin_op));
166                }
167            }
168        }
169        None
170    }
171    // pub
172    fn essa_assign_statement(
173        &mut self,
174        bb: &BasicBlock,
175        switch_block: &BasicBlock,
176        value: u128,
177        discr: &Operand<'tcx>,
178        body: &mut Body<'tcx>,
179    ) {
180        let switch_block_data = &body.basic_blocks[*switch_block];
181
182        // let mut essa_operands: IndexVec<_, _> = IndexVec::with_capacity(2);
183        let magic_number = 213134123 as u64;
184        let magic_number_operand = Operand::Constant(Box::new(ConstOperand {
185            span: rustc_span::DUMMY_SP,
186            user_ty: None,
187            const_: Const::from_usize(self.tcx, magic_number),
188        }));
189        let Lt_operand = Operand::Constant(Box::new(ConstOperand {
190            span: rustc_span::DUMMY_SP,
191            user_ty: None,
192            const_: Const::from_usize(self.tcx, 1),
193        }));
194        let Le_operand = Operand::Constant(Box::new(ConstOperand {
195            span: rustc_span::DUMMY_SP,
196            user_ty: None,
197            const_: Const::from_usize(self.tcx, 2),
198        }));
199        let Ge_operand = Operand::Constant(Box::new(ConstOperand {
200            span: rustc_span::DUMMY_SP,
201            user_ty: None,
202            const_: Const::from_usize(self.tcx, 3),
203        }));
204        let Gt_operand = Operand::Constant(Box::new(ConstOperand {
205            span: rustc_span::DUMMY_SP,
206            user_ty: None,
207            const_: Const::from_usize(self.tcx, 4),
208        }));
209        if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
210            if let Some((op1, op2, cmp_op)) =
211                self.extract_condition(switch_place, switch_block_data)
212            {
213                let block_data: &mut BasicBlockData<'tcx> = &mut body.basic_blocks.as_mut()[*bb];
214
215                let const_op1: Option<&ConstOperand<'_>> = op1.constant();
216                let const_op2: Option<&ConstOperand<'_>> = op2.constant();
217                let cmp_operand: Operand<'_> = match cmp_op.clone() {
218                    BinOp::Lt => Lt_operand.clone(),
219                    BinOp::Le => Le_operand.clone(),
220                    BinOp::Gt => Gt_operand.clone(),
221                    BinOp::Ge => Ge_operand.clone(),
222                    _ => panic!("not a comparison operator"),
223                };
224                let flip_cmp_operand: Operand<'_> = match Self::flip(cmp_op) {
225                    BinOp::Lt => Gt_operand.clone(),
226                    BinOp::Le => Ge_operand.clone(),
227                    BinOp::Gt => Lt_operand.clone(),
228                    BinOp::Ge => Le_operand.clone(),
229                    _ => panic!("not a comparison operator"),
230                };
231
232                match (const_op1, const_op2) {
233                    (None, None) => {
234                        match (op1, op2) {
235                            (
236                                Operand::Copy(p1) | Operand::Move(p1),
237                                Operand::Copy(p2) | Operand::Move(p2),
238                            ) => {
239                                let ADT = AggregateKind::Adt(
240                                    self.ssatransformer.essa_def_id.clone(),
241                                    rustc_abi::VariantIdx::from_u32(0),
242                                    GenericArgs::empty(),
243                                    None,
244                                    None,
245                                );
246                                let place1 = Place::from(p1);
247                                let place2 = Place::from(p2);
248                                let rvalue1;
249                                let rvalue2;
250                                let mut operand1: IndexVec<_, _> = IndexVec::with_capacity(4);
251                                let mut operand2: IndexVec<_, _> = IndexVec::with_capacity(4);
252
253                                if value == 0 {
254                                    operand1.push(Operand::Copy(Place::from(p1)));
255                                    operand1.push(Operand::Copy(Place::from(p2)));
256                                    operand1.push(flip_cmp_operand.clone());
257                                    operand1.push(magic_number_operand.clone());
258
259                                    operand2.push(Operand::Copy(Place::from(p2)));
260                                    operand2.push(Operand::Copy(Place::from(p1)));
261                                    operand2.push(cmp_operand.clone());
262                                    operand2.push(magic_number_operand.clone());
263                                    //     rvalue1 =
264                                    //     Rvalue::Aggregate(Box::new(AggregateKind::Tuple), operand1);
265                                    // rvalue2 =
266                                    //     Rvalue::Aggregate(Box::new(AggregateKind::Tuple), operand2);
267                                    rvalue1 = Rvalue::Aggregate(Box::new(ADT.clone()), operand1);
268                                    rvalue2 = Rvalue::Aggregate(Box::new(ADT.clone()), operand2);
269                                } else {
270                                    operand1.push(Operand::Copy(Place::from(p1)));
271                                    operand1.push(Operand::Copy(Place::from(p2)));
272                                    operand1.push(cmp_operand.clone());
273                                    operand1.push(magic_number_operand.clone());
274
275                                    operand2.push(Operand::Copy(Place::from(p2)));
276                                    operand2.push(Operand::Copy(Place::from(p1)));
277                                    operand2.push(flip_cmp_operand.clone());
278                                    operand2.push(magic_number_operand.clone());
279                                    // rvalue1 =
280                                    //     Rvalue::Aggregate(Box::new(AggregateKind::Tuple), operand1);
281                                    // rvalue2 =
282                                    //     Rvalue::Aggregate(Box::new(AggregateKind::Tuple), operand2);
283                                    rvalue1 = Rvalue::Aggregate(Box::new(ADT.clone()), operand1);
284                                    rvalue2 = Rvalue::Aggregate(Box::new(ADT.clone()), operand2);
285                                }
286
287                                let assign_stmt1 = Statement {
288                                    source_info: SourceInfo::outermost(body.span),
289                                    kind: StatementKind::Assign(Box::new((place1, rvalue1))),
290                                };
291                                let assign_stmt2 = Statement {
292                                    source_info: SourceInfo::outermost(body.span),
293                                    kind: StatementKind::Assign(Box::new((place2, rvalue2))),
294                                };
295                                block_data.statements.insert(0, assign_stmt2);
296                                block_data.statements.insert(0, assign_stmt1);
297
298                                for i in 0..2 {
299                                    let essa_in_body = block_data.statements.get_mut(i).unwrap();
300                                    let essa_ptr = essa_in_body as *const _;
301                                    self.ssatransformer.essa_statements.insert(essa_ptr, true);
302                                }
303                            }
304                            _ => panic!("Expected a place"),
305                        };
306                    }
307                    (None, Some(_)) | (Some(_), None) => {
308                        let mut operand: IndexVec<_, _> = IndexVec::with_capacity(3);
309
310                        let place = match op1 {
311                            Operand::Copy(p) | Operand::Move(p) => Place::from(p),
312                            _ => panic!("Expected a place"),
313                        };
314                        operand.push(op1.clone());
315                        operand.push(op2.clone());
316                        let rvalue;
317                        if value == 0 {
318                            operand.push(flip_cmp_operand.clone());
319                        } else {
320                            operand.push(cmp_operand.clone());
321                        }
322                        let ADT = AggregateKind::Adt(
323                            self.ssatransformer.essa_def_id.clone(),
324                            rustc_abi::VariantIdx::from_u32(0),
325                            GenericArgs::empty(),
326                            None,
327                            None,
328                        );
329                        rvalue = Rvalue::Aggregate(Box::new(ADT.clone()), operand);
330                        let assign_stmt = Statement {
331                            source_info: SourceInfo::outermost(body.span),
332                            kind: StatementKind::Assign(Box::new((place, rvalue))),
333                        };
334                        block_data.statements.insert(0, assign_stmt);
335
336                        for i in 0..1 {
337                            let essa_in_body = block_data.statements.get_mut(i).unwrap();
338                            let essa_ptr = essa_in_body as *const _;
339                            self.ssatransformer.essa_statements.insert(essa_ptr, true);
340                        }
341                    }
342
343                    (Some(_), Some(_)) => {}
344                }
345            };
346        }
347
348        // block_data.statements.insert(0, assign_stmt);
349    }
350    pub fn flip(binOp: BinOp) -> BinOp {
351        match binOp {
352            BinOp::Lt => BinOp::Ge,
353            BinOp::Le => BinOp::Gt,
354            BinOp::Gt => BinOp::Le,
355            BinOp::Ge => BinOp::Lt,
356            _ => panic!("flip() called on non-comparison operator"),
357        }
358    }
359    pub fn rename_variables(&mut self, body: &mut Body<'tcx>) {
360        for local in body.local_decls.indices() {
361            self.ssatransformer.reaching_def.insert(local, None);
362        }
363        // self.ssatransformer.local_defination_block = Self::map_locals_to_definition_block(&self.body.borrow());
364
365        let order = SSATransformer::depth_first_search_preorder(
366            &self.ssatransformer.dom_tree,
367            body.basic_blocks.indices().next().unwrap().clone(),
368        );
369        for bb in order {
370            self.process_basic_block(bb, body);
371        }
372    }
373
374    fn process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
375        self.rename_statement(bb, body);
376        self.rename_terminator(bb, body);
377        let terminator = body.basic_blocks[bb].terminator();
378        let successors: Vec<_> = terminator.successors().collect();
379        if let TerminatorKind::SwitchInt { .. } = &terminator.kind {
380            for succ_bb in successors.clone() {
381                self.process_essa_statments(succ_bb, body, bb);
382            }
383        }
384
385        for succ_bb in successors {
386            self.process_phi_functions(succ_bb, body, bb);
387        }
388    }
389    pub fn process_essa_statments(
390        &mut self,
391        succ_bb: BasicBlock,
392        body: &mut Body<'tcx>,
393        switch_bb: BasicBlock,
394    ) {
395        let switch_block_data = &body.basic_blocks[switch_bb];
396        if let Some(terminator) = &switch_block_data.terminator {
397            if let TerminatorKind::SwitchInt { discr, .. } = &terminator.kind {
398                if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
399                    if let Some((op1, op2, cmp_op)) =
400                        self.extract_condition(switch_place, switch_block_data)
401                    {
402                        if op2.constant().is_none() {
403                            let essa_statement = body.basic_blocks.as_mut()[succ_bb]
404                                .statements
405                                .get_mut(0)
406                                .unwrap();
407                            match &mut essa_statement.kind {
408                                StatementKind::Assign(box (place, rvalue)) => {
409                                    if let Rvalue::Aggregate(_, operands) = rvalue {
410                                        let loc_1: usize = 0;
411                                        let loc_2: usize = 1;
412
413                                        operands[FieldIdx::from_usize(loc_1)] = op1.clone();
414                                        operands[FieldIdx::from_usize(loc_2)] = op2.clone();
415                                    }
416                                }
417                                _ => {}
418                            }
419                            let essa_statement = body.basic_blocks.as_mut()[succ_bb]
420                                .statements
421                                .get_mut(1)
422                                .unwrap();
423                            match &mut essa_statement.kind {
424                                StatementKind::Assign(box (place, rvalue)) => {
425                                    if let Rvalue::Aggregate(_, operands) = rvalue {
426                                        let loc_1: usize = 0;
427                                        let loc_2: usize = 1;
428                                        operands[FieldIdx::from_usize(loc_1)] = op2.clone();
429                                        operands[FieldIdx::from_usize(loc_2)] = op1.clone();
430                                    }
431                                }
432                                _ => {}
433                            }
434                        } else {
435                            let essa_statement = body.basic_blocks.as_mut()[succ_bb]
436                                .statements
437                                .get_mut(0)
438                                .unwrap();
439                            match &mut essa_statement.kind {
440                                StatementKind::Assign(box (place, rvalue)) => {
441                                    if let Rvalue::Aggregate(_, operands) = rvalue {
442                                        let loc: usize = 0;
443                                        operands[FieldIdx::from_usize(loc)] = op1.clone();
444                                    }
445                                }
446                                _ => {}
447                            }
448                        }
449                    }
450                }
451            }
452        }
453    }
454
455    fn process_phi_functions(
456        &mut self,
457        succ_bb: BasicBlock,
458        body: &mut Body<'tcx>,
459        do_bb: BasicBlock,
460    ) {
461        for statement in body.basic_blocks.as_mut()[succ_bb].statements.iter_mut() {
462            let phi_stmt = statement as *const _;
463
464            if SSATransformer::is_phi_statement(&self.ssatransformer, statement) {
465                if let StatementKind::Assign(box (_, rvalue)) = &mut statement.kind {
466                    if let Rvalue::Aggregate(_, operands) = rvalue {
467                        let operand_count = operands.len();
468                        let index = self
469                            .ssatransformer
470                            .phi_index
471                            .entry(phi_stmt)
472                            .or_insert(0)
473                            .clone();
474
475                        if index < operand_count {
476                            // self.replace_operand(&mut operands[(index).into()], &succ_bb);s
477                            match &mut operands[FieldIdx::from_usize(index)] {
478                                Operand::Copy(place) | Operand::Move(place) => {
479                                    self.replace_place(place, &do_bb);
480                                }
481                                _ => {}
482                            }
483                            *self.ssatransformer.phi_index.entry(phi_stmt).or_insert(0) += 1;
484                            // if *index >= operand_count {
485                            //     self.ssatransformer.phi_index.remove(&phi_stmt);
486                            // }
487                        }
488                    }
489                }
490            }
491        }
492    }
493
494    pub fn rename_statement(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
495        for statement in body.basic_blocks.as_mut()[bb].statements.iter_mut() {
496            // let rc_stat = Rc::new(RefCell::new(statement));
497            let is_phi = SSATransformer::is_phi_statement(&self.ssatransformer, statement);
498            let is_essa = SSATransformer::is_essa_statement(&self.ssatransformer, statement);
499            match &mut statement.kind {
500                StatementKind::Assign(box (place, rvalue)) => {
501                    if !is_phi {
502                        if !is_essa {
503                            self.replace_rvalue(rvalue, &bb);
504                            self.rename_local_def(place, &bb, true);
505                        } else {
506                            self.ssa_rename_local_def(place, &bb, true);
507                        }
508                    } else {
509                        self.ssa_rename_local_def(place, &bb, false);
510                    }
511                }
512                // StatementKind::FakeRead(_, place)
513                StatementKind::Deinit(place) | StatementKind::SetDiscriminant { place, .. } => {
514                    // let place_mut = unsafe { &mut *(place as *const _ as *mut _) };
515
516                    // self.replace_place(place.as_mut());
517                }
518                StatementKind::StorageLive(local) => {
519                    // self.rename_local_def(*local);
520                }
521                StatementKind::StorageDead(local) => {
522                    // self.replace_local(local);
523                }
524                _ => {}
525            }
526        }
527    }
528
529    fn rename_terminator(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
530        let terminator: &mut Terminator<'tcx> = body.basic_blocks.as_mut()[bb].terminator_mut();
531        match &mut terminator.kind {
532            TerminatorKind::Call {
533                args, destination, ..
534            } => {
535                // for operand in args {
536                //     self.replace_operand(operand);
537                // }
538                // if let Some((place, _)) = destination {
539                //     self.rename_def(place);
540                // }
541            }
542            TerminatorKind::Assert { cond, .. } => {
543                self.replace_operand(cond, &bb);
544            }
545            TerminatorKind::Drop { place, .. } => {
546                self.replace_place(place, &bb);
547            }
548            TerminatorKind::SwitchInt { discr, .. } => {
549                self.replace_operand(discr, &bb);
550            }
551            _ => {}
552        }
553    }
554
555    fn replace_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, bb: &BasicBlock) {
556        match rvalue {
557            Rvalue::Use(operand)
558            | Rvalue::Repeat(operand, _)
559            | Rvalue::UnaryOp(_, operand)
560            | Rvalue::Cast(_, operand, _)
561            | Rvalue::ShallowInitBox(operand, _) => {
562                self.replace_operand(operand, &bb);
563            }
564            Rvalue::BinaryOp(_, box (lhs, rhs)) => {
565                self.replace_operand(lhs, &bb);
566                self.replace_operand(rhs, &bb);
567            }
568            Rvalue::Aggregate(_, operands) => {
569                for operand in operands {
570                    self.replace_operand(operand, &bb);
571                }
572            }
573            _ => {}
574        }
575    }
576
577    fn replace_operand(&mut self, operand: &mut Operand<'tcx>, bb: &BasicBlock) {
578        match operand {
579            Operand::Copy(place) | Operand::Move(place) => {
580                self.replace_place(place, bb);
581                // print!("replace_operand: {:?} -> {:?}\n", place.local, place.local);
582            }
583            _ => {}
584        }
585    }
586
587    fn replace_place(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock) {
588        // let old_local = place.local;
589        self.update_reachinf_def(&place.local, &bb);
590
591        if let Some(Some(reaching_local)) = self.ssatransformer.reaching_def.get(&place.local) {
592            let local = reaching_local.clone();
593            *place = Place::from(local);
594        } else {
595        }
596    }
597
598    fn ssa_rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
599        // let old_local = place.as_local().as_mut().unwrap();
600        self.update_reachinf_def(&place.local, &bb);
601        let Place {
602            local: old_local,
603            projection: _,
604        } = place;
605
606        let new_local = Local::from_u32(self.ssatransformer.local_index);
607        self.ssatransformer.local_index += 1;
608
609        let _old_local = old_local.clone();
610        self.ssatransformer
611            .ssa_locals_map
612            .entry(*old_local)
613            .or_insert_with(HashSet::new)
614            .insert(new_local.clone());
615
616        *place = Place::from(new_local);
617        self.ssatransformer
618            .local_defination_block
619            .insert(new_local.clone(), bb.clone());
620        let old_local_reaching = self
621            .ssatransformer
622            .reaching_def
623            .get(&_old_local.clone())
624            .unwrap();
625
626        self.ssatransformer
627            .reaching_def
628            .insert(new_local.clone(), *old_local_reaching);
629        self.ssatransformer
630            .reaching_def
631            .insert(_old_local.clone(), Some(new_local.clone()));
632
633        // self.reaching_def
634        //     .entry(old_local)
635        //     .or_default()
636        //     .replace(Some(old_local));
637    }
638    fn rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
639        // let old_local = place.as_local().as_mut().unwrap();
640        self.update_reachinf_def(&place.local, &bb);
641        let Place {
642            local: old_local,
643            projection: _,
644        } = place;
645        //find the original local defination assign statement
646        if self.ssatransformer.skipped.contains(&old_local.as_u32()) && not_phi {
647            self.ssatransformer.skipped.remove(&old_local.as_u32());
648            self.ssatransformer
649                .reaching_def
650                .insert(*old_local, Some(*old_local));
651            self.ssatransformer
652                .locals_map
653                .entry(*old_local)
654                .or_insert_with(HashSet::new)
655                .insert(*old_local);
656            return;
657        }
658        let new_local = Local::from_u32(self.ssatransformer.local_index);
659        self.ssatransformer.local_index += 1;
660        self.ssatransformer
661            .locals_map
662            .entry(*old_local)
663            .or_insert_with(HashSet::new)
664            .insert(new_local);
665
666        let _old_local = old_local.clone();
667        *place = Place::from(new_local);
668        self.ssatransformer
669            .local_defination_block
670            .insert(new_local.clone(), bb.clone());
671        let old_local_reaching = self
672            .ssatransformer
673            .reaching_def
674            .get(&_old_local.clone())
675            .unwrap();
676
677        self.ssatransformer
678            .reaching_def
679            .insert(new_local.clone(), *old_local_reaching);
680        self.ssatransformer
681            .reaching_def
682            .insert(_old_local.clone(), Some(new_local.clone()));
683
684        // self.reaching_def
685        //     .entry(old_local)
686        //     .or_default()
687        //     .replace(Some(old_local));
688    }
689
690    pub fn dominates_(&self, def_bb: &BasicBlock, bb: &BasicBlock) -> bool {
691        let mut visited = HashSet::new();
692
693        let mut stack = self.ssatransformer.dom_tree.get(def_bb).unwrap().clone();
694        while let Some(block) = stack.pop() {
695            if !visited.insert(block) {
696                continue;
697            }
698
699            if block == *bb {
700                return true;
701            }
702
703            if let Some(children) = self.ssatransformer.dom_tree.get(&block) {
704                stack.extend(children);
705            }
706        }
707
708        false
709    }
710    fn update_reachinf_def(&mut self, local: &Local, bb: &BasicBlock) {
711        // if self.ssatransformer.reaching_def[local]!= None {
712        //     return;
713        // }
714        let mut r = self.ssatransformer.reaching_def[local];
715        let mut dominate_bool = true;
716        if r != None {
717            let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
718        }
719
720        while !(r == None || dominate_bool) {
721            r = self.ssatransformer.reaching_def[&r.unwrap()];
722            if r != None {
723                let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
724
725                dominate_bool = self.dominates_(&def_bb, bb);
726            }
727        }
728
729        if let Some(entry) = self.ssatransformer.reaching_def.get_mut(local) {
730            *entry = r.clone();
731        }
732    }
733}
734
735// impl<'tcx> MutVisitor<'tcx> for Replacer< 'tcx> {
736//     fn tcx(&self) -> TyCtxt<'tcx> {
737//         self.tcx
738//     }
739
740//     fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) {
741//         let new_local = self.copy_classes[*local];
742//         // We must not unify two locals that are borrowed. But this is fine if one is borrowed and
743//         // the other is not. We chose to check the original local, and not the target. That way, if
744//         // the original local is borrowed and the target is not, we do not pessimize the whole class.
745//         if self.borrowed_locals.contains(*local) {
746//             return;
747//         }
748//         match ctxt {
749//             // Do not modify the local in storage statements.
750//             PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {}
751//             // The local should have been marked as non-SSA.
752//             PlaceContext::MutatingUse(_) => assert_eq!(*local, new_local),
753//             // We access the value.
754//             _ => *local = new_local,
755//             // _ => *local = new_local,
756//         }
757//     }
758
759//     fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, loc: Location) {
760//         if let Some(new_projection) = self.process_projection(place.projection, loc) {
761//             place.projection = self.tcx().mk_place_elems(&new_projection);
762//         }
763//         // Any non-mutating use context is ok.
764//         let ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
765//         self.visit_local(&mut place.local, ctxt, loc);
766//         print!("{:?}", place);
767//     }
768
769//     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
770//         if let Operand::Move(place) = *operand
771//             // A move out of a projection of a copy is equivalent to a copy of the original
772//             // projection.
773//             && !place.is_indirect_first_projection()
774//             && !self.fully_moved.contains(place.local)
775//         {
776//             *operand = Operand::Copy(place);
777//         }
778//         self.super_operand(operand, loc);
779//     }
780
781//     fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
782//         // When removing storage statements, we need to remove both (#107511).
783//         if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = stmt.kind
784//             && self.storage_to_remove.contains(l)
785//         {
786//             stmt.make_nop();
787//             return;
788//         }
789
790//         self.super_statement(stmt, loc);
791
792//         // Do not leave tautological assignments around.
793//         if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
794//             && let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) | Rvalue::CopyForDeref(rhs) =
795//                 *rhs
796//             && lhs == rhs
797//         {
798//             stmt.make_nop();
799//         }
800//     }
801//     fn visit_body_preserves_cfg(&mut self, body: &mut Body<'tcx>) {}
802//     fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
803//         let BasicBlockData {
804//             statements,
805//             terminator,
806//             is_cleanup: _,
807//         } = data;
808//     }
809// }