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