[LLVMbugs] [Bug 23897] New: x86_64 fp128 incorrect mangled name, calling convention

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Fri Jun 19 11:57:14 PDT 2015


https://llvm.org/bugs/show_bug.cgi?id=23897

            Bug ID: 23897
           Summary: x86_64 fp128 incorrect mangled name, calling
                    convention
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: chh at google.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

clang -target x86_64-linux-android uses IEEEquad format (fp128) for long
double.
See latest change in http://reviews.llvm.org/D8357.

This is equivalent to gcc's __float128 type, but clang x86_64-linux-android's
long double type is still incompatible with gcc's __float128, or Android's gcc
long double for x86_64. 

(1) Android x86_64 g++ uses mangled name 'g' for long double and __float128
types,
but clang target x86_64-linux-android uses 'e' for long double type.

(2) According to AMD64 ABI http://www.x86-64.org/documentation/abi.pdf
__float128 values should be passed and returned in SSE registers, xmm0 etc.,
but llvm uses %rsi and %rdi now.

llvm's X86CallingConv.td has handled f64 and f80, but not f128 yet.

The following test case runs on native x86_64 host 
with g++ and long double implemented as fp80.
(a) llvm x86_64-linux-android's long double is fp128
    but is not passed/returned as __float128.
(b) llvm x86_64-linux-gnu's long double is fp80 
    and is passed/returned as __float80.

$ cat t.cpp

typedef double D;
typedef long double LD;
extern "C" {
void printf(const char*, ...);
int memcmp(const void *s1, const void *s2, unsigned long);
void print_double_ptr(void*p);
void print_long_double_ptr(void*p);
void print_float80_ptr(void*p);
void print_float128_ptr(void*p);
void print_double_value(double v);
void print_long_double_value(long double v);
// pass my long double and let gcc x64 print it as __float80.
void print_float80_value(long double v);
// pass my long double and let gcc x64 print it as __float128.
void print_float128_value(long double v);
}
D myd = 1.0;
LD myld = 1.0L;
extern D gd;     // gcc x64 double
extern LD gld;   // gcc x64 long double
extern LD gf80;  // gcc x64 __float80
extern LD gf128; // gcc x64 __float128
void mycompare(const char *msg, const void *s1, const void *s2, unsigned long
n) {
  printf("%s: they are %s\n", msg, memcmp(s1, s2, n) ? "different" : "the
same");
}
extern "C" LD get_my_LD_as_LD() { return myld; }
extern "C" LD get_my_LD_as_F80() { return myld; }
extern "C" LD get_my_LD_as_F128() { return myld; }
void mytest() {
  mycompare("my long double vs gcc long double", &myld, &gld, sizeof(myld));
  mycompare("my long double vs gcc __float80", &myld, &gf80, sizeof(myld));
  mycompare("my long double vs gcc __float128", &myld, &gf128, sizeof(myld));
  print_double_ptr(&myd);
  print_long_double_ptr(&myld);
  print_float80_ptr(&myld);
  print_float128_ptr(&myld);
  printf("==== pass my long double to gcc x64 printer:\n");
  print_double_value(myd);
  print_long_double_value(myld);
  print_float80_value(myld);
  print_float128_value(myld);
}


$ cat dump.cpp

typedef double D;
typedef long double LD;
typedef __float80 F80;
typedef __float128 F128;
extern "C" {
void printf(const char*, ...);
void print_double_ptr(void*p)
{ printf(" as double ptr      %f\n", (double)*(double*)p); }
void print_long_double_ptr(void*p)
{ printf(" as long double ptr %f\n", (double)*(long double*)p); }
void print_float80_ptr(void*p)
{ printf(" as __float80 ptr   %f\n", (double)*(__float80*)p); }
void print_float128_ptr(void*p)
{ printf(" as __float128 ptr  %f\n", (double)*(__float128*)p); }
void print_double_value(double v)
{ printf(" as double      %f\n", (double)v); }
void print_long_double_value(long double v)
{ printf(" as long double %f\n", (double)v); }
void print_float80_value(F80 v)
{ printf(" as __float80   %f\n", (double)v); }
void print_float128_value(F128 v)
{ printf(" as __float128  %f\n", (double)v); }
}
D gd = 1.0;
LD gld = 1.0L;
F80 gf80 = 1.0L;
F128 gf128 = 1.0L;
extern "C" LD get_my_LD_as_LD();
extern "C" F80 get_my_LD_as_F80();
extern "C" F128 get_my_LD_as_F128();
void get_print_long_double() {
  printf("==== get and print my long double:\n");
  print_long_double_value(get_my_LD_as_LD());
  print_float80_value(get_my_LD_as_F80());
  print_float128_value(get_my_LD_as_F128());
}
int main() {
  extern void mytest();
  printf("gcc x64 sizeof(double)=%zu\nsizeof(long double)=%zu\n"
         "sizeof(__float80)=%zu\nsizeof(__float128)=%zu\n",
         sizeof(D), sizeof(LD), sizeof(F80), sizeof(F128));
  mytest();
  get_print_long_double();
  return 0;
}


$ clang++ -target x86_64-linux-android -c -o ./t.android.o ./t.cpp
$ g++ -o dump.android.exe dump.cpp t.android.o

$ dump.android.exe
gcc x64 sizeof(double)=8
sizeof(long double)=16
sizeof(__float80)=16
sizeof(__float128)=16
my long double vs gcc long double: they are different
my long double vs gcc __float80: they are different
my long double vs gcc __float128: they are the same
 as double ptr      1.000000
 as long double ptr 0.000000
 as __float80 ptr   0.000000
 as __float128 ptr  1.000000
==== pass my long double to gcc x64 printer:
 as double      1.000000
 as long double -nan
 as __float80   -nan
 as __float128  0.000000
==== get and print my long double:
 as long double 0.000000
 as __float80   0.000000
 as __float128  0.000000


$ clang++ -target x86_64-linux-gnu -c -o ./t.gnu.o ./t.cpp
$ g++ -o dump.gnu.exe dump.cpp t.gnu.o
$ dump.gnu.exe
gcc x64 sizeof(double)=8
sizeof(long double)=16
sizeof(__float80)=16
sizeof(__float128)=16
my long double vs gcc long double: they are the same
my long double vs gcc __float80: they are the same
my long double vs gcc __float128: they are different
 as double ptr      1.000000
 as long double ptr 1.000000
 as __float80 ptr   1.000000
 as __float128 ptr  0.000000
==== pass my long double to gcc x64 printer:
 as double      1.000000
 as long double 1.000000
 as __float80   1.000000
 as __float128  0.000000
==== get and print my long double:
 as long double 1.000000
 as __float80   1.000000
 as __float128  0.000000

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150619/d3317032/attachment.html>


More information about the llvm-bugs mailing list