-
Notifications
You must be signed in to change notification settings - Fork 10.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[X86][clang] Disable long double type for -mno-x87 option
This patch attempts to fix a compiler crash that occurs when long double type is used with -mno-x87 compiler option. The option disables x87 target feature, which in turn disables x87 registers, so CG cannot select them for x86_fp80 LLVM IR type. Long double is lowered as x86_fp80 for some targets, so it leads to a crash. The option seems to contradict the SystemV ABI, which requires long double to be represented as a 80-bit floating point, and it also requires to use x87 registers. To avoid that, `long double` type is disabled when -mno-x87 option is set. In addition to that, `float` and `double` also use x87 registers for return values on 32-bit x86, so they are disabled as well. Differential Revision: https://reviews.llvm.org/D98895
- Loading branch information
Showing
10 changed files
with
389 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple i686-linux-gnu -target-feature -x87 -DRET_ERROR | ||
// RUN: %clang_cc1 -fsyntax-only -verify %s -triple i686-linux-gnu -DNOERROR | ||
|
||
#ifdef NOERROR | ||
// expected-no-diagnostics | ||
#endif | ||
|
||
typedef long double long_double; | ||
|
||
// Declaration is fine, unless it is called or defined. | ||
double decl(long_double x, long_double y); | ||
|
||
template <typename T> | ||
T decl_ld_del(T); | ||
|
||
// No code is generated for deleted functions | ||
long_double decl_ld_del(long_double) = delete; | ||
double decl_ld_del(double) = delete; | ||
float decl_ld_del(float) = delete; | ||
|
||
#ifndef NOERROR | ||
// expected-error@+4{{'def' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
// expected-note@+3{{'def' defined here}} | ||
// expected-note@+2{{'x' defined here}} | ||
#endif | ||
int def(long_double x) { | ||
#ifndef NOERROR | ||
// expected-error@+2{{'x' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
return (int)x; | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+3{{'ld_args' defined here}} | ||
// expected-note@+2{{'ld_args' defined here}} | ||
#endif | ||
int ld_args(long_double x, long_double y); | ||
|
||
int call1(float x, float y) { | ||
#ifndef NOERROR | ||
// expected-error@+2 2{{'ld_args' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
return ld_args(x, y); | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+2{{'ld_ret' defined here}} | ||
#endif | ||
long_double ld_ret(double x, double y); | ||
|
||
int call2(float x, float y) { | ||
#ifndef NOERROR | ||
// expected-error@+2{{'ld_ret' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
return (int)ld_ret(x, y); | ||
} | ||
|
||
int binop(double x, double y) { | ||
#ifndef NOERROR | ||
// expected-error@+2 2{{expression requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
double z = (long_double)x * (long_double)y; | ||
return (int)z; | ||
} | ||
|
||
void assign1(long_double *ret, double x) { | ||
#ifndef NOERROR | ||
// expected-error@+2{{expression requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
*ret = x; | ||
} | ||
|
||
struct st_long_double1 { | ||
#ifndef NOERROR | ||
// expected-note@+2{{'ld' defined here}} | ||
#endif | ||
long_double ld; | ||
}; | ||
|
||
struct st_long_double2 { | ||
#ifndef NOERROR | ||
// expected-note@+2{{'ld' defined here}} | ||
#endif | ||
long_double ld; | ||
}; | ||
|
||
struct st_long_double3 { | ||
#ifndef NOERROR | ||
// expected-note@+2{{'ld' defined here}} | ||
#endif | ||
long_double ld; | ||
}; | ||
|
||
void assign2() { | ||
struct st_long_double1 st; | ||
#ifndef NOERROR | ||
// expected-error@+3{{expression requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
// expected-error@+2{{'ld' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
st.ld = 0.42; | ||
} | ||
|
||
void assign3() { | ||
struct st_long_double2 st; | ||
#ifndef NOERROR | ||
// expected-error@+3{{expression requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
// expected-error@+2{{'ld' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
st.ld = 42; | ||
} | ||
|
||
void assign4(double d) { | ||
struct st_long_double3 st; | ||
#ifndef NOERROR | ||
// expected-error@+3{{expression requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
// expected-error@+2{{'ld' requires 'long_double' (aka 'long double') type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
st.ld = d; | ||
} | ||
|
||
void assign5() { | ||
// unused variable declaration is fine | ||
long_double ld = 0.42; | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+3{{'d_ret1' defined here}} | ||
// expected-error@+2{{'d_ret1' requires 'double' return type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
double d_ret1(float x) { | ||
return 0.0; | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+2{{'d_ret2' defined here}} | ||
#endif | ||
double d_ret2(float x); | ||
|
||
int d_ret3(float x) { | ||
#ifndef NOERROR | ||
// expected-error@+2{{'d_ret2' requires 'double' return type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
return (int)d_ret2(x); | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+3{{'f_ret1' defined here}} | ||
// expected-error@+2{{'f_ret1' requires 'float' return type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
float f_ret1(float x) { | ||
return 0.0f; | ||
} | ||
|
||
#ifndef NOERROR | ||
// expected-note@+2{{'f_ret2' defined here}} | ||
#endif | ||
float f_ret2(float x); | ||
|
||
int f_ret3(float x) { | ||
#ifndef NOERROR | ||
// expected-error@+2{{'f_ret2' requires 'float' return type support, but target 'i686-unknown-linux-gnu' does not support it}} | ||
#endif | ||
return (int)f_ret2(x); | ||
} |
Oops, something went wrong.