commit
b8329da5e8
19 changed files with 466 additions and 547 deletions
40
Cargo.lock
generated
40
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
159
rustc_tests/Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue