Index: clang/lib/AST/Interp/Floating.h =================================================================== --- clang/lib/AST/Interp/Floating.h +++ clang/lib/AST/Interp/Floating.h @@ -97,7 +97,9 @@ bool isInf() const { return F.isInfinity(); } bool isFinite() const { return F.isFinite(); } bool isNormal() const { return F.isNormal(); } + bool isDenormal() const { return F.isDenormal(); } llvm::FPClassTest classify() const { return F.classify(); } + APFloat::fltCategory getCategory() const { return F.getCategory(); } ComparisonCategoryResult compare(const Floating &RHS) const { return Compare(F, RHS.F); Index: clang/lib/AST/Interp/InterpBuiltin.cpp =================================================================== --- clang/lib/AST/Interp/InterpBuiltin.cpp +++ clang/lib/AST/Interp/InterpBuiltin.cpp @@ -234,6 +234,37 @@ return true; } +/// Five int32 values followed by one floating value. +static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func) { + const Floating &Val = S.Stk.peek(); + + unsigned Index; + switch (Val.getCategory()) { + case APFloat::fcNaN: + Index = 0; + break; + case APFloat::fcInfinity: + Index = 1; + break; + case APFloat::fcNormal: + Index = Val.isDenormal() ? 3 : 2; + break; + case APFloat::fcZero: + Index = 4; + break; + } + + // The last argument is first on the stack. + unsigned Offset = align(primSize(PT_Float)) + + ((1 + (4 - Index)) * align(primSize(PT_Sint32))); + + const Integral<32, true> &I = S.Stk.peek>(Offset); + S.Stk.push>(I); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) { InterpFrame *Frame = S.Current; APValue Dummy; @@ -316,6 +347,10 @@ if (interp__builtin_isfpclass(S, OpPC, Frame, F)) return Ret(S, OpPC, Dummy); break; + case Builtin::BI__builtin_fpclassify: + if (interp__builtin_fpclassify(S, OpPC, Frame, F)) + return Ret(S, OpPC, Dummy); + break; default: return false; Index: clang/test/AST/Interp/builtin-functions.cpp =================================================================== --- clang/test/AST/Interp/builtin-functions.cpp +++ clang/test/AST/Interp/builtin-functions.cpp @@ -116,3 +116,16 @@ char isfpclass_snan_2 [__builtin_isfpclass(__builtin_nansl(""), 0x0207) ? 1 : -1]; // ~fcFinite char isfpclass_snan_3 [!__builtin_isfpclass(__builtin_nans(""), 0x01F8) ? 1 : -1]; // fcFinite } + +namespace fpclassify { + char classify_nan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nan(""))]; + char classify_snan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nans(""))]; + char classify_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, __builtin_inf())]; + char classify_neg_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, -__builtin_inf())]; + char classify_normal [__builtin_fpclassify(-1, -1, +1, -1, -1, 1.539)]; + char classify_normal2 [__builtin_fpclassify(-1, -1, +1, -1, -1, 1e-307)]; + char classify_denorm [__builtin_fpclassify(-1, -1, -1, +1, -1, 1e-308)]; + char classify_denorm2 [__builtin_fpclassify(-1, -1, -1, +1, -1, -1e-308)]; + char classify_zero [__builtin_fpclassify(-1, -1, -1, -1, +1, 0.0)]; + char classify_neg_zero[__builtin_fpclassify(-1, -1, -1, -1, +1, -0.0)]; +}