about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <oli-obk@users.noreply.github.com>2017-08-29 09:53:34 +0200
committerGitHub <noreply@github.com>2017-08-29 09:53:34 +0200
commitb8329da5e88683bf497f5584d2dde2b824cb86b6 (patch)
tree23fccdea7ca314b3e83c4873eebe8b2894322d39
parent44a360d8ba3cd77e86fcb510808e2b1c550d4c46 (diff)
parent55eaf5eb5e5854f7f7b47e9a990ef17fbc505f14 (diff)
downloadrust-b8329da5e88683bf497f5584d2dde2b824cb86b6.tar.gz
rust-b8329da5e88683bf497f5584d2dde2b824cb86b6.zip
Merge pull request #311 from RalfJung/memory
Memory API refactoring
-rw-r--r--Cargo.lock40
-rw-r--r--miri/bin/miri.rs28
-rw-r--r--miri/fn_call.rs6
-rw-r--r--miri/intrinsic.rs4
-rw-r--r--rustc_tests/Cargo.lock159
-rw-r--r--rustc_tests/src/main.rs31
-rw-r--r--src/librustc_mir/interpret/cast.rs1
-rw-r--r--src/librustc_mir/interpret/eval_context.rs218
-rw-r--r--src/librustc_mir/interpret/memory.rs309
-rw-r--r--src/librustc_mir/interpret/mod.rs4
-rw-r--r--src/librustc_mir/interpret/step.rs26
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs109
-rw-r--r--src/librustc_mir/interpret/traits.rs16
-rw-r--r--src/librustc_mir/interpret/validation.rs2
-rw-r--r--src/librustc_mir/interpret/value.rs22
-rw-r--r--tests/compile-fail/null_pointer_deref.rs2
-rw-r--r--tests/compile-fail/wild_pointer_deref.rs2
-rw-r--r--tests/compiletest.rs30
-rw-r--r--tests/run-pass-fullmir/integer-ops.rs4
19 files changed, 466 insertions, 547 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9e41c301087..00ae333b467 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/miri/bin/miri.rs b/miri/bin/miri.rs
index 29c47e35570..337a723a40d 100644
--- a/miri/bin/miri.rs
+++ b/miri/bin/miri.rs
@@ -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);
 }
diff --git a/miri/fn_call.rs b/miri/fn_call.rs
index cb7ee73e996..7dc8f54849f 100644
--- a/miri/fn_call.rs
+++ b/miri/fn_call.rs
@@ -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)
diff --git a/miri/intrinsic.rs b/miri/intrinsic.rs
index 3e04f859871..8c722a46ae3 100644
--- a/miri/intrinsic.rs
+++ b/miri/intrinsic.rs
@@ -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)?;
                 }
             }
diff --git a/rustc_tests/Cargo.lock b/rustc_tests/Cargo.lock
index 2b6e311bf1b..f2ad1c2c3b0 100644
--- a/rustc_tests/Cargo.lock
+++ b/rustc_tests/Cargo.lock
@@ -14,24 +14,46 @@ dependencies = [
 ]
 
 [[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,11 +65,20 @@ 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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -83,7 +114,6 @@ 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)",
@@ -91,16 +121,6 @@ dependencies = [
 ]
 
 [[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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -118,9 +138,15 @@ 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)",
@@ -129,59 +155,6 @@ dependencies = [
 ]
 
 [[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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -191,11 +164,6 @@ dependencies = [
 ]
 
 [[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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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"
diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs
index 4cff381b332..ea699833f6f 100644
--- a/rustc_tests/src/main.rs
+++ b/rustc_tests/src/main.rs
@@ -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 {
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index c6016509d23..2f45347d113 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -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 {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 3e00b8a6fbc..044f37947d3 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -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);
                 }
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 34de9596f24..e1a0a7d3659 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -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,118 +1238,55 @@ 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(());
+            }
+        };
 
-    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),
+        {
+            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 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,
-        )
-    }
 
-    fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> {
-        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()),
-            _ => bug!("bad integer size: {}", size),
+        // 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,
+                );
+            }
+            _ => {}
         }
-    }
-
-    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 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)
     }
 
-    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()
-            },
-        )
+    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 => 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),
+        }
     }
 }
 
@@ -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()),
@@ -1501,44 +1444,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
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index 603451a9442..9dcb1c9b0f5 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -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;
 
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index c43ad18e0d8..ea90e39489d 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -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,
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index af70d9eb846..60893fcec18 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -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 })
-    }
 }
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 07d7de854b9..3f7e10a9eaf 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -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))
     }
 
diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs
index 20b601b538c..6454e12e037 100644
--- a/src/librustc_mir/interpret/validation.rs
+++ b/src/librustc_mir/interpret/validation.rs
@@ -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)?;
diff --git a/src/librustc_mir/interpret/value.rs b/src/librustc_mir/interpret/value.rs
index 8abb0b86bf8..e052ec1e391 100644
--- a/src/librustc_mir/interpret/value.rs
+++ b/src/librustc_mir/interpret/value.rs
@@ -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))
                 })
             }
diff --git a/tests/compile-fail/null_pointer_deref.rs b/tests/compile-fail/null_pointer_deref.rs
index 20b93aab160..5a26856eba0 100644
--- a/tests/compile-fail/null_pointer_deref.rs
+++ b/tests/compile-fail/null_pointer_deref.rs
@@ -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);
 }
diff --git a/tests/compile-fail/wild_pointer_deref.rs b/tests/compile-fail/wild_pointer_deref.rs
index 373e308e1c0..57da8dfc01b 100644
--- a/tests/compile-fail/wild_pointer_deref.rs
+++ b/tests/compile-fail/wild_pointer_deref.rs
@@ -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);
 }
diff --git a/tests/compiletest.rs b/tests/compiletest.rs
index 89aa195602e..e7c82367b29 100644
--- a/tests/compiletest.rs
+++ b/tests/compiletest.rs
@@ -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]
diff --git a/tests/run-pass-fullmir/integer-ops.rs b/tests/run-pass-fullmir/integer-ops.rs
index e761cdd6237..0964b1b32b5 100644
--- a/tests/run-pass-fullmir/integer-ops.rs
+++ b/tests/run-pass-fullmir/integer-ops.rs
@@ -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);