|
10 | 10 |
|
11 | 11 | use llvm::BasicBlockRef;
|
12 | 12 | use rustc::mir::repr as mir;
|
| 13 | +use trans::adt; |
13 | 14 | use trans::base;
|
14 | 15 | use trans::build;
|
15 | 16 | use trans::common::Block;
|
@@ -46,8 +47,28 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
46 | 47 | build::CondBr(bcx, cond.immediate(), lltrue, llfalse, DebugLoc::None);
|
47 | 48 | }
|
48 | 49 |
|
49 |
| - mir::Terminator::Switch { .. } => { |
50 |
| - unimplemented!() |
| 50 | + mir::Terminator::Switch { ref discr, ref adt_def, ref targets } => { |
| 51 | + let adt_ty = bcx.tcx().lookup_item_type(adt_def.did).ty; |
| 52 | + let represented_ty = adt::represent_type(bcx.ccx(), adt_ty); |
| 53 | + |
| 54 | + let discr_lvalue = self.trans_lvalue(bcx, discr); |
| 55 | + let discr = adt::trans_get_discr(bcx, &represented_ty, discr_lvalue.llval, None); |
| 56 | + |
| 57 | + // The else branch of the Switch can't be hit, so branch to an unreachable |
| 58 | + // instruction so LLVM knows that |
| 59 | + // FIXME it might be nice to have just one such block (created lazilly), we could |
| 60 | + // store it in the "MIR trans" state. |
| 61 | + let unreachable_blk = bcx.fcx.new_temp_block("enum-variant-unreachable"); |
| 62 | + build::Unreachable(unreachable_blk); |
| 63 | + |
| 64 | + let switch = build::Switch(bcx, discr, unreachable_blk.llbb, targets.len()); |
| 65 | + assert_eq!(adt_def.variants.len(), targets.len()); |
| 66 | + for (adt_variant, target) in adt_def.variants.iter().zip(targets) { |
| 67 | + let llval = adt::trans_case(bcx, &*represented_ty, adt_variant.disr_val); |
| 68 | + let llbb = self.llblock(*target); |
| 69 | + |
| 70 | + build::AddCase(switch, llval, llbb) |
| 71 | + } |
51 | 72 | }
|
52 | 73 |
|
53 | 74 | mir::Terminator::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
|
0 commit comments