Add winapi pseudo calling convention

On Windows when calling Windows API functions the calling conventions differ based on the architecture. The correct calling convention is often gotten wrong and GHC’s suggestion is somewhat misleading. A new pseudo calling convention would solve these issues.

Motivation

On x86 the default calling convention for Windows API calls is stdcall, but on x86_64 it is a variant of __fastcall.

Due to historical reasons people tend to think stdcall is the actual calling convention for both. On x86_64 GHC would then generate the following warning

* the 'stdcall' calling convention is unsupported on this platform,
  treating as ccall
* When checking declaration:
    foreign import stdcall unsafe "static shlobj.h ShellExecuteA" c_ShellExecuteA

Which is confusing as it’s technically incorrect, but also users seem to replace the stdcall with cdecl in the source, which ends up breaking x86.

The solution to this ends up needing to use CPP to correctly choose the right calling convention. This CPP has to be repeated over and over and over again.

Only looking at base we see this workaround is used:

> git grep WINDOWS_CCONV | wc -l
87

and in Win32

> git grep WINDOWS_CCONV | wc -l
525

Proposed Change

The Haskell 2010 FFI specs allow for the flexibility to implement custom calling conventions. In fact we already do this with the CApi calling convention.

It would simplify code, ease confusion and remove the need for CPP if we have a new pseudo calling convention winapi that is to be used specifically for calls to Windows API calls.

Concretely I propose having the following:

foreign import winapi "foo" c_foo :: IO ()

Where the compiler will determine the right calling convention to use for the target platform.

I do not propose to change the warning, as for general code, cdecl is the right suggestion as native compilers will correctly reinterpret this to the x86_64 ABI calling convention.

The maintenance should be fairly low as the ABI is set and won’t change.

I propose this to be added without needing a language extension, as it does not modify the language at all. It just makes use of clauses already in the existing specification.

Drawbacks

Foreign exports become slightly confusing. The calling convention should really only be used for imports and wrappers but the FFI specification does not allow the flexibily of having calling conventions only one way.

Alternatives

The standard pattern used to work around this is usually

#if defined(i386_HOST_ARCH)
# define WINDOWS_CCONV stdcall
#elif defined(x86_64_HOST_ARCH)
# define WINDOWS_CCONV ccall
#else
# error Unknown mingw32 arch
#endif

An alternative implementation would be to extend the list of standard CPP defines for GHC to include WINDOWS_CCONV. This however means you still need to have {-# LANGUAGE CPP #-} in order to use.

Unresolved Questions

What should happen with foreign export code?

I propose to let

foreign export winapi "foo" c_foo :: IO ()

have the same semantics as import for determining the calling convention. It has a valid use-case in if the user wants to create a “Windows API” style DLL.