[cfe-dev] ILP32, -arch i386 and x86_64 Apple systems

Jeffrey Walton via cfe-dev cfe-dev at lists.llvm.org
Tue Dec 1 10:16:08 PST 2015


Hi Everyone,

(Re-asking on CFE-Dev). We took a bug report on some line assembly
code (https://github.com/weidai11/cryptopp/issues/72). I have two
questions at the end on ILP32, Clang and Apple.

The code that took the bug performs the following:

        asm volatile
        (
            // save ebx in case -fPIC is being used
# if BOOL_X32 || BOOL_X64
            "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
# else
            "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)
        );

The BOOL_* defines are mutually exclusive. BOOL_X32 is set when
__ILP32__ is defined. BOOL_X86 is defined when __i386__ (and friends)
is defined. BOOL_X64 is defined when __x86_64__ (and friends) is
defined. We set the defines based on " System V Application Binary
Interface, AMD64 (With LP64 and ILP32 Programming Models)" [1].

The compiler error is:

    $ make cpu.o
    clang++ -DNDEBUG -g2 -O2 -arch i386 -fPIC -march=native -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.

It appears Clang sets ILP32 related defines when using -arch i386 on x86_64:

    $ 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

As far as I know, when using ILP32 on x86_64, we must interact with
the stack using 64-bit values and registers.

My first question is, is _ILP32_ and _i386_ supposed to be defined
together? According to the docs I found, its not an expected/valid
configuration. _ILP32_ and _x86_64_ is an expected/valid
configuration.

My second question is, how should I work around this? Should I special
case Clang on Apple and attempt to push a 32-bit value? Or should I do
something else?

Thanks in advance.

*****

A related bug report was opened at "LLVM Bug 25688 - Clang defines
__ILP32__ when using -arch i386 on an x86_64 Intel",
https://llvm.org/bugs/show_bug.cgi?id=25688.

*****

Here are the docs I found, but its not clear to me what document is
controlling in this case.

The "OS X ABI Function Call Guide" [0] does not discuss it, and often
defers to the System V guides.

The "System V Application Binary Interface, AMD64 (With LP64 and ILP32
Programming Models)" [1] states we should see either (1) __ILP32__
alone; or (2) both __ILP32__ and __x86_64__ (some hand waiving).

The "SYSTEM V APPLICATION BINARY INTERFACE for Intel 386" [2] does not
discuss it, and does not mention __ILP32__.

[0] http://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/Mac_OS_X_ABI_Function_Calls.pdf
[1] http://sites.google.com/site/x32abi/documents/abi.pdf
[2] http://www.sco.com/developers/devspecs/abi386-4.pdf


More information about the cfe-dev mailing list