Skip to content

Commit 9021ce9

Browse files
committed
[Clang] Enable KF and KC mode for [_Complex] __float128
The headers provided with recent GNU toolchains for PPC have code that includes typedefs such as: typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__KC__))) This patch allows clang to compile programs that contain #include <math.h> with -mfloat128 which it currently fails to compile. Fixes: https://bugs.llvm.org/show_bug.cgi?id=46068 Differential revision: https://reviews.llvm.org/D80374
1 parent 81b7901 commit 9021ce9

File tree

6 files changed

+41
-10
lines changed

6 files changed

+41
-10
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
657657
/// getRealTypeForBitwidth -
658658
/// sets floating point QualTy according to specified bitwidth.
659659
/// Returns empty type if there is no appropriate target types.
660-
QualType getRealTypeForBitwidth(unsigned DestWidth) const;
660+
QualType getRealTypeForBitwidth(unsigned DestWidth, bool ExplicitIEEE) const;
661661

662662
bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const;
663663

clang/include/clang/Basic/TargetInfo.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,13 @@ class TargetInfo : public virtual TransferrableTargetInfo,
368368
virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
369369
bool IsSigned) const;
370370

371-
/// Return floating point type with specified width.
372-
RealType getRealTypeByWidth(unsigned BitWidth) const;
371+
/// Return floating point type with specified width. On PPC, there are
372+
/// three possible types for 128-bit floating point: "PPC double-double",
373+
/// IEEE 754R quad precision, and "long double" (which under the covers
374+
/// is represented as one of those two). At this time, there is no support
375+
/// for an explicit "PPC double-double" type (i.e. __ibm128) so we only
376+
/// need to differentiate between "long double" and IEEE quad precision.
377+
RealType getRealTypeByWidth(unsigned BitWidth, bool ExplicitIEEE) const;
373378

374379
/// Return the alignment (in bits) of the specified integer type enum.
375380
///

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10644,8 +10644,10 @@ QualType ASTContext::getIntTypeForBitwidth(unsigned DestWidth,
1064410644
/// getRealTypeForBitwidth -
1064510645
/// sets floating point QualTy according to specified bitwidth.
1064610646
/// Returns empty type if there is no appropriate target types.
10647-
QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const {
10648-
TargetInfo::RealType Ty = getTargetInfo().getRealTypeByWidth(DestWidth);
10647+
QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth,
10648+
bool ExplicitIEEE) const {
10649+
TargetInfo::RealType Ty =
10650+
getTargetInfo().getRealTypeByWidth(DestWidth, ExplicitIEEE);
1064910651
switch (Ty) {
1065010652
case TargetInfo::Float:
1065110653
return FloatTy;

clang/lib/Basic/TargetInfo.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
265265
return NoInt;
266266
}
267267

268-
TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
268+
TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth,
269+
bool ExplicitIEEE) const {
269270
if (getFloatWidth() == BitWidth)
270271
return Float;
271272
if (getDoubleWidth() == BitWidth)
@@ -277,6 +278,10 @@ TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
277278
return LongDouble;
278279
break;
279280
case 128:
281+
// The caller explicitly asked for an IEEE compliant type but we still
282+
// have to check if the target supports it.
283+
if (ExplicitIEEE)
284+
return hasFloat128Type() ? Float128 : NoFloat;
280285
if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() ||
281286
&getLongDoubleFormat() == &llvm::APFloat::IEEEquad())
282287
return LongDouble;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3942,7 +3942,8 @@ bool Sema::checkMSInheritanceAttrOnDefinition(
39423942
/// parseModeAttrArg - Parses attribute mode string and returns parsed type
39433943
/// attribute.
39443944
static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
3945-
bool &IntegerMode, bool &ComplexMode) {
3945+
bool &IntegerMode, bool &ComplexMode,
3946+
bool &ExplicitIEEE) {
39463947
IntegerMode = true;
39473948
ComplexMode = false;
39483949
switch (Str.size()) {
@@ -3963,7 +3964,12 @@ static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
39633964
case 'X':
39643965
DestWidth = 96;
39653966
break;
3967+
case 'K': // KFmode - IEEE quad precision (__float128)
3968+
ExplicitIEEE = true;
3969+
DestWidth = Str[1] == 'I' ? 0 : 128;
3970+
break;
39663971
case 'T':
3972+
ExplicitIEEE = false;
39673973
DestWidth = 128;
39683974
break;
39693975
}
@@ -4024,6 +4030,7 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
40244030
unsigned DestWidth = 0;
40254031
bool IntegerMode = true;
40264032
bool ComplexMode = false;
4033+
bool ExplicitIEEE = false;
40274034
llvm::APInt VectorSize(64, 0);
40284035
if (Str.size() >= 4 && Str[0] == 'V') {
40294036
// Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2).
@@ -4036,7 +4043,7 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
40364043
!Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
40374044
VectorSize.isPowerOf2()) {
40384045
parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
4039-
IntegerMode, ComplexMode);
4046+
IntegerMode, ComplexMode, ExplicitIEEE);
40404047
// Avoid duplicate warning from template instantiation.
40414048
if (!InInstantiation)
40424049
Diag(AttrLoc, diag::warn_vector_mode_deprecated);
@@ -4046,7 +4053,8 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
40464053
}
40474054

40484055
if (!VectorSize)
4049-
parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
4056+
parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode,
4057+
ExplicitIEEE);
40504058

40514059
// FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
40524060
// and friends, at least with glibc.
@@ -4112,7 +4120,7 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
41124120
NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
41134121
OldElemTy->isSignedIntegerType());
41144122
else
4115-
NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
4123+
NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitIEEE);
41164124

41174125
if (NewElemTy.isNull()) {
41184126
Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;

clang/test/Sema/attr-mode.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// RUN: -verify %s
55
// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_64BIT_PPC64 -fsyntax-only \
66
// RUN: -verify %s
7+
// RUN: %clang_cc1 -triple powerpc64-pc-linux-gnu -DTEST_F128_PPC64 -fsyntax-only \
8+
// RUN: -verify -target-feature +float128 %s
79
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnux32 -DTEST_64BIT_X86 -fsyntax-only \
810
// RUN: -verify %s
911
// RUN: %clang_cc1 -triple mips-linux-gnu -DTEST_MIPS_32 -fsyntax-only \
@@ -90,6 +92,15 @@ void f_ft128_arg(long double *x);
9092
void f_ft128_complex_arg(_Complex long double *x);
9193
void test_TFtype(f128ibm *a) { f_ft128_arg (a); }
9294
void test_TCtype(c128ibm *a) { f_ft128_complex_arg (a); }
95+
#elif TEST_F128_PPC64
96+
typedef int invalid_7 __attribute((mode(KF))); // expected-error{{type of machine mode does not match type of base type}}
97+
typedef int invalid_8 __attribute((mode(KI))); // expected-error{{unknown machine mode}}
98+
typedef _Complex float cf128 __attribute__((mode(KC)));
99+
typedef float f128 __attribute__((mode(KF)));
100+
void f_f128_arg(__float128 *x);
101+
void f_f128_complex_arg(_Complex __float128 *x);
102+
void test_KFtype(f128 *a) { f_f128_arg(a); }
103+
void test_KCtype(cf128 *a) { f_f128_complex_arg(a); }
93104
#elif TEST_MIPS_32
94105
typedef unsigned int gcc_unwind_word __attribute__((mode(unwind_word)));
95106
int foo[sizeof(gcc_unwind_word) == 4 ? 1 : -1];

0 commit comments

Comments
 (0)