Merge pull request #440 from adierking/windowstests

tests: port the test harness to Windows
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42607a2..3d52ee8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,8 +55,6 @@
     message(FATAL_ERROR "CMAKE_SWIFT_COMPILER must be defined to enable swift")
   endif()
 
-  find_package(Swift REQUIRED CONFIG)
-
   string(TOLOWER ${CMAKE_SYSTEM_NAME} swift_os)
   get_swift_host_arch(swift_arch)
 
diff --git a/cmake/modules/DispatchUtilities.cmake b/cmake/modules/DispatchUtilities.cmake
index 15d8cd7..fea3622 100644
--- a/cmake/modules/DispatchUtilities.cmake
+++ b/cmake/modules/DispatchUtilities.cmake
@@ -1,15 +1,19 @@
 
 function(dispatch_set_linker target)
+  if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
+    set(CMAKE_HOST_EXECUTABLE_SUFFIX .exe)
+  endif()
+
   if(USE_GOLD_LINKER)
     set_property(TARGET ${target}
                  APPEND_STRING
                  PROPERTY LINK_FLAGS
-                   -fuse-ld=gold)
+                   -fuse-ld=gold${CMAKE_HOST_EXECUTABLE_SUFFIX})
   endif()
   if(USE_LLD_LINKER)
     set_property(TARGET ${target}
                  APPEND_STRING
                  PROPERTY LINK_FLAGS
-                   -fuse-ld=lld)
+                   -fuse-ld=lld${CMAKE_HOST_EXECUTABLE_SUFFIX})
   endif()
 endfunction()
diff --git a/private/private.h b/private/private.h
index 7fba396..19ccccd 100644
--- a/private/private.h
+++ b/private/private.h
@@ -182,7 +182,7 @@
 #define DISPATCH_COCOA_COMPAT 0
 #endif
 
-#if DISPATCH_COCOA_COMPAT
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 
 #define DISPATCH_CF_SPI_VERSION 20160712
 
@@ -190,6 +190,8 @@
 typedef mach_port_t dispatch_runloop_handle_t;
 #elif defined(__linux__) || defined(__FreeBSD__)
 typedef int dispatch_runloop_handle_t;
+#elif defined(_WIN32)
+typedef void *dispatch_runloop_handle_t;
 #else
 #error "runloop support not implemented on this platform"
 #endif
@@ -218,12 +220,14 @@
 _dispatch_runloop_root_queue_create_4CF(const char *_Nullable label,
 		unsigned long flags);
 
-#if TARGET_OS_MAC
+#if TARGET_OS_MAC || defined(_WIN32)
 API_AVAILABLE(macos(10.9), ios(7.0))
 DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW
-mach_port_t
+dispatch_runloop_handle_t
 _dispatch_runloop_root_queue_get_port_4CF(dispatch_queue_t queue);
+#endif
 
+#if TARGET_OS_MAC
 #ifdef __BLOCKS__
 API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
 DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
@@ -259,7 +263,7 @@
 DISPATCH_EXPORT
 void (*_Nullable _dispatch_end_NSAutoReleasePool)(void *);
 
-#endif /* DISPATCH_COCOA_COMPAT */
+#endif /* DISPATCH_COCOA_COMPAT || defined(_WIN32) */
 
 API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
 DISPATCH_EXPORT DISPATCH_NOTHROW
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4790ac6..4da1b3f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -63,7 +63,6 @@
   target_sources(dispatch
                  PRIVATE
                    shims/generic_sys_queue.h
-                   shims/generic_win_stubs.c
                    shims/generic_win_stubs.h
                    shims/getprogname.c)
 endif()
diff --git a/src/queue.c b/src/queue.c
index b1b4458..adb1e1c 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -93,10 +93,14 @@
 #endif
 #endif
 
-#if DISPATCH_COCOA_COMPAT
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 static dispatch_once_t _dispatch_main_q_handle_pred;
+#endif
+#if DISPATCH_COCOA_COMPAT
 static void _dispatch_runloop_queue_poke(dispatch_queue_t dq,
 		dispatch_qos_t qos, dispatch_wakeup_flags_t flags);
+#endif
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 static void _dispatch_runloop_queue_handle_init(void *ctxt);
 static void _dispatch_runloop_queue_handle_dispose(dispatch_queue_t dq);
 #endif
@@ -4476,7 +4480,7 @@
 	return _dispatch_queue_class_wakeup(dq, qos, flags, target);
 }
 
-#if DISPATCH_COCOA_COMPAT
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 DISPATCH_ALWAYS_INLINE
 static inline bool
 _dispatch_runloop_handle_is_valid(dispatch_runloop_handle_t handle)
@@ -4485,6 +4489,8 @@
 	return MACH_PORT_VALID(handle);
 #elif defined(__linux__)
 	return handle >= 0;
+#elif defined(_WIN32)
+	return handle != INVALID_HANDLE_VALUE;
 #else
 #error "runloop support not implemented on this platform"
 #endif
@@ -4499,6 +4505,8 @@
 #elif defined(__linux__)
 	// decode: 0 is a valid fd, so offset by 1 to distinguish from NULL
 	return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt) - 1;
+#elif defined(_WIN32)
+	return ((dispatch_runloop_handle_t)(uintptr_t)dq->do_ctxt);
 #else
 #error "runloop support not implemented on this platform"
 #endif
@@ -4513,6 +4521,8 @@
 #elif defined(__linux__)
 	// encode: 0 is a valid fd, so offset by 1 to distinguish from NULL
 	dq->do_ctxt = (void *)(uintptr_t)(handle + 1);
+#elif defined(_WIN32)
+	dq->do_ctxt = (void *)(uintptr_t)handle;
 #else
 #error "runloop support not implemented on this platform"
 #endif
@@ -4527,7 +4537,7 @@
 	old_state = os_atomic_and_orig2o(dqu._dq, dq_state, ~clear_bits, relaxed);
 	return _dq_state_max_qos(old_state);
 }
-#endif // DISPATCH_COCOA_COMPAT
+#endif
 
 void
 _dispatch_runloop_queue_wakeup(dispatch_queue_t dq, dispatch_qos_t qos,
@@ -5112,7 +5122,7 @@
 	return _dispatch_queue_drain(dq, dic, flags, owned, true);
 }
 
-#if DISPATCH_COCOA_COMPAT
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 DISPATCH_NOINLINE
 static void
 _dispatch_main_queue_update_priority_from_thread(void)
@@ -6178,7 +6188,7 @@
 
 static bool _dispatch_program_is_probably_callback_driven;
 
-#if DISPATCH_COCOA_COMPAT
+#if DISPATCH_COCOA_COMPAT || defined(_WIN32)
 
 dispatch_queue_t
 _dispatch_runloop_root_queue_create_4CF(const char *label, unsigned long flags)
@@ -6242,7 +6252,7 @@
 	_dispatch_runloop_queue_wakeup(dq, 0, false);
 }
 
-#if TARGET_OS_MAC
+#if TARGET_OS_MAC || defined(_WIN32)
 dispatch_runloop_handle_t
 _dispatch_runloop_root_queue_get_port_4CF(dispatch_queue_t dq)
 {
@@ -6305,6 +6315,8 @@
 		}
 	}
 	handle = fd;
+#elif defined(_WIN32)
+	handle = INVALID_HANDLE_VALUE;
 #else
 #error "runloop support not implemented on this platform"
 #endif
@@ -6332,6 +6344,8 @@
 #elif defined(__linux__)
 	int rc = close(handle);
 	(void)dispatch_assume_zero(rc);
+#elif defined(_WIN32)
+	CloseHandle(handle);
 #else
 #error "runloop support not implemented on this platform"
 #endif
diff --git a/src/shims/generic_win_stubs.c b/src/shims/generic_win_stubs.c
deleted file mode 100644
index 67b6f51..0000000
--- a/src/shims/generic_win_stubs.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "internal.h"
-
-/*
- * This file contains stubbed out functions we are using during
- * the initial Windows port.  When the port is complete, this file
- * should be empty (and thus removed).
- */
-
-void
-_dispatch_runloop_queue_dispose(dispatch_queue_t dq DISPATCH_UNUSED,
-		bool *allow_free DISPATCH_UNUSED)
-{
-	WIN_PORT_ERROR();
-}
-
-void
-_dispatch_runloop_queue_xref_dispose(dispatch_queue_t dq DISPATCH_UNUSED)
-{
-	WIN_PORT_ERROR();
-}
-
-/*
- * Stubbed out static data
- */
diff --git a/src/swift/Dispatch.swift b/src/swift/Dispatch.swift
index 0fd138d..2ba8192 100644
--- a/src/swift/Dispatch.swift
+++ b/src/swift/Dispatch.swift
@@ -38,10 +38,10 @@
 
 @_transparent
 @available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
-public func dispatchPrecondition(condition: @autoclosure () -> DispatchPredicate) {
+public func dispatchPrecondition(condition: @autoclosure () -> DispatchPredicate, file: StaticString = #file, line: UInt = #line) {
 	// precondition is able to determine release-vs-debug asserts where the overlay
 	// cannot, so formulating this into a call that we can call with precondition()
-	precondition(_dispatchPreconditionTest(condition()), "dispatchPrecondition failure")
+	precondition(_dispatchPreconditionTest(condition()), "dispatchPrecondition failure", file: file, line: line)
 }
 
 /// qos_class_t
diff --git a/src/swift/DispatchStubs.cc b/src/swift/DispatchStubs.cc
index 594f666..0625cc9 100644
--- a/src/swift/DispatchStubs.cc
+++ b/src/swift/DispatchStubs.cc
@@ -13,7 +13,11 @@
 #include <dispatch/dispatch.h>
 #include <stdio.h>
 
+#if defined(__ELF__) || defined(__MACH__) || defined(__WASM__)
 #define DISPATCH_RUNTIME_STDLIB_INTERFACE __attribute__((__visibility__("default")))
+#else
+#define DISPATCH_RUNTIME_STDLIB_INTERFACE __declspec(dllexport)
+#endif
 
 #if USE_OBJC
 @protocol OS_dispatch_source;
@@ -54,6 +58,7 @@
 #endif /* USE_OBJC */
 
 #if !USE_OBJC
+DISPATCH_RUNTIME_STDLIB_INTERFACE
 extern "C" void * objc_retainAutoreleasedReturnValue(void *obj);
 #endif