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