[cfe-users] Integrated assembler, -arch i386 and ILP32

Jeffrey Walton via cfe-users cfe-users at lists.llvm.org
Mon Nov 30 16:55:42 PST 2015


Hi Everyone,

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 Clang, Apple and ILP32.

The code performs the following:

        asm volatile
        (
            // save ebx in case -fPIC is being used
            // TODO: this might need an early clobber on EDI.
# 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)
        );

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 conditions based on " System V
Application Binary Interface, AMD64 (With LP64 and ILP32 Programming
Models)", http://sites.google.com/site/x32abi/documents/abi.pdf.

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:

    $ 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, we must interact with the stack
using 64-bit values.

My first question is, is _ILP32_ and _i386_ supposed to be defined
together? According to the docs I found, its not an expected/legal
configuration. _ILP32_ and _x86_64_ is an expected/legal
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.



More information about the cfe-users mailing list