Skip to content

Commit a0efd41

Browse files
committed
Use ValTree in all type level constants
1 parent 8de1c1a commit a0efd41

File tree

177 files changed

+1108
-760
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

177 files changed

+1108
-760
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,19 @@ pub(crate) fn codegen_constant<'tcx>(
120120
ConstantKind::Ty(ct) => ct,
121121
ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
122122
};
123-
let const_val = match const_.val {
124-
ConstKind::Value(const_val) => const_val,
125-
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) if fx.tcx.is_static(def.did) => {
123+
match const_.val {
124+
ConstKind::Value(valtree) => codegen_valtree(fx, valtree, const_.ty, constant.span),
125+
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
126+
if fx.tcx.is_static(def.did) =>
127+
{
126128
assert!(substs.is_empty());
127129
assert!(promoted.is_none());
128130

129-
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
131+
codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx)
130132
}
131133
ConstKind::Unevaluated(unevaluated) => {
132134
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
133-
Ok(const_val) => const_val,
135+
Ok(const_val) => codegen_const_value(fx, const_val, const_.ty),
134136
Err(_) => {
135137
span_bug!(constant.span, "erroneous constant not captured by required_consts");
136138
}
@@ -141,9 +143,53 @@ pub(crate) fn codegen_constant<'tcx>(
141143
| ConstKind::Bound(_, _)
142144
| ConstKind::Placeholder(_)
143145
| ConstKind::Error(_) => unreachable!("{:?}", const_),
146+
}
147+
}
148+
149+
pub(crate) fn codegen_valtree<'tcx>(
150+
fx: &mut FunctionCx<'_, '_, 'tcx>,
151+
valtree: ty::ValTree<'tcx>,
152+
ty: Ty<'tcx>,
153+
span: Span,
154+
) -> CValue<'tcx> {
155+
let layout = fx.layout_of(ty);
156+
let tcx = fx.tcx;
157+
let mut encode_slice = |valtree: ty::ValTree<'_>| {
158+
let s: Vec<u8> = valtree
159+
.unwrap_branch()
160+
.iter()
161+
.map(|b| u8::try_from(b.unwrap_leaf()).unwrap())
162+
.collect();
163+
let alloc_id = fx.tcx.allocate_bytes(&s);
164+
165+
let ptr = pointer_for_alloc_id(fx, alloc_id, Mutability::Not).get_addr(fx);
166+
let len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(s.len()).unwrap());
167+
CValue::by_val_pair(ptr, len, layout)
144168
};
145169

146-
codegen_const_value(fx, const_val, const_.ty)
170+
match *ty.kind() {
171+
ty::Ref(_, pointee, _) => match *pointee.kind() {
172+
ty::Str => encode_slice(valtree),
173+
ty::Slice(elem_ty) if elem_ty == tcx.types.u8 => encode_slice(valtree),
174+
ty::Array(elem_ty, _) if elem_ty == tcx.types.u8 => {
175+
let s: Vec<u8> = valtree
176+
.unwrap_branch()
177+
.iter()
178+
.map(|b| u8::try_from(b.unwrap_leaf()).unwrap())
179+
.collect();
180+
let alloc_id = fx.tcx.allocate_bytes(&s);
181+
fx.cx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
182+
let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, Mutability::Not);
183+
let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
184+
#[cfg(debug_assertions)]
185+
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
186+
let ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
187+
CValue::by_val(ptr, layout)
188+
}
189+
_ => span_bug!(span, "{}: {:?}", ty, valtree),
190+
},
191+
_ => codegen_const_value(fx, ConstValue::Scalar(valtree.unwrap_leaf().into()), ty),
192+
}
147193
}
148194

149195
pub(crate) fn codegen_const_value<'tcx>(
@@ -237,8 +283,16 @@ fn pointer_for_allocation<'tcx>(
237283
alloc: &'tcx Allocation,
238284
) -> crate::pointer::Pointer {
239285
let alloc_id = fx.tcx.create_memory_alloc(alloc);
286+
pointer_for_alloc_id(fx, alloc_id, alloc.mutability)
287+
}
288+
289+
fn pointer_for_alloc_id<'tcx>(
290+
fx: &mut FunctionCx<'_, '_, 'tcx>,
291+
alloc_id: AllocId,
292+
mutability: Mutability,
293+
) -> crate::pointer::Pointer {
240294
fx.cx.constants_cx.todo.push(TodoItem::Alloc(alloc_id));
241-
let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, alloc.mutability);
295+
let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, mutability);
242296

243297
let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
244298
#[cfg(debug_assertions)]
@@ -420,17 +474,19 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
420474
assert!(cx.todo.is_empty(), "{:?}", cx.todo);
421475
}
422476

423-
pub(crate) fn mir_operand_get_const_val<'tcx>(
477+
pub(crate) fn mir_operand_get_const_int<'tcx>(
424478
fx: &FunctionCx<'_, '_, 'tcx>,
425479
operand: &Operand<'tcx>,
426-
) -> Option<ConstValue<'tcx>> {
480+
) -> Option<ty::ScalarInt> {
481+
mir_operand_get_const(fx, operand)?.try_to_scalar_int()
482+
}
483+
484+
pub(crate) fn mir_operand_get_const<'tcx>(
485+
_fx: &FunctionCx<'_, '_, 'tcx>,
486+
operand: &Operand<'tcx>,
487+
) -> Option<mir::ConstantKind<'tcx>> {
427488
match operand {
428489
Operand::Copy(_) | Operand::Move(_) => None,
429-
Operand::Constant(const_) => match const_.literal {
430-
ConstantKind::Ty(const_) => {
431-
fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value()
432-
}
433-
ConstantKind::Val(val, _) => Some(val),
434-
},
490+
Operand::Constant(const_) => Some(const_.literal),
435491
}
436492
}

compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
5252
ret.write_cvalue(fx, res);
5353
};
5454
llvm.x86.sse2.cmp.ps | llvm.x86.sse2.cmp.pd, (c x, c y, o kind) {
55-
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.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) {
55+
let kind_const = crate::constant::mir_operand_get_const_int(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const");
56+
let flt_cc = match kind_const.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,
@@ -82,19 +82,19 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
8282
});
8383
};
8484
llvm.x86.sse2.psrli.d, (c a, o imm8) {
85-
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
85+
let imm8 = crate::constant::mir_operand_get_const_int(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.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
87+
let res_lane = match imm8.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
};
9191
CValue::by_val(res_lane, res_lane_layout)
9292
});
9393
};
9494
llvm.x86.sse2.pslli.d, (c a, o imm8) {
95-
let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const");
95+
let imm8 = crate::constant::mir_operand_get_const_int(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.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) {
97+
let res_lane = match imm8.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

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,24 +82,17 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
8282
let total_len = lane_count * 2;
8383

8484
let indexes = {
85-
use rustc_middle::mir::interpret::*;
86-
let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");
87-
88-
let idx_bytes = match idx_const {
89-
ConstValue::ByRef { alloc, offset } => {
90-
let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
91-
let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */);
92-
alloc.get_bytes(fx, ptr, size).unwrap()
93-
}
85+
let idx_const = crate::constant::mir_operand_get_const(fx, idx).expect("simd_shuffle* idx not const").const_for_ty().expect("simd shuffle arg must be structural-eq");
86+
87+
let idxs = match idx_const.val.try_to_value() {
88+
Some(ty::ValTree::Branch(branches)) => branches,
9489
_ => unreachable!("{:?}", idx_const),
9590
};
9691

97-
(0..ret_lane_count).map(|i| {
98-
let i = usize::try_from(i).unwrap();
99-
let idx = rustc_middle::mir::interpret::read_target_uint(
100-
fx.tcx.data_layout.endian,
101-
&idx_bytes[4*i.. 4*i + 4],
102-
).expect("read_target_uint");
92+
assert_eq!(u64::try_from(idxs.len()), Ok(ret_lane_count));
93+
idxs.iter().map(|idx|{
94+
let idx = idx.unwrap_leaf();
95+
let idx = u32::try_from(idx).expect("simd_shuffle indices are u32");
10396
u16::try_from(idx).expect("try_from u32")
10497
}).collect::<Vec<u16>>()
10598
};
@@ -121,7 +114,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
121114

122115
simd_insert, (c base, o idx, c val) {
123116
// FIXME validate
124-
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
117+
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_int(fx, idx) {
125118
idx_const
126119
} else {
127120
fx.tcx.sess.span_fatal(
@@ -130,7 +123,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
130123
);
131124
};
132125

133-
let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
126+
let idx = idx_const.to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const));
134127
let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
135128
if idx >= lane_count.into() {
136129
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
@@ -143,7 +136,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
143136

144137
simd_extract, (c v, o idx) {
145138
validate_simd_type!(fx, intrinsic, span, v.layout().ty);
146-
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
139+
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_int(fx, idx) {
147140
idx_const
148141
} else {
149142
fx.tcx.sess.span_warn(
@@ -159,7 +152,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
159152
return;
160153
};
161154

162-
let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
155+
let idx = idx_const.to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|_| panic!("kind not scalar: {:?}", idx_const));
163156
let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
164157
if idx >= lane_count.into() {
165158
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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ use crate::MemFlags;
1212
use rustc_ast as ast;
1313
use rustc_hir::lang_items::LangItem;
1414
use rustc_index::vec::Idx;
15-
use rustc_middle::mir::interpret::ConstValue;
15+
use rustc_middle::mir::interpret::{ConstValue, Scalar};
1616
use rustc_middle::mir::AssertKind;
1717
use rustc_middle::mir::{self, SwitchTargets};
1818
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
1919
use rustc_middle::ty::print::with_no_trimmed_paths;
20+
use rustc_middle::ty::ValTree;
2021
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
2122
use rustc_span::source_map::Span;
2223
use rustc_span::{sym, Symbol};
@@ -634,7 +635,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
634635
// promotes any complex rvalues to constants.
635636
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
636637
if let mir::Operand::Constant(constant) = arg {
637-
let c = self.eval_mir_constant(constant);
638+
let c = self.eval_mir_constant(constant).map(Result::unwrap);
638639
let (llval, ty) =
639640
self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c);
640641
return OperandRef {
@@ -829,7 +830,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
829830
let ty = constant.ty();
830831
let size = bx.layout_of(ty).size;
831832
let scalar = match const_value {
832-
ConstValue::Scalar(s) => s,
833+
Ok(ConstValue::Scalar(Scalar::Int(s))) | Err(ValTree::Leaf(s)) => s,
833834
_ => span_bug!(
834835
span,
835836
"expected Scalar for promoted asm const, but got {:#?}",
@@ -1152,7 +1153,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11521153
caller.line as u32,
11531154
caller.col_display as u32 + 1,
11541155
));
1155-
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
1156+
OperandRef::from_const(bx, Ok(const_loc), bx.tcx().caller_location_ty(), span)
11561157
};
11571158

11581159
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.

compiler/rustc_codegen_ssa/src/mir/constant.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::ty::layout::HasTyCtxt;
66
use rustc_middle::ty::{self, Ty};
77
use rustc_span::source_map::Span;
88
use rustc_target::abi::Abi;
9+
use rustc_errors::ErrorReported;
910

1011
use super::FunctionCx;
1112

@@ -17,17 +18,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1718
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
1819
let val = self.eval_mir_constant(constant)?;
1920
let ty = self.monomorphize(constant.ty());
20-
Ok(OperandRef::from_const(bx, val, ty))
21+
Ok(OperandRef::from_const(bx, val, ty, constant.span))
2122
}
2223

2324
pub fn eval_mir_constant(
2425
&self,
2526
constant: &mir::Constant<'tcx>,
26-
) -> Result<ConstValue<'tcx>, ErrorHandled> {
27+
) -> Result<Result<ConstValue<'tcx>, ty::ValTree<'tcx>>, ErrorHandled> {
2728
let ct = self.monomorphize(constant.literal);
2829
let ct = match ct {
2930
mir::ConstantKind::Ty(ct) => ct,
30-
mir::ConstantKind::Val(val, _) => return Ok(val),
31+
mir::ConstantKind::Val(val, _) => return Ok(Ok(val)),
3132
};
3233
match ct.val {
3334
ty::ConstKind::Unevaluated(ct) => self
@@ -37,8 +38,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
3738
.map_err(|err| {
3839
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
3940
err
40-
}),
41-
ty::ConstKind::Value(value) => Ok(value),
41+
})
42+
.map(Ok),
43+
ty::ConstKind::Value(value) => Ok(Err(value)),
44+
// Already reported an error, nothing to do.
45+
ty::ConstKind::Error(_) => Err(ErrorHandled::Reported(ErrorReported)),
4246
err => span_bug!(
4347
constant.span,
4448
"encountered bad ConstKind after monomorphizing: {:?}",

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
113113
.tcx()
114114
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
115115
.unwrap();
116-
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
116+
OperandRef::from_const(bx, Ok(value), ret_ty, span).immediate_or_packed_pair(bx)
117117
}
118118
sym::offset => {
119119
let ptr = args[0].immediate();

0 commit comments

Comments
 (0)