Skip to content

Commit 8adc69a

Browse files
committed
Auto merge of #53779 - RalfJung:miri-refactor, r=oli-obk
Miri refactor: Final round Tying up some loose ends that I noticed in the previous PRs -- and finally getting argument passing into a shape where @eddyb says it is "okay", which is a big improvement over the previous verdict that I cannot quote in public. ;) Also move a bunch of useful helpers to construct `Scalar` from miri to here. Cc @eddyb r? @oli-obk
2 parents c6047ea + 97d693a commit 8adc69a

19 files changed

+595
-556
lines changed

src/librustc/ich/impls_ty.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
512512
mem::discriminant(&self).hash_stable(hcx, hasher);
513513

514514
match *self {
515+
FunctionArgCountMismatch |
515516
DanglingPointerDeref |
516517
DoubleFree |
517518
InvalidMemoryAccess |
@@ -558,7 +559,11 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
558559
},
559560
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
560561
MachineError(ref err) => err.hash_stable(hcx, hasher),
561-
FunctionPointerTyMismatch(a, b) => {
562+
FunctionAbiMismatch(a, b) => {
563+
a.hash_stable(hcx, hasher);
564+
b.hash_stable(hcx, hasher)
565+
},
566+
FunctionArgMismatch(a, b) => {
562567
a.hash_stable(hcx, hasher);
563568
b.hash_stable(hcx, hasher)
564569
},

src/librustc/mir/interpret/error.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
use std::{fmt, env};
1212

1313
use mir;
14-
use ty::{FnSig, Ty, layout};
14+
use ty::{Ty, layout};
1515
use ty::layout::{Size, Align};
1616
use rustc_data_structures::sync::Lrc;
17+
use rustc_target::spec::abi::Abi;
1718

1819
use super::{
1920
Pointer, Lock, AccessKind
@@ -182,7 +183,10 @@ pub enum EvalErrorKind<'tcx, O> {
182183
/// This variant is used by machines to signal their own errors that do not
183184
/// match an existing variant
184185
MachineError(String),
185-
FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
186+
187+
FunctionAbiMismatch(Abi, Abi),
188+
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
189+
FunctionArgCountMismatch,
186190
NoMirFor(String),
187191
UnterminatedCString(Pointer),
188192
DanglingPointerDeref,
@@ -290,8 +294,8 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
290294
use self::EvalErrorKind::*;
291295
match *self {
292296
MachineError(ref inner) => inner,
293-
FunctionPointerTyMismatch(..) =>
294-
"tried to call a function through a function pointer of a different type",
297+
FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionArgCountMismatch =>
298+
"tried to call a function through a function pointer of incompatible type",
295299
InvalidMemoryAccess =>
296300
"tried to access memory through an invalid pointer",
297301
DanglingPointerDeref =>
@@ -459,9 +463,15 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
459463
write!(f, "type validation failed: {}", err)
460464
}
461465
NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
462-
FunctionPointerTyMismatch(sig, got) =>
463-
write!(f, "tried to call a function with sig {} through a \
464-
function pointer of type {}", sig, got),
466+
FunctionAbiMismatch(caller_abi, callee_abi) =>
467+
write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}",
468+
callee_abi, caller_abi),
469+
FunctionArgMismatch(caller_ty, callee_ty) =>
470+
write!(f, "tried to call a function with argument of type {:?} \
471+
passing data of type {:?}",
472+
callee_ty, caller_ty),
473+
FunctionArgCountMismatch =>
474+
write!(f, "tried to call a function with incorrect number of arguments"),
465475
BoundsCheck { ref len, ref index } =>
466476
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
467477
ReallocatedWrongMemoryKind(ref old, ref new) =>

src/librustc/mir/interpret/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,14 @@ pub struct GlobalId<'tcx> {
8585
pub trait PointerArithmetic: layout::HasDataLayout {
8686
// These are not supposed to be overridden.
8787

88+
#[inline(always)]
89+
fn pointer_size(self) -> Size {
90+
self.data_layout().pointer_size
91+
}
92+
8893
//// Trunace the given value to the pointer size; also return whether there was an overflow
8994
fn truncate_to_ptr(self, val: u128) -> (u64, bool) {
90-
let max_ptr_plus_1 = 1u128 << self.data_layout().pointer_size.bits();
95+
let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
9196
((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
9297
}
9398

@@ -491,7 +496,9 @@ pub struct Allocation {
491496
/// Note that the bytes of a pointer represent the offset of the pointer
492497
pub bytes: Vec<u8>,
493498
/// Maps from byte addresses to allocations.
494-
/// Only the first byte of a pointer is inserted into the map.
499+
/// Only the first byte of a pointer is inserted into the map; i.e.,
500+
/// every entry in this map applies to `pointer_size` consecutive bytes starting
501+
/// at the given offset.
495502
pub relocations: Relocations,
496503
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
497504
pub undef_mask: UndefMask,

src/librustc/mir/interpret/value.rs

+96-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ty::layout::{HasDataLayout, Size};
1414
use ty::subst::Substs;
1515
use hir::def_id::DefId;
1616

17-
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend};
17+
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
1818

1919
/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
2020
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
@@ -58,6 +58,7 @@ impl<'tcx> ConstValue<'tcx> {
5858
self.try_to_scalar()?.to_ptr().ok()
5959
}
6060

61+
#[inline]
6162
pub fn new_slice(
6263
val: Scalar,
6364
len: u64,
@@ -69,23 +70,27 @@ impl<'tcx> ConstValue<'tcx> {
6970
}.into())
7071
}
7172

73+
#[inline]
7274
pub fn new_dyn_trait(val: Scalar, vtable: Pointer) -> Self {
7375
ConstValue::ScalarPair(val, Scalar::Ptr(vtable).into())
7476
}
7577
}
7678

7779
impl<'tcx> Scalar {
80+
#[inline]
7881
pub fn ptr_null(cx: impl HasDataLayout) -> Self {
7982
Scalar::Bits {
8083
bits: 0,
8184
size: cx.data_layout().pointer_size.bytes() as u8,
8285
}
8386
}
8487

88+
#[inline]
8589
pub fn zst() -> Self {
8690
Scalar::Bits { bits: 0, size: 0 }
8791
}
8892

93+
#[inline]
8994
pub fn ptr_signed_offset(self, i: i64, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
9095
let layout = cx.data_layout();
9196
match self {
@@ -100,6 +105,7 @@ impl<'tcx> Scalar {
100105
}
101106
}
102107

108+
#[inline]
103109
pub fn ptr_offset(self, i: Size, cx: impl HasDataLayout) -> EvalResult<'tcx, Self> {
104110
let layout = cx.data_layout();
105111
match self {
@@ -114,6 +120,7 @@ impl<'tcx> Scalar {
114120
}
115121
}
116122

123+
#[inline]
117124
pub fn ptr_wrapping_signed_offset(self, i: i64, cx: impl HasDataLayout) -> Self {
118125
let layout = cx.data_layout();
119126
match self {
@@ -128,6 +135,7 @@ impl<'tcx> Scalar {
128135
}
129136
}
130137

138+
#[inline]
131139
pub fn is_null_ptr(self, cx: impl HasDataLayout) -> bool {
132140
match self {
133141
Scalar::Bits { bits, size } => {
@@ -138,14 +146,53 @@ impl<'tcx> Scalar {
138146
}
139147
}
140148

149+
#[inline]
150+
pub fn is_null(self) -> bool {
151+
match self {
152+
Scalar::Bits { bits, .. } => bits == 0,
153+
Scalar::Ptr(_) => false
154+
}
155+
}
156+
157+
#[inline]
141158
pub fn from_bool(b: bool) -> Self {
142159
Scalar::Bits { bits: b as u128, size: 1 }
143160
}
144161

162+
#[inline]
145163
pub fn from_char(c: char) -> Self {
146164
Scalar::Bits { bits: c as u128, size: 4 }
147165
}
148166

167+
#[inline]
168+
pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
169+
let i = i.into();
170+
debug_assert_eq!(truncate(i, size), i,
171+
"Unsigned value {} does not fit in {} bits", i, size.bits());
172+
Scalar::Bits { bits: i, size: size.bytes() as u8 }
173+
}
174+
175+
#[inline]
176+
pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
177+
let i = i.into();
178+
// `into` performed sign extension, we have to truncate
179+
let truncated = truncate(i as u128, size);
180+
debug_assert_eq!(sign_extend(truncated, size) as i128, i,
181+
"Signed value {} does not fit in {} bits", i, size.bits());
182+
Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
183+
}
184+
185+
#[inline]
186+
pub fn from_f32(f: f32) -> Self {
187+
Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
188+
}
189+
190+
#[inline]
191+
pub fn from_f64(f: f64) -> Self {
192+
Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
193+
}
194+
195+
#[inline]
149196
pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
150197
match self {
151198
Scalar::Bits { bits, size } => {
@@ -157,6 +204,7 @@ impl<'tcx> Scalar {
157204
}
158205
}
159206

207+
#[inline]
160208
pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
161209
match self {
162210
Scalar::Bits { bits: 0, .. } => err!(InvalidNullPointerUsage),
@@ -165,13 +213,15 @@ impl<'tcx> Scalar {
165213
}
166214
}
167215

216+
#[inline]
168217
pub fn is_bits(self) -> bool {
169218
match self {
170219
Scalar::Bits { .. } => true,
171220
_ => false,
172221
}
173222
}
174223

224+
#[inline]
175225
pub fn is_ptr(self) -> bool {
176226
match self {
177227
Scalar::Ptr(_) => true,
@@ -209,6 +259,13 @@ impl<'tcx> Scalar {
209259
Ok(b as u32)
210260
}
211261

262+
pub fn to_u64(self) -> EvalResult<'static, u64> {
263+
let sz = Size::from_bits(64);
264+
let b = self.to_bits(sz)?;
265+
assert_eq!(b as u64 as u128, b);
266+
Ok(b as u64)
267+
}
268+
212269
pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
213270
let b = self.to_bits(cx.data_layout().pointer_size)?;
214271
assert_eq!(b as u64 as u128, b);
@@ -231,12 +288,30 @@ impl<'tcx> Scalar {
231288
Ok(b as i32)
232289
}
233290

291+
pub fn to_i64(self) -> EvalResult<'static, i64> {
292+
let sz = Size::from_bits(64);
293+
let b = self.to_bits(sz)?;
294+
let b = sign_extend(b, sz) as i128;
295+
assert_eq!(b as i64 as i128, b);
296+
Ok(b as i64)
297+
}
298+
234299
pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
235300
let b = self.to_bits(cx.data_layout().pointer_size)?;
236301
let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
237302
assert_eq!(b as i64 as i128, b);
238303
Ok(b as i64)
239304
}
305+
306+
#[inline]
307+
pub fn to_f32(self) -> EvalResult<'static, f32> {
308+
Ok(f32::from_bits(self.to_u32()?))
309+
}
310+
311+
#[inline]
312+
pub fn to_f64(self) -> EvalResult<'static, f64> {
313+
Ok(f64::from_bits(self.to_u64()?))
314+
}
240315
}
241316

242317
impl From<Pointer> for Scalar {
@@ -308,6 +383,16 @@ impl<'tcx> ScalarMaybeUndef {
308383
self.not_undef()?.to_char()
309384
}
310385

386+
#[inline(always)]
387+
pub fn to_f32(self) -> EvalResult<'tcx, f32> {
388+
self.not_undef()?.to_f32()
389+
}
390+
391+
#[inline(always)]
392+
pub fn to_f64(self) -> EvalResult<'tcx, f64> {
393+
self.not_undef()?.to_f64()
394+
}
395+
311396
#[inline(always)]
312397
pub fn to_u8(self) -> EvalResult<'tcx, u8> {
313398
self.not_undef()?.to_u8()
@@ -318,6 +403,11 @@ impl<'tcx> ScalarMaybeUndef {
318403
self.not_undef()?.to_u32()
319404
}
320405

406+
#[inline(always)]
407+
pub fn to_u64(self) -> EvalResult<'tcx, u64> {
408+
self.not_undef()?.to_u64()
409+
}
410+
321411
#[inline(always)]
322412
pub fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, u64> {
323413
self.not_undef()?.to_usize(cx)
@@ -333,6 +423,11 @@ impl<'tcx> ScalarMaybeUndef {
333423
self.not_undef()?.to_i32()
334424
}
335425

426+
#[inline(always)]
427+
pub fn to_i64(self) -> EvalResult<'tcx, i64> {
428+
self.not_undef()?.to_i64()
429+
}
430+
336431
#[inline(always)]
337432
pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
338433
self.not_undef()?.to_isize(cx)

src/librustc/ty/structural_impls.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,12 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
487487
use ::mir::interpret::EvalErrorKind::*;
488488
Some(match *self {
489489
MachineError(ref err) => MachineError(err.clone()),
490-
FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
490+
FunctionAbiMismatch(a, b) => FunctionAbiMismatch(a, b),
491+
FunctionArgMismatch(a, b) => FunctionArgMismatch(
491492
tcx.lift(&a)?,
492493
tcx.lift(&b)?,
493494
),
495+
FunctionArgCountMismatch => FunctionArgCountMismatch,
494496
NoMirFor(ref s) => NoMirFor(s.clone()),
495497
UnterminatedCString(ptr) => UnterminatedCString(ptr),
496498
DanglingPointerDeref => DanglingPointerDeref,

src/librustc_mir/const_eval.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -288,21 +288,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
288288
)
289289
}
290290

291-
fn try_ptr_op<'a>(
291+
fn ptr_op<'a>(
292292
_ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
293293
_bin_op: mir::BinOp,
294-
left: Scalar,
294+
_left: Scalar,
295295
_left_layout: TyLayout<'tcx>,
296-
right: Scalar,
296+
_right: Scalar,
297297
_right_layout: TyLayout<'tcx>,
298-
) -> EvalResult<'tcx, Option<(Scalar, bool)>> {
299-
if left.is_bits() && right.is_bits() {
300-
Ok(None)
301-
} else {
302-
Err(
303-
ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
304-
)
305-
}
298+
) -> EvalResult<'tcx, (Scalar, bool)> {
299+
Err(
300+
ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(),
301+
)
306302
}
307303

308304
fn find_foreign_static<'a>(

0 commit comments

Comments
 (0)