Skip to content

Commit 3127a9c

Browse files
committed
Prepare mir::Constant for ty::Const only supporting valtrees
1 parent 3ecde6f commit 3127a9c

File tree

38 files changed

+367
-151
lines changed

38 files changed

+367
-151
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
88
use rustc_middle::mir::interpret::{
99
read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar,
1010
};
11-
use rustc_middle::ty::{Const, ConstKind};
11+
use rustc_middle::ty::ConstKind;
1212

1313
use cranelift_codegen::ir::GlobalValueData;
1414
use cranelift_module::*;
@@ -39,7 +39,10 @@ impl ConstantCx {
3939
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
4040
let mut all_constants_ok = true;
4141
for constant in &fx.mir.required_consts {
42-
let const_ = fx.monomorphize(constant.literal);
42+
let const_ = match fx.monomorphize(constant.literal) {
43+
ConstantSource::Ty(ct) => ct,
44+
ConstantSource::Val(..) => continue,
45+
};
4346
match const_.val {
4447
ConstKind::Value(_) => {}
4548
ConstKind::Unevaluated(def, ref substs, promoted) => {
@@ -113,19 +116,17 @@ pub(crate) fn codegen_constant<'tcx>(
113116
fx: &mut FunctionCx<'_, '_, 'tcx>,
114117
constant: &Constant<'tcx>,
115118
) -> CValue<'tcx> {
116-
let const_ = fx.monomorphize(constant.literal);
119+
let const_ = match fx.monomorphize(constant.literal) {
120+
ConstantSource::Ty(ct) => ct,
121+
ConstantSource::Val(val, ty) => return codegen_const_value(fx, val, ty),
122+
};
117123
let const_val = match const_.val {
118124
ConstKind::Value(const_val) => const_val,
119125
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
120126
assert!(substs.is_empty());
121127
assert!(promoted.is_none());
122128

123-
return codegen_static_ref(
124-
fx,
125-
def.did,
126-
fx.layout_of(fx.monomorphize(&constant.literal.ty)),
127-
)
128-
.to_cvalue(fx);
129+
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
129130
}
130131
ConstKind::Unevaluated(def, ref substs, promoted) => {
131132
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) {
@@ -422,11 +423,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
422423
pub(crate) fn mir_operand_get_const_val<'tcx>(
423424
fx: &FunctionCx<'_, '_, 'tcx>,
424425
operand: &Operand<'tcx>,
425-
) -> Option<&'tcx Const<'tcx>> {
426+
) -> Option<ConstValue<'tcx>> {
426427
match operand {
427428
Operand::Copy(_) | Operand::Move(_) => None,
428-
Operand::Constant(const_) => {
429-
Some(fx.monomorphize(const_.literal).eval(fx.tcx, ParamEnv::reveal_all()))
430-
}
429+
Operand::Constant(const_) => match const_.literal {
430+
ConstantSource::Ty(const_) => {
431+
fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value()
432+
}
433+
ConstantSource::Val(val, _) => Some(val),
434+
},
431435
}
432436
}

compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
5353
};
5454
llvm.x86.sse2.cmp.ps | llvm.x86.sse2.cmp.pd, (c x, c y, o kind) {
5555
let kind_const = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const");
56-
let flt_cc = match kind_const.val.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
56+
let flt_cc = match kind_const.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
5757
0 => FloatCC::Equal,
5858
1 => FloatCC::LessThan,
5959
2 => FloatCC::LessThanOrEqual,
@@ -84,7 +84,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
8484
llvm.x86.sse2.psrli.d, (c a, o imm8) {
8585
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
8686
simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
87-
let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
87+
let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
8888
imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
8989
_ => fx.bcx.ins().iconst(types::I32, 0),
9090
};
@@ -94,7 +94,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
9494
llvm.x86.sse2.pslli.d, (c a, o imm8) {
9595
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
9696
simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| {
97-
let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
97+
let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
9898
imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
9999
_ => fx.bcx.ins().iconst(types::I32, 0),
100100
};

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
8585
use rustc_middle::mir::interpret::*;
8686
let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");
8787

88-
let idx_bytes = match idx_const.val {
89-
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) => {
88+
let idx_bytes = match idx_const {
89+
ConstValue::ByRef { alloc, offset } => {
9090
let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
9191
let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */);
9292
alloc.get_bytes(fx, ptr, size).unwrap()
@@ -130,7 +130,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
130130
);
131131
};
132132

133-
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
133+
let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
134134
let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
135135
if idx >= lane_count.into() {
136136
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
@@ -159,7 +159,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
159159
return;
160160
};
161161

162-
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
162+
let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
163163
let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
164164
if idx >= lane_count.into() {
165165
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));

compiler/rustc_codegen_ssa/src/mir/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
860860
}
861861
mir::InlineAsmOperand::SymFn { ref value } => {
862862
let literal = self.monomorphize(value.literal);
863-
if let ty::FnDef(def_id, substs) = *literal.ty.kind() {
863+
if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
864864
let instance = ty::Instance::resolve_for_fn_ptr(
865865
bx.tcx(),
866866
ty::ParamEnv::reveal_all(),

compiler/rustc_codegen_ssa/src/mir/constant.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2424
&self,
2525
constant: &mir::Constant<'tcx>,
2626
) -> Result<ConstValue<'tcx>, ErrorHandled> {
27-
match self.monomorphize(constant.literal).val {
27+
let ct = self.monomorphize(constant.literal);
28+
let ct = match ct {
29+
mir::ConstantSource::Ty(ct) => ct,
30+
mir::ConstantSource::Val(val, _) => return Ok(val),
31+
};
32+
match ct.val {
2833
ty::ConstKind::Unevaluated(def, substs, promoted) => self
2934
.cx
3035
.tcx()

compiler/rustc_middle/src/mir/interpret/value.rs

+18
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,25 @@ pub enum ConstValue<'tcx> {
4747
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
4848
static_assert_size!(ConstValue<'_>, 32);
4949

50+
impl From<Scalar> for ConstValue<'tcx> {
51+
fn from(s: Scalar) -> Self {
52+
Self::Scalar(s)
53+
}
54+
}
55+
5056
impl<'tcx> ConstValue<'tcx> {
57+
pub fn lift<'lifted>(self, tcx: TyCtxt<'lifted>) -> Option<ConstValue<'lifted>> {
58+
Some(match self {
59+
ConstValue::Scalar(s) => ConstValue::Scalar(s),
60+
ConstValue::Slice { data, start, end } => {
61+
ConstValue::Slice { data: tcx.lift(data)?, start, end }
62+
}
63+
ConstValue::ByRef { alloc, offset } => {
64+
ConstValue::ByRef { alloc: tcx.lift(alloc)?, offset }
65+
}
66+
})
67+
}
68+
5169
#[inline]
5270
pub fn try_to_scalar(&self) -> Option<Scalar> {
5371
match *self {

compiler/rustc_middle/src/mir/mod.rs

+124-9
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
1111
use crate::ty::print::{FmtPrinter, Printer};
1212
use crate::ty::subst::{Subst, SubstsRef};
1313
use crate::ty::{self, List, Ty, TyCtxt};
14-
use crate::ty::{AdtDef, InstanceDef, Region, UserTypeAnnotationIndex};
14+
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
1515
use rustc_hir as hir;
1616
use rustc_hir::def::{CtorKind, Namespace};
1717
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
1818
use rustc_hir::{self, GeneratorKind};
19-
use rustc_target::abi::VariantIdx;
19+
use rustc_target::abi::{Size, VariantIdx};
2020

2121
use polonius_engine::Atom;
2222
pub use rustc_ast::Mutability;
@@ -30,6 +30,7 @@ use rustc_span::symbol::Symbol;
3030
use rustc_span::{Span, DUMMY_SP};
3131
use rustc_target::asm::InlineAsmRegOrRegClass;
3232
use std::borrow::Cow;
33+
use std::convert::TryInto;
3334
use std::fmt::{self, Debug, Display, Formatter, Write};
3435
use std::ops::{ControlFlow, Index, IndexMut};
3536
use std::slice;
@@ -2032,7 +2033,7 @@ impl<'tcx> Operand<'tcx> {
20322033
Operand::Constant(box Constant {
20332034
span,
20342035
user_ty: None,
2035-
literal: ty::Const::zero_sized(tcx, ty),
2036+
literal: ConstantSource::Ty(ty::Const::zero_sized(tcx, ty)),
20362037
})
20372038
}
20382039

@@ -2063,7 +2064,7 @@ impl<'tcx> Operand<'tcx> {
20632064
Operand::Constant(box Constant {
20642065
span,
20652066
user_ty: None,
2066-
literal: ty::Const::from_scalar(tcx, val, ty),
2067+
literal: ConstantSource::Val(val.into(), ty),
20672068
})
20682069
}
20692070

@@ -2405,12 +2406,21 @@ pub struct Constant<'tcx> {
24052406
/// Needed for NLL to impose user-given type constraints.
24062407
pub user_ty: Option<UserTypeAnnotationIndex>,
24072408

2408-
pub literal: &'tcx ty::Const<'tcx>,
2409+
pub literal: ConstantSource<'tcx>,
2410+
}
2411+
2412+
#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
2413+
pub enum ConstantSource<'tcx> {
2414+
/// This constant came from the type system
2415+
Ty(&'tcx ty::Const<'tcx>),
2416+
/// This constant cannot go back into the type system, as it represents
2417+
/// something the type system cannot handle (e.g. pointers).
2418+
Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
24092419
}
24102420

24112421
impl Constant<'tcx> {
24122422
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
2413-
match self.literal.val.try_to_scalar() {
2423+
match self.literal.const_for_ty()?.val.try_to_scalar() {
24142424
Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
24152425
GlobalAlloc::Static(def_id) => {
24162426
assert!(!tcx.is_thread_local_static(def_id));
@@ -2422,7 +2432,92 @@ impl Constant<'tcx> {
24222432
}
24232433
}
24242434
pub fn ty(&self) -> Ty<'tcx> {
2425-
self.literal.ty
2435+
self.literal.ty()
2436+
}
2437+
}
2438+
2439+
impl From<&'tcx ty::Const<'tcx>> for ConstantSource<'tcx> {
2440+
fn from(ct: &'tcx ty::Const<'tcx>) -> Self {
2441+
Self::Ty(ct)
2442+
}
2443+
}
2444+
2445+
impl ConstantSource<'tcx> {
2446+
/// Returns `None` if the constant is not trivially safe for use in the type system.
2447+
pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> {
2448+
match self {
2449+
ConstantSource::Ty(c) => Some(c),
2450+
ConstantSource::Val(..) => None,
2451+
}
2452+
}
2453+
2454+
pub fn ty(&self) -> Ty<'tcx> {
2455+
match self {
2456+
ConstantSource::Ty(c) => c.ty,
2457+
ConstantSource::Val(_, ty) => ty,
2458+
}
2459+
}
2460+
2461+
#[inline]
2462+
pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> {
2463+
match self {
2464+
ConstantSource::Ty(c) => c.val.try_to_value(),
2465+
ConstantSource::Val(val, _) => Some(val),
2466+
}
2467+
}
2468+
2469+
#[inline]
2470+
pub fn try_to_scalar(self) -> Option<Scalar> {
2471+
self.try_to_value()?.try_to_scalar()
2472+
}
2473+
2474+
#[inline]
2475+
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
2476+
self.try_to_value()?.try_to_scalar()?.to_int().ok()
2477+
}
2478+
2479+
#[inline]
2480+
pub fn try_to_bits(self, size: Size) -> Option<u128> {
2481+
self.try_to_scalar_int()?.to_bits(size).ok()
2482+
}
2483+
2484+
#[inline]
2485+
pub fn try_to_bool(self) -> Option<bool> {
2486+
self.try_to_scalar_int()?.try_into().ok()
2487+
}
2488+
2489+
#[inline]
2490+
pub fn try_eval_bits(
2491+
&self,
2492+
tcx: TyCtxt<'tcx>,
2493+
param_env: ty::ParamEnv<'tcx>,
2494+
ty: Ty<'tcx>,
2495+
) -> Option<u128> {
2496+
match self {
2497+
Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty),
2498+
Self::Val(val, t) => {
2499+
assert_eq!(*t, ty);
2500+
let size =
2501+
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
2502+
val.try_to_bits(size)
2503+
}
2504+
}
2505+
}
2506+
2507+
#[inline]
2508+
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
2509+
match self {
2510+
Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
2511+
Self::Val(val, _) => val.try_to_bool(),
2512+
}
2513+
}
2514+
2515+
#[inline]
2516+
pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u64> {
2517+
match self {
2518+
Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
2519+
Self::Val(val, _) => val.try_to_machine_usize(tcx),
2520+
}
24262521
}
24272522
}
24282523

@@ -2609,11 +2704,14 @@ impl<'tcx> Debug for Constant<'tcx> {
26092704

26102705
impl<'tcx> Display for Constant<'tcx> {
26112706
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
2612-
match self.literal.ty.kind() {
2707+
match self.ty().kind() {
26132708
ty::FnDef(..) => {}
26142709
_ => write!(fmt, "const ")?,
26152710
}
2616-
pretty_print_const(self.literal, fmt, true)
2711+
match self.literal {
2712+
ConstantSource::Ty(c) => pretty_print_const(c, fmt, true),
2713+
ConstantSource::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
2714+
}
26172715
}
26182716
}
26192717

@@ -2632,6 +2730,23 @@ fn pretty_print_const(
26322730
})
26332731
}
26342732

2733+
fn pretty_print_const_value(
2734+
val: interpret::ConstValue<'tcx>,
2735+
ty: Ty<'tcx>,
2736+
fmt: &mut Formatter<'_>,
2737+
print_types: bool,
2738+
) -> fmt::Result {
2739+
use crate::ty::print::PrettyPrinter;
2740+
ty::tls::with(|tcx| {
2741+
let val = val.lift(tcx).unwrap();
2742+
let ty = tcx.lift(ty).unwrap();
2743+
let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS);
2744+
cx.print_alloc_ids = true;
2745+
cx.pretty_print_const_value(val, ty, print_types)?;
2746+
Ok(())
2747+
})
2748+
}
2749+
26352750
impl<'tcx> graph::DirectedGraph for Body<'tcx> {
26362751
type Node = BasicBlock;
26372752
}

compiler/rustc_middle/src/mir/tcx.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> {
227227
{
228228
match self {
229229
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
230-
&Operand::Constant(ref c) => c.literal.ty,
230+
&Operand::Constant(ref c) => c.literal.ty(),
231231
}
232232
}
233233
}

0 commit comments

Comments
 (0)