From 562fd2c99b70691affe7776a1900e95ee7da0b3b Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Thu, 2 Jun 2022 14:06:57 -0700 Subject: [PATCH] [flang][runtime] Emit error message rather than crashing for MOD(ULO)(x,P=0) Add extra arguments and checks to the runtime support library so that a call to the intrinsic functions MOD and MODULO with "denominator" argument P of zero will cause a crash with a source location rather than an uninformative floating-point error or integer division by zero signal. Additional work is required in lowering to (1) pass source file path and source line number arguments and (2) actually call these runtime library APIs instead of emitting inline code for MOD &/or MODULO. Differential Revision: https://reviews.llvm.org/D127034 --- flang/include/flang/Runtime/numeric.h | 54 ++++++++----- flang/runtime/numeric.cpp | 109 ++++++++++++++++---------- 2 files changed, 103 insertions(+), 60 deletions(-) diff --git a/flang/include/flang/Runtime/numeric.h b/flang/include/flang/Runtime/numeric.h index 6130a25e401c..a1645eb4ef67 100644 --- a/flang/include/flang/Runtime/numeric.h +++ b/flang/include/flang/Runtime/numeric.h @@ -214,48 +214,66 @@ bool RTNAME(IsNaN16)(CppTypeFor); // MOD & MODULO CppTypeFor RTNAME(ModInteger1)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger2)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModInteger8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModInteger16)( CppTypeFor, - CppTypeFor); + CppTypeFor, const char *sourceFile = nullptr, + int sourceLine = 0); #endif CppTypeFor RTNAME(ModReal4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModReal8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModReal10)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModReal16)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger1)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger2)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloInteger8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModuloInteger16)( CppTypeFor, - CppTypeFor); + CppTypeFor, const char *sourceFile = nullptr, + int sourceLine = 0); #endif CppTypeFor RTNAME(ModuloReal4)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloReal8)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloReal10)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); CppTypeFor RTNAME(ModuloReal16)( - CppTypeFor, CppTypeFor); + CppTypeFor, CppTypeFor, + const char *sourceFile = nullptr, int sourceLine = 0); // NINT CppTypeFor RTNAME(Nint4_1)( diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index c04d50111934..4ffb282a87c7 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "terminator.h" #include "flang/Runtime/numeric.h" #include "flang/Common/long-double.h" #include @@ -62,14 +63,24 @@ template inline T Fraction(T x) { } // MOD & MODULO (16.9.135, .136) -template inline T IntMod(T x, T p) { +template +inline T IntMod(T x, T p, const char *sourceFile, int sourceLine) { + if (p == 0) { + Terminator{sourceFile, sourceLine}.Crash( + IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); + } auto mod{x - (x / p) * p}; if (IS_MODULO && (x > 0) != (p > 0)) { mod += p; } return mod; } -template inline T RealMod(T x, T p) { +template +inline T RealMod(T x, T p, const char *sourceFile, int sourceLine) { + if (p == 0) { + Terminator{sourceFile, sourceLine}.Crash( + IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); + } if constexpr (IS_MODULO) { return x - std::floor(x / p) * p; } else { @@ -542,99 +553,113 @@ bool RTNAME(IsNaN16)(CppTypeFor x) { CppTypeFor RTNAME(ModInteger1)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger2)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger4)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModInteger8)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModInteger16)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModReal4)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModReal8)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #if LONG_DOUBLE == 80 CppTypeFor RTNAME(ModReal10)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #elif LONG_DOUBLE == 128 CppTypeFor RTNAME(ModReal16)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModuloInteger1)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger2)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger4)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloInteger8)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ModuloInteger16)( CppTypeFor x, - CppTypeFor p) { - return IntMod(x, p); + CppTypeFor p, const char *sourceFile, + int sourceLine) { + return IntMod(x, p, sourceFile, sourceLine); } #endif CppTypeFor RTNAME(ModuloReal4)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } CppTypeFor RTNAME(ModuloReal8)( - CppTypeFor x, CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #if LONG_DOUBLE == 80 CppTypeFor RTNAME(ModuloReal10)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #elif LONG_DOUBLE == 128 CppTypeFor RTNAME(ModuloReal16)( - CppTypeFor x, - CppTypeFor p) { - return RealMod(x, p); + CppTypeFor x, CppTypeFor p, + const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #endif