From fb3ac376ad61e2b57a2f110a1f71d7318bf4238f Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 13 Jul 2018 16:29:00 +0200
Subject: [PATCH 1/4] run fullMIR tests in appveyor

---
 appveyor.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/appveyor.yml b/appveyor.yml
index 46580f274b..2e2920591f 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -35,6 +35,8 @@ test_script:
     - set RUST_BACKTRACE=1
     - cargo build --release
     - cargo test --release
+    - set MIRI_SYSROOT=C:\Users\appveyor\.xargo\HOST
+    - cargo test --release
 
 notifications:
     - provider: Email

From 9396310317481963aeb0aa44d8f54911e94f8a1d Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 13 Jul 2018 16:30:27 +0200
Subject: [PATCH 2/4] appveyor: put 64bit config first, it seems to usually be
 faster

---
 appveyor.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/appveyor.yml b/appveyor.yml
index 2e2920591f..6aee7e75a9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -2,10 +2,10 @@ environment:
     global:
         PROJECT_NAME: miri
     matrix:
-        - TARGET: i686-pc-windows-msvc
-          MSYS2_BITS: 32
         - TARGET: x86_64-pc-windows-msvc
           MSYS2_BITS: 64
+        - TARGET: i686-pc-windows-msvc
+          MSYS2_BITS: 32
 
 # branches to build
 branches:

From 216b8f74075a6f555c3cc1bf8a2dab16af35ca0a Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 15 Jul 2018 23:47:28 +0200
Subject: [PATCH 3/4] shim some Windows functions

---
 src/fn_call.rs | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/src/fn_call.rs b/src/fn_call.rs
index 8105330b32..de40ef943a 100644
--- a/src/fn_call.rs
+++ b/src/fn_call.rs
@@ -623,11 +623,24 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
             }
 
             // Windows API subs
-            "AddVectoredExceptionHandler" |
-            "SetThreadStackGuarantee" => {
-                let usize = self.tcx.types.usize;
+            "AddVectoredExceptionHandler" => {
                 // any non zero value works for the stdlib. This is just used for stackoverflows anyway
-                self.write_scalar(dest, Scalar::from_u128(1), usize)?;
+                self.write_scalar(dest, Scalar::from_u128(1), dest_ty)?;
+            },
+            "GetModuleHandleW" |
+            "GetProcAddress" |
+            "InitializeCriticalSection" |
+            "EnterCriticalSection" |
+            "TryEnterCriticalSection" |
+            "LeaveCriticalSection" |
+            "DeleteCriticalSection" |
+            "SetLastError" => {
+                // pretend these do not exist/nothing happened, by returning zero
+                self.write_scalar(dest, Scalar::from_u128(0), dest_ty)?;
+            },
+            "GetLastError" => {
+                // this is c::ERROR_CALL_NOT_IMPLEMENTED
+                self.write_scalar(dest, Scalar::from_u128(120), dest_ty)?;
             },
 
             // We can't execute anything else

From e1a3b9606e712dac18bae566498d2fa93ca0c276 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 16 Jul 2018 11:42:46 +0200
Subject: [PATCH 4/4] TLS on Windows

---
 src/fn_call.rs | 30 +++++++++++++++++++++++++++++-
 src/lib.rs     | 20 ++++++++++++++++++--
 src/tls.rs     |  1 +
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/fn_call.rs b/src/fn_call.rs
index de40ef943a..31b3b4b18d 100644
--- a/src/fn_call.rs
+++ b/src/fn_call.rs
@@ -607,7 +607,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
             }
 
             "_tlv_atexit" => {
-                return err!(Unimplemented("can't interpret with full mir for osx target".to_owned()));
+                return err!(Unimplemented("Thread-local store is not fully supported on macOS".to_owned()));
             },
 
             // Stub out all the other pthread calls to just return 0
@@ -643,6 +643,34 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
                 self.write_scalar(dest, Scalar::from_u128(120), dest_ty)?;
             },
 
+            // Windows TLS
+            "TlsAlloc" => {
+                // This just creates a key; Windows does not natively support TLS dtors.
+
+                // Figure out how large a TLS key actually is. This is c::DWORD.
+                let key_size = self.layout_of(dest_ty)?.size;
+
+                // Create key and return it
+                let key = self.memory.create_tls_key(None) as u128;
+                if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
+                    return err!(OutOfTls);
+                }
+                self.write_scalar(dest, Scalar::from_u128(key), dest_ty)?;
+            }
+            "TlsGetValue" => {
+                let key = self.value_to_scalar(args[0])?.to_bytes()?;
+                let ptr = self.memory.load_tls(key)?;
+                self.write_ptr(dest, ptr, dest_ty)?;
+            }
+            "TlsSetValue" => {
+                let key = self.value_to_scalar(args[0])?.to_bytes()?;
+                let new_ptr = self.into_ptr(args[1].value)?;
+                self.memory.store_tls(key, new_ptr)?;
+
+                // Return success (1)
+                self.write_scalar(dest, Scalar::from_u128(1), dest_ty)?;
+            }
+
             // We can't execute anything else
             _ => {
                 return err!(Unimplemented(
diff --git a/src/lib.rs b/src/lib.rs
index 520d696405..5a2d7e77d6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -141,7 +141,12 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
     main_id: DefId,
     start_wrapper: Option<DefId>,
 ) -> EvalResult<'tcx, (EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>, Option<Pointer>)> {
-    let mut ecx = EvalContext::new(tcx.at(syntax::codemap::DUMMY_SP), ty::ParamEnv::reveal_all(), Default::default(), Default::default());
+    let mut ecx = EvalContext::new(
+        tcx.at(syntax::codemap::DUMMY_SP),
+        ty::ParamEnv::reveal_all(),
+        Default::default(),
+        MemoryData::new()
+    );
 
     let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
     let main_mir = ecx.load_mir(main_instance.def)?;
@@ -338,7 +343,7 @@ pub struct TlsEntry<'tcx> {
     dtor: Option<ty::Instance<'tcx>>,
 }
 
-#[derive(Clone, Default, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct MemoryData<'tcx> {
     /// The Key to use for the next thread-local allocation.
     next_thread_local: TlsKey,
@@ -355,6 +360,17 @@ pub struct MemoryData<'tcx> {
     statics: HashMap<GlobalId<'tcx>, AllocId>,
 }
 
+impl<'tcx> MemoryData<'tcx> {
+    fn new() -> Self {
+        MemoryData {
+            next_thread_local: 1, // start with 1 as we must not use 0 on Windows
+            thread_local: BTreeMap::new(),
+            locks: HashMap::new(),
+            statics: HashMap::new(),
+        }
+    }
+}
+
 impl<'tcx> Hash for MemoryData<'tcx> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         let MemoryData {
diff --git a/src/tls.rs b/src/tls.rs
index 45805f3aa8..ffcf862915 100644
--- a/src/tls.rs
+++ b/src/tls.rs
@@ -139,6 +139,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
                 None => self.memory.fetch_tls_dtor(None)?,
             };
         }
+        // FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.
         Ok(())
     }
 }