]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/hair/constant.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_mir / hair / constant.rs
CommitLineData
a1dfa0c6 1use syntax::ast;
dc9dc135 2use rustc::ty::{self, Ty, TyCtxt, ParamEnv, layout::Size};
a1dfa0c6
XL
3use syntax_pos::symbol::Symbol;
4use rustc::mir::interpret::{ConstValue, Scalar};
5
6#[derive(PartialEq)]
7crate enum LitToConstError {
8 UnparseableFloat,
9 Reported,
10}
11
dc9dc135 12crate fn lit_to_const<'tcx>(
a1dfa0c6 13 lit: &'tcx ast::LitKind,
dc9dc135 14 tcx: TyCtxt<'tcx>,
a1dfa0c6
XL
15 ty: Ty<'tcx>,
16 neg: bool,
dc9dc135 17) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
a1dfa0c6
XL
18 use syntax::ast::*;
19
20 let trunc = |n| {
dc9dc135 21 let param_ty = ParamEnv::reveal_all().and(ty);
a1dfa0c6
XL
22 let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
23 trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
9fa01778 24 let result = truncate(n, width);
a1dfa0c6 25 trace!("trunc result: {}", result);
dc9dc135 26 Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
a1dfa0c6
XL
27 };
28
29 use rustc::mir::interpret::*;
30 let lit = match *lit {
31 LitKind::Str(ref s, _) => {
32 let s = s.as_str();
dc9dc135
XL
33 let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
34 let allocation = tcx.intern_const_alloc(allocation);
35 ConstValue::Slice { data: allocation, start: 0, end: s.len() }
a1dfa0c6
XL
36 },
37 LitKind::ByteStr(ref data) => {
38 let id = tcx.allocate_bytes(data);
39 ConstValue::Scalar(Scalar::Ptr(id.into()))
40 },
dc9dc135 41 LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))),
a1dfa0c6
XL
42 LitKind::Int(n, _) if neg => {
43 let n = n as i128;
44 let n = n.overflowing_neg().0;
45 trunc(n as u128)?
46 },
47 LitKind::Int(n, _) => trunc(n)?,
60c5eb7d 48 LitKind::Float(n, _) => {
e74abb32 49 let fty = match ty.kind {
a1dfa0c6
XL
50 ty::Float(fty) => fty,
51 _ => bug!()
52 };
53 parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)?
54 }
55 LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)),
56 LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
dc9dc135 57 LitKind::Err(_) => unreachable!(),
a1dfa0c6 58 };
60c5eb7d 59 Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty }))
a1dfa0c6
XL
60}
61
62fn parse_float<'tcx>(
63 num: Symbol,
64 fty: ast::FloatTy,
65 neg: bool,
66) -> Result<ConstValue<'tcx>, ()> {
67 let num = num.as_str();
68 use rustc_apfloat::ieee::{Single, Double};
dc9dc135 69 let scalar = match fty {
a1dfa0c6
XL
70 ast::FloatTy::F32 => {
71 num.parse::<f32>().map_err(|_| ())?;
72 let mut f = num.parse::<Single>().unwrap_or_else(|e| {
73 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
74 });
75 if neg {
76 f = -f;
77 }
dc9dc135 78 Scalar::from_f32(f)
a1dfa0c6
XL
79 }
80 ast::FloatTy::F64 => {
81 num.parse::<f64>().map_err(|_| ())?;
82 let mut f = num.parse::<Double>().unwrap_or_else(|e| {
dc9dc135 83 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
a1dfa0c6
XL
84 });
85 if neg {
86 f = -f;
87 }
dc9dc135 88 Scalar::from_f64(f)
a1dfa0c6
XL
89 }
90 };
91
dc9dc135 92 Ok(ConstValue::Scalar(scalar))
a1dfa0c6 93}