sepavloff updated this revision to Diff 299887.
sepavloff added a comment.
Added ActOnPragmaFPExceptions
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D89849/new/
https://reviews.llvm.org/D89849
Files:
clang/docs/LanguageExtensions.rst
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParsePragma.cpp
clang/lib/Sema/SemaAttr.cpp
clang/test/CodeGen/pragma-fp-exc.cpp
clang/test/Parser/pragma-fp.cpp
Index: clang/test/Parser/pragma-fp.cpp
===================================================================
--- clang/test/Parser/pragma-fp.cpp
+++ clang/test/Parser/pragma-fp.cpp
@@ -1,14 +1,14 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
void test_0(int *List, int Length) {
-/* expected-error@+1 {{missing option; expected 'contract' or 'reassociate'}} */
+/* expected-error@+1 {{missing option; expected 'contract', 'reassociate' or 'exceptions'}} */
#pragma clang fp
for (int i = 0; i < Length; i++) {
List[i] = i;
}
}
void test_1(int *List, int Length) {
-/* expected-error@+1 {{invalid option 'blah'; expected 'contract' or 'reassociate'}} */
+/* expected-error@+1 {{invalid option 'blah'; expected 'contract', 'reassociate' or 'exceptions'}} */
#pragma clang fp blah
for (int i = 0; i < Length; i++) {
List[i] = i;
@@ -62,3 +62,14 @@
#pragma clang fp contract(fast)
}
}
+
+void test_9(float *dest, float a, float b) {
+/* expected-error@+1 {{unexpected argument 'on' to '#pragma clang fp exceptions'; expected 'ignore', 'maytrap' or 'strict'}} */
+#pragma clang fp exceptions(on)
+ *dest = a + b;
+}
+
+void test_10(float *dest, float a, float b) {
+#pragma clang fp exceptions(maytrap) contract(fast) reassociate(on)
+ *dest = a + b;
+}
Index: clang/test/CodeGen/pragma-fp-exc.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/pragma-fp-exc.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DEF %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-STRICT %s
+
+float func_01(float x, float y, float z) {
+ float res = x + y;
+ {
+#pragma clang fp exceptions(maytrap)
+ res += z;
+ }
+ return res;
+}
+// CHECK-DEF-LABEL: @_Z7func_01fff
+// CHECK-DEF: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+// CHECK-DEF: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
+
+// CHECK-STRICT-LABEL: @_Z7func_01fff
+// CHECK-STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict")
+// CHECK-STRICT: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -1016,6 +1016,11 @@
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());
}
+void Sema::ActOnPragmaFPExceptions(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind FPE) {
+ setExceptionMode(Loc, FPE);
+}
+
void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
SourceLocation Loc) {
// Visibility calculations will consider the namespace's visibility.
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -2850,11 +2850,12 @@
namespace {
/// Used as the annotation value for tok::annot_pragma_fp.
struct TokFPAnnotValue {
- enum FlagKinds { Contract, Reassociate };
+ enum FlagKinds { Contract, Reassociate, Exceptions };
enum FlagValues { On, Off, Fast };
- FlagKinds FlagKind;
- FlagValues FlagValue;
+ llvm::Optional<LangOptions::FPModeKind> ContractValue;
+ llvm::Optional<LangOptions::FPModeKind> ReassociateValue;
+ llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
};
} // end anonymous namespace
@@ -2871,6 +2872,7 @@
return;
}
+ auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
while (Tok.is(tok::identifier)) {
IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
@@ -2879,6 +2881,7 @@
OptionInfo->getName())
.Case("contract", TokFPAnnotValue::Contract)
.Case("reassociate", TokFPAnnotValue::Reassociate)
+ .Case("exceptions", TokFPAnnotValue::Exceptions)
.Default(None);
if (!FlagKind) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
@@ -2897,25 +2900,49 @@
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
<< PP.getSpelling(Tok) << OptionInfo->getName()
- << (FlagKind == TokFPAnnotValue::Reassociate);
+ << static_cast<int>(*FlagKind);
return;
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
- auto FlagValue =
- llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
- II->getName())
- .Case("on", TokFPAnnotValue::On)
- .Case("off", TokFPAnnotValue::Off)
- .Case("fast", TokFPAnnotValue::Fast)
- .Default(llvm::None);
-
- if (!FlagValue || (FlagKind == TokFPAnnotValue::Reassociate &&
- FlagValue == TokFPAnnotValue::Fast)) {
- PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
- << PP.getSpelling(Tok) << OptionInfo->getName()
- << (FlagKind == TokFPAnnotValue::Reassociate);
- return;
+ if (FlagKind == TokFPAnnotValue::Contract) {
+ AnnotValue->ContractValue =
+ llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
+ II->getName())
+ .Case("on", LangOptions::FPModeKind::FPM_On)
+ .Case("off", LangOptions::FPModeKind::FPM_Off)
+ .Case("fast", LangOptions::FPModeKind::FPM_Fast)
+ .Default(llvm::None);
+ if (!AnnotValue->ContractValue) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
+ return;
+ }
+ } else if (FlagKind == TokFPAnnotValue::Reassociate) {
+ AnnotValue->ReassociateValue =
+ llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
+ II->getName())
+ .Case("on", LangOptions::FPModeKind::FPM_On)
+ .Case("off", LangOptions::FPModeKind::FPM_Off)
+ .Default(llvm::None);
+ if (!AnnotValue->ReassociateValue) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
+ return;
+ }
+ } else if (FlagKind == TokFPAnnotValue::Exceptions) {
+ AnnotValue->ExceptionsValue =
+ llvm::StringSwitch<llvm::Optional<LangOptions::FPExceptionModeKind>>(
+ II->getName())
+ .Case("ignore", LangOptions::FPE_Ignore)
+ .Case("maytrap", LangOptions::FPE_MayTrap)
+ .Case("strict", LangOptions::FPE_Strict)
+ .Default(llvm::None);
+ if (!AnnotValue->ExceptionsValue) {
+ PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
+ << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
+ return;
+ }
}
PP.Lex(Tok);
@@ -2925,17 +2952,6 @@
return;
}
PP.Lex(Tok);
-
- auto *AnnotValue = new (PP.getPreprocessorAllocator())
- TokFPAnnotValue{*FlagKind, *FlagValue};
- // Generate the fp annotation token.
- Token FPTok;
- FPTok.startToken();
- FPTok.setKind(tok::annot_pragma_fp);
- FPTok.setLocation(PragmaName.getLocation());
- FPTok.setAnnotationEndLoc(PragmaName.getLocation());
- FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
- TokenList.push_back(FPTok);
}
if (Tok.isNot(tok::eod)) {
@@ -2944,6 +2960,14 @@
return;
}
+ Token FPTok;
+ FPTok.startToken();
+ FPTok.setKind(tok::annot_pragma_fp);
+ FPTok.setLocation(PragmaName.getLocation());
+ FPTok.setAnnotationEndLoc(PragmaName.getLocation());
+ FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
+ TokenList.push_back(FPTok);
+
auto TokenArray = std::make_unique<Token[]>(TokenList.size());
std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
@@ -3006,24 +3030,16 @@
auto *AnnotValue =
reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
- if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
- Actions.ActOnPragmaFPReassociate(
- Tok.getLocation(), AnnotValue->FlagValue == TokFPAnnotValue::On);
- else {
- LangOptions::FPModeKind FPC;
- switch (AnnotValue->FlagValue) {
- case TokFPAnnotValue::Off:
- FPC = LangOptions::FPM_Off;
- break;
- case TokFPAnnotValue::On:
- FPC = LangOptions::FPM_On;
- break;
- case TokFPAnnotValue::Fast:
- FPC = LangOptions::FPM_Fast;
- break;
- }
- Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
- }
+ if (AnnotValue->ReassociateValue)
+ Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
+ *AnnotValue->ReassociateValue ==
+ LangOptions::FPModeKind::FPM_On);
+ if (AnnotValue->ContractValue)
+ Actions.ActOnPragmaFPContract(Tok.getLocation(),
+ *AnnotValue->ContractValue);
+ if (AnnotValue->ExceptionsValue)
+ Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
+ *AnnotValue->ExceptionsValue);
ConsumeAnnotationToken();
}
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9894,6 +9894,10 @@
/// \#pragma STDC FENV_ACCESS
void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
+ /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
+ void ActOnPragmaFPExceptions(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind);
+
/// Called to set constant rounding mode for floating point operations.
void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1382,12 +1382,13 @@
"pipeline, pipeline_initiation_interval, vectorize_predicate, or distribute">;
def err_pragma_fp_invalid_option : Error<
- "%select{invalid|missing}0 option%select{ %1|}0; expected 'contract' or 'reassociate'">;
+ "%select{invalid|missing}0 option%select{ %1|}0; expected 'contract', 'reassociate' or 'exceptions'">;
def err_pragma_fp_invalid_argument : Error<
- "unexpected argument '%0' to '#pragma clang fp %1'; "
+ "unexpected argument '%0' to '#pragma clang fp %1'; expected "
"%select{"
- "expected 'fast' or 'on' or 'off'|"
- "expected 'on' or 'off'}2">;
+ "'fast' or 'on' or 'off'|"
+ "'on' or 'off'|"
+ "'ignore', 'maytrap' or 'strict'}2">;
def err_pragma_invalid_keyword : Error<
"invalid argument; expected 'enable'%select{|, 'full'}0%select{|, 'assume_safety'}1 or 'disable'">;
Index: clang/docs/LanguageExtensions.rst
===================================================================
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -3182,7 +3182,7 @@
float f(float x, float y, float z)
{
// Enable floating point reassociation across statements
- #pragma fp reassociate(on)
+ #pragma clang fp reassociate(on)
float t = x + y;
float v = t + z;
}
@@ -3211,6 +3211,31 @@
section of the code. This can be useful when fast contraction is otherwise
enabled for the translation unit with the ``-ffp-contract=fast`` flag.
+
+``#pragma clang fp exceptions`` specifies floating point exception behavior. It
+may take one the the values: ``ignore``, ``maytrap`` or ``strict``. Meaning of
+these values is same as for `constrained floating point intrinsics <http://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics>`_.
+
+.. code-block:: c++
+
+ {
+ // Preserve floating point exceptions
+ #pragma fp exceptions(strict)
+ z = x + y;
+ if (fetestexcept(FE_OVERFLOW))
+ ...
+ }
+
+A ``#pragma clang fp`` pragma may contain any number of options:
+
+.. code-block:: c++
+
+ void func(float *dest, float a, float b) {
+ #pragma clang fp exceptions(maytrap) contract(fast) reassociate(on)
+ ...
+ }
+
+
The ``#pragma float_control`` pragma allows precise floating-point
semantics and floating-point exception behavior to be specified
for a section of the source code. This pragma can only appear at file scope or
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits