2018-08-22 16:52:01 -03:00
|
|
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2017-07-21 17:25:30 +02:00
|
|
|
//! This module contains everything needed to instantiate an interpreter.
|
|
|
|
//! This separation exists to ensure that no fancy miri features like
|
|
|
|
//! interpreting common C functions leak into CTFE.
|
|
|
|
|
2018-08-23 21:22:27 +02:00
|
|
|
use rustc::hir::def_id::DefId;
|
2018-08-26 12:59:59 +02:00
|
|
|
use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
|
2017-12-12 17:14:49 +01:00
|
|
|
use rustc::mir;
|
2018-08-23 21:22:27 +02:00
|
|
|
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
|
|
|
|
|
2018-08-26 12:59:59 +02:00
|
|
|
use super::{EvalContext, PlaceTy, OpTy};
|
2018-08-23 19:04:33 +02:00
|
|
|
|
2017-07-21 17:25:30 +02:00
|
|
|
/// Methods of this trait signifies a point where CTFE evaluation would fail
|
2018-09-20 10:12:21 +02:00
|
|
|
/// and some use case dependent behaviour can instead be applied.
|
|
|
|
/// FIXME: We should be able to get rid of the 'a here if we can get rid of the 'a in
|
|
|
|
/// `snapshot::EvalSnapshot`.
|
|
|
|
pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
2017-07-21 17:25:30 +02:00
|
|
|
/// Additional data that can be accessed via the Memory
|
2018-09-20 10:12:21 +02:00
|
|
|
type MemoryData;
|
2017-07-21 17:25:30 +02:00
|
|
|
|
2017-07-28 16:48:43 +02:00
|
|
|
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
2018-09-20 10:12:21 +02:00
|
|
|
type MemoryKinds: ::std::fmt::Debug + Copy + Eq;
|
2018-08-26 12:59:59 +02:00
|
|
|
|
|
|
|
/// The memory kind to use for mutated statics -- or None if those are not supported.
|
|
|
|
const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
|
2017-07-28 16:48:43 +02:00
|
|
|
|
2018-10-02 20:20:14 +02:00
|
|
|
/// Whether to enforce the validity invariant
|
|
|
|
const ENFORCE_VALIDITY: bool;
|
|
|
|
|
2018-09-20 10:12:21 +02:00
|
|
|
/// Called before a basic block terminator is executed.
|
|
|
|
/// You can use this to detect endlessly running programs.
|
|
|
|
fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>;
|
2018-09-09 10:06:39 +02:00
|
|
|
|
2017-07-28 09:52:19 +02:00
|
|
|
/// Entry point to all function calls.
|
|
|
|
///
|
2018-08-23 19:04:33 +02:00
|
|
|
/// Returns either the mir to use for the call, or `None` if execution should
|
|
|
|
/// just proceed (which usually means this hook did all the work that the
|
|
|
|
/// called function should usually have done). In the latter case, it is
|
|
|
|
/// this hook's responsibility to call `goto_block(ret)` to advance the instruction pointer!
|
|
|
|
/// (This is to support functions like `__rust_maybe_catch_panic` that neither find a MIR
|
|
|
|
/// nor just jump to `ret`, but instead push their own stack frame.)
|
|
|
|
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
|
|
|
|
/// was used.
|
2018-09-20 10:12:21 +02:00
|
|
|
fn find_fn(
|
2018-01-16 09:31:48 +01:00
|
|
|
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
2017-07-21 17:25:30 +02:00
|
|
|
instance: ty::Instance<'tcx>,
|
2018-08-13 16:14:22 +02:00
|
|
|
args: &[OpTy<'tcx>],
|
2018-08-23 19:04:33 +02:00
|
|
|
dest: Option<PlaceTy<'tcx>>,
|
|
|
|
ret: Option<mir::BasicBlock>,
|
|
|
|
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>>;
|
2017-07-25 11:32:48 +02:00
|
|
|
|
2018-08-23 19:04:33 +02:00
|
|
|
/// Directly process an intrinsic without pushing a stack frame.
|
|
|
|
/// If this returns successfully, the engine will take care of jumping to the next block.
|
2018-09-20 10:12:21 +02:00
|
|
|
fn call_intrinsic(
|
2018-01-16 09:31:48 +01:00
|
|
|
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
2017-07-28 13:08:27 +02:00
|
|
|
instance: ty::Instance<'tcx>,
|
2018-08-13 16:14:22 +02:00
|
|
|
args: &[OpTy<'tcx>],
|
|
|
|
dest: PlaceTy<'tcx>,
|
2017-07-28 13:08:27 +02:00
|
|
|
) -> EvalResult<'tcx>;
|
|
|
|
|
2018-08-23 21:22:27 +02:00
|
|
|
/// Called for read access to a foreign static item.
|
2018-08-26 12:59:59 +02:00
|
|
|
/// This can be called multiple times for the same static item and should return consistent
|
|
|
|
/// results. Once the item is *written* the first time, as usual for statics a copy is
|
|
|
|
/// made and this function is not called again.
|
2018-09-20 10:12:21 +02:00
|
|
|
fn find_foreign_static(
|
2018-08-23 21:22:27 +02:00
|
|
|
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
|
|
|
def_id: DefId,
|
|
|
|
) -> EvalResult<'tcx, &'tcx Allocation>;
|
|
|
|
|
2018-08-28 01:14:29 +02:00
|
|
|
/// Called for all binary operations on integer(-like) types when one operand is a pointer
|
|
|
|
/// value, and for the `Offset` operation that is inherently about pointers.
|
2017-07-25 11:32:48 +02:00
|
|
|
///
|
2017-08-01 11:11:57 +02:00
|
|
|
/// Returns a (value, overflowed) pair if the operation succeeded
|
2018-09-20 10:12:21 +02:00
|
|
|
fn ptr_op(
|
2018-01-16 09:31:48 +01:00
|
|
|
ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
|
2017-07-25 11:32:48 +02:00
|
|
|
bin_op: mir::BinOp,
|
2018-05-20 23:43:16 +02:00
|
|
|
left: Scalar,
|
2018-08-13 16:14:22 +02:00
|
|
|
left_layout: TyLayout<'tcx>,
|
2018-05-20 23:43:16 +02:00
|
|
|
right: Scalar,
|
2018-08-13 16:14:22 +02:00
|
|
|
right_layout: TyLayout<'tcx>,
|
2018-08-28 01:14:29 +02:00
|
|
|
) -> EvalResult<'tcx, (Scalar, bool)>;
|
2017-07-28 16:48:43 +02:00
|
|
|
|
|
|
|
/// Heap allocations via the `box` keyword
|
|
|
|
///
|
|
|
|
/// Returns a pointer to the allocated memory
|
2018-09-20 10:12:21 +02:00
|
|
|
fn box_alloc(
|
2018-01-16 09:31:48 +01:00
|
|
|
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
2018-08-13 16:14:22 +02:00
|
|
|
dest: PlaceTy<'tcx>,
|
2017-09-25 15:55:21 +02:00
|
|
|
) -> EvalResult<'tcx>;
|
2017-09-15 13:02:33 +02:00
|
|
|
|
2018-08-23 19:04:33 +02:00
|
|
|
/// Execute a validation operation
|
2018-09-20 10:12:21 +02:00
|
|
|
fn validation_op(
|
2018-01-16 09:31:48 +01:00
|
|
|
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
2017-12-14 11:36:28 +01:00
|
|
|
_op: ::rustc::mir::ValidationOp,
|
|
|
|
_operand: &::rustc::mir::ValidationOperand<'tcx, ::rustc::mir::Place<'tcx>>,
|
|
|
|
) -> EvalResult<'tcx> {
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-07-21 17:25:30 +02:00
|
|
|
}
|