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