|
8 | 8 | //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
|
9 | 9 |
|
10 | 10 | use crate::{
|
11 |
| - rustc_internal::crate_item, |
| 11 | + rustc_internal::{crate_item, item_def_id}, |
12 | 12 | stable_mir::{self},
|
13 | 13 | };
|
14 | 14 | use rustc_middle::ty::{tls::with, TyCtxt};
|
@@ -47,3 +47,112 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
|
47 | 47 | debug!(?crate_name, ?crate_num, "smir_crate");
|
48 | 48 | stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
|
49 | 49 | }
|
| 50 | + |
| 51 | +pub fn mir_body(item: &stable_mir::CrateItem) -> stable_mir::mir::Body { |
| 52 | + with(|tcx| { |
| 53 | + let def_id = item_def_id(item); |
| 54 | + let mir = tcx.optimized_mir(def_id); |
| 55 | + stable_mir::mir::Body { |
| 56 | + blocks: mir |
| 57 | + .basic_blocks |
| 58 | + .iter() |
| 59 | + .map(|block| stable_mir::mir::BasicBlock { |
| 60 | + terminator: rustc_terminator_to_terminator(block.terminator()), |
| 61 | + statements: block.statements.iter().map(rustc_statement_to_statement).collect(), |
| 62 | + }) |
| 63 | + .collect(), |
| 64 | + } |
| 65 | + }) |
| 66 | +} |
| 67 | + |
| 68 | +fn rustc_statement_to_statement( |
| 69 | + s: &rustc_middle::mir::Statement<'_>, |
| 70 | +) -> stable_mir::mir::Statement { |
| 71 | + use rustc_middle::mir::StatementKind::*; |
| 72 | + match &s.kind { |
| 73 | + Assign(assign) => stable_mir::mir::Statement::Assign( |
| 74 | + rustc_place_to_place(&assign.0), |
| 75 | + rustc_rvalue_to_rvalue(&assign.1), |
| 76 | + ), |
| 77 | + FakeRead(_) => todo!(), |
| 78 | + SetDiscriminant { .. } => todo!(), |
| 79 | + Deinit(_) => todo!(), |
| 80 | + StorageLive(_) => todo!(), |
| 81 | + StorageDead(_) => todo!(), |
| 82 | + Retag(_, _) => todo!(), |
| 83 | + PlaceMention(_) => todo!(), |
| 84 | + AscribeUserType(_, _) => todo!(), |
| 85 | + Coverage(_) => todo!(), |
| 86 | + Intrinsic(_) => todo!(), |
| 87 | + ConstEvalCounter => todo!(), |
| 88 | + Nop => stable_mir::mir::Statement::Nop, |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +fn rustc_rvalue_to_rvalue(rvalue: &rustc_middle::mir::Rvalue<'_>) -> stable_mir::mir::Operand { |
| 93 | + use rustc_middle::mir::Rvalue::*; |
| 94 | + match rvalue { |
| 95 | + Use(op) => rustc_op_to_op(op), |
| 96 | + Repeat(_, _) => todo!(), |
| 97 | + Ref(_, _, _) => todo!(), |
| 98 | + ThreadLocalRef(_) => todo!(), |
| 99 | + AddressOf(_, _) => todo!(), |
| 100 | + Len(_) => todo!(), |
| 101 | + Cast(_, _, _) => todo!(), |
| 102 | + BinaryOp(_, _) => todo!(), |
| 103 | + CheckedBinaryOp(_, _) => todo!(), |
| 104 | + NullaryOp(_, _) => todo!(), |
| 105 | + UnaryOp(_, _) => todo!(), |
| 106 | + Discriminant(_) => todo!(), |
| 107 | + Aggregate(_, _) => todo!(), |
| 108 | + ShallowInitBox(_, _) => todo!(), |
| 109 | + CopyForDeref(_) => todo!(), |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +fn rustc_op_to_op(op: &rustc_middle::mir::Operand<'_>) -> stable_mir::mir::Operand { |
| 114 | + use rustc_middle::mir::Operand::*; |
| 115 | + match op { |
| 116 | + Copy(place) => stable_mir::mir::Operand::Copy(rustc_place_to_place(place)), |
| 117 | + Move(place) => stable_mir::mir::Operand::Move(rustc_place_to_place(place)), |
| 118 | + Constant(c) => stable_mir::mir::Operand::Constant(c.to_string()), |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +fn rustc_place_to_place(place: &rustc_middle::mir::Place<'_>) -> stable_mir::mir::Place { |
| 123 | + assert_eq!(&place.projection[..], &[]); |
| 124 | + stable_mir::mir::Place { local: place.local.as_usize() } |
| 125 | +} |
| 126 | + |
| 127 | +fn rustc_terminator_to_terminator( |
| 128 | + terminator: &rustc_middle::mir::Terminator<'_>, |
| 129 | +) -> stable_mir::mir::Terminator { |
| 130 | + use rustc_middle::mir::TerminatorKind::*; |
| 131 | + use stable_mir::mir::Terminator; |
| 132 | + match &terminator.kind { |
| 133 | + Goto { target } => Terminator::Goto { target: target.as_usize() }, |
| 134 | + SwitchInt { discr, targets } => Terminator::SwitchInt { |
| 135 | + discr: rustc_op_to_op(discr), |
| 136 | + targets: targets |
| 137 | + .iter() |
| 138 | + .map(|(value, target)| stable_mir::mir::SwitchTarget { |
| 139 | + value, |
| 140 | + target: target.as_usize(), |
| 141 | + }) |
| 142 | + .collect(), |
| 143 | + otherwise: targets.otherwise().as_usize(), |
| 144 | + }, |
| 145 | + Resume => Terminator::Resume, |
| 146 | + Abort => Terminator::Abort, |
| 147 | + Return => Terminator::Return, |
| 148 | + Unreachable => Terminator::Unreachable, |
| 149 | + Drop { .. } => todo!(), |
| 150 | + Call { .. } => todo!(), |
| 151 | + Assert { .. } => todo!(), |
| 152 | + Yield { .. } => todo!(), |
| 153 | + GeneratorDrop => todo!(), |
| 154 | + FalseEdge { .. } => todo!(), |
| 155 | + FalseUnwind { .. } => todo!(), |
| 156 | + InlineAsm { .. } => todo!(), |
| 157 | + } |
| 158 | +} |
0 commit comments