Merge pull request #311 from RalfJung/memory

Memory API refactoring
This commit is contained in:
Oliver Schneider 2017-08-29 09:53:34 +02:00 committed by GitHub
commit b8329da5e8
19 changed files with 466 additions and 547 deletions

40
Cargo.lock generated
View file

@ -21,24 +21,24 @@ dependencies = [
[[package]]
name = "backtrace"
version = "0.3.2"
source = "git+https://github.com/alexcrichton/backtrace-rs#3d96a9242ed2096984d15d177f4762b699bee6d4"
source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4"
dependencies = [
"backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.12"
source = "git+https://github.com/alexcrichton/backtrace-rs#3d96a9242ed2096984d15d177f4762b699bee6d4"
source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -99,7 +99,7 @@ dependencies = [
[[package]]
name = "dtoa"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -113,12 +113,12 @@ dependencies = [
[[package]]
name = "gcc"
version = "0.3.51"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itoa"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -137,7 +137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.28"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -175,7 +175,7 @@ name = "memchr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -207,7 +207,7 @@ name = "rand"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
"magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -230,7 +230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-demangle"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -267,8 +267,8 @@ name = "serde_json"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -353,13 +353,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a"
"checksum itoa 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f74cf6ca1bdbc28496a2b9798ab7fccc2ca5a42cace95bb2b219577216a5fb90"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb7b49972ee23d8aa1026c365a5b440ba08e35075f18c459980c7395c221ec48"
"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6"
"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527"
@ -370,7 +370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"

View file

@ -19,7 +19,11 @@ use rustc::ty::TyCtxt;
use syntax::ast::{self, MetaItemKind, NestedMetaItemKind};
use std::path::PathBuf;
struct MiriCompilerCalls(RustcDefaultCalls);
struct MiriCompilerCalls {
default: RustcDefaultCalls,
/// whether we are building for the host
host_target: bool,
}
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
fn early_callback(
@ -30,7 +34,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
descriptions: &rustc_errors::registry::Registry,
output: ErrorOutputType,
) -> Compilation {
self.0.early_callback(
self.default.early_callback(
matches,
sopts,
cfg,
@ -47,7 +51,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
ofile: &Option<PathBuf>,
descriptions: &rustc_errors::registry::Registry,
) -> Option<(Input, Option<PathBuf>)> {
self.0.no_input(
self.default.no_input(
matches,
sopts,
cfg,
@ -64,17 +68,17 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
) -> Compilation {
self.0.late_callback(matches, sess, input, odir, ofile)
self.default.late_callback(matches, sess, input, odir, ofile)
}
fn build_controller(
&mut self,
sess: &Session,
matches: &getopts::Matches,
) -> CompileController<'a> {
let mut control = self.0.build_controller(sess, matches);
let mut control = self.default.build_controller(sess, matches);
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
control.after_analysis.callback = Box::new(after_analysis);
if std::env::var("MIRI_HOST_TARGET") != Ok("yes".to_owned()) {
if !self.host_target {
// only fully compile targets on the host
control.after_analysis.stop = Compilation::Stop;
}
@ -254,6 +258,16 @@ fn main() {
// for auxilary builds in unit tests
args.push("-Zalways-encode-mir".to_owned());
let mut host_target = false;
args.retain(|arg| if arg == "--miri_host_target" {
host_target = true;
false // remove the flag, rustc doesn't know it
} else {
true
});
rustc_driver::run_compiler(&args, &mut MiriCompilerCalls(RustcDefaultCalls), None, None);
rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
default: RustcDefaultCalls,
host_target,
}, None, None);
}

View file

@ -421,11 +421,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
return err!(OutOfTls);
}
// TODO: Does this need checking for alignment?
self.memory.write_uint(
self.memory.write_primval(
key_ptr.to_ptr()?,
key,
PrimVal::Bytes(key),
key_size.bytes(),
false,
)?;
// Return success (0)

View file

@ -4,7 +4,7 @@ use rustc::ty::layout::Layout;
use rustc::ty::{self, Ty};
use rustc_miri::interpret::{EvalResult, Lvalue, LvalueExtra, PrimVal, PrimValKind, Value, Pointer,
HasMemory, EvalContext, PtrAndAlign, ValTy};
HasMemory, AccessKind, EvalContext, PtrAndAlign, ValTy};
use helpers::EvalContextExt as HelperEvalContextExt;
@ -624,7 +624,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
if count > 0 {
// HashMap relies on write_bytes on a NULL ptr with count == 0 to work
// TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
self.memory.check_align(ptr, ty_align)?;
self.memory.check_align(ptr, ty_align, Some(AccessKind::Write))?;
self.memory.write_repeat(ptr, val_byte, size * count)?;
}
}

159
rustc_tests/Cargo.lock generated
View file

@ -13,25 +13,47 @@ dependencies = [
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace"
version = "0.3.2"
source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4"
dependencies = [
"backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.12"
source = "git+https://github.com/alexcrichton/backtrace-rs#ac8f8d150ad114b735a020c37762426fc7ad18c4"
dependencies = [
"gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cargo_metadata"
version = "0.2.3"
name = "cfg-if"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dtoa"
version = "0.4.1"
name = "dbghelp-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
@ -43,10 +65,19 @@ dependencies = [
]
[[package]]
name = "itoa"
version = "0.3.1"
name = "gcc"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.8"
@ -83,23 +114,12 @@ name = "miri"
version = "0.1.0"
dependencies = [
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_miri 0.1.0",
]
[[package]]
name = "num-traits"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "0.2.2"
@ -117,10 +137,16 @@ name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-demangle"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_miri"
version = "0.1.0"
dependencies = [
"backtrace 0.3.2 (git+https://github.com/alexcrichton/backtrace-rs)",
"byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -128,59 +154,6 @@ dependencies = [
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_derive_internals"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.4"
@ -190,11 +163,6 @@ dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
@ -213,30 +181,37 @@ name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum backtrace 0.3.2 (git+https://github.com/alexcrichton/backtrace-rs)" = "<none>"
"checksum backtrace-sys 0.1.12 (git+https://github.com/alexcrichton/backtrace-rs)" = "<none>"
"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
"checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b"
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb7b49972ee23d8aa1026c365a5b440ba08e35075f18c459980c7395c221ec48"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View file

@ -20,7 +20,11 @@ use rustc::hir::{self, itemlikevisit};
use rustc::ty::TyCtxt;
use syntax::ast;
struct MiriCompilerCalls(RustcDefaultCalls);
struct MiriCompilerCalls {
default: RustcDefaultCalls,
/// whether we are building for the host
host_target: bool,
}
impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
fn early_callback(
@ -31,7 +35,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
descriptions: &rustc_errors::registry::Registry,
output: ErrorOutputType
) -> Compilation {
self.0.early_callback(matches, sopts, cfg, descriptions, output)
self.default.early_callback(matches, sopts, cfg, descriptions, output)
}
fn no_input(
&mut self,
@ -42,7 +46,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
ofile: &Option<PathBuf>,
descriptions: &rustc_errors::registry::Registry
) -> Option<(Input, Option<PathBuf>)> {
self.0.no_input(matches, sopts, cfg, odir, ofile, descriptions)
self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
}
fn late_callback(
&mut self,
@ -52,13 +56,13 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>
) -> Compilation {
self.0.late_callback(matches, sess, input, odir, ofile)
self.default.late_callback(matches, sess, input, odir, ofile)
}
fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
let mut control = self.0.build_controller(sess, matches);
let mut control = self.default.build_controller(sess, matches);
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
control.after_analysis.callback = Box::new(after_analysis);
if std::env::var("MIRI_HOST_TARGET") != Ok("yes".to_owned()) {
if !self.host_target {
// only fully compile targets on the host
control.after_analysis.stop = Compilation::Stop;
}
@ -139,7 +143,15 @@ fn main() {
}
let stderr = std::io::stderr();
write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
let mut args: Vec<String> = std::env::args().collect();
let mut host_target = false;
let mut args: Vec<String> = std::env::args().filter(|arg| {
if arg == "--miri_host_target" {
host_target = true;
false // remove the flag, rustc doesn't know it
} else {
true
}
}).collect();
// file to process
args.push(path.display().to_string());
@ -168,7 +180,10 @@ fn main() {
let buf = BufWriter::default();
let output = buf.clone();
let result = std::panic::catch_unwind(|| {
rustc_driver::run_compiler(&args, &mut MiriCompilerCalls(RustcDefaultCalls), None, Some(Box::new(buf)));
rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
default: RustcDefaultCalls,
host_target,
}, None, Some(Box::new(buf)));
});
match result {

View file

@ -10,6 +10,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
src_ty: Ty<'tcx>,
dest_ty: Ty<'tcx>,
) -> EvalResult<'tcx, PrimVal> {
trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty);
let src_kind = self.ty_to_primval_kind(src_ty)?;
match val {

View file

@ -578,12 +578,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
discr_val: u128,
variant_idx: usize,
discr_size: u64,
discr_signed: bool,
) -> EvalResult<'tcx> {
// FIXME(solson)
let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
let discr_dest = dest_ptr.offset(discr_offset, &self)?;
self.memory.write_uint(discr_dest, discr_val, discr_size)?;
self.memory.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr_size, discr_signed)?;
let dest = Lvalue::Ptr {
ptr: PtrAndAlign {
@ -723,6 +724,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
discr_val,
variant,
discr_size,
false,
)?;
} else {
bug!("tried to assign {:?} to Layout::General", kind);
@ -765,24 +767,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
let operand_ty = self.operand_ty(operand);
assert_eq!(self.type_size(operand_ty)?, Some(0));
}
let (offset, TyAndPacked { ty, packed: _ }) =
self.nonnull_offset_and_ty(
dest_ty,
nndiscr,
discrfield_source,
)?;
// TODO: The packed flag is ignored
// FIXME(solson)
let dest = self.force_allocation(dest)?.to_ptr()?;
let dest = dest.offset(offset.bytes(), &self)?;
let dest_size = self.type_size(ty)?.expect(
"bad StructWrappedNullablePointer discrfield",
);
self.memory.write_maybe_aligned_mut(
!nonnull.packed,
|mem| mem.write_int(dest, 0, dest_size),
self.write_struct_wrapped_null_pointer(
dest_ty,
nndiscr,
discrfield_source,
dest,
)?;
}
} else {
@ -997,16 +986,17 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
let ptr = self.force_allocation(lval)?.to_ptr()?;
let discr_val = self.read_discriminant_value(ptr, ty)?;
if let ty::TyAdt(adt_def, _) = ty.sty {
trace!("Read discriminant {}, valid discriminants {:?}", discr_val, adt_def.discriminants(self.tcx).collect::<Vec<_>>());
if adt_def.discriminants(self.tcx).all(|v| {
discr_val != v.to_u128_unchecked()
})
{
return err!(InvalidDiscriminant);
}
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
} else {
bug!("rustc only generates Rvalue::Discriminant for enums");
}
self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?;
}
}
@ -1017,6 +1007,33 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Ok(())
}
pub(crate) fn write_struct_wrapped_null_pointer(
&mut self,
dest_ty: ty::Ty<'tcx>,
nndiscr: u64,
discrfield_source: &layout::FieldPath,
dest: Lvalue,
) -> EvalResult<'tcx> {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
dest_ty,
nndiscr,
discrfield_source,
)?;
let nonnull = self.force_allocation(dest)?.to_ptr()?.offset(
offset.bytes(),
&self,
)?;
trace!("struct wrapped nullable pointer type: {}", ty);
// only the pointer part of a fat pointer is used for this space optimization
let discr_size = self.type_size(ty)?.expect(
"bad StructWrappedNullablePointer discrfield",
);
self.memory.write_maybe_aligned_mut(!packed, |mem| {
// We're writing 0, signedness does not matter
mem.write_primval(nonnull, PrimVal::Bytes(0), discr_size, false)
})
}
pub(super) fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::TyRawPtr(ref tam) |
@ -1294,6 +1311,96 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
}
pub fn read_discriminant_value(
&self,
adt_ptr: MemoryPointer,
adt_ty: Ty<'tcx>,
) -> EvalResult<'tcx, u128> {
use rustc::ty::layout::Layout::*;
let adt_layout = self.type_layout(adt_ty)?;
//trace!("read_discriminant_value {:#?}", adt_layout);
let discr_val = match *adt_layout {
General { discr, .. } => {
let discr_size = discr.size().bytes();
self.memory.read_primval(adt_ptr, discr_size, false)?.to_bytes()?
}
CEnum {
discr,
signed,
..
} => {
let discr_size = discr.size().bytes();
self.memory.read_primval(adt_ptr, discr_size, signed)?.to_bytes()?
}
RawNullablePointer { nndiscr, value } => {
let discr_size = value.size(&self.tcx.data_layout).bytes();
trace!("rawnullablepointer with size {}", discr_size);
self.read_nonnull_discriminant_value(
adt_ptr,
nndiscr as u128,
discr_size,
)?
}
StructWrappedNullablePointer {
nndiscr,
ref discrfield_source,
..
} => {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
adt_ty,
nndiscr,
discrfield_source,
)?;
let nonnull = adt_ptr.offset(offset.bytes(), &*self)?;
trace!("struct wrapped nullable pointer type: {}", ty);
// only the pointer part of a fat pointer is used for this space optimization
let discr_size = self.type_size(ty)?.expect(
"bad StructWrappedNullablePointer discrfield",
);
self.read_maybe_aligned(!packed, |ectx| {
ectx.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size)
})?
}
// The discriminant_value intrinsic returns 0 for non-sum types.
Array { .. } |
FatPointer { .. } |
Scalar { .. } |
Univariant { .. } |
Vector { .. } |
UntaggedUnion { .. } => 0,
};
Ok(discr_val)
}
fn read_nonnull_discriminant_value(
&self,
ptr: MemoryPointer,
nndiscr: u128,
discr_size: u64,
) -> EvalResult<'tcx, u128> {
trace!(
"read_nonnull_discriminant_value: {:?}, {}, {}",
ptr,
nndiscr,
discr_size
);
// We are only interested in 0 vs. non-0, the sign does not matter for this
let null = match self.memory.read_primval(ptr, discr_size, false)? {
PrimVal::Bytes(0) => true,
PrimVal::Bytes(_) |
PrimVal::Ptr(..) => false,
PrimVal::Undef => return err!(ReadUndefBytes),
};
assert!(nndiscr == 0 || nndiscr == 1);
Ok(if !null { nndiscr } else { 1 - nndiscr })
}
pub fn read_global_as_value(&self, gid: GlobalId) -> Value {
Value::ByRef(*self.globals.get(&gid).expect("global not cached"))
}
@ -1515,7 +1622,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
Value::ByVal(primval) => {
let size = self.type_size(dest_ty)?.expect("dest type must be sized");
self.memory.write_primval(dest, primval, size)
if size == 0 {
assert!(primval.is_undef());
Ok(())
} else {
// TODO: Do we need signedness?
self.memory.write_primval(dest.to_ptr()?, primval, size, false)
}
}
Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty),
}
@ -1553,11 +1666,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
);
let field_0_ptr = ptr.offset(field_0.bytes(), &self)?.into();
let field_1_ptr = ptr.offset(field_1.bytes(), &self)?.into();
// TODO: What about signedess?
self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_primval(field_0_ptr, a, field_0_size)
ectx.memory.write_primval(field_0_ptr, a, field_0_size, false)
})?;
self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_primval(field_1_ptr, b, field_1_size)
ectx.memory.write_primval(field_1_ptr, b, field_1_size, false)
})?;
Ok(())
}
@ -1675,18 +1789,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
ptr: MemoryPointer,
pointee_ty: Ty<'tcx>,
) -> EvalResult<'tcx, Value> {
let p = self.memory.read_ptr(ptr)?;
let ptr_size = self.memory.pointer_size();
let p : Pointer = self.memory.read_ptr_sized_unsigned(ptr)?.into();
if self.type_is_sized(pointee_ty) {
Ok(p.to_value())
} else {
trace!("reading fat pointer extra of type {}", pointee_ty);
let extra = ptr.offset(self.memory.pointer_size(), self)?;
let extra = ptr.offset(ptr_size, self)?;
match self.tcx.struct_tail(pointee_ty).sty {
ty::TyDynamic(..) => Ok(p.to_value_with_vtable(
self.memory.read_ptr(extra)?.to_ptr()?,
self.memory.read_ptr_sized_unsigned(extra)?.to_ptr()?,
)),
ty::TySlice(..) | ty::TyStr => Ok(
p.to_value_with_len(self.memory.read_usize(extra)?),
p.to_value_with_len(self.memory.read_ptr_sized_unsigned(extra)?.to_bytes()? as u64),
),
_ => bug!("unsized primval ptr read from {:?}", pointee_ty),
}
@ -1696,10 +1811,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
fn try_read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
use syntax::ast::FloatTy;
let ptr = ptr.to_ptr()?;
let val = match ty.sty {
ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr.to_ptr()?)?),
ty::TyBool => {
let val = self.memory.read_primval(ptr, 1, false)?;
let val = match val {
PrimVal::Bytes(0) => false,
PrimVal::Bytes(1) => true,
_ => return err!(InvalidBool),
};
PrimVal::from_bool(val)
}
ty::TyChar => {
let c = self.memory.read_uint(ptr.to_ptr()?, 4)? as u32;
let c = self.memory.read_primval(ptr, 4, false)?.to_bytes()? as u32;
match ::std::char::from_u32(c) {
Some(ch) => PrimVal::from_char(ch),
None => return err!(InvalidChar(c as u128)),
@ -1716,15 +1840,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
I128 => 16,
Is => self.memory.pointer_size(),
};
// if we transmute a ptr to an isize, reading it back into a primval shouldn't panic
// Due to read_ptr ignoring the sign, we need to jump around some hoops
match self.memory.read_int(ptr.to_ptr()?, size) {
Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. }) if size == self.memory.pointer_size() =>
// Reading as an int failed because we are seeing ptr bytes *and* we are actually reading at ptr size.
// Let's try again, reading a ptr this time.
self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
other => PrimVal::from_i128(other?),
}
self.memory.read_primval(ptr, size, true)?
}
ty::TyUint(uint_ty) => {
@ -1737,36 +1853,24 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
U128 => 16,
Us => self.memory.pointer_size(),
};
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
// for consistency's sake, we use the same code as above
match self.memory.read_uint(ptr.to_ptr()?, size) {
Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. })
if size == self.memory.pointer_size() => {
self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval()
}
other => PrimVal::from_u128(other?),
}
self.memory.read_primval(ptr, size, false)?
}
ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr.to_ptr()?)?),
ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr.to_ptr()?)?),
ty::TyFloat(FloatTy::F32) => PrimVal::Bytes(self.memory.read_primval(ptr, 4, false)?.to_bytes()?),
ty::TyFloat(FloatTy::F64) => PrimVal::Bytes(self.memory.read_primval(ptr, 8, false)?.to_bytes()?),
ty::TyFnPtr(_) => self.memory.read_ptr(ptr.to_ptr()?)?.into_inner_primval(),
ty::TyFnPtr(_) => self.memory.read_ptr_sized_unsigned(ptr)?,
ty::TyRef(_, ref tam) |
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr.to_ptr()?, tam.ty).map(Some),
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, tam.ty).map(Some),
ty::TyAdt(def, _) => {
if def.is_box() {
return self.read_ptr(ptr.to_ptr()?, ty.boxed_ty()).map(Some);
return self.read_ptr(ptr, ty.boxed_ty()).map(Some);
}
use rustc::ty::layout::Layout::*;
if let CEnum { discr, signed, .. } = *self.type_layout(ty)? {
let size = discr.size().bytes();
if signed {
PrimVal::from_i128(self.memory.read_int(ptr.to_ptr()?, size)?)
} else {
PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?)
}
self.memory.read_primval(ptr, size, signed)?
} else {
return Ok(None);
}

View file

@ -3,7 +3,7 @@ use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque};
use std::{fmt, iter, ptr, mem, io};
use std::cell::Cell;
use rustc::ty;
use rustc::ty::Instance;
use rustc::ty::layout::{self, TargetDataLayout, HasDataLayout};
use syntax::ast::Mutability;
use rustc::middle::region::CodeExtent;
@ -250,10 +250,10 @@ pub struct Memory<'a, 'tcx, M: Machine<'tcx>> {
/// Function "allocations". They exist solely so pointers have something to point to, and
/// we can figure out what they point to.
functions: Vec<ty::Instance<'tcx>>,
functions: Vec<Instance<'tcx>>,
/// Inverse map of `functions` so we don't allocate a new pointer every time we need one
function_alloc_cache: HashMap<ty::Instance<'tcx>, AllocId>,
function_alloc_cache: HashMap<Instance<'tcx>, AllocId>,
/// Target machine data layout to emulate.
pub layout: &'a TargetDataLayout,
@ -297,7 +297,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
})
}
pub fn create_fn_alloc(&mut self, instance: ty::Instance<'tcx>) -> MemoryPointer {
pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer {
if let Some(&alloc_id) = self.function_alloc_cache.get(&instance) {
return MemoryPointer::new(alloc_id, 0);
}
@ -476,27 +476,38 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
}
/// Check that the pointer is aligned AND non-NULL.
pub fn check_align(&self, ptr: Pointer, align: u64) -> EvalResult<'tcx> {
let offset = match ptr.into_inner_primval() {
pub fn check_align(&self, ptr: Pointer, align: u64, access: Option<AccessKind>) -> EvalResult<'tcx> {
// Check non-NULL/Undef, extract offset
let (offset, alloc_align) = match ptr.into_inner_primval() {
PrimVal::Ptr(ptr) => {
let alloc = self.get(ptr.alloc_id)?;
if alloc.align < align {
return err!(AlignmentCheckFailed {
has: alloc.align,
required: align,
});
}
ptr.offset
(ptr.offset, alloc.align)
}
PrimVal::Bytes(bytes) => {
let v = ((bytes as u128) % (1 << self.pointer_size())) as u64;
if v == 0 {
return err!(InvalidNullPointerUsage);
}
v
(v, align) // the base address if the "integer allocation" is 0 and hence always aligned
}
PrimVal::Undef => return err!(ReadUndefBytes),
};
// See if alignment checking is disabled
let enforce_alignment = match access {
Some(AccessKind::Read) => self.reads_are_aligned.get(),
Some(AccessKind::Write) => self.writes_are_aligned.get(),
None => true,
};
if !enforce_alignment {
return Ok(());
}
// Check alignment
if alloc_align < align {
return err!(AlignmentCheckFailed {
has: alloc_align,
required: align,
});
}
if offset % align == 0 {
Ok(())
} else {
@ -804,7 +815,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
}
}
pub fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation<M::MemoryKinds>> {
fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation<M::MemoryKinds>> {
let alloc = self.get_mut_unchecked(id)?;
if alloc.mutable == Mutability::Mutable {
Ok(alloc)
@ -813,7 +824,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
}
}
pub fn get_fn(&self, ptr: MemoryPointer) -> EvalResult<'tcx, ty::Instance<'tcx>> {
pub fn get_fn(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Instance<'tcx>> {
if ptr.offset != 0 {
return err!(InvalidFunctionPointer);
}
@ -933,9 +944,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
align: u64,
) -> EvalResult<'tcx, &[u8]> {
// Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
if self.reads_are_aligned.get() {
self.check_align(ptr.into(), align)?;
}
self.check_align(ptr.into(), align, Some(AccessKind::Read))?;
if size == 0 {
return Ok(&[]);
}
@ -955,9 +964,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
align: u64,
) -> EvalResult<'tcx, &mut [u8]> {
// Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
if self.writes_are_aligned.get() {
self.check_align(ptr.into(), align)?;
}
self.check_align(ptr.into(), align, Some(AccessKind::Write))?;
if size == 0 {
return Ok(&mut []);
}
@ -995,7 +1002,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
/// Reading and writing
impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
/// mark an allocation pointed to by a static as static and initialized
pub fn mark_inner_allocation(
fn mark_inner_allocation_initialized(
&mut self,
alloc: AllocId,
mutability: Mutability,
@ -1056,7 +1063,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
};
// recurse into inner allocations
for &alloc in relocations.values() {
self.mark_inner_allocation(alloc, mutability)?;
self.mark_inner_allocation_initialized(alloc, mutability)?;
}
// put back the relocations
self.alloc_map
@ -1074,14 +1081,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
align: u64,
nonoverlapping: bool,
) -> EvalResult<'tcx> {
// Empty accesses don't need to be valid pointers, but they should still be aligned
self.check_align(src, align, Some(AccessKind::Read))?;
self.check_align(dest, align, Some(AccessKind::Write))?;
if size == 0 {
// Empty accesses don't need to be valid pointers, but they should still be aligned
if self.reads_are_aligned.get() {
self.check_align(src, align)?;
}
if self.writes_are_aligned.get() {
self.check_align(dest, align)?;
}
return Ok(());
}
let src = src.to_ptr()?;
@ -1148,22 +1151,18 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
}
pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
self.check_align(ptr, 1, Some(AccessKind::Read))?;
if size == 0 {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
if self.reads_are_aligned.get() {
self.check_align(ptr, 1)?;
}
return Ok(&[]);
}
self.get_bytes(ptr.to_ptr()?, size, 1)
}
pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
self.check_align(ptr, 1, Some(AccessKind::Write))?;
if src.is_empty() {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
if self.writes_are_aligned.get() {
self.check_align(ptr, 1)?;
}
return Ok(());
}
let bytes = self.get_bytes_mut(ptr.to_ptr()?, src.len() as u64, 1)?;
@ -1172,11 +1171,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
}
pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
self.check_align(ptr, 1, Some(AccessKind::Write))?;
if count == 0 {
// Empty accesses don't need to be valid pointers, but they should still be non-NULL
if self.writes_are_aligned.get() {
self.check_align(ptr, 1)?;
}
return Ok(());
}
let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, 1)?;
@ -1186,40 +1183,48 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
Ok(())
}
pub fn read_ptr(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Pointer> {
let size = self.pointer_size();
pub fn read_primval(&self, ptr: MemoryPointer, size: u64, signed: bool) -> EvalResult<'tcx, PrimVal> {
self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer
let endianess = self.endianess();
let bytes = self.get_bytes_unchecked(ptr, size, size)?;
let bytes = self.get_bytes_unchecked(ptr, size, self.int_align(size))?;
// Undef check happens *after* we established that the alignment is correct.
// We must not return Ok() for unaligned pointers!
if self.check_defined(ptr, size).is_err() {
return Ok(PrimVal::Undef.into());
}
let offset = read_target_uint(endianess, bytes).unwrap();
assert_eq!(offset as u64 as u128, offset);
let offset = offset as u64;
let alloc = self.get(ptr.alloc_id)?;
match alloc.relocations.get(&ptr.offset) {
Some(&alloc_id) => Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, offset)).into()),
None => Ok(PrimVal::Bytes(offset as u128).into()),
// Now we do the actual reading
let bytes = if signed {
read_target_int(endianess, bytes).unwrap() as u128
} else {
read_target_uint(endianess, bytes).unwrap()
};
// See if we got a pointer
if size != self.pointer_size() {
if self.relocations(ptr, size)?.count() != 0 {
return err!(ReadPointerAsBytes);
}
} else {
let alloc = self.get(ptr.alloc_id)?;
match alloc.relocations.get(&ptr.offset) {
Some(&alloc_id) => return Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, bytes as u64))),
None => {},
}
}
// We don't. Just return the bytes.
Ok(PrimVal::Bytes(bytes))
}
pub fn write_ptr(&mut self, dest: MemoryPointer, ptr: MemoryPointer) -> EvalResult<'tcx> {
self.write_usize(dest, ptr.offset as u64)?;
self.get_mut(dest.alloc_id)?.relocations.insert(
dest.offset,
ptr.alloc_id,
);
Ok(())
pub fn read_ptr_sized_unsigned(&self, ptr: MemoryPointer) -> EvalResult<'tcx, PrimVal> {
self.read_primval(ptr, self.pointer_size(), false)
}
pub fn write_primval(&mut self, dest: Pointer, val: PrimVal, size: u64) -> EvalResult<'tcx> {
match val {
PrimVal::Ptr(ptr) => {
pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
let endianess = self.endianess();
let bytes = match val {
PrimVal::Ptr(val) => {
assert_eq!(size, self.pointer_size());
self.write_ptr(dest.to_ptr()?, ptr)
val.offset as u128
}
PrimVal::Bytes(bytes) => {
@ -1233,119 +1238,56 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
16 => !0,
n => bug!("unexpected PrimVal::Bytes size: {}", n),
};
self.write_uint(dest.to_ptr()?, bytes & mask, size)
bytes & mask
}
PrimVal::Undef => self.mark_definedness(dest, size, false),
PrimVal::Undef => {
self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?;
return Ok(());
}
};
{
let align = self.int_align(size);
let dst = self.get_bytes_mut(ptr, size, align)?;
if signed {
write_target_int(endianess, dst, bytes as i128).unwrap();
} else {
write_target_uint(endianess, dst, bytes).unwrap();
}
}
}
pub fn read_bool(&self, ptr: MemoryPointer) -> EvalResult<'tcx, bool> {
let bytes = self.get_bytes(ptr, 1, self.layout.i1_align.abi())?;
match bytes[0] {
0 => Ok(false),
1 => Ok(true),
_ => err!(InvalidBool),
// See if we have to also write a relocation
match val {
PrimVal::Ptr(val) => {
self.get_mut(ptr.alloc_id)?.relocations.insert(
ptr.offset,
val.alloc_id,
);
}
_ => {}
}
Ok(())
}
pub fn write_bool(&mut self, ptr: MemoryPointer, b: bool) -> EvalResult<'tcx> {
let align = self.layout.i1_align.abi();
self.get_bytes_mut(ptr, 1, align).map(
|bytes| bytes[0] = b as u8,
)
pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, val: PrimVal) -> EvalResult<'tcx> {
let ptr_size = self.pointer_size();
self.write_primval(ptr, val, ptr_size, false)
}
fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> {
fn int_align(&self, size: u64) -> u64 {
// We assume pointer-sized integers have the same alignment as pointers.
// We also assume signed and unsigned integers of the same size have the same alignment.
match size {
1 => Ok(self.layout.i8_align.abi()),
2 => Ok(self.layout.i16_align.abi()),
4 => Ok(self.layout.i32_align.abi()),
8 => Ok(self.layout.i64_align.abi()),
16 => Ok(self.layout.i128_align.abi()),
1 => self.layout.i8_align.abi(),
2 => self.layout.i16_align.abi(),
4 => self.layout.i32_align.abi(),
8 => self.layout.i64_align.abi(),
16 => self.layout.i128_align.abi(),
_ => bug!("bad integer size: {}", size),
}
}
pub fn read_int(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx, i128> {
let align = self.int_align(size)?;
self.get_bytes(ptr, size, align).map(|b| {
read_target_int(self.endianess(), b).unwrap()
})
}
pub fn write_int(&mut self, ptr: MemoryPointer, n: i128, size: u64) -> EvalResult<'tcx> {
let align = self.int_align(size)?;
let endianess = self.endianess();
let b = self.get_bytes_mut(ptr, size, align)?;
write_target_int(endianess, b, n).unwrap();
Ok(())
}
pub fn read_uint(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx, u128> {
let align = self.int_align(size)?;
self.get_bytes(ptr, size, align).map(|b| {
read_target_uint(self.endianess(), b).unwrap()
})
}
pub fn write_uint(&mut self, ptr: MemoryPointer, n: u128, size: u64) -> EvalResult<'tcx> {
let align = self.int_align(size)?;
let endianess = self.endianess();
let b = self.get_bytes_mut(ptr, size, align)?;
write_target_uint(endianess, b, n).unwrap();
Ok(())
}
pub fn read_isize(&self, ptr: MemoryPointer) -> EvalResult<'tcx, i64> {
self.read_int(ptr, self.pointer_size()).map(|i| i as i64)
}
pub fn write_isize(&mut self, ptr: MemoryPointer, n: i64) -> EvalResult<'tcx> {
let size = self.pointer_size();
self.write_int(ptr, n as i128, size)
}
pub fn read_usize(&self, ptr: MemoryPointer) -> EvalResult<'tcx, u64> {
self.read_uint(ptr, self.pointer_size()).map(|i| i as u64)
}
pub fn write_usize(&mut self, ptr: MemoryPointer, n: u64) -> EvalResult<'tcx> {
let size = self.pointer_size();
self.write_uint(ptr, n as u128, size)
}
pub fn write_f32(&mut self, ptr: MemoryPointer, f: f32) -> EvalResult<'tcx> {
let endianess = self.endianess();
let align = self.layout.f32_align.abi();
let b = self.get_bytes_mut(ptr, 4, align)?;
write_target_f32(endianess, b, f).unwrap();
Ok(())
}
pub fn write_f64(&mut self, ptr: MemoryPointer, f: f64) -> EvalResult<'tcx> {
let endianess = self.endianess();
let align = self.layout.f64_align.abi();
let b = self.get_bytes_mut(ptr, 8, align)?;
write_target_f64(endianess, b, f).unwrap();
Ok(())
}
pub fn read_f32(&self, ptr: MemoryPointer) -> EvalResult<'tcx, f32> {
self.get_bytes(ptr, 4, self.layout.f32_align.abi()).map(
|b| {
read_target_f32(self.endianess(), b).unwrap()
},
)
}
pub fn read_f64(&self, ptr: MemoryPointer) -> EvalResult<'tcx, f64> {
self.get_bytes(ptr, 8, self.layout.f64_align.abi()).map(
|b| {
read_target_f64(self.endianess(), b).unwrap()
},
)
}
}
/// Relocations
@ -1493,6 +1435,7 @@ fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result<u128
layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
}
}
fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i128, io::Error> {
match endianess {
layout::Endian::Little => source.read_int128::<LittleEndian>(source.len()),
@ -1500,44 +1443,6 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i128,
}
}
////////////////////////////////////////////////////////////////////////////////
// Methods to access floats in the target endianess
////////////////////////////////////////////////////////////////////////////////
fn write_target_f32(
endianess: layout::Endian,
mut target: &mut [u8],
data: f32,
) -> Result<(), io::Error> {
match endianess {
layout::Endian::Little => target.write_f32::<LittleEndian>(data),
layout::Endian::Big => target.write_f32::<BigEndian>(data),
}
}
fn write_target_f64(
endianess: layout::Endian,
mut target: &mut [u8],
data: f64,
) -> Result<(), io::Error> {
match endianess {
layout::Endian::Little => target.write_f64::<LittleEndian>(data),
layout::Endian::Big => target.write_f64::<BigEndian>(data),
}
}
fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result<f32, io::Error> {
match endianess {
layout::Endian::Little => source.read_f32::<LittleEndian>(),
layout::Endian::Big => source.read_f32::<BigEndian>(),
}
}
fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result<f64, io::Error> {
match endianess {
layout::Endian::Little => source.read_f64::<LittleEndian>(),
layout::Endian::Big => source.read_f64::<BigEndian>(),
}
}
////////////////////////////////////////////////////////////////////////////////
// Undefined byte tracking
////////////////////////////////////////////////////////////////////////////////

View file

@ -27,9 +27,9 @@ pub use self::eval_context::{EvalContext, Frame, ResourceLimits, StackPopCleanup
pub use self::lvalue::{Lvalue, LvalueExtra, GlobalId};
pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory, AllocIdKind};
pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory, AccessKind, AllocIdKind};
use self::memory::{PointerArithmetic, Lock, AccessKind};
use self::memory::{PointerArithmetic, Lock};
use self::range_map::RangeMap;

View file

@ -11,8 +11,8 @@ use rustc::ty;
use rustc::ty::layout::Layout;
use rustc::ty::subst::Substs;
use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue,
HasMemory, MemoryKind, Machine};
use super::{EvalResult, EvalContext, StackPopCleanup, PtrAndAlign, GlobalId, Lvalue,
MemoryKind, Machine, PrimVal};
use syntax::codemap::Span;
use syntax::ast::Mutability;
@ -106,10 +106,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Layout::General { discr, .. } => {
let discr_size = discr.size().bytes();
let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
self.memory.write_uint(
self.memory.write_primval(
dest_ptr,
variant_index as u128,
PrimVal::Bytes(variant_index as u128),
discr_size,
false
)?
}
@ -125,23 +126,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
..
} => {
if variant_index as u64 != nndiscr {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
self.write_struct_wrapped_null_pointer(
dest_ty,
nndiscr,
discrfield_source,
dest,
)?;
let nonnull = self.force_allocation(dest)?.to_ptr()?.offset(
offset.bytes(),
&self,
)?;
trace!("struct wrapped nullable pointer type: {}", ty);
// only the pointer part of a fat pointer is used for this space optimization
let discr_size = self.type_size(ty)?.expect(
"bad StructWrappedNullablePointer discrfield",
);
self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_uint(nonnull, 0, discr_size)
})?;
}
}
@ -229,7 +219,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
ptr_size,
MemoryKind::UninitializedStatic,
)?;
self.memory.write_usize(ptr, 0)?;
self.memory.write_ptr_sized_unsigned(ptr, PrimVal::Bytes(0))?;
self.memory.mark_static_initalized(ptr.alloc_id, mutability)?;
self.globals.insert(
cid,

View file

@ -1,12 +1,11 @@
use rustc::mir;
use rustc::ty::{self, TypeVariants, Ty};
use rustc::ty::{self, TypeVariants};
use rustc::ty::layout::Layout;
use syntax::codemap::Span;
use syntax::abi::Abi;
use super::{EvalError, EvalResult, EvalErrorKind, EvalContext, eval_context, TyAndPacked,
PtrAndAlign, Lvalue, MemoryPointer, PrimVal, Value, Machine, HasMemory, ValTy};
use super::eval_context::IntegerExt;
use super::{EvalResult, EvalContext, eval_context,
PtrAndAlign, Lvalue, PrimVal, Value, Machine, ValTy};
use rustc_data_structures::indexed_vec::Idx;
@ -395,10 +394,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
ty::InstanceDef::Virtual(_, idx) => {
let ptr_size = self.memory.pointer_size();
let (ptr, vtable) = args[0].into_ptr_vtable_pair(&self.memory)?;
let fn_ptr = self.memory.read_ptr(
vtable.offset(ptr_size * (idx as u64 + 3), &self)?,
)?;
let instance = self.memory.get_fn(fn_ptr.to_ptr()?)?;
let fn_ptr = self.memory.read_ptr_sized_unsigned(
vtable.offset(ptr_size * (idx as u64 + 3), &self)?
)?.to_ptr()?;
let instance = self.memory.get_fn(fn_ptr)?;
let mut args = args.to_vec();
let ty = self.get_field_ty(args[0].ty, 0)?.ty; // TODO: packed flag is ignored
args[0].ty = ty;
@ -408,98 +407,4 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
}
}
pub fn read_discriminant_value(
&self,
adt_ptr: MemoryPointer,
adt_ty: Ty<'tcx>,
) -> EvalResult<'tcx, u128> {
use rustc::ty::layout::Layout::*;
let adt_layout = self.type_layout(adt_ty)?;
//trace!("read_discriminant_value {:#?}", adt_layout);
let discr_val = match *adt_layout {
General { discr, .. } |
CEnum {
discr,
signed: false,
..
} => {
let discr_size = discr.size().bytes();
self.memory.read_uint(adt_ptr, discr_size)?
}
CEnum {
discr,
signed: true,
..
} => {
let discr_size = discr.size().bytes();
self.memory.read_int(adt_ptr, discr_size)? as u128
}
RawNullablePointer { nndiscr, value } => {
let discr_size = value.size(&self.tcx.data_layout).bytes();
trace!("rawnullablepointer with size {}", discr_size);
self.read_nonnull_discriminant_value(
adt_ptr,
nndiscr as u128,
discr_size,
)?
}
StructWrappedNullablePointer {
nndiscr,
ref discrfield_source,
..
} => {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
adt_ty,
nndiscr,
discrfield_source,
)?;
let nonnull = adt_ptr.offset(offset.bytes(), &*self)?;
trace!("struct wrapped nullable pointer type: {}", ty);
// only the pointer part of a fat pointer is used for this space optimization
let discr_size = self.type_size(ty)?.expect(
"bad StructWrappedNullablePointer discrfield",
);
self.read_maybe_aligned(!packed, |ectx| {
ectx.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size)
})?
}
// The discriminant_value intrinsic returns 0 for non-sum types.
Array { .. } |
FatPointer { .. } |
Scalar { .. } |
Univariant { .. } |
Vector { .. } |
UntaggedUnion { .. } => 0,
};
Ok(discr_val)
}
fn read_nonnull_discriminant_value(
&self,
ptr: MemoryPointer,
nndiscr: u128,
discr_size: u64,
) -> EvalResult<'tcx, u128> {
trace!(
"read_nonnull_discriminant_value: {:?}, {}, {}",
ptr,
nndiscr,
discr_size
);
let not_null = match self.memory.read_uint(ptr, discr_size) {
Ok(0) => false,
Ok(_) |
Err(EvalError { kind: EvalErrorKind::ReadPointerAsBytes, .. }) => true,
Err(e) => return Err(e),
};
assert!(nndiscr == 0 || nndiscr == 1);
Ok(if not_null { nndiscr } else { 1 - nndiscr })
}
}

View file

@ -63,19 +63,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
let drop = eval_context::resolve_drop_in_place(self.tcx, ty);
let drop = self.memory.create_fn_alloc(drop);
self.memory.write_ptr(vtable, drop)?;
self.memory.write_ptr_sized_unsigned(vtable, PrimVal::Ptr(drop))?;
let size_ptr = vtable.offset(ptr_size, &self)?;
self.memory.write_usize(size_ptr, size)?;
self.memory.write_ptr_sized_unsigned(size_ptr, PrimVal::Bytes(size as u128))?;
let align_ptr = vtable.offset(ptr_size * 2, &self)?;
self.memory.write_usize(align_ptr, align)?;
self.memory.write_ptr_sized_unsigned(align_ptr, PrimVal::Bytes(align as u128))?;
for (i, method) in ::rustc::traits::get_vtable_methods(self.tcx, trait_ref).enumerate() {
if let Some((def_id, substs)) = method {
let instance = eval_context::resolve(self.tcx, def_id, substs);
let fn_ptr = self.memory.create_fn_alloc(instance);
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
self.memory.write_ptr(method_ptr, fn_ptr)?;
self.memory.write_ptr_sized_unsigned(method_ptr, PrimVal::Ptr(fn_ptr))?;
}
}
@ -105,10 +105,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
vtable: MemoryPointer,
) -> EvalResult<'tcx, (u64, u64)> {
let pointer_size = self.memory.pointer_size();
let size = self.memory.read_usize(vtable.offset(pointer_size, self)?)?;
let align = self.memory.read_usize(
vtable.offset(pointer_size * 2, self)?,
)?;
let size = self.memory.read_ptr_sized_unsigned(vtable.offset(pointer_size, self)?)?.to_bytes()? as u64;
let align = self.memory.read_ptr_sized_unsigned(
vtable.offset(pointer_size * 2, self)?
)?.to_bytes()? as u64;
Ok((size, align))
}

View file

@ -275,7 +275,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
// Check alignment and non-NULLness
let (_, align) = self.size_and_align_of_dst(pointee_ty, val)?;
let ptr = val.into_ptr(&self.memory)?;
self.memory.check_align(ptr, align)?;
self.memory.check_align(ptr, align, None)?;
// Recurse
let pointee_lvalue = self.val_to_lvalue(val, pointee_ty)?;

View file

@ -176,13 +176,13 @@ impl<'a, 'tcx: 'a> Value {
mem: &Memory<'a, 'tcx, M>,
) -> EvalResult<'tcx, Pointer> {
use self::Value::*;
match *self {
Ok(match *self {
ByRef(PtrAndAlign { ptr, aligned }) => {
mem.read_maybe_aligned(aligned, |mem| mem.read_ptr(ptr.to_ptr()?))
mem.read_maybe_aligned(aligned, |mem| mem.read_ptr_sized_unsigned(ptr.to_ptr()?))?
}
ByVal(ptr) |
ByValPair(ptr, _) => Ok(ptr.into()),
}
ByValPair(ptr, _) => ptr,
}.into())
}
pub(super) fn into_ptr_vtable_pair<M: Machine<'tcx>>(
@ -196,11 +196,11 @@ impl<'a, 'tcx: 'a> Value {
aligned,
}) => {
mem.read_maybe_aligned(aligned, |mem| {
let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
let vtable = mem.read_ptr(
let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
let vtable = mem.read_ptr_sized_unsigned(
ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?,
)?;
Ok((ptr, vtable.to_ptr()?))
)?.to_ptr()?;
Ok((ptr, vtable))
})
}
@ -222,10 +222,10 @@ impl<'a, 'tcx: 'a> Value {
aligned,
}) => {
mem.read_maybe_aligned(aligned, |mem| {
let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
let len = mem.read_usize(
let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
let len = mem.read_ptr_sized_unsigned(
ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?,
)?;
)?.to_bytes()? as u64;
Ok((ptr, len))
})
}

View file

@ -1,4 +1,4 @@
fn main() {
let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: a memory access tried to interpret some bytes as a pointer
let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: invalid use of NULL pointer
panic!("this should never print: {}", x);
}

View file

@ -1,5 +1,5 @@
fn main() {
let p = 42 as *const i32;
let p = 44 as *const i32;
let x = unsafe { *p }; //~ ERROR: a memory access tried to interpret some bytes as a pointer
panic!("this should never print: {}", x);
}

View file

@ -126,15 +126,14 @@ fn miri_pass(path: &str, target: &str, host: &str, fullmir: bool, opt: bool) {
// For now, only validate without optimizations. Inlining breaks validation.
flags.push("-Zmir-emit-validate=1".to_owned());
}
if target == host {
flags.push("--miri_host_target".to_owned());
}
config.target_rustcflags = Some(flags.join(" "));
// don't actually execute the final binary, it might be for other targets and we only care
// about running miri, not the binary.
config.runtool = Some("echo \"\" || ".to_owned());
if target == host {
std::env::set_var("MIRI_HOST_TARGET", "yes");
}
compiletest::run_tests(&config);
std::env::set_var("MIRI_HOST_TARGET", "");
}
fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
@ -182,17 +181,24 @@ fn get_host() -> String {
String::from(host)
}
#[test]
fn run_pass_miri() {
fn run_pass_miri(opt: bool) {
let sysroot = get_sysroot();
let host = get_host();
for &opt in [false, true].iter() {
for_all_targets(&sysroot, |target| {
miri_pass("tests/run-pass", &target, &host, false, opt);
});
miri_pass("tests/run-pass-fullmir", &host, &host, true, opt);
}
for_all_targets(&sysroot, |target| {
miri_pass("tests/run-pass", &target, &host, false, opt);
});
miri_pass("tests/run-pass-fullmir", &host, &host, true, opt);
}
#[test]
fn run_pass_miri_noopt() {
run_pass_miri(false);
}
#[test]
fn run_pass_miri_opt() {
run_pass_miri(true);
}
#[test]

View file

@ -14,6 +14,10 @@
use std::i32;
pub fn main() {
// This tests that do (not) do sign extension properly when loading integers
assert_eq!(u32::max_value() as i64, 4294967295);
assert_eq!(i32::min_value() as i64, -2147483648);
assert_eq!(i8::min_value(), -128);
assert_eq!(i8::max_value(), 127);