1
Fork 0

Auto merge of #87123 - RalfJung:miri-provenance-overhaul, r=oli-obk

CTFE/Miri engine Pointer type overhaul

This fixes the long-standing problem that we are using `Scalar` as a type to represent pointers that might be integer values (since they point to a ZST). The main problem is that with int-to-ptr casts, there are multiple ways to represent the same pointer as a `Scalar` and it is unclear if "normalization" (i.e., the cast) already happened or not. This leads to ugly methods like `force_mplace_ptr` and `force_op_ptr`.
Another problem this solves is that in Miri, it would make a lot more sense to have the `Pointer::offset` field represent the full absolute address (instead of being relative to the `AllocId`). This means we can do ptr-to-int casts without access to any machine state, and it means that the overflow checks on pointer arithmetic are (finally!) accurate.

To solve this, the `Pointer` type is made entirely parametric over the provenance, so that we can use `Pointer<AllocId>` inside `Scalar` but use `Pointer<Option<AllocId>>` when accessing memory (where `None` represents the case that we could not figure out an `AllocId`; in that case the `offset` is an absolute address). Moreover, the `Provenance` trait determines if a pointer with a given provenance can be cast to an integer by simply dropping the provenance.

I hope this can be read commit-by-commit, but the first commit does the bulk of the work. It introduces some FIXMEs that are resolved later.
Fixes https://github.com/rust-lang/miri/issues/841
Miri PR: https://github.com/rust-lang/miri/pull/1851
r? `@oli-obk`
This commit is contained in:
bors 2021-07-17 15:26:27 +00:00
commit c78ebb7bdc
106 changed files with 1317 additions and 1407 deletions

View file

@ -38,7 +38,7 @@ crate fn lit_to_const<'tcx>(
}
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::Ptr(id.into()))
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
}
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))

View file

@ -928,7 +928,11 @@ impl<'tcx> Cx<'tcx> {
} else {
let ptr = self.tcx.create_static_alloc(id);
ExprKind::StaticRef {
literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty),
literal: ty::Const::from_scalar(
self.tcx,
Scalar::from_pointer(ptr.into(), &self.tcx),
ty,
),
def_id: id,
}
};

View file

@ -123,7 +123,7 @@ impl IntRange {
// straight to the result, after doing a bit of checking. (We
// could remove this branch and just fall through, which
// is more general but much slower.)
if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) {
if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) {
return Some(bits);
}
}