Should my intel C++ compiler (intel64) be setting _M_X64 ?

Should my intel C++ compiler (intel64) be setting _M_X64 ?

Hello,

I had some trouble compiling some opens-ource code with the intel C++ compiler (version 13.0.1 20121010, intel64 architecture). The code contained the following directives:

----------

#if defined(UTK__C_Intel) || defined(UTK__C_MSVC)
  #if defined(_M_IX86)
    #define UTK__Arch_Intel_x86
  #elif defined(_M_X64) || defined(_M_AMD64)
    #define UTK__Arch_AMD64
  #elif defined(_M_PPC)
    #define UTK__Arch_PowerPC
  #elif defined(_M_IA64)
    #define UTK__Arch_Itanium
  #elif defined(_M_MRX000)
    #define UTK__Arch_MIPS
  #else
    #error Architecture not supported.
  #endif
------------

The error "Architecture not supported" as triggered. Shoulkdn't  _M_X64 be defined by the compiler?

Thank you for your help.

14 帖子 / 0 全新
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项

Hello,

the _M_X64 macro is only defined for the Windows* version of our compiler. Have you used it on Linux* or Mac OS*? It's not supported there.

Solution:
Use __x86_64 or _LP64 instead.

Best regards,

Georg Zitzlsberger

>>...Shouldn't _M_X64 be defined by the compiler?

It has to be defined if the code is compiled for Intel CPUs.

When verifying support for different platforms in a case for 64-bit platform on Intel CPU I discovered that a macro _M_AMD64 defined as well and this is how that piece of codes looks like:

#if defined ( _M_IX86 )
#pragma message ( "*** Message: Compiling for Intel Processing Unit ( 32-bit ) ***" )
#endif
#if defined ( _M_IA64 )
#pragma message ( "*** Message: Compiling for Intel Processing Unit ( 64-bit Itanium ) ***" )
#endif
#if defined ( _M_X64 )
#pragma message ( "*** Message: Compiling for Intel Processing Unit ( 64-bit ) ***" )
#endif
#if defined ( _M_AMD64 )
#pragma message ( "*** Message: Compiling for AMD Processing Unit ( 64-bit ) ***" )
#endif
#if defined ( _M_ARM )
#pragma message ( "*** Message: Compiling for ARM Processing Unit ***" )
#endif
#if defined ( _M_SH )
#pragma message ( "*** Message: Compiling for SH Processing Unit ***" )
#endif
#if defined ( _M_MRX000 )
#pragma message ( "*** Message: Compiling for Mips Processing Unit ***" )
#endif
#if defined ( _M_ALPHA )
#pragma message ( "*** Message: Compiling for Alpha Processing Unit ***" )
#endif
#if defined ( _M_PPC )
#pragma message ( "*** Message: Compiling for PowerPc Processing Unit ***" )
#endif
#if defined ( _M_M68K )
#pragma message ( "*** Message: Compiling for Motorola Processing Unit ***" )
#endif

It is not clear for me why _M_AMD64 macro is also defined. I asked about it on some forum long time ago and had no clear answer.

For example, here is a compiler's output:

...
------ Build started: Project: MemTestApp, Configuration: Release x64 ------
Compiling...
Stdafx.cpp
Compiling...
MemTestApp.cpp
*** Message: Compiling for Intel Processing Unit ( 64-bit ) ***
*** Message: Compiling for AMD Processing Unit ( 64-bit ) ***
Linking...
Generating code
Finished generating code
Embedding manifest...
MemTestApp - 0 error(s), 0 warning(s)
...

I also know that a 64-bit version of 'MemTestApp' will work on Intel and AMD CPUs and I verified it a couple of months ago.

Hi Georg,

>>...the _M_X64 macro is only defined for the Windows* version of our compiler...

This is what MSDN says about a pre-defined ANSI macro _M_X64:
...
_M_X64 - Defined for x64 processors
...

My understanding is as follows: if some project is compiled for a 64-bit platform then _M_X64 has to be defined. If Intel C++ compiler defines the macro on a 64-bit WIndows platform and doesn't define the macro on 64-bit Linux or Mac platforms it doesn't look right because all macros with a prefix '_M_' are ANSI pre-defined macros.

I gave you a complete set of '_M_'-like macros.

I didn't have an opportunity to verify just three macros: _M_MRX000, _M_ALPHA and _M_PPC. All the rest are defined when different C++ compilers are used to compile my project for different platforms.

I also corrected a little inconsistency with _M_IA64 macro:

#if defined ( _M_IA64 )
#pragma message ( "*** Message: Compiling for Intel Processing Unit ( 64-bit Itanium ) ***" )
#endif

I did a quick verification on how legacy C++ compilers are dealing with it and I did not find anything except for a note:

...
/* dos.h

Defines structs, unions, macros, and functions for dealing
with MSDOS and the Intel iAPX86 microprocessor family.
...

As you can see in 1992 a generic term 'iAPX86 microprocessor' was used in Turbo C++ v3.0.

>My understanding is as follows: if some project is compiled for a 64-bit platform then _M_X64 has to be defined. If Intel C++ compiler defines >the macro on a 64-bit WIndows platform and doesn't define the macro on 64-bit Linux or Mac platforms it doesn't look right because all macros >with a prefix '_M_' are ANSI pre-defined macros

It makes no difference what ANSI/ISO says. On Windows platform we predefine the same macros as the Microsoft compiler and on Linux we predefine the same macros as the GNU compiler. This is necessary for compatibility.

>>...It makes no difference what ANSI/ISO says...

Is that an official statement from Intel? Does it mean that Intel C++ compiler team and support guys don't want to take ANSI standard into account?

>>...and on Linux we predefine the same macros as the GNU compiler. This is necessary for compatibility...

It means that if the GNU C/C++ compiler has a _M_X64 bug then Intel C++ compiler on Linux platform perfectly reproduces it because of compatibility. It makes no sense at all.

I see this again and again that Intel C++ compiler team simply copies some feature(s) or functionality without doing a proper analysis and without asking a question "What if this is wrong in the GNU compiler?".

[ A statement from Bernhard ]

>>...I had some trouble compiling some opens-ource code with the intel C++ compiler (version 13.0.1 20121010, intel64 architecture)...

Could you specify on what platform you're working? That is, a 64-bit WIndows, Linux or Mac?

Hello Sergey,

maybe I should express this clearer. _M_* macros are Microsoft* specific only - please see this:
http://msdn.microsoft.com/en-us/library/vstudio/b0084kay.aspx

No one in the GNU* world would ever expect those to be oblige. Hence we don't handle them in our Linux* and Mac OS* X compilers, too.
Both worlds are different by design - just think about LP64 vs. LLP64!

Back to the original question: Is there a platform independent way to test for 64 bit compilation?
Answer: There is not. It always requires to take the platform into account. Even if Intel compilers provide the Microsoft* specific macros for Linux*, it won't work with GNU* compilers, thus being another dead-end regarding portability.

Best regards,

Georg Zitzlsberger

Thank you, Georg! I will need to take into account these differences. I just checked a MinGW documentation and I found two notes:

Note 1
...
`__LP64__'
`_LP64'
These macros are defined, with value 1, if (and only if) the
compilation is for a target where `long int' and pointer both use
64-bits and `int' uses 32-bit.
...

Note 2
....
System-specific Predefined Macros
--------------------------------------------------------

The C preprocessor normally predefines several macros that indicate
what type of system and machine is in use. They are obviously
different on each target supported by GCC. This manual, being for all
systems and machines, cannot tell you what their names are, but you can
use `cpp -dM' to see them all. *Note Invocation::. All system-specific
predefined macros expand to the constant 1, so you can test them with
either `#ifdef' or `#if'.

The C standard requires that all system-specific macros be part of
the "reserved namespace". All names which begin with two underscores,
or an underscore and a capital letter, are reserved for the compiler and
library to use as they wish. However, historically system-specific
macros have had names with no special prefix; for instance, it is common
to find `unix' defined on Unix systems. For all such macros, GCC
provides a parallel macro with two underscores added at the beginning
and the end. If `unix' is defined, `__unix__' will be defined too.
There will never be more than two underscores; the parallel of `_mips'
is `__mips__'.

When the `-ansi' option, or any `-std' option that requests strict
conformance, is given to the compiler, all the system-specific
predefined macros outside the reserved namespace are suppressed. The
parallel macros, inside the reserved namespace, remain defined.

We are slowly phasing out all predefined macros which are outside the
reserved namespace. You should never use them in new programs, and we
encourage you to correct older code to use the parallel macros whenever
you find it. We don't recommend you use the system-specific macros that
are in the reserved namespace, either. It is better in the long run to
check specifically for features you need, using a tool such as `autoconf'.
...

As Sergey hints, a typical method for distinguishing 32- vs. 64-bit platform is by C pointer size. I think the method based on e.g. sizeof(int *) or (C99) PTRDIFF_MAX is as close as you could call to a standard C method. If your dependencies on 32- vs. 64-bit are covered by such standard facilities, evidently you should take advantage of them.
The C standard doesn't deal at all with pre-defined macros which distinguish platform environment. As mentioned earlier in the thread, the Intel compilers usually set the same macros as the Microsoft or gnu compiler which is being modeled, This leaves the __INTEL_COMPILER macros as a way to distinguish from those compilers.
There have been some weakly documented macros you could set to turn off Microsoft bug compatibility for certain cases, but I don't see how that is relevant to the original topic of this thread. In the case of known bugs in gnu compilers, it's usually been possible to get bug fixes quickly enough that the best solution was to update compilers to compatible versions.

>>...the _M_X64 macro is only defined for the Windows* version of our compiler...

I tested two very simple workarounds to resolve that problem if some C/C++ compiler doesn't define _M_X64 macro ( or _M_??? like macros ):

[ Solution 1 ]
...
// Define for a 64-bit platform ( in some header or in a makefile )
#define _SIZEOF_INT 4
#define _SIZEOF_SIZE_T 8
...
#if ( _SIZEOF_INT == 4 && _SIZEOF_SIZE_T == 8 )
#pragma message ( "Compiling for a 64-bit platform" )
#define _M_X64
#endif
...

[ Solution 2 ]

Define _M_X64 macro in a makefile project file for a 64-bit Linux platform.

[ Note ]

>>..._M_* macros are Microsoft* specific only...

Even if _M_X64 macro has a letter M it doesn't stand for Microsoft. Even if these macros are Microsoft specific the letter M stands for Machine and it is a more generic term. A letter L ( in _LP64 macro ) stands for Linux and, of course, that is why Microsoft doesn't support / use it.

As I already mentioned it is no longer a problem for me since workarounds are simple and working.

As Sergey points out, if your actual concern is the nature of size_t, there also you should simply rely on standard syntax to make your code portable. On most current platforms, of course, size_t and pointer types will match as 32- or 64-bit data types.

登陆并发表评论。