From: Petar Jovanovic Date: Thu, 26 Feb 2015 18:19:22 +0000 (+0000) Subject: Add support for generating MIPS legacy NaN X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=056cc8470bec0bb318e9ebf36b790a2d3137020c;p=clang Add support for generating MIPS legacy NaN Currently, the NaN values emitted for MIPS architectures do not cover non-IEEE754-2008 compliant case. This change fixes the issue. Patch by Vladimir Radosavljevic. Differential Revision: http://reviews.llvm.org/D7882 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230653 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 69a5404468..e00e0f5a58 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -638,6 +638,12 @@ public: return std::string(1, *Constraint); } + /// \brief Returns true if NaN encoding is IEEE 754-2008. + /// Only MIPS allows a different encoding. + virtual bool isNan2008() const { + return true; + } + /// \brief Returns a string of target-specific clobbers, in LLVM format. virtual const char *getClobbers() const = 0; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 6569626a35..083572bc3e 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -7590,10 +7590,23 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, else if (S->getString().getAsInteger(0, fill)) return false; - if (SNaN) - Result = llvm::APFloat::getSNaN(Sem, false, &fill); - else - Result = llvm::APFloat::getQNaN(Sem, false, &fill); + if (Context.getTargetInfo().isNan2008()) { + if (SNaN) + Result = llvm::APFloat::getSNaN(Sem, false, &fill); + else + Result = llvm::APFloat::getQNaN(Sem, false, &fill); + } else { + // Prior to IEEE 754-2008, architectures were allowed to choose whether + // the first bit of their significand was set for qNaN or sNaN. MIPS chose + // a different encoding to what became a standard in 2008, and for pre- + // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as + // sNaN. This is now known as "legacy NaN" encoding. + if (SNaN) + Result = llvm::APFloat::getQNaN(Sem, false, &fill); + else + Result = llvm::APFloat::getSNaN(Sem, false, &fill); + } + return true; } diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index a848d4ce2e..03cd853d66 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -5674,6 +5674,10 @@ public: return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; } + bool isNan2008() const override { + return IsNan2008; + } + StringRef getABI() const override { return ABI; } bool setCPU(const std::string &Name) override { bool IsMips32 = getTriple().getArch() == llvm::Triple::mips || diff --git a/test/CodeGen/builtin-nan-legacy.c b/test/CodeGen/builtin-nan-legacy.c new file mode 100644 index 0000000000..cd0f0fd14f --- /dev/null +++ b/test/CodeGen/builtin-nan-legacy.c @@ -0,0 +1,13 @@ +// RUN: %clang -target mipsel-unknown-linux -mnan=legacy -emit-llvm -S %s -o - | FileCheck %s +// CHECK: float 0x7FF4000000000000, float 0x7FF8000000000000 +// CHECK: double 0x7FF4000000000000, double 0x7FF8000000000000 + +float f[] = { + __builtin_nan(""), + __builtin_nans(""), +}; + +double d[] = { + __builtin_nan(""), + __builtin_nans(""), +};