Only SwitchInt over integers, not all consts
Also use a Cow to avoid full Vec for all SwitchInts
This commit is contained in:
parent
aac82d9b13
commit
a00a0adc79
10 changed files with 154 additions and 101 deletions
|
|
@ -11,6 +11,7 @@
|
|||
use llvm::{self, ValueRef, BasicBlockRef};
|
||||
use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err};
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::const_val::ConstInt;
|
||||
use rustc::ty::{self, layout, TypeFoldable};
|
||||
use rustc::mir;
|
||||
use abi::{Abi, FnType, ArgType};
|
||||
|
|
@ -134,14 +135,24 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
||||
// TODO: cond_br if only 1 value
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
let discr = self.trans_operand(&bcx, discr).immediate();
|
||||
let switch = bcx.switch(discr, llblock(self, *otherwise), values.len());
|
||||
for (value, target) in values.iter().zip(targets) {
|
||||
let val = Const::from_constval(bcx.ccx, value.clone(), switch_ty);
|
||||
let llbb = llblock(self, *target);
|
||||
bcx.add_case(switch, val.llval, llbb)
|
||||
let discr = self.trans_operand(&bcx, discr);
|
||||
if switch_ty == bcx.tcx().types.bool {
|
||||
let lltrue = llblock(self, targets[0]);
|
||||
let llfalse = llblock(self, targets[1]);
|
||||
if let [ConstInt::Infer(0)] = values[..] {
|
||||
bcx.cond_br(discr.immediate(), llfalse, lltrue);
|
||||
} else {
|
||||
bcx.cond_br(discr.immediate(), lltrue, llfalse);
|
||||
}
|
||||
} else {
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
let switch = bcx.switch(discr.immediate(),
|
||||
llblock(self, *otherwise), values.len());
|
||||
for (value, target) in values.iter().zip(targets) {
|
||||
let val = Const::from_constint(bcx.ccx, value);
|
||||
let llbb = llblock(self, *target);
|
||||
bcx.add_case(switch, val.llval, llbb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,33 @@ impl<'tcx> Const<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_constint<'a>(ccx: &CrateContext<'a, 'tcx>, ci: &ConstInt)
|
||||
-> Const<'tcx> {
|
||||
let tcx = ccx.tcx();
|
||||
let (llval, ty) = match *ci {
|
||||
I8(v) => (C_integral(Type::i8(ccx), v as u64, true), tcx.types.i8),
|
||||
I16(v) => (C_integral(Type::i16(ccx), v as u64, true), tcx.types.i16),
|
||||
I32(v) => (C_integral(Type::i32(ccx), v as u64, true), tcx.types.i32),
|
||||
I64(v) => (C_integral(Type::i64(ccx), v as u64, true), tcx.types.i64),
|
||||
I128(v) => (C_big_integral(Type::i128(ccx), v as u128), tcx.types.i128),
|
||||
Isize(v) => {
|
||||
let i = v.as_i64(ccx.tcx().sess.target.int_type);
|
||||
(C_integral(Type::int(ccx), i as u64, true), tcx.types.isize)
|
||||
},
|
||||
U8(v) => (C_integral(Type::i8(ccx), v as u64, false), tcx.types.u8),
|
||||
U16(v) => (C_integral(Type::i16(ccx), v as u64, false), tcx.types.u16),
|
||||
U32(v) => (C_integral(Type::i32(ccx), v as u64, false), tcx.types.u32),
|
||||
U64(v) => (C_integral(Type::i64(ccx), v, false), tcx.types.u64),
|
||||
U128(v) => (C_big_integral(Type::i128(ccx), v), tcx.types.u128),
|
||||
Usize(v) => {
|
||||
let u = v.as_u64(ccx.tcx().sess.target.uint_type);
|
||||
(C_integral(Type::int(ccx), u, false), tcx.types.usize)
|
||||
},
|
||||
Infer(_) | InferSigned(_) => bug!("MIR must not use `{:?}`", ci),
|
||||
};
|
||||
Const { llval: llval, ty: ty }
|
||||
}
|
||||
|
||||
/// Translate ConstVal into a LLVM constant value.
|
||||
pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
cv: ConstVal,
|
||||
|
|
@ -72,26 +99,7 @@ impl<'tcx> Const<'tcx> {
|
|||
ConstVal::Float(F64(v)) => C_floating_f64(v, llty),
|
||||
ConstVal::Float(FInfer {..}) => bug!("MIR must not use `{:?}`", cv),
|
||||
ConstVal::Bool(v) => C_bool(ccx, v),
|
||||
ConstVal::Integral(I8(v)) => C_integral(Type::i8(ccx), v as u64, true),
|
||||
ConstVal::Integral(I16(v)) => C_integral(Type::i16(ccx), v as u64, true),
|
||||
ConstVal::Integral(I32(v)) => C_integral(Type::i32(ccx), v as u64, true),
|
||||
ConstVal::Integral(I64(v)) => C_integral(Type::i64(ccx), v as u64, true),
|
||||
ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128),
|
||||
ConstVal::Integral(Isize(v)) => {
|
||||
let i = v.as_i64(ccx.tcx().sess.target.int_type);
|
||||
C_integral(Type::int(ccx), i as u64, true)
|
||||
},
|
||||
ConstVal::Integral(U8(v)) => C_integral(Type::i8(ccx), v as u64, false),
|
||||
ConstVal::Integral(U16(v)) => C_integral(Type::i16(ccx), v as u64, false),
|
||||
ConstVal::Integral(U32(v)) => C_integral(Type::i32(ccx), v as u64, false),
|
||||
ConstVal::Integral(U64(v)) => C_integral(Type::i64(ccx), v, false),
|
||||
ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v),
|
||||
ConstVal::Integral(Usize(v)) => {
|
||||
let u = v.as_u64(ccx.tcx().sess.target.uint_type);
|
||||
C_integral(Type::int(ccx), u, false)
|
||||
},
|
||||
ConstVal::Integral(Infer(_)) |
|
||||
ConstVal::Integral(InferSigned(_)) => bug!("MIR must not use `{:?}`", cv),
|
||||
ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
|
||||
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
|
||||
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
|
||||
ConstVal::Struct(_) | ConstVal::Tuple(_) |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue