let total_len = in_len as u64 * 2;
- let (vector, indirect) = match args {
+ let vector = match args {
Some(args) => {
match consts::const_expr(bcx.ccx(), &args[2], substs, None,
// this should probably help simd error reporting
consts::TrueConst::Yes) {
- Ok((vector, _)) => (vector, false),
+ Ok((vector, _)) => vector,
Err(err) => bcx.sess().span_fatal(span, &err.description()),
}
}
- None => (llargs[2], !type_is_immediate(bcx.ccx(), arg_tys[2]))
+ None => llargs[2]
};
let indices: Option<Vec<_>> = (0..n)
.map(|i| {
let arg_idx = i;
- let val = if indirect {
- Load(bcx, StructGEP(bcx, vector, i))
- } else {
- const_get_elt(vector, &[i as libc::c_uint])
- };
- let c = const_to_opt_uint(val);
- match c {
+ let val = const_get_elt(vector, &[i as libc::c_uint]);
+ match const_to_opt_uint(val) {
None => {
emit_error!("shuffle index #{} is not a constant", arg_idx);
None
use type_::Type;
use super::{MirContext, TempRef, drop};
+use super::constant::Const;
use super::lvalue::{LvalueRef, load_fat_ptr};
use super::operand::OperandRef;
use super::operand::OperandValue::{self, FatPtr, Immediate, Ref};
let discr = bcx.with_block(|bcx| base::to_immediate(bcx, discr, switch_ty));
let switch = bcx.switch(discr, self.llblock(*otherwise), values.len());
for (value, target) in values.iter().zip(targets) {
- let constant = mir::Constant {
- literal: mir::Literal::Value {
- value: value.clone()
- },
- ty: switch_ty,
- span: terminator.span
- };
- let val = self.trans_constant(&bcx, &constant).immediate();
+ let val = Const::from_constval(bcx.ccx(), value.clone(), switch_ty);
let llbb = self.llblock(*target);
- build::AddCase(switch, val, llbb)
+ build::AddCase(switch, val.llval, llbb)
}
}
(&args[..], None)
};
+ let is_shuffle = intrinsic.map_or(false, |name| {
+ name.starts_with("simd_shuffle")
+ });
let mut idx = 0;
for arg in first_args {
+ // The indices passed to simd_shuffle* in the
+ // third argument must be constant. This is
+ // checked by const-qualification, which also
+ // promotes any complex rvalues to constants.
+ if is_shuffle && idx == 2 {
+ match *arg {
+ mir::Operand::Consume(_) => {
+ span_bug!(terminator.span,
+ "shuffle indices must be constant");
+ }
+ mir::Operand::Constant(ref constant) => {
+ let val = self.trans_constant(&bcx, constant);
+ llargs.push(val.llval);
+ idx += 1;
+ continue;
+ }
+ }
+ }
+
let val = self.trans_operand(&bcx, arg).val;
self.trans_argument(&bcx, val, &mut llargs, &fn_ty,
&mut idx, &mut callee.data);
/// The LLVM type might not be the same for a single Rust type,
/// e.g. each enum variant would have its own LLVM struct type.
#[derive(Copy, Clone)]
-struct Const<'tcx> {
- llval: ValueRef,
- ty: Ty<'tcx>
+pub struct Const<'tcx> {
+ pub llval: ValueRef,
+ pub ty: Ty<'tcx>
}
impl<'tcx> Const<'tcx> {
- fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
+ pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> {
Const {
llval: llval,
ty: ty
}
/// Translate ConstVal into a LLVM constant value.
- fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
- cv: ConstVal,
- ty: Ty<'tcx>)
- -> Const<'tcx> {
+ pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
+ cv: ConstVal,
+ ty: Ty<'tcx>)
+ -> Const<'tcx> {
let llty = type_of::type_of(ccx, ty);
let val = match cv {
ConstVal::Float(v) => C_floating_f64(v, llty),
}
}
- fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
+ pub fn to_operand<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
let llty = type_of::immediate_type_of(ccx, self.ty);
let llvalty = val_ty(self.llval);
pub fn trans_constant(&mut self,
bcx: &BlockAndBuilder<'bcx, 'tcx>,
constant: &mir::Constant<'tcx>)
- -> OperandRef<'tcx>
+ -> Const<'tcx>
{
let ty = bcx.monomorphize(&constant.ty);
let result = match constant.literal.clone() {
// types, which would not work with MirConstContext.
if common::type_is_zero_size(bcx.ccx(), ty) {
let llty = type_of::type_of(bcx.ccx(), ty);
- return OperandRef {
- val: OperandValue::Immediate(C_null(llty)),
- ty: ty
- };
+ return Const::new(C_null(llty), ty);
}
let substs = bcx.tcx().mk_substs(bcx.monomorphize(substs));
}
};
- let val = match result {
+ match result {
Ok(v) => v,
Err(ConstEvalFailure::Compiletime(_)) => {
// We've errored, so we don't have to produce working code.
"MIR constant {:?} results in runtime panic: {}",
constant, err.description())
}
- };
-
- let operand = val.to_operand(bcx.ccx());
- if let OperandValue::Ref(ptr) = operand.val {
- // If this is a OperandValue::Ref to an immediate constant, load it.
- self.trans_load(bcx, ptr, operand.ty)
- } else {
- operand
}
}
}
}
mir::Operand::Constant(ref constant) => {
- self.trans_constant(bcx, constant)
+ let val = self.trans_constant(bcx, constant);
+ let operand = val.to_operand(bcx.ccx());
+ if let OperandValue::Ref(ptr) = operand.val {
+ // If this is a OperandValue::Ref to an immediate constant, load it.
+ self.trans_load(bcx, ptr, operand.ty)
+ } else {
+ operand
+ }
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(repr_simd, rustc_attrs, platform_intrinsics)]
+#![feature(repr_simd, platform_intrinsics)]
// ignore-pretty : (#23623) problems when ending with // comments
}}
}
-#[rustc_no_mir] // FIXME #27840 MIR doesn't handle shuffle constants.
fn main() {
let x2 = i32x2(20, 21);
let x3 = i32x3(30, 31, 32);