The question
Does Microsoft actually support X32 (as opposed to X86 and X64)?
TL;DR answer
The answer is "No, it's not supported by Microsoft." The preprocessor macros don't lead to any identification of X32, the command line options and IDE options don't exist, and the strings identifying such a compiler don't exist.
The long answer — Part I
"There are no header strings for X32"
Disregarding the following facts:
- no official documentation of such a feature exists,
- no option in Visual Studio or
cl.exe /?
to enable/disable it exists, and
strings -el clui.dll
shows no sign of such an option,
strings -el "%VCINSTALLDIR%\bin\1033\clui.dll" | find "Microsoft (R)"
shows no sign of a matching header string either:
4Microsoft (R) C/C++ Optimizing Compiler Version %s
-for Microsoft (R) .NET Framework version %s
(Microsoft (R) C/C++ Optimizing Compiler
FMicrosoft (R) C/C++ Optimizing Compiler Version %s for MIPS R-Series
)Microsoft (R) MIPS Assembler Version %s
CMicrosoft (R) C/C++ Optimizing Compiler Version %s for Renesas SH
<Microsoft (R) C/C++ Optimizing Compiler Version %s for ARM
:Microsoft (R) C/C++ Standard Compiler Version %s for x86
<Microsoft (R) C/C++ Optimizing Compiler Version %s for x86
GMicrosoft (R) 32-bit C/C++ Optimizing Compiler Version %s for PowerPC
@Microsoft (R) C/C++ Optimizing Compiler Version %s for Itanium
<Microsoft (R) C/C++ Optimizing Compiler Version %s for x64
>Microsoft (R) C/C++ Optimizing Compiler Version %s for ARM64
Microsoft (R) MIPS Assembler
The same output is seen in the bin\x86_amd64\1033\clui.dll
and bin\x86_arm\1033\clui.dll
files, so it's not like that one file simply didn't include it.
The long answer — Part II
"Windows doesn't do data models"
Let's suppose it did. How would you detect it? In the case of GLIBC, __ILP32__
is defined for x32 and x86 while __LP64__
is defined for amd64, denoting the data model used. Additionally, __x86_64__
will be defined for the AMD64 architecture. If __x86_64__
is defined and __ILP32__
is defined, then you're using the X32 ABI, else you're using the AMD64 ABI. For C, that's all that matters. If you're utilizing assembly code, that's where the differentiation between the X32 ABI and the x86 ABI matters, hence checking __x86_64__
to determine that the architecture targeted is 64-bit and checking __ILP32__
to determine whether the 32-bit or 64-bit ABI is in use. For example:
#ifdef __x86_64__
# ifdef __ILP32__
// Use X32 version of myfunc().
extern long myfunc_x32 (const char *);
long (*myfunc)(const char *) = myfunc_x32;
# else /* !__ILP32__ */
// Use AMD64 version of myfunc().
extern long myfunc_amd64 (const char *);
long (*myfunc)(const char *) = myfunc_amd64;
# endif /* __ILP32__ */
/* !__x86_64__ */
#elif defined __i386__
// Use x86 version of myfunc().
extern long myfunc_x86 (const char *);
long (*myfunc)(const char *) = myfunc_x86;
/* !__i386__ */
#else
// Use generic version of myfunc() since no optimized versions are available.
long myfunc(const char *);
#endif /* __x86_64__ */
However, there is no macro indicating the data model on Windows. You target one of the following architectures:
- 32-bit x86 (
_M_IX86
)
- 64-bit AMD64 (
_M_AMD64
/_M_X64
)
- (32-bit?) ARM (
_M_ARM
)
Theoretically one could use _M_AMD64
and _M_X64
independently to determine whether X32 exists, but if _M_AMD64
is defined, _M_X64
is also defined.
The long answer — Part III
"The bad news"
In the end, after searching to find anything, perhaps even long forgotten material, there is no evidence that Windows has supported or ever will support coding for an X32 ABI like Linux. The preprocessor macros don't help in identifying X32, the command line options and IDE options don't exist, and the strings identifying such a compiler don't exist.
The long answer — A new hope dashed
"These aren't the macros you're looking for"
One could hypothetically use the currently existing macros to check, but it's not like it helps in this case because X32 for Windows doesn't exist. It's not unlike the GLIBC check, though instead of enabling X32 if __ILP32__
is defined, you enable it if _M_X64
is not defined.
#ifdef _M_AMD64
# ifndef _M_X64
# define ABI_STR "X32"
# else
# define ABI_STR "AMD64"
# endif
#elif defined _M_IX86
# define ABI_STR "X86"
#else
# error unsupported CPU/architecture
#endif
Of course, if _M_AMD64
is defined, then _M_X64
is defined too, further reinforcing the evidence that there is no X32 for Windows.