]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/mir/constant.rs
56d4342e6e1618094c8f74575996db1f38002339
[rust.git] / src / librustc_codegen_ssa / mir / constant.rs
1 use rustc::mir::interpret::ErrorHandled;
2 use rustc_mir::const_eval::const_field;
3 use rustc::mir;
4 use rustc_data_structures::indexed_vec::Idx;
5 use rustc::mir::interpret::GlobalId;
6 use rustc::ty::{self, Ty};
7 use rustc::ty::layout;
8 use syntax::source_map::Span;
9 use traits::*;
10
11 use super::FunctionCx;
12
13 impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14     fn fully_evaluate(
15         &mut self,
16         bx: &Bx,
17         constant: &'tcx ty::LazyConst<'tcx>,
18     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
19         match *constant {
20             ty::LazyConst::Unevaluated(def_id, ref substs) => {
21                 let tcx = bx.tcx();
22                 let param_env = ty::ParamEnv::reveal_all();
23                 let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
24                 let cid = GlobalId {
25                     instance,
26                     promoted: None,
27                 };
28                 tcx.const_eval(param_env.and(cid))
29             },
30             ty::LazyConst::Evaluated(constant) => Ok(constant),
31         }
32     }
33
34     pub fn eval_mir_constant(
35         &mut self,
36         bx: &Bx,
37         constant: &mir::Constant<'tcx>,
38     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
39         let c = self.monomorphize(&constant.literal);
40         self.fully_evaluate(bx, c)
41     }
42
43     /// process constant containing SIMD shuffle indices
44     pub fn simd_shuffle_indices(
45         &mut self,
46         bx: &Bx,
47         span: Span,
48         ty: Ty<'tcx>,
49         constant: Result<ty::Const<'tcx>, ErrorHandled>,
50     ) -> (Bx::Value, Ty<'tcx>) {
51         constant
52             .and_then(|c| {
53                 let field_ty = c.ty.builtin_index().unwrap();
54                 let fields = match c.ty.sty {
55                     ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
56                     ref other => bug!("invalid simd shuffle type: {}", other),
57                 };
58                 let values: Result<Vec<_>, ErrorHandled> = (0..fields).map(|field| {
59                     let field = const_field(
60                         bx.tcx(),
61                         ty::ParamEnv::reveal_all(),
62                         None,
63                         mir::Field::new(field as usize),
64                         c,
65                     )?;
66                     if let Some(prim) = field.val.try_to_scalar() {
67                         let layout = bx.layout_of(field_ty);
68                         let scalar = match layout.abi {
69                             layout::Abi::Scalar(ref x) => x,
70                             _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
71                         };
72                         Ok(bx.scalar_to_backend(
73                             prim, scalar,
74                             bx.immediate_backend_type(layout),
75                         ))
76                     } else {
77                         bug!("simd shuffle field {:?}", field)
78                     }
79                 }).collect();
80                 let llval = bx.const_struct(&values?, false);
81                 Ok((llval, c.ty))
82             })
83             .unwrap_or_else(|_| {
84                 bx.tcx().sess.span_err(
85                     span,
86                     "could not evaluate shuffle_indices at compile time",
87                 );
88                 // We've errored, so we don't have to produce working code.
89                 let ty = self.monomorphize(&ty);
90                 let llty = bx.backend_type(bx.layout_of(ty));
91                 (bx.const_undef(llty), ty)
92             })
93     }
94 }