about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBjörn Steinbrink <bsteinbr@gmail.com>2015-11-08 19:11:11 +0100
committerBjörn Steinbrink <bsteinbr@gmail.com>2015-11-09 16:54:58 +0100
commitb0d7338d6db5751258cd763e7e990852d6c32b8f (patch)
treef9a1ca0525a3392535810d653307d54d92c53ce5
parent86069e45fe8fc15bc6103ffde9b4371ce826df2c (diff)
downloadrust-b0d7338d6db5751258cd763e7e990852d6c32b8f.tar.gz
rust-b0d7338d6db5751258cd763e7e990852d6c32b8f.zip
[MIR trans] Add support for SwitchInt
-rw-r--r--src/librustc_trans/trans/mir/block.rs11
-rw-r--r--src/librustc_trans/trans/mir/constant.rs66
-rw-r--r--src/test/run-pass/mir_trans_switchint.rs24
3 files changed, 71 insertions, 30 deletions
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index b47e66ef7f5..ccab9a20e75 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 1b61001834a..43973fe5558 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 00000000000..edde5f3c895
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}