aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Northover <Tim.Northover@arm.com>2013-01-22 09:46:51 +0000
committerTim Northover <Tim.Northover@arm.com>2013-01-22 09:46:51 +0000
commit9ec55f24b8f848bb37a9971100cf2fca379d5572 (patch)
treefdb28f0db2d5d873ef4c3bbfa1ce7aaddf5b5399
parent6a94c1ea2d9ee397cc9d75045117a39e8f62235d (diff)
Switch to APFloat constructor taking fltSemantics.
This change also makes the serialisation store the required semantics, fixing an issue where PPC128 was always assumed when re-reading a 128-bit value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173139 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Expr.h25
-rw-r--r--include/clang/AST/Stmt.h11
-rw-r--r--include/clang/Serialization/ASTReader.h3
-rw-r--r--lib/AST/Expr.cpp41
-rw-r--r--lib/AST/ExprConstant.cpp3
-rw-r--r--lib/Serialization/ASTReader.cpp6
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp4
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp3
-rw-r--r--test/PCH/floating-literal.c18
9 files changed, 99 insertions, 15 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 5b6e660832..715e6cbf9f 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1214,8 +1214,8 @@ public:
class APFloatStorage : private APNumericStorage {
public:
- llvm::APFloat getValue(bool IsIEEE) const {
- return llvm::APFloat(getIntValue(), IsIEEE);
+ llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
+ return llvm::APFloat(Semantics, getIntValue());
}
void setValue(ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
@@ -1322,12 +1322,31 @@ public:
static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty);
llvm::APFloat getValue() const {
- return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE);
+ return APFloatStorage::getValue(getSemantics());
}
void setValue(ASTContext &C, const llvm::APFloat &Val) {
+ assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics");
APFloatStorage::setValue(C, Val);
}
+ /// Get a raw enumeration value representing the floating-point semantics of
+ /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
+ APFloatSemantics getRawSemantics() const {
+ return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics);
+ }
+
+ /// Set the raw enumeration value representing the floating-point semantics of
+ /// this literal (32-bit IEEE, x87, ...), suitable for serialisation.
+ void setRawSemantics(APFloatSemantics Sem) {
+ FloatingLiteralBits.Semantics = Sem;
+ }
+
+ /// Return the APFloat semantics this literal uses.
+ const llvm::fltSemantics &getSemantics() const;
+
+ /// Set the APFloat semantics this literal uses.
+ void setSemantics(const llvm::fltSemantics &Sem);
+
bool isExact() const { return FloatingLiteralBits.IsExact; }
void setExact(bool E) { FloatingLiteralBits.IsExact = E; }
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index e1073627bc..2a1af77b8c 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -174,11 +174,20 @@ protected:
unsigned Kind : 2;
};
+ enum APFloatSemantics {
+ IEEEhalf,
+ IEEEsingle,
+ IEEEdouble,
+ x87DoubleExtended,
+ IEEEquad,
+ PPCDoubleDouble
+ };
+
class FloatingLiteralBitfields {
friend class FloatingLiteral;
unsigned : NumExprBits;
- unsigned IsIEEE : 1; // Distinguishes between PPC128 and IEEE128.
+ unsigned Semantics : 3; // Provides semantics for APFloat construction
unsigned IsExact : 1;
};
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 994008de44..3fe65de914 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1658,7 +1658,8 @@ public:
llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx);
/// \brief Read a floating-point value
- llvm::APFloat ReadAPFloat(const RecordData &Record, unsigned &Idx);
+ llvm::APFloat ReadAPFloat(const RecordData &Record,
+ const llvm::fltSemantics &Sem, unsigned &Idx);
// \brief Read a string
static std::string ReadString(const RecordData &Record, unsigned &Idx);
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index e3ff29d2d0..6888c46ae4 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -646,16 +646,14 @@ FloatingLiteral::FloatingLiteral(ASTContext &C, const llvm::APFloat &V,
bool isexact, QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
false, false), Loc(L) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
+ setSemantics(V.getSemantics());
FloatingLiteralBits.IsExact = isexact;
setValue(C, V);
}
FloatingLiteral::FloatingLiteral(ASTContext &C, EmptyShell Empty)
: Expr(FloatingLiteralClass, Empty) {
- FloatingLiteralBits.IsIEEE =
- &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad;
+ setRawSemantics(IEEEhalf);
FloatingLiteralBits.IsExact = false;
}
@@ -670,6 +668,41 @@ FloatingLiteral::Create(ASTContext &C, EmptyShell Empty) {
return new (C) FloatingLiteral(C, Empty);
}
+const llvm::fltSemantics &FloatingLiteral::getSemantics() const {
+ switch(FloatingLiteralBits.Semantics) {
+ case IEEEhalf:
+ return llvm::APFloat::IEEEhalf;
+ case IEEEsingle:
+ return llvm::APFloat::IEEEsingle;
+ case IEEEdouble:
+ return llvm::APFloat::IEEEdouble;
+ case x87DoubleExtended:
+ return llvm::APFloat::x87DoubleExtended;
+ case IEEEquad:
+ return llvm::APFloat::IEEEquad;
+ case PPCDoubleDouble:
+ return llvm::APFloat::PPCDoubleDouble;
+ }
+ llvm_unreachable("Unrecognised floating semantics");
+}
+
+void FloatingLiteral::setSemantics(const llvm::fltSemantics &Sem) {
+ if (&Sem == &llvm::APFloat::IEEEhalf)
+ FloatingLiteralBits.Semantics = IEEEhalf;
+ else if (&Sem == &llvm::APFloat::IEEEsingle)
+ FloatingLiteralBits.Semantics = IEEEsingle;
+ else if (&Sem == &llvm::APFloat::IEEEdouble)
+ FloatingLiteralBits.Semantics = IEEEdouble;
+ else if (&Sem == &llvm::APFloat::x87DoubleExtended)
+ FloatingLiteralBits.Semantics = x87DoubleExtended;
+ else if (&Sem == &llvm::APFloat::IEEEquad)
+ FloatingLiteralBits.Semantics = IEEEquad;
+ else if (&Sem == &llvm::APFloat::PPCDoubleDouble)
+ FloatingLiteralBits.Semantics = PPCDoubleDouble;
+ else
+ llvm_unreachable("Unknown floating semantics");
+}
+
/// getValueAsApproximateDouble - This returns the value as an inaccurate
/// double. Note that this may cause loss of precision, but is useful for
/// debugging dumps, etc.
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 64fd40b7a6..71489cb03c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -3629,7 +3629,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
SmallVector<APValue, 4> Elts;
if (EltTy->isRealFloatingType()) {
const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(EltTy);
- bool isIEESem = &Sem != &APFloat::PPCDoubleDouble;
unsigned FloatEltSize = EltSize;
if (&Sem == &APFloat::x87DoubleExtended)
FloatEltSize = 80;
@@ -3639,7 +3638,7 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) {
Elt = SValInt.rotl(i*EltSize+FloatEltSize).trunc(FloatEltSize);
else
Elt = SValInt.rotr(i*EltSize).trunc(FloatEltSize);
- Elts.push_back(APValue(APFloat(Elt, isIEESem)));
+ Elts.push_back(APValue(APFloat(Sem, Elt)));
}
} else if (EltTy->isIntegerType()) {
for (unsigned i = 0; i < NElts; i++) {
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 97766d0f7d..4e6e6db876 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -6669,8 +6669,10 @@ llvm::APSInt ASTReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
}
/// \brief Read a floating-point value
-llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
- return llvm::APFloat(ReadAPInt(Record, Idx));
+llvm::APFloat ASTReader::ReadAPFloat(const RecordData &Record,
+ const llvm::fltSemantics &Sem,
+ unsigned &Idx) {
+ return llvm::APFloat(Sem, ReadAPInt(Record, Idx));
}
// \brief Read a string
diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp
index 6735c3cf00..7f26a1752b 100644
--- a/lib/Serialization/ASTReaderStmt.cpp
+++ b/lib/Serialization/ASTReaderStmt.cpp
@@ -378,8 +378,10 @@ void ASTStmtReader::VisitIntegerLiteral(IntegerLiteral *E) {
void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
- E->setValue(Reader.getContext(), Reader.ReadAPFloat(Record, Idx));
+ E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record[Idx++]));
E->setExact(Record[Idx++]);
+ E->setValue(Reader.getContext(),
+ Reader.ReadAPFloat(Record, E->getSemantics(), Idx));
E->setLocation(ReadSourceLocation(Record, Idx));
}
diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp
index 0c6dc5dba0..6b96c500c3 100644
--- a/lib/Serialization/ASTWriterStmt.cpp
+++ b/lib/Serialization/ASTWriterStmt.cpp
@@ -324,8 +324,9 @@ void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) {
void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
VisitExpr(E);
- Writer.AddAPFloat(E->getValue(), Record);
+ Record.push_back(E->getRawSemantics());
Record.push_back(E->isExact());
+ Writer.AddAPFloat(E->getValue(), Record);
Writer.AddSourceLocation(E->getLocation(), Record);
Code = serialization::EXPR_FLOATING_LITERAL;
}
diff --git a/test/PCH/floating-literal.c b/test/PCH/floating-literal.c
new file mode 100644
index 0000000000..7bf10d4e79
--- /dev/null
+++ b/test/PCH/floating-literal.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple mips64-none-linux-gnu -emit-pch -o %t %s
+// RUN: %clang_cc1 -x ast -ast-print %t | FileCheck %s
+
+// Make sure the semantics of FloatingLiterals are stored correctly in
+// the AST. Previously, the ASTWriter didn't store anything and the
+// reader assumed PPC 128-bit float semantics, which is incorrect for
+// targets with 128-bit IEEE long doubles.
+
+long double foo = 1.0E4000L;
+// CHECK: long double foo = 1.0E+4000L;
+
+// Just as well check the others are still sane while we're here...
+
+double bar = 1.0E300;
+// CHECK: double bar = 1.0E+300;
+
+float wibble = 1.0E40;
+// CHECK: float wibble = 1.0E+40;