From b0d7338d6db5751258cd763e7e990852d6c32b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Sun, 8 Nov 2015 19:11:11 +0100 Subject: [PATCH] [MIR trans] Add support for SwitchInt --- src/librustc_trans/trans/mir/block.rs | 11 +++- src/librustc_trans/trans/mir/constant.rs | 66 ++++++++++++++---------- src/test/run-pass/mir_trans_switchint.rs | 24 +++++++++ 3 files changed, 71 insertions(+), 30 deletions(-) create mode 100644 src/test/run-pass/mir_trans_switchint.rs diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index b47e66ef7f55a..ccab9a20e75d8 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -50,8 +50,15 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { unimplemented!() } - mir::Terminator::SwitchInt { .. } => { - unimplemented!() + mir::Terminator::SwitchInt { ref discr, switch_ty, ref values, ref targets } => { + let (otherwise, targets) = targets.split_last().unwrap(); + let discr = build::Load(bcx, self.trans_lvalue(bcx, discr).llval); + let switch = build::Switch(bcx, discr, self.llblock(*otherwise), values.len()); + for (value, target) in values.iter().zip(targets) { + let llval = self.trans_constval(bcx, value, switch_ty); + let llbb = self.llblock(*target); + build::AddCase(switch, llval, llbb) + } } mir::Terminator::Diverge => { diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 1b61001834a99..43973fe555837 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -9,6 +9,7 @@ // except according to those terms. use llvm::ValueRef; +use middle::ty::Ty; use rustc::middle::const_eval::ConstVal; use rustc_mir::repr as mir; use trans::consts::{self, TrueConst}; @@ -18,45 +19,54 @@ use trans::type_of; use super::MirContext; impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { + pub fn trans_constval(&mut self, + bcx: Block<'bcx, 'tcx>, + cv: &ConstVal, + ty: Ty<'tcx>) + -> ValueRef + { + let ccx = bcx.ccx(); + let llty = type_of::type_of(ccx, ty); + match *cv { + ConstVal::Float(v) => common::C_floating_f64(v, llty), + ConstVal::Bool(v) => common::C_bool(ccx, v), + ConstVal::Int(v) => common::C_integral(llty, v as u64, true), + ConstVal::Uint(v) => common::C_integral(llty, v, false), + ConstVal::Str(ref v) => common::C_str_slice(ccx, v.clone()), + ConstVal::ByteStr(ref v) => consts::addr_of(ccx, + common::C_bytes(ccx, v), + 1, + "byte_str"), + ConstVal::Struct(id) | ConstVal::Tuple(id) => { + let expr = bcx.tcx().map.expect_expr(id); + let (llval, _) = match consts::const_expr(ccx, + expr, + bcx.fcx.param_substs, + None, + TrueConst::Yes) { + Ok(v) => v, + Err(_) => panic!("constant eval failure"), + }; + llval + } + ConstVal::Function(_) => { + unimplemented!() + } + } + } + pub fn trans_constant(&mut self, bcx: Block<'bcx, 'tcx>, constant: &mir::Constant<'tcx>) -> ValueRef { - let ccx = bcx.ccx(); let constant_ty = bcx.monomorphize(&constant.ty); - let llty = type_of::type_of(ccx, constant_ty); match constant.literal { mir::Literal::Item { .. } => { unimplemented!() } mir::Literal::Value { ref value } => { - match *value { - ConstVal::Float(v) => common::C_floating_f64(v, llty), - ConstVal::Bool(v) => common::C_bool(ccx, v), - ConstVal::Int(v) => common::C_integral(llty, v as u64, true), - ConstVal::Uint(v) => common::C_integral(llty, v, false), - ConstVal::Str(ref v) => common::C_str_slice(ccx, v.clone()), - ConstVal::ByteStr(ref v) => consts::addr_of(ccx, - common::C_bytes(ccx, v), - 1, - "byte_str"), - ConstVal::Struct(id) | ConstVal::Tuple(id) => { - let expr = bcx.tcx().map.expect_expr(id); - let (llval, _) = match consts::const_expr(ccx, - expr, - bcx.fcx.param_substs, - None, - TrueConst::Yes) { - Ok(v) => v, - Err(_) => panic!("constant eval failure"), - }; - llval - } - ConstVal::Function(_) => { - unimplemented!() - } - } + self.trans_constval(bcx, value, constant_ty) } } } diff --git a/src/test/run-pass/mir_trans_switchint.rs b/src/test/run-pass/mir_trans_switchint.rs new file mode 100644 index 0000000000000..edde5f3c89587 --- /dev/null +++ b/src/test/run-pass/mir_trans_switchint.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +#[rustc_mir] +pub fn foo(x: i8) -> i32 { + match x { + 1 => 0, + _ => 1, + } +} + +fn main() { + assert_eq!(foo(0), 1); + assert_eq!(foo(1), 0); +}