__ILP32__ 和 __i386__ 是有效配置吗?
Is __ILP32__ and __i386__ a valid configuration?
我们在 OS X 上针对 Clang 下的某些 X32 代码获取了错误报告(错误如下所示)。用户尝试使用 -arch i386
在 Intel x86_64 系统上编译代码。 X32 is 32-bit integers, longs and pointers.
根据 System V Application Binary Interface, AMD64 (With LP64 and ILP32 Programming Models)(第 104 页),有效配置要么是单独的 __ILP32__
,要么是 __ILP32__
和 __x86_64__
(还有朋友,例如 amd64
代替 __x86_64__
).
我也查了SYSTEM V APPLICATION BINARY INTERFACE for Intel386,里面没有提到__ILP32__
和朋友。所以我认为 __ILP32__
不应该出现在纯 32 位系统上。
我认为以上应该足以回答问题,但我在 OS X 系统上使用 Clang。 OS X ABI Function Call Guide 不讨论它,并且通常遵循 System V 指南。但是,引用的 System V 指南来自 2003 年,早于 X32,因此没有处理。
我的问题是,__ILP32__
和__i386__
是有效的组合或配置吗?
为了完整起见,这里是代码和编译器错误。我不是要解决这个问题。
源代码
BOOL_X32
是在环境中定义__ILP32__
时定义的
asm volatile
(
// save ebx in case -fPIC is being used
# if BOOL_X32 || BOOL_X64
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
# else // BOOL_X86
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
# endif
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
: "a" (input), "c" (0)
);
编译器错误
X32 主要是 32 位。但是,当使用汇编语言与堆栈交互时,我们需要push/pop 64 位寄存器和值。
$ make cpu.o
clang++ -DNDEBUG -g2 -O2 -arch i386 -fPIC -pipe -c cpu.cpp
cpu.cpp:104:4: error: register %rbx is only available in 64-bit mode
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
^
<inline asm>:1:8: note: instantiated into assembly here
pushq %rbx; cpuid; mov %ebx, %edi; popq %rbx
^~~~~
cpu.cpp:104:4: error: register %rbx is only available in 64-bit mode
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
^
<inline asm>:1:42: note: instantiated into assembly here
pushq %rbx; cpuid; mov %ebx, %edi; popq %rbx
^~~~
2 errors generated.
最后,这里是在 x86_64 系统上使用 -arch i386
时 Clang 的预处理器宏:
$ clang++ -arch i386 -dM -E - < /dev/null | egrep -i "(86|64|ilp)"
#define _ILP32 1
#define __ILP32__ 1
...
#define __i386 1
#define __i386__ 1
#define i386 1
是的,__i386__
和 __ILP32__
是完全有效的配置。这意味着您在 int
、long
和指针为 32 位宽的编译器上构建 32 位 x86 代码。
虽然像 "ILP32" 这样的数据模型名称通常用于描述 64 位系统,但使用这样的名称,或存在与之相关的宏,对指令集没有任何暗示.虽然 System V ABI 没有声明这个宏应该存在于 32 位系统上,但它也没有声明它不能存在!
总之。如果您需要确定正在使用的指令集,请使用 __i386__
和 __x86_64__
;这就是他们在那里的目的。
我们在 OS X 上针对 Clang 下的某些 X32 代码获取了错误报告(错误如下所示)。用户尝试使用 -arch i386
在 Intel x86_64 系统上编译代码。 X32 is 32-bit integers, longs and pointers.
根据 System V Application Binary Interface, AMD64 (With LP64 and ILP32 Programming Models)(第 104 页),有效配置要么是单独的 __ILP32__
,要么是 __ILP32__
和 __x86_64__
(还有朋友,例如 amd64
代替 __x86_64__
).
我也查了SYSTEM V APPLICATION BINARY INTERFACE for Intel386,里面没有提到__ILP32__
和朋友。所以我认为 __ILP32__
不应该出现在纯 32 位系统上。
我认为以上应该足以回答问题,但我在 OS X 系统上使用 Clang。 OS X ABI Function Call Guide 不讨论它,并且通常遵循 System V 指南。但是,引用的 System V 指南来自 2003 年,早于 X32,因此没有处理。
我的问题是,__ILP32__
和__i386__
是有效的组合或配置吗?
为了完整起见,这里是代码和编译器错误。我不是要解决这个问题。
源代码
BOOL_X32
是在环境中定义__ILP32__
时定义的
asm volatile
(
// save ebx in case -fPIC is being used
# if BOOL_X32 || BOOL_X64
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
# else // BOOL_X86
"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
# endif
: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
: "a" (input), "c" (0)
);
编译器错误
X32 主要是 32 位。但是,当使用汇编语言与堆栈交互时,我们需要push/pop 64 位寄存器和值。
$ make cpu.o
clang++ -DNDEBUG -g2 -O2 -arch i386 -fPIC -pipe -c cpu.cpp
cpu.cpp:104:4: error: register %rbx is only available in 64-bit mode
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
^
<inline asm>:1:8: note: instantiated into assembly here
pushq %rbx; cpuid; mov %ebx, %edi; popq %rbx
^~~~~
cpu.cpp:104:4: error: register %rbx is only available in 64-bit mode
"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
^
<inline asm>:1:42: note: instantiated into assembly here
pushq %rbx; cpuid; mov %ebx, %edi; popq %rbx
^~~~
2 errors generated.
最后,这里是在 x86_64 系统上使用 -arch i386
时 Clang 的预处理器宏:
$ clang++ -arch i386 -dM -E - < /dev/null | egrep -i "(86|64|ilp)"
#define _ILP32 1
#define __ILP32__ 1
...
#define __i386 1
#define __i386__ 1
#define i386 1
是的,__i386__
和 __ILP32__
是完全有效的配置。这意味着您在 int
、long
和指针为 32 位宽的编译器上构建 32 位 x86 代码。
虽然像 "ILP32" 这样的数据模型名称通常用于描述 64 位系统,但使用这样的名称,或存在与之相关的宏,对指令集没有任何暗示.虽然 System V ABI 没有声明这个宏应该存在于 32 位系统上,但它也没有声明它不能存在!
总之。如果您需要确定正在使用的指令集,请使用 __i386__
和 __x86_64__
;这就是他们在那里的目的。