From 4aea70ed3292f02aa111ff6894805e2613dd81e8 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Wed, 7 Aug 2019 23:31:26 +0700 Subject: [PATCH] [FPEnv] Extended FPOptions with new attributes This change added two new attributes, rounding mode and exception behavior to the structure FPOptions. These attributes allow more flexible treatment of specific floating point environment than it is provided by #pragma STDC FENV_ACCESS. Differential Revision: https://reviews.llvm.org/D65994 --- clang/include/clang/AST/Stmt.h | 4 +-- clang/include/clang/Basic/LangOptions.h | 48 ++++++++++++++++++++++++++++----- clang/include/clang/Sema/Sema.h | 14 +++++++--- clang/lib/Parse/ParseStmt.cpp | 4 +-- clang/lib/Sema/SemaAttr.cpp | 8 ++++++ clang/lib/Sema/TreeTransform.h | 4 +-- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 253b769..0b29857 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -530,7 +530,7 @@ protected: /// This is only meaningful for operations on floating point /// types and 0 otherwise. - unsigned FPFeatures : 3; + unsigned FPFeatures : 8; SourceLocation OpLoc; }; @@ -601,7 +601,7 @@ protected: unsigned OperatorKind : 6; // Only meaningful for floating point types. - unsigned FPFeatures : 3; + unsigned FPFeatures : 8; }; class CXXRewrittenBinaryOperatorBitfields { diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index ae4a4b2..524ae9a 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -357,17 +357,25 @@ public: class FPOptions { public: FPOptions() : fp_contract(LangOptions::FPC_Off), - fenv_access(LangOptions::FEA_Off) {} + fenv_access(LangOptions::FEA_Off), + rounding(LangOptions::FPR_ToNearest), + exceptions(LangOptions::FPE_Ignore) + {} // Used for serializing. explicit FPOptions(unsigned I) : fp_contract(static_cast(I & 3)), - fenv_access(static_cast((I >> 2) & 1)) + fenv_access(static_cast((I >> 2) & 1)), + rounding(static_cast((I >> 3) & 7)), + exceptions(static_cast((I >> 6) & 3)) {} explicit FPOptions(const LangOptions &LangOpts) : fp_contract(LangOpts.getDefaultFPContractMode()), - fenv_access(LangOptions::FEA_Off) {} + fenv_access(LangOptions::FEA_Off), + rounding(LangOptions::FPR_ToNearest), + exceptions(LangOptions::FPE_Ignore) + {} // FIXME: Use getDefaultFEnvAccessMode() when available. bool allowFPContractWithinStatement() const { @@ -398,14 +406,42 @@ public: void setDisallowFEnvAccess() { fenv_access = LangOptions::FEA_Off; } + LangOptions::FPRoundingModeKind getRoundingMode() const { + return static_cast(rounding); + } + + void setRoundingMode(LangOptions::FPRoundingModeKind RM) { + rounding = RM; + } + + LangOptions::FPExceptionModeKind getExceptionMode() const { + return static_cast(exceptions); + } + + void setExceptionMode(LangOptions::FPExceptionModeKind EM) { + exceptions = EM; + } + + bool isFPConstrained() const { + return getRoundingMode() != LangOptions::FPR_ToNearest || + getExceptionMode() != LangOptions::FPE_Ignore || + allowFEnvAccess(); + } + /// Used to serialize this. - unsigned getInt() const { return fp_contract | (fenv_access << 2); } + unsigned getInt() const { + return fp_contract | (fenv_access << 2) | (rounding << 3) + | (exceptions << 6); + } private: - /// Adjust BinaryOperator::FPFeatures to match the total bit-field size - /// of these two. + /// Adjust BinaryOperatorBitfields::FPFeatures and + /// CXXOperatorCallExprBitfields::FPFeatures to match the total bit-field size + /// of these fields. unsigned fp_contract : 2; unsigned fenv_access : 1; + unsigned rounding : 3; + unsigned exceptions : 2; }; /// Describes the kind of translation unit being processed. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 64a6793..5a33e4a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1306,12 +1306,12 @@ public: /// should not be used elsewhere. void EmitCurrentDiagnostic(unsigned DiagID); - /// Records and restores the FP_CONTRACT state on entry/exit of compound + /// Records and restores the FPFeatures state on entry/exit of compound /// statements. - class FPContractStateRAII { + class FPFeaturesStateRAII { public: - FPContractStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {} - ~FPContractStateRAII() { S.FPFeatures = OldFPFeaturesState; } + FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {} + ~FPFeaturesStateRAII() { S.FPFeatures = OldFPFeaturesState; } private: Sema& S; @@ -9409,6 +9409,12 @@ public: /// \#pragma STDC FENV_ACCESS void ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC); + /// Called to set rounding mode for floating point operations. + void setRoundingMode(LangOptions::FPRoundingModeKind); + + /// Called to set exception behavior for floating point operations. + void setExceptionMode(LangOptions::FPExceptionModeKind); + /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. void AddAlignmentAttributesForRecord(RecordDecl *RD); diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 0339328..492db4d6 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1014,9 +1014,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Tok.getLocation(), "in compound statement ('{}')"); - // Record the state of the FP_CONTRACT pragma, restore on leaving the + // Record the state of the FPFeatures, restore on leaving the // compound statement. - Sema::FPContractStateRAII SaveFPContractState(Actions); + Sema::FPFeaturesStateRAII SaveFPContractState(Actions); InMessageExpressionRAIIObject InMessage(*this, false); BalancedDelimiterTracker T(*this, tok::l_brace); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index cd2a652..9b8dc148 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -940,6 +940,14 @@ void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) { } } +void Sema::setRoundingMode(LangOptions::FPRoundingModeKind FPR) { + FPFeatures.setRoundingMode(FPR); +} + +void Sema::setExceptionMode(LangOptions::FPExceptionModeKind FPE) { + FPFeatures.setExceptionMode(FPE); +} + void Sema::ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC) { switch (FPC) { case LangOptions::FEA_On: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index d610535..6b90a9e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -9938,7 +9938,7 @@ TreeTransform::TransformBinaryOperator(BinaryOperator *E) { RHS.get() == E->getRHS()) return E; - Sema::FPContractStateRAII FPContractState(getSema()); + Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), @@ -10464,7 +10464,7 @@ TreeTransform::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) return SemaRef.MaybeBindToTemporary(E); - Sema::FPContractStateRAII FPContractState(getSema()); + Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); getSema().FPFeatures = E->getFPFeatures(); return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), -- 2.7.4