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};
12pub 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 while let Some(block) = worklist.pop_front() {
42 if let Some(df_blocks) = self.ssatransformer.df.get(&block) {
43 for &df_block in df_blocks {
44 if !processed.contains(&df_block) {
45 phi_functions.get_mut(&df_block).unwrap().insert(*var);
46 processed.insert(df_block);
47
48 worklist.push_back(df_block);
49 }
50 }
51 }
52 }
53 }
68 }
69
70 for (block, vars) in phi_functions {
71 for var in vars.clone() {
72 let decl = body.local_decls[var].clone();
73 let predecessors = body.basic_blocks.predecessors()[block].clone();
77
78 let mut operands = IndexVec::with_capacity(predecessors.len());
79 for _ in 0..predecessors.len() {
80 operands.push(Operand::Copy(Place::from(var)));
81 }
82 let phi_stmt: Statement<'_> = Statement::new(
83 SourceInfo::outermost(body.span),
84 StatementKind::Assign(Box::new((
85 Place::from(var),
86 Rvalue::Aggregate(
87 Box::new(AggregateKind::Adt(
88 self.ssatransformer.phi_def_id.clone(),
89 rustc_abi::VariantIdx::from_u32(0),
90 GenericArgs::empty(),
91 None,
92 None,
93 )),
94 operands,
95 ),
96 ))),
97 );
98 body.basic_blocks_mut()[block]
106 .statements
107 .insert(0, phi_stmt);
108 }
109 }
110 }
111 pub fn insert_essa_statement(&mut self, body: &mut Body<'tcx>) {
112 let order = SSATransformer::depth_first_search_preorder(
113 &self.ssatransformer.dom_tree,
114 body.basic_blocks.indices().next().unwrap(),
115 );
116
117 for &bb in &order {
118 self.essa_process_basic_block(bb, body);
119 }
120 }
121
122 fn essa_process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
123 let switch_block_data = body.basic_blocks[bb].clone();
124
125 if let Some(terminator) = &switch_block_data.terminator {
126 if let TerminatorKind::SwitchInt { discr, targets, .. } = &terminator.kind {
127 if targets.iter().count() == 1 {
128 let (value, target) = targets.iter().next().unwrap();
129 self.essa_assign_statement(&target, &bb, value, discr, body);
130
131 let otherwise = targets.otherwise();
132 self.essa_assign_statement(&otherwise, &bb, 1, discr, body);
133 }
134 }
135 }
136 }
137
138 fn extract_condition(
139 &self,
140 place: &Place<'tcx>,
141 switch_block: &BasicBlockData<'tcx>,
142 ) -> Option<(Operand<'tcx>, Operand<'tcx>, BinOp)> {
143 for stmt in &switch_block.statements {
144 if let StatementKind::Assign(assign) = &stmt.kind {
145 let (lhs, rvalue) = &**assign;
146 if let Rvalue::BinaryOp(bin_op, pair) = rvalue {
147 let (op1, op2) = &**pair;
148 if lhs == place {
149 let return_op1: &Operand<'tcx> = &op1;
150 let return_op2: &Operand<'tcx> = &op2;
151
152 return Some((return_op1.clone(), return_op2.clone(), *bin_op));
153 }
154 }
155 }
156 }
157 None
158 }
159 fn make_const_operand(&self, val: u64) -> Operand<'tcx> {
160 Operand::Constant(Box::new(ConstOperand {
161 span: rustc_span::DUMMY_SP,
162 user_ty: None,
163 const_: Const::from_usize(self.tcx, val),
164 }))
165 }
166
167 fn op_to_code(op: BinOp) -> u64 {
168 match op {
169 BinOp::Lt => 1,
170 BinOp::Le => 2,
171 BinOp::Ge => 3,
172 BinOp::Gt => 4,
173 BinOp::Eq => 5,
174 BinOp::Ne => 6,
175 _ => 7,
176 }
177 }
178 fn trace_operand_source(
179 &self,
180 body: &Body<'tcx>,
181 mut current_block: BasicBlock,
182 target_place: Place<'tcx>,
183 ) -> Operand<'tcx> {
184 let mut visited = HashSet::new();
185 let current_place = target_place;
186
187 while visited.insert(current_block) {
188 let data = &body.basic_blocks[current_block];
189 for stmt in data.statements.iter().rev() {
190 if let StatementKind::Assign(assign) = &stmt.kind {
191 let (lhs, rvalue) = &**assign;
192 if *lhs == current_place {
193 match rvalue {
194 Rvalue::Use(op, ..) => return op.clone(),
195 _ => return Operand::Copy(current_place),
196 }
197 }
198 }
199 }
200
201 let preds = &body.basic_blocks.predecessors()[current_block];
202 if preds.len() == 1 {
203 current_block = preds[0];
204 } else {
205 break;
206 }
207 }
208
209 Operand::Copy(current_place)
210 }
211 fn essa_assign_statement(
215 &mut self,
216 bb: &BasicBlock,
217 switch_block: &BasicBlock,
218 value: u128,
219 discr: &Operand<'tcx>,
220 body: &mut Body<'tcx>,
221 ) {
222 let switch_block_data = &body.basic_blocks[*switch_block];
223
224 let magic_number_operand = self.make_const_operand(switch_block.as_usize() as u64);
225
226 if let Operand::Copy(switch_place) | Operand::Move(switch_place) = discr {
228 if let Some((op1, op2, cmp_op)) =
230 self.extract_condition(switch_place, switch_block_data)
231 {
232 let op1 = if let Some(p1) = op1.place() {
233 self.trace_operand_source(body, *switch_block, p1)
234 } else {
235 op1
236 };
237
238 let op2 = if let Some(p2) = op2.place() {
239 self.trace_operand_source(body, *switch_block, p2)
240 } else {
241 op2
242 };
243 rap_debug!(
244 "essa trace_operand_source op1:{:?} op2:{:?} cmp_op:{:?} value:{:?}\n",
245 op1,
246 op2,
247 cmp_op,
248 value
249 );
250 let block_data: &mut BasicBlockData<'tcx> = &mut body.basic_blocks.as_mut()[*bb];
251
252 let const_op1: Option<&ConstOperand<'_>> = op1.constant();
253 let const_op2: Option<&ConstOperand<'_>> = op2.constant();
254
255 let cmp_operand = self.make_const_operand(Self::op_to_code(cmp_op));
257 let flip_cmp_operand =
258 self.make_const_operand(Self::op_to_code(Self::flip(cmp_op)));
259 let reverse_cmp_operand =
260 self.make_const_operand(Self::op_to_code(Self::reverse(cmp_op)));
261 let flip_reverse_cmp_operand =
262 self.make_const_operand(Self::op_to_code(Self::flip(Self::reverse(cmp_op))));
263
264 match (const_op1, const_op2) {
265 (None, None) => {
267 match (op1, op2) {
268 (
269 Operand::Copy(p1) | Operand::Move(p1),
270 Operand::Copy(p2) | Operand::Move(p2),
271 ) => {
272 let adt_kind = AggregateKind::Adt(
273 self.ssatransformer.essa_def_id.clone(),
274 rustc_abi::VariantIdx::from_u32(0),
275 GenericArgs::empty(),
276 None,
277 None,
278 );
279 let place1 = Place::from(p1);
280 let place2 = Place::from(p2);
281 let rvalue1;
282 let rvalue2;
283 let mut operand1: IndexVec<_, _> = IndexVec::with_capacity(4);
284 let mut operand2: IndexVec<_, _> = IndexVec::with_capacity(4);
285
286 if value == 0 {
288 operand1.push(Operand::Copy(Place::from(p1)));
291 operand1.push(Operand::Copy(Place::from(p2)));
292 operand1.push(flip_cmp_operand.clone());
293 operand1.push(magic_number_operand.clone());
294
295 operand2.push(Operand::Copy(Place::from(p2)));
297 operand2.push(Operand::Copy(Place::from(p1)));
298 operand2.push(flip_reverse_cmp_operand.clone());
299 operand2.push(magic_number_operand.clone());
300
301 rvalue1 =
302 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand1);
303 rvalue2 =
304 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand2);
305 } else {
306 operand1.push(Operand::Copy(Place::from(p1)));
309 operand1.push(Operand::Copy(Place::from(p2)));
310 operand1.push(cmp_operand.clone());
311 operand1.push(magic_number_operand.clone());
312
313 operand2.push(Operand::Copy(Place::from(p2)));
315 operand2.push(Operand::Copy(Place::from(p1)));
316 operand2.push(reverse_cmp_operand.clone());
317 operand2.push(magic_number_operand.clone());
318
319 rvalue1 =
320 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand1);
321 rvalue2 =
322 Rvalue::Aggregate(Box::new(adt_kind.clone()), operand2);
323 }
324
325 let assign_stmt1 = Statement::new(
326 SourceInfo::outermost(body.span),
327 StatementKind::Assign(Box::new((place1, rvalue1))),
328 );
329 let assign_stmt2 = Statement::new(
330 SourceInfo::outermost(body.span),
331 StatementKind::Assign(Box::new((place2, rvalue2))),
332 );
333
334 let mut insert_index = 0;
335 for (i, stmt) in block_data.statements.iter().enumerate() {
336 if !SSATransformer::is_essa_statement(
337 &self.ssatransformer,
338 stmt,
339 ) {
340 break;
341 }
342 insert_index = i + 1;
343 }
344
345 block_data.statements.insert(insert_index, assign_stmt1);
346 block_data.statements.insert(insert_index + 1, assign_stmt2);
347
348 for i in insert_index..insert_index + 2 {
349 let essa_in_body = block_data.statements.get_mut(i).unwrap();
350 rap_trace!(
351 "Inserted eSSA statement {:?} in block {:?}",
352 essa_in_body,
353 magic_number_operand
354 );
355 }
356 }
357 _ => panic!("Expected a place"),
358 };
359 }
360
361 (None, Some(_)) | (Some(_), None) => {
363 let mut operand: IndexVec<_, _> = IndexVec::with_capacity(3);
364 let place;
365
366 if op1.constant().is_none() {
374 place = match op1 {
375 Operand::Copy(p) | Operand::Move(p) => Place::from(p),
376 _ => panic!("Expected a place"),
377 };
378 operand.push(op1.clone());
379 operand.push(op2.clone());
380 } else {
381 place = match op2 {
382 Operand::Copy(p) | Operand::Move(p) => Place::from(p),
383 _ => panic!("Expected a place"),
384 };
385 operand.push(op2.clone());
386 operand.push(op1.clone());
387 }
388
389 let rvalue;
390 if value == 0 {
391 operand.push(flip_cmp_operand.clone());
392 } else {
393 operand.push(cmp_operand.clone());
394 }
395 operand.push(magic_number_operand.clone());
396 let adt_kind = AggregateKind::Adt(
397 self.ssatransformer.essa_def_id.clone(),
398 rustc_abi::VariantIdx::from_u32(0),
399 GenericArgs::empty(),
400 None,
401 None,
402 );
403 rvalue = Rvalue::Aggregate(Box::new(adt_kind.clone()), operand);
404
405 let assign_stmt = Statement::new(
406 SourceInfo::outermost(body.span),
407 StatementKind::Assign(Box::new((place, rvalue))),
408 );
409 let mut insert_index = 0;
410 for (i, stmt) in block_data.statements.iter().enumerate() {
411 if !SSATransformer::is_essa_statement(&self.ssatransformer, stmt) {
412 break;
413 }
414 insert_index = i + 1;
415 }
416
417 block_data.statements.insert(insert_index, assign_stmt);
418
419 let essa_in_body = block_data.statements.get_mut(insert_index).unwrap();
420 let essa_ptr = essa_in_body as *const _;
421
422 rap_trace!(
423 "Inserted eSSA statement {:?} in block {:?}",
424 essa_in_body,
425 magic_number_operand
426 );
427 }
428
429 (Some(_), Some(_)) => {}
430 }
431 };
432 }
433
434 }
436 pub fn flip(binOp: BinOp) -> BinOp {
437 match binOp {
438 BinOp::Lt => BinOp::Ge,
439 BinOp::Le => BinOp::Gt,
440 BinOp::Gt => BinOp::Le,
441 BinOp::Ge => BinOp::Lt,
442 BinOp::Eq => BinOp::Ne,
443 BinOp::Ne => BinOp::Eq,
444 _ => panic!("flip() called on non-comparison operator"),
445 }
446 }
447 pub fn reverse(binOp: BinOp) -> BinOp {
448 match binOp {
449 BinOp::Lt => BinOp::Gt,
450 BinOp::Le => BinOp::Ge,
451 BinOp::Gt => BinOp::Lt,
452 BinOp::Ge => BinOp::Le,
453 BinOp::Eq => BinOp::Ne,
454 BinOp::Ne => BinOp::Eq,
455 _ => panic!("flip() called on non-comparison operator"),
456 }
457 }
458 pub fn rename_variables(&mut self, body: &mut Body<'tcx>) {
459 for local in body.local_decls.indices() {
460 self.ssatransformer.reaching_def.insert(local, None);
461 }
462 let order = SSATransformer::depth_first_search_preorder(
465 &self.ssatransformer.dom_tree,
466 body.basic_blocks.indices().next().unwrap().clone(),
467 );
468 for bb in order {
469 self.process_basic_block(bb, body);
470 }
471
472 rap_debug!("new_locals_to_declare {:?}", self.new_locals_to_declare);
473
474 let mut locals_to_add: Vec<_> = self.new_locals_to_declare.iter().collect();
475 locals_to_add.sort_by_key(|(new_local, _)| new_local.index());
476 rap_debug!("locals_to_add {:?}", locals_to_add);
477 for (new_local, original_local) in locals_to_add {
478 let original_decl = &body.local_decls[*original_local];
479
480 let new_decl = original_decl.clone();
481
482 let pushed_index = body.local_decls.push(new_decl);
483 rap_debug!("Ok with {:?} {:?}", pushed_index, *new_local);
484 assert_eq!(pushed_index, *new_local);
485 }
486 }
487
488 fn process_basic_block(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
489 self.rename_statement(bb, body);
490 self.rename_terminator(bb, body);
491 let terminator = body.basic_blocks[bb].terminator();
492 let successors: Vec<_> = terminator.successors().collect();
493 if let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind {
494 if targets.iter().count() == 1 {
495 for succ_bb in successors.clone() {
496 self.rename_essa_statments(succ_bb, body, bb);
497 }
498 }
499 }
500
501 for succ_bb in successors {
502 self.rename_phi_functions(succ_bb, body, bb);
503 }
504 }
505 fn rename_essa_statments(
506 &mut self,
507 succ_bb: BasicBlock,
508 body: &mut Body<'tcx>,
509 do_bb: BasicBlock,
510 ) {
511 for statement in body.basic_blocks.as_mut()[succ_bb].statements.iter_mut() {
513 if self.ssatransformer.is_essa_statement(statement) {
515 if let Some(pred_block) = self.ssatransformer.get_essa_source_block(statement) {
518 if pred_block != do_bb {
521 continue;
522 }
523
524 if let StatementKind::Assign(assign) = &mut statement.kind {
526 let (_, rvalue) = &mut **assign;
527 if let Rvalue::Aggregate(_, operands) = rvalue {
528 let index = 0;
530 if index < operands.len() {
531 self.replace_operand(
533 &mut operands[FieldIdx::from_usize(index)],
534 &do_bb,
535 );
536 }
537 }
538 }
539 }
540 }
541 }
542 }
543
544 fn rename_phi_functions(
545 &mut self,
546 succ_bb: BasicBlock,
547 body: &mut Body<'tcx>,
548 do_bb: BasicBlock,
549 ) {
550 for (stmt_idx, statement) in body.basic_blocks.as_mut()[succ_bb]
551 .statements
552 .iter_mut()
553 .enumerate()
554 {
555 let location = Location {
556 block: succ_bb,
557 statement_index: stmt_idx,
558 };
559
560 if SSATransformer::is_phi_statement(&self.ssatransformer, statement) {
561 if let StatementKind::Assign(assign) = &mut statement.kind {
562 let (_, rvalue) = &mut **assign;
563 if let Rvalue::Aggregate(_, operands) = rvalue {
564 let operand_count = operands.len();
565 let index = *self.ssatransformer.phi_index.entry(location).or_insert(0);
566
567 if index < operand_count {
568 match &mut operands[FieldIdx::from_usize(index)] {
569 Operand::Copy(place) | Operand::Move(place) => {
570 self.replace_place(place, &do_bb);
571 }
572 _ => {}
573 }
574 *self.ssatransformer.phi_index.entry(location).or_insert(0) += 1;
575 }
576 }
577 }
578 }
579 }
580 }
581 pub fn rename_statement(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
582 for statement in body.basic_blocks.as_mut()[bb].statements.iter_mut() {
583 let is_phi = SSATransformer::is_phi_statement(&self.ssatransformer, statement);
585 let is_essa = SSATransformer::is_essa_statement(&self.ssatransformer, statement);
586 rap_trace!(
587 "IS in statement at block {:?}: {:?}, is_phi: {}, is_essa: {}",
588 bb,
589 statement.clone(),
590 is_phi,
591 is_essa
592 );
593 match &mut statement.kind {
594 StatementKind::Assign(assign) => {
595 let (place, rvalue) = &mut **assign;
596 if !is_phi {
597 if !is_essa {
598 rap_trace!(
599 "Renaming in statement at block {:?}: {:?}",
600 bb,
601 rvalue.clone()
602 );
603 self.replace_rvalue(rvalue, &bb);
604 self.rename_local_def(place, &bb, true);
605 } else {
606 self.ssa_rename_local_def(place, &bb, true);
607 }
608 } else {
609 self.ssa_rename_local_def(place, &bb, false);
610 }
611 }
612 StatementKind::StorageLive(local) => {
614 }
616 StatementKind::StorageDead(local) => {
617 }
619 _ => {}
620 }
621 }
622 }
623
624 fn rename_terminator(&mut self, bb: BasicBlock, body: &mut Body<'tcx>) {
625 let terminator: &mut Terminator<'tcx> = body.basic_blocks.as_mut()[bb].terminator_mut();
626 match &mut terminator.kind {
627 TerminatorKind::Call {
628 args, destination, ..
629 } => {
630 for op in args.iter_mut() {
631 match &mut op.node {
632 Operand::Copy(place) | Operand::Move(place) => {
633 self.replace_place(place, &bb);
634 }
635 Operand::Constant(const_operand) => {}
636 #[cfg(rapx_rustc_ge_196)]
637 Operand::RuntimeChecks(_) => {}
638 }
639 }
640 self.rename_local_def(destination, &bb, true);
641 }
642 TerminatorKind::Assert { cond, .. } => {
643 self.replace_operand(cond, &bb);
644 }
645 TerminatorKind::Drop { place, .. } => {
646 self.replace_place(place, &bb);
647 }
648 TerminatorKind::SwitchInt { discr, .. } => {
649 self.replace_operand(discr, &bb);
650 }
651 _ => {}
652 }
653 }
654
655 fn replace_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, bb: &BasicBlock) {
656 match rvalue {
657 Rvalue::Use(operand, ..)
658 | Rvalue::Repeat(operand, _)
659 | Rvalue::UnaryOp(_, operand)
660 | Rvalue::Cast(_, operand, _) => {
661 self.replace_operand(operand, &bb);
662 }
663 #[cfg(not(rapx_rustc_ge_196))]
664 Rvalue::ShallowInitBox(operand, _) => {
665 self.replace_operand(operand, &bb);
666 }
667 Rvalue::BinaryOp(_, pair) => {
668 let (lhs, rhs) = &mut **pair;
669 self.replace_operand(lhs, &bb);
670 self.replace_operand(rhs, &bb);
671 }
672 Rvalue::Aggregate(_, operands) => {
673 for operand in operands {
674 self.replace_operand(operand, &bb);
675 }
676 }
677 _ => {}
678 }
679 }
680
681 fn replace_operand(&mut self, operand: &mut Operand<'tcx>, bb: &BasicBlock) {
682 match operand {
683 Operand::Copy(place) | Operand::Move(place) => {
684 self.replace_place(place, bb);
685 }
687 _ => {}
688 }
689 }
690
691 fn replace_place(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock) {
692 self.update_reachinf_def(&place.local, &bb);
694
695 if let Some(Some(reaching_local)) = self.ssatransformer.reaching_def.get(&place.local) {
696 let local = reaching_local.clone();
697 let mut new_place: Place<'_> = Place::from(local);
698 new_place.projection = place.projection;
699
700 *place = new_place;
701 } else {
702 }
703 }
704
705 fn ssa_rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
706 self.update_reachinf_def(&place.local, &bb);
708 let Place {
709 local: old_local,
710 projection: _,
711 } = place.clone();
712 let old_place = place.clone();
713 if old_local.as_u32() == 0 {
714 return;
715 }
716 let new_local = Local::from_usize(self.ssatransformer.local_index);
717 self.ssatransformer.local_index += 1;
718 let new_place: Place<'_> = Place::from(new_local);
719 *place = new_place.clone();
720 self.new_locals_to_declare.insert(new_local, old_local);
721
722 let _old_local = old_local.clone();
723 self.ssatransformer
724 .ssa_locals_map
725 .entry(old_place)
726 .or_insert_with(HashSet::new)
727 .insert(new_place);
728
729 self.ssatransformer
730 .local_defination_block
731 .insert(new_local.clone(), bb.clone());
732 let old_local_reaching = self
733 .ssatransformer
734 .reaching_def
735 .get(&_old_local.clone())
736 .unwrap();
737
738 self.ssatransformer
739 .reaching_def
740 .insert(new_local.clone(), *old_local_reaching);
741 self.ssatransformer
742 .reaching_def
743 .insert(_old_local.clone(), Some(new_local.clone()));
744
745 }
750 fn rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
751 self.update_reachinf_def(&place.local, &bb);
753 let Place {
754 local: old_local,
755 projection: _,
756 } = place.clone();
757 let old_place = place.clone();
758 if old_local.as_u32() == 0 {
759 return;
760 }
761
762 if self.ssatransformer.skipped.contains(&old_local.as_usize()) && not_phi {
763 self.ssatransformer.skipped.remove(&old_local.as_usize());
764 self.ssatransformer
765 .reaching_def
766 .insert(old_local, Some(old_local));
767 self.ssatransformer
768 .places_map
769 .entry(old_place)
770 .or_insert_with(HashSet::new)
771 .insert(old_place);
772 return;
773 }
774 let new_local = Local::from_usize(self.ssatransformer.local_index);
775 let mut new_place: Place<'_> = Place::from(new_local);
776 self.new_locals_to_declare.insert(new_local, old_local);
777
778 new_place.projection = place.projection;
779 *place = new_place.clone();
780
781 if old_local.as_u32() == 0 {
783 return;
784 }
785
786 self.ssatransformer.local_index += 1;
787 self.ssatransformer
788 .places_map
789 .entry(old_place)
790 .or_insert_with(HashSet::new)
791 .insert(new_place);
792
793 let _old_local = old_local.clone();
794 self.ssatransformer
795 .local_defination_block
796 .insert(new_local.clone(), bb.clone());
797 let old_local_reaching = self
798 .ssatransformer
799 .reaching_def
800 .get(&_old_local.clone())
801 .unwrap();
802
803 self.ssatransformer
804 .reaching_def
805 .insert(new_local.clone(), *old_local_reaching);
806 self.ssatransformer
807 .reaching_def
808 .insert(_old_local.clone(), Some(new_local.clone()));
809
810 }
815
816 pub fn dominates_(&self, def_bb: &BasicBlock, bb: &BasicBlock) -> bool {
817 let mut visited = HashSet::new();
818
819 let mut stack = self.ssatransformer.dom_tree.get(def_bb).unwrap().clone();
820 while let Some(block) = stack.pop() {
821 if !visited.insert(block) {
822 continue;
823 }
824
825 if block == *bb {
826 return true;
827 }
828
829 if let Some(children) = self.ssatransformer.dom_tree.get(&block) {
830 stack.extend(children);
831 }
832 }
833
834 false
835 }
836 fn update_reachinf_def(&mut self, local: &Local, bb: &BasicBlock) {
837 let mut r = self.ssatransformer.reaching_def[local];
841 let mut dominate_bool = true;
842 if r != None {
843 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
844 }
845
846 while !(r == None || dominate_bool) {
847 r = self.ssatransformer.reaching_def[&r.unwrap()];
848 if r != None {
849 let def_bb = self.ssatransformer.local_defination_block[&r.unwrap()];
850
851 dominate_bool = self.dominates_(&def_bb, bb);
852 }
853 }
854
855 if let Some(entry) = self.ssatransformer.reaching_def.get_mut(local) {
856 *entry = r.clone();
857 }
858 }
859}
860
861