Skip to content

Commit e21d2c8

Browse files
committed
Move all functions used by the queries to query.rs
1 parent 43221a6 commit e21d2c8

File tree

2 files changed

+98
-108
lines changed

2 files changed

+98
-108
lines changed

src/librustc_mir/const_eval.rs

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,19 @@
11
// Not in interpret to make sure we do not use private implementation details
22

3-
use std::convert::TryInto;
4-
use std::error::Error;
5-
use std::fmt;
6-
use std::hash::Hash;
7-
83
use rustc::mir;
9-
use rustc::ty::layout::{self, VariantIdx};
4+
use rustc::ty::layout::VariantIdx;
105
use rustc::ty::{self, TyCtxt};
116

12-
use syntax::{
13-
source_map::{Span, DUMMY_SP},
14-
symbol::Symbol,
15-
};
7+
use syntax::{source_map::DUMMY_SP, symbol::Symbol};
168

17-
use crate::interpret::{
18-
intern_const_alloc_recursive, Allocation, ConstValue, ImmTy, Immediate, InterpCx, OpTy, Scalar,
19-
};
9+
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InterpCx};
2010

2111
mod error;
2212
mod query;
2313

2414
pub use error::*;
2515
pub use query::*;
2616

27-
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
28-
/// `simd_shuffle` and const patterns in match arms.
29-
///
30-
/// The function containing the `match` that is currently being analyzed may have generic bounds
31-
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
32-
/// of a function's generic parameter will require knowledge about the bounds on the generic
33-
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
34-
fn mk_eval_cx<'mir, 'tcx>(
35-
tcx: TyCtxt<'tcx>,
36-
span: Span,
37-
param_env: ty::ParamEnv<'tcx>,
38-
can_access_statics: bool,
39-
) -> CompileTimeEvalContext<'mir, 'tcx> {
40-
debug!("mk_eval_cx: {:?}", param_env);
41-
InterpCx::new(
42-
tcx.at(span),
43-
param_env,
44-
CompileTimeInterpreter::new(),
45-
MemoryExtra { can_access_statics },
46-
)
47-
}
48-
49-
fn op_to_const<'tcx>(
50-
ecx: &CompileTimeEvalContext<'_, 'tcx>,
51-
op: OpTy<'tcx>,
52-
) -> &'tcx ty::Const<'tcx> {
53-
// We do not have value optimizations for everything.
54-
// Only scalars and slices, since they are very common.
55-
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
56-
// from scalar unions that are initialized with one of their zero sized variants. We could
57-
// instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all
58-
// the usual cases of extracting e.g. a `usize`, without there being a real use case for the
59-
// `Undef` situation.
60-
let try_as_immediate = match op.layout.abi {
61-
layout::Abi::Scalar(..) => true,
62-
layout::Abi::ScalarPair(..) => match op.layout.ty.kind {
63-
ty::Ref(_, inner, _) => match inner.kind {
64-
ty::Slice(elem) => elem == ecx.tcx.types.u8,
65-
ty::Str => true,
66-
_ => false,
67-
},
68-
_ => false,
69-
},
70-
_ => false,
71-
};
72-
let immediate = if try_as_immediate {
73-
Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
74-
} else {
75-
// It is guaranteed that any non-slice scalar pair is actually ByRef here.
76-
// When we come back from raw const eval, we are always by-ref. The only way our op here is
77-
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
78-
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
79-
// structs containing such.
80-
op.try_as_mplace()
81-
};
82-
let val = match immediate {
83-
Ok(mplace) => {
84-
let ptr = mplace.ptr.to_ptr().unwrap();
85-
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
86-
ConstValue::ByRef { alloc, offset: ptr.offset }
87-
}
88-
// see comment on `let try_as_immediate` above
89-
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
90-
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
91-
ScalarMaybeUndef::Undef => {
92-
// When coming out of "normal CTFE", we'll always have an `Indirect` operand as
93-
// argument and we will not need this. The only way we can already have an
94-
// `Immediate` is when we are called from `const_field`, and that `Immediate`
95-
// comes from a constant so it can happen have `Undef`, because the indirect
96-
// memory that was read had undefined bytes.
97-
let mplace = op.assert_mem_place();
98-
let ptr = mplace.ptr.to_ptr().unwrap();
99-
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
100-
ConstValue::ByRef { alloc, offset: ptr.offset }
101-
}
102-
},
103-
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
104-
let (data, start) = match a.not_undef().unwrap() {
105-
Scalar::Ptr(ptr) => {
106-
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
107-
}
108-
Scalar::Raw { .. } => (
109-
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
110-
0,
111-
),
112-
};
113-
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
114-
let start = start.try_into().unwrap();
115-
let len: usize = len.try_into().unwrap();
116-
ConstValue::Slice { data, start, end: start + len }
117-
}
118-
};
119-
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
120-
}
121-
12217
/// Extracts a field of a (variant of a) const.
12318
// this function uses `unwrap` copiously, because an already validated constant must have valid
12419
// fields and can thus never fail outside of compiler bugs

src/librustc_mir/const_eval/query.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,98 @@ fn eval_body_using_ecx<'mir, 'tcx>(
262262
debug!("eval_body_using_ecx done: {:?}", *ret);
263263
Ok(ret)
264264
}
265+
266+
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
267+
/// `simd_shuffle` and const patterns in match arms.
268+
///
269+
/// The function containing the `match` that is currently being analyzed may have generic bounds
270+
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
271+
/// of a function's generic parameter will require knowledge about the bounds on the generic
272+
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
273+
pub(super) fn mk_eval_cx<'mir, 'tcx>(
274+
tcx: TyCtxt<'tcx>,
275+
span: Span,
276+
param_env: ty::ParamEnv<'tcx>,
277+
can_access_statics: bool,
278+
) -> CompileTimeEvalContext<'mir, 'tcx> {
279+
debug!("mk_eval_cx: {:?}", param_env);
280+
InterpCx::new(
281+
tcx.at(span),
282+
param_env,
283+
CompileTimeInterpreter::new(),
284+
MemoryExtra { can_access_statics },
285+
)
286+
}
287+
288+
pub(super) fn op_to_const<'tcx>(
289+
ecx: &CompileTimeEvalContext<'_, 'tcx>,
290+
op: OpTy<'tcx>,
291+
) -> &'tcx ty::Const<'tcx> {
292+
// We do not have value optimizations for everything.
293+
// Only scalars and slices, since they are very common.
294+
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
295+
// from scalar unions that are initialized with one of their zero sized variants. We could
296+
// instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all
297+
// the usual cases of extracting e.g. a `usize`, without there being a real use case for the
298+
// `Undef` situation.
299+
let try_as_immediate = match op.layout.abi {
300+
layout::Abi::Scalar(..) => true,
301+
layout::Abi::ScalarPair(..) => match op.layout.ty.kind {
302+
ty::Ref(_, inner, _) => match inner.kind {
303+
ty::Slice(elem) => elem == ecx.tcx.types.u8,
304+
ty::Str => true,
305+
_ => false,
306+
},
307+
_ => false,
308+
},
309+
_ => false,
310+
};
311+
let immediate = if try_as_immediate {
312+
Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
313+
} else {
314+
// It is guaranteed that any non-slice scalar pair is actually ByRef here.
315+
// When we come back from raw const eval, we are always by-ref. The only way our op here is
316+
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
317+
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
318+
// structs containing such.
319+
op.try_as_mplace()
320+
};
321+
let val = match immediate {
322+
Ok(mplace) => {
323+
let ptr = mplace.ptr.to_ptr().unwrap();
324+
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
325+
ConstValue::ByRef { alloc, offset: ptr.offset }
326+
}
327+
// see comment on `let try_as_immediate` above
328+
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
329+
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
330+
ScalarMaybeUndef::Undef => {
331+
// When coming out of "normal CTFE", we'll always have an `Indirect` operand as
332+
// argument and we will not need this. The only way we can already have an
333+
// `Immediate` is when we are called from `const_field`, and that `Immediate`
334+
// comes from a constant so it can happen have `Undef`, because the indirect
335+
// memory that was read had undefined bytes.
336+
let mplace = op.assert_mem_place();
337+
let ptr = mplace.ptr.to_ptr().unwrap();
338+
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
339+
ConstValue::ByRef { alloc, offset: ptr.offset }
340+
}
341+
},
342+
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
343+
let (data, start) = match a.not_undef().unwrap() {
344+
Scalar::Ptr(ptr) => {
345+
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
346+
}
347+
Scalar::Raw { .. } => (
348+
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
349+
0,
350+
),
351+
};
352+
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
353+
let start = start.try_into().unwrap();
354+
let len: usize = len.try_into().unwrap();
355+
ConstValue::Slice { data, start, end: start + len }
356+
}
357+
};
358+
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
359+
}

0 commit comments

Comments
 (0)