Skip to content

Commit 4ffdd9a

Browse files
committed
Move function definitions before their first use
1 parent e21d2c8 commit 4ffdd9a

File tree

1 file changed

+138
-138
lines changed

1 file changed

+138
-138
lines changed

src/librustc_mir/const_eval/query.rs

Lines changed: 138 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,144 @@ pub fn note_on_undefined_behavior_error() -> &'static str {
2121
repository if you believe it should not be considered undefined behavior."
2222
}
2323

24+
// Returns a pointer to where the result lives
25+
fn eval_body_using_ecx<'mir, 'tcx>(
26+
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
27+
cid: GlobalId<'tcx>,
28+
body: &'mir mir::Body<'tcx>,
29+
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
30+
debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
31+
let tcx = ecx.tcx.tcx;
32+
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
33+
assert!(!layout.is_unsized());
34+
let ret = ecx.allocate(layout, MemoryKind::Stack);
35+
36+
let name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
37+
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
38+
trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
39+
40+
// Assert all args (if any) are zero-sized types; `eval_body_using_ecx` doesn't
41+
// make sense if the body is expecting nontrivial arguments.
42+
// (The alternative would be to use `eval_fn_call` with an args slice.)
43+
for arg in body.args_iter() {
44+
let decl = body.local_decls.get(arg).expect("arg missing from local_decls");
45+
let layout = ecx.layout_of(decl.ty.subst(tcx, cid.instance.substs))?;
46+
assert!(layout.is_zst())
47+
}
48+
49+
ecx.push_stack_frame(
50+
cid.instance,
51+
body.span,
52+
body,
53+
Some(ret.into()),
54+
StackPopCleanup::None { cleanup: false },
55+
)?;
56+
57+
// The main interpreter loop.
58+
ecx.run()?;
59+
60+
// Intern the result
61+
intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?;
62+
63+
debug!("eval_body_using_ecx done: {:?}", *ret);
64+
Ok(ret)
65+
}
66+
67+
/// The `InterpCx` is only meant to be used to do field and index projections into constants for
68+
/// `simd_shuffle` and const patterns in match arms.
69+
///
70+
/// The function containing the `match` that is currently being analyzed may have generic bounds
71+
/// that inform us about the generic bounds of the constant. E.g., using an associated constant
72+
/// of a function's generic parameter will require knowledge about the bounds on the generic
73+
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
74+
pub(super) fn mk_eval_cx<'mir, 'tcx>(
75+
tcx: TyCtxt<'tcx>,
76+
span: Span,
77+
param_env: ty::ParamEnv<'tcx>,
78+
can_access_statics: bool,
79+
) -> CompileTimeEvalContext<'mir, 'tcx> {
80+
debug!("mk_eval_cx: {:?}", param_env);
81+
InterpCx::new(
82+
tcx.at(span),
83+
param_env,
84+
CompileTimeInterpreter::new(),
85+
MemoryExtra { can_access_statics },
86+
)
87+
}
88+
89+
pub(super) fn op_to_const<'tcx>(
90+
ecx: &CompileTimeEvalContext<'_, 'tcx>,
91+
op: OpTy<'tcx>,
92+
) -> &'tcx ty::Const<'tcx> {
93+
// We do not have value optimizations for everything.
94+
// Only scalars and slices, since they are very common.
95+
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
96+
// from scalar unions that are initialized with one of their zero sized variants. We could
97+
// instead allow `ConstValue::Scalar` to store `ScalarMaybeUndef`, but that would affect all
98+
// the usual cases of extracting e.g. a `usize`, without there being a real use case for the
99+
// `Undef` situation.
100+
let try_as_immediate = match op.layout.abi {
101+
layout::Abi::Scalar(..) => true,
102+
layout::Abi::ScalarPair(..) => match op.layout.ty.kind {
103+
ty::Ref(_, inner, _) => match inner.kind {
104+
ty::Slice(elem) => elem == ecx.tcx.types.u8,
105+
ty::Str => true,
106+
_ => false,
107+
},
108+
_ => false,
109+
},
110+
_ => false,
111+
};
112+
let immediate = if try_as_immediate {
113+
Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
114+
} else {
115+
// It is guaranteed that any non-slice scalar pair is actually ByRef here.
116+
// When we come back from raw const eval, we are always by-ref. The only way our op here is
117+
// by-val is if we are in const_field, i.e., if this is (a field of) something that we
118+
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
119+
// structs containing such.
120+
op.try_as_mplace()
121+
};
122+
let val = match immediate {
123+
Ok(mplace) => {
124+
let ptr = mplace.ptr.to_ptr().unwrap();
125+
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
126+
ConstValue::ByRef { alloc, offset: ptr.offset }
127+
}
128+
// see comment on `let try_as_immediate` above
129+
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
130+
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
131+
ScalarMaybeUndef::Undef => {
132+
// When coming out of "normal CTFE", we'll always have an `Indirect` operand as
133+
// argument and we will not need this. The only way we can already have an
134+
// `Immediate` is when we are called from `const_field`, and that `Immediate`
135+
// comes from a constant so it can happen have `Undef`, because the indirect
136+
// memory that was read had undefined bytes.
137+
let mplace = op.assert_mem_place();
138+
let ptr = mplace.ptr.to_ptr().unwrap();
139+
let alloc = ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
140+
ConstValue::ByRef { alloc, offset: ptr.offset }
141+
}
142+
},
143+
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
144+
let (data, start) = match a.not_undef().unwrap() {
145+
Scalar::Ptr(ptr) => {
146+
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
147+
}
148+
Scalar::Raw { .. } => (
149+
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
150+
0,
151+
),
152+
};
153+
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
154+
let start = start.try_into().unwrap();
155+
let len: usize = len.try_into().unwrap();
156+
ConstValue::Slice { data, start, end: start + len }
157+
}
158+
};
159+
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
160+
}
161+
24162
fn validate_and_turn_into_const<'tcx>(
25163
tcx: TyCtxt<'tcx>,
26164
constant: RawConst<'tcx>,
@@ -219,141 +357,3 @@ pub fn const_eval_raw_provider<'tcx>(
219357
}
220358
})
221359
}
222-
223-
// Returns a pointer to where the result lives
224-
fn eval_body_using_ecx<'mir, 'tcx>(
225-
ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
226-
cid: GlobalId<'tcx>,
227-
body: &'mir mir::Body<'tcx>,
228-
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
229-
debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
230-
let tcx = ecx.tcx.tcx;
231-
let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
232-
assert!(!layout.is_unsized());
233-
let ret = ecx.allocate(layout, MemoryKind::Stack);
234-
235-
let name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()));
236-
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
237-
trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
238-
239-
// Assert all args (if any) are zero-sized types; `eval_body_using_ecx` doesn't
240-
// make sense if the body is expecting nontrivial arguments.
241-
// (The alternative would be to use `eval_fn_call` with an args slice.)
242-
for arg in body.args_iter() {
243-
let decl = body.local_decls.get(arg).expect("arg missing from local_decls");
244-
let layout = ecx.layout_of(decl.ty.subst(tcx, cid.instance.substs))?;
245-
assert!(layout.is_zst())
246-
}
247-
248-
ecx.push_stack_frame(
249-
cid.instance,
250-
body.span,
251-
body,
252-
Some(ret.into()),
253-
StackPopCleanup::None { cleanup: false },
254-
)?;
255-
256-
// The main interpreter loop.
257-
ecx.run()?;
258-
259-
// Intern the result
260-
intern_const_alloc_recursive(ecx, tcx.static_mutability(cid.instance.def_id()), ret)?;
261-
262-
debug!("eval_body_using_ecx done: {:?}", *ret);
263-
Ok(ret)
264-
}
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)