Skip to content

Commit

Permalink
Port more zero arg intrinsics to the const_eval query
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jun 19, 2019
1 parent bd9b93d commit 26c486f
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 66 deletions.
9 changes: 9 additions & 0 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
}

impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
fn from(err: ErrorHandled) -> Self {
match err {
ErrorHandled::Reported => InterpError::ReferencedConstant,
ErrorHandled::TooGeneric => InterpError::TooGeneric,
}.into()
}
}

impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx, u64>) -> Self {
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
Expand Down
25 changes: 5 additions & 20 deletions src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
self.call(llfn, &[], None)
}
"size_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.size_of(tp_ty).bytes())
}
"va_start" => {
self.va_start(args[0].immediate())
}
Expand Down Expand Up @@ -192,10 +188,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.const_usize(self.size_of(tp_ty).bytes())
}
}
"min_align_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.align_of(tp_ty).bytes())
}
"min_align_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
Expand All @@ -205,10 +197,11 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.const_usize(self.align_of(tp_ty).bytes())
}
}
"pref_align_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
}
"size_of" |
"pref_align_of" |
"min_align_of" |
"needs_drop" |
"type_id" |
"type_name" => {
let gid = GlobalId {
instance,
Expand All @@ -217,9 +210,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
}
"type_id" => {
self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
}
"init" => {
let ty = substs.type_at(0);
if !self.layout_of(ty).is_zst() {
Expand All @@ -242,11 +232,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
"uninit" | "forget" => {
return;
}
"needs_drop" => {
let tp_ty = substs.type_at(0);

self.const_bool(self.type_needs_drop(tp_ty))
}
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
Expand Down
27 changes: 24 additions & 3 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ pub fn const_eval_provider<'tcx>(
ty::FnDef(_, substs) => substs,
_ => bug!("intrinsic with type {:?}", ty),
};
return Ok(eval_intrinsic(tcx, def_id, substs));
return Ok(eval_intrinsic(tcx, key.param_env, def_id, substs));
}

tcx.const_eval_raw(key).and_then(|val| {
Expand All @@ -606,12 +606,15 @@ pub fn const_eval_provider<'tcx>(

fn eval_intrinsic<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> &'tcx ty::Const<'tcx> {
match &*tcx.item_name(def_id).as_str() {
let tp_ty = substs.type_at(0);
let name = &*tcx.item_name(def_id).as_str();
match name {
"type_name" => {
let alloc = alloc_type_name(tcx, substs.type_at(0));
let alloc = alloc_type_name(tcx, tp_ty);
tcx.mk_const(ty::Const {
val: ConstValue::Slice {
data: alloc,
Expand All @@ -621,6 +624,24 @@ fn eval_intrinsic<'tcx>(
ty: tcx.mk_static_str(),
})
},
"needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
"size_of" |
"min_align_of" |
"pref_align_of" => {
let layout = tcx.layout_of(param_env.and(tp_ty)).unwrap();
let n = match name {
"pref_align_of" => layout.align.pref.bytes(),
"min_align_of" => layout.align.abi.bytes(),
"size_of" => layout.size.bytes(),
_ => bug!(),
};
ty::Const::from_usize(tcx, n)
},
"type_id" => ty::Const::from_bits(
tcx,
tcx.type_id_hash(tp_ty).into(),
param_env.and(tcx.types.u64),
),
other => bug!("`{}` is not a zero arg intrinsic", other),
}
}
Expand Down
8 changes: 1 addition & 7 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::mir::interpret::{
ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, InterpError,
truncate, sign_extend,
Expand Down Expand Up @@ -652,12 +651,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
// Our result will later be validated anyway, and there seems no good reason
// to have to fail early here. This is also more consistent with
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
match err {
ErrorHandled::Reported => InterpError::ReferencedConstant,
ErrorHandled::TooGeneric => InterpError::TooGeneric,
}
})?;
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
}

Expand Down
49 changes: 13 additions & 36 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use rustc::ty;
use rustc::ty::layout::{LayoutOf, Primitive, Size};
use rustc::mir::BinOp;
use rustc::mir::interpret::{
InterpResult, InterpError, Scalar,
InterpResult, InterpError, Scalar, GlobalId,
};

use super::{
Machine, PlaceTy, OpTy, InterpretCx, Immediate,
Machine, PlaceTy, OpTy, InterpretCx,
};

mod type_name;
Expand Down Expand Up @@ -51,41 +51,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {

let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
match intrinsic_name {
"min_align_of" => {
let elem_ty = substs.type_at(0);
let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
let align_val = Scalar::from_uint(elem_align, dest.layout.size);
self.write_scalar(align_val, dest)?;
}

"needs_drop" => {
let ty = substs.type_at(0);
let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
let val = Scalar::from_bool(ty_needs_drop);
self.write_scalar(val, dest)?;
}

"size_of" => {
let ty = substs.type_at(0);
let size = self.layout_of(ty)?.size.bytes() as u128;
let size_val = Scalar::from_uint(size, dest.layout.size);
self.write_scalar(size_val, dest)?;
}

"type_id" => {
let ty = substs.type_at(0);
let type_id = self.tcx.type_id_hash(ty) as u128;
let id_val = Scalar::from_uint(type_id, dest.layout.size);
self.write_scalar(id_val, dest)?;
}

"min_align_of" |
"needs_drop" |
"size_of" |
"type_id" |
"type_name" => {
let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
let alloc_len = alloc.bytes.len() as u64;
let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
self.write_immediate(name_val, dest)?;
let gid = GlobalId {
instance,
promoted: None,
};
let val = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid))?;
let val = self.eval_const_to_op(val, None)?;
self.copy_op(val, dest)?;
}

| "ctpop"
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/consts/const-size_of-cycle.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
LL | pub fn size_of<T>() -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
LL | pub fn size_of<T>() -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/issues/issue-44415.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
LL | pub fn size_of<T>() -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
LL | pub fn size_of<T>() -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
Expand Down

0 comments on commit 26c486f

Please sign in to comment.