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
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 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 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 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 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 = 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 = 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 }
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 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 let original_decl = &body.local_decls[*original_local];
439
440 let new_decl = original_decl.clone();
442
443 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 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 }
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 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::StorageLive(local) => {
591 }
593 StatementKind::StorageDead(local) => {
594 }
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 }
658 _ => {}
659 }
660 }
661
662 fn replace_place(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock) {
663 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 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 }
721 fn rename_local_def(&mut self, place: &mut Place<'tcx>, bb: &BasicBlock, not_phi: bool) {
722 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 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 }
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 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