diff --git a/flang/include/flang/Optimizer/Support/Utils.h b/flang/include/flang/Optimizer/Support/Utils.h index d5b045924f3c0..34c8e79173bcd 100644 --- a/flang/include/flang/Optimizer/Support/Utils.h +++ b/flang/include/flang/Optimizer/Support/Utils.h @@ -14,8 +14,11 @@ #define FORTRAN_OPTIMIZER_SUPPORT_UTILS_H #include "flang/Common/default-kinds.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Support/FatalError.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/BuiltinAttributes.h" @@ -70,6 +73,66 @@ fromDefaultKinds(const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) { static_cast( defKinds.GetDefaultKind(Fortran::common::TypeCategory::Real))}; } + +inline std::string mlirTypeToString(mlir::Type type) { + std::string result{}; + llvm::raw_string_ostream sstream(result); + sstream << type; + return result; +} + +inline std::string numericMlirTypeToFortran(fir::FirOpBuilder &builder, + mlir::Type type, mlir::Location loc, + const llvm::Twine &name) { + if (type.isF16()) + return "REAL(KIND=2)"; + else if (type.isBF16()) + return "REAL(KIND=3)"; + else if (type.isTF32()) + return "REAL(KIND=unknown)"; + else if (type.isF32()) + return "REAL(KIND=4)"; + else if (type.isF64()) + return "REAL(KIND=8)"; + else if (type.isF80()) + return "REAL(KIND=10)"; + else if (type.isF128()) + return "REAL(KIND=16)"; + else if (type.isInteger(8)) + return "INTEGER(KIND=1)"; + else if (type.isInteger(16)) + return "INTEGER(KIND=2)"; + else if (type.isInteger(32)) + return "INTEGER(KIND=4)"; + else if (type.isInteger(64)) + return "INTEGER(KIND=8)"; + else if (type.isInteger(128)) + return "INTEGER(KIND=16)"; + else if (type == fir::ComplexType::get(builder.getContext(), 2)) + return "COMPLEX(KIND=2)"; + else if (type == fir::ComplexType::get(builder.getContext(), 3)) + return "COMPLEX(KIND=3)"; + else if (type == fir::ComplexType::get(builder.getContext(), 4)) + return "COMPLEX(KIND=4)"; + else if (type == fir::ComplexType::get(builder.getContext(), 8)) + return "COMPLEX(KIND=8)"; + else if (type == fir::ComplexType::get(builder.getContext(), 10)) + return "COMPLEX(KIND=10)"; + else if (type == fir::ComplexType::get(builder.getContext(), 16)) + return "COMPLEX(KIND=16)"; + else + fir::emitFatalError(loc, "unsupported type in " + name + ": " + + fir::mlirTypeToString(type)); +} + +inline void intrinsicTypeTODO(fir::FirOpBuilder &builder, mlir::Type type, + mlir::Location loc, + const llvm::Twine &intrinsicName) { + TODO(loc, + "intrinsic: " + + fir::numericMlirTypeToFortran(builder, type, loc, intrinsicName) + + " in " + intrinsicName); +} } // namespace fir #endif // FORTRAN_OPTIMIZER_SUPPORT_UTILS_H diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 7f354d7e77560..2b6beffd851a1 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -1235,7 +1235,7 @@ searchMathOperation(fir::FirOpBuilder &builder, llvm::StringRef name, static void checkPrecisionLoss(llvm::StringRef name, mlir::FunctionType funcType, const FunctionDistance &distance, - mlir::Location loc) { + fir::FirOpBuilder &builder, mlir::Location loc) { if (!distance.isLosingPrecision()) return; @@ -1249,13 +1249,20 @@ static void checkPrecisionLoss(llvm::StringRef name, llvm::raw_string_ostream sstream(message); if (name == "pow") { assert(funcType.getNumInputs() == 2 && "power operator has two arguments"); - sstream << funcType.getInput(0) << " ** " << funcType.getInput(1); + std::string displayName{" ** "}; + sstream << numericMlirTypeToFortran(builder, funcType.getInput(0), loc, + displayName) + << displayName + << numericMlirTypeToFortran(builder, funcType.getInput(1), loc, + displayName); } else { - sstream << name << "("; + sstream << name.upper() << "("; if (funcType.getNumInputs() > 0) - sstream << funcType.getInput(0); - for (mlir::Type argType : funcType.getInputs().drop_front()) - sstream << ", " << argType; + sstream << numericMlirTypeToFortran(builder, funcType.getInput(0), loc, + name); + for (mlir::Type argType : funcType.getInputs().drop_front()) { + sstream << ", " << numericMlirTypeToFortran(builder, argType, loc, name); + } sstream << ")"; } sstream << "'"; @@ -1373,7 +1380,7 @@ void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name) { else if (isCoarrayIntrinsic(name)) TODO(loc, "coarray: intrinsic " + llvm::Twine(name)); else - TODO(loc, "intrinsic: " + llvm::Twine(name)); + TODO(loc, "intrinsic: " + llvm::Twine(name.upper())); } template @@ -1756,7 +1763,7 @@ IntrinsicLibrary::getRuntimeCallGenerator(llvm::StringRef name, if (!mathOp && bestNearMatch) { // Use the best near match, optionally issuing an error, // if types conversions cause precision loss. - checkPrecisionLoss(name, soughtFuncType, bestMatchDistance, loc); + checkPrecisionLoss(name, soughtFuncType, bestMatchDistance, builder, loc); mathOp = bestNearMatch; } @@ -4373,7 +4380,7 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, // Real case if (resultType == mlir::FloatType::getF128(builder.getContext())) - TODO(loc, "intrinsic: modulo for floating point of KIND=16"); + TODO(loc, "REAL(KIND=16): in MODULO intrinsic"); auto remainder = builder.create(loc, args[0], args[1]); mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType()); auto remainderIsNotZero = builder.create( diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index cb4035d53d5b5..b958a30eb6e5b 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -11,7 +11,7 @@ #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" -#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Support/Utils.h" #include "flang/Runtime/numeric.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -240,10 +240,7 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder, mlir::Value x) { mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - - if (fltTy.isF16()) { - TODO(loc, "support for REAL with KIND = 2 in EXPONENT"); - } else if (fltTy.isF32()) { + if (fltTy.isF32()) { if (resultType.isInteger(32)) func = fir::runtime::getRuntimeFunc(loc, builder); else if (resultType.isInteger(64)) @@ -264,7 +261,7 @@ mlir::Value fir::runtime::genExponent(fir::FirOpBuilder &builder, else if (resultType.isInteger(64)) func = fir::runtime::getRuntimeFunc(loc, builder); } else - fir::emitFatalError(loc, "unsupported REAL kind in EXPONENT"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "EXPONENT"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -278,9 +275,7 @@ mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x) { mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in FRACTION"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -289,7 +284,7 @@ mlir::Value fir::runtime::genFraction(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in FRACTION"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "FRACTION"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -307,9 +302,7 @@ mlir::Value fir::runtime::genMod(fir::FirOpBuilder &builder, mlir::Location loc, if (fltTy != p.getType()) fir::emitFatalError(loc, "arguments type mismatch in MOD"); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in MOD"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -318,7 +311,7 @@ mlir::Value fir::runtime::genMod(fir::FirOpBuilder &builder, mlir::Location loc, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in MOD"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "MOD"); auto funcTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -337,9 +330,7 @@ mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in NEAREST"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -348,7 +339,7 @@ mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in NEAREST"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "NEAREST"); auto funcTy = func.getFunctionType(); @@ -374,9 +365,7 @@ mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in RRSPACING"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -385,7 +374,7 @@ mlir::Value fir::runtime::genRRSpacing(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in RRSPACING"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "RRSPACING"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { @@ -401,9 +390,7 @@ mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in SCALE"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -412,7 +399,7 @@ mlir::Value fir::runtime::genScale(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in SCALE"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "SCALE"); auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); @@ -480,9 +467,7 @@ mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in FRACTION"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -491,7 +476,7 @@ mlir::Value fir::runtime::genSetExponent(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in FRACTION"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "SET_EXPONENT"); auto funcTy = func.getFunctionType(); auto args = fir::runtime::createArguments(builder, loc, funcTy, x, i); @@ -505,9 +490,7 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - if (fltTy.isF16()) - TODO(loc, "support for REAL with KIND = 2 in SPACING"); - else if (fltTy.isF32()) + if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -516,7 +499,7 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "unsupported REAL kind in SPACING"); + fir::intrinsicTypeTODO(builder, fltTy, loc, "SPACING"); auto funcTy = func.getFunctionType(); llvm::SmallVector args = { diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp index 9d47d65ece360..fabbff818b6f0 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -11,7 +11,7 @@ #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" -#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Support/Utils.h" #include "flang/Runtime/reduction.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -652,9 +652,7 @@ void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc, auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); auto eleTy = arrTy.cast().getEleTy(); fir::factory::CharacterExprHelper charHelper{builder, loc}; - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision MAXLOC"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -675,7 +673,7 @@ void fir::runtime::genMaxloc(fir::FirOpBuilder &builder, mlir::Location loc, else if (charHelper.isCharacterScalar(eleTy)) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in MAXLOC"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "MAXLOC"); genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, back); } @@ -702,9 +700,7 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision MAXVAL"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -723,7 +719,7 @@ mlir::Value fir::runtime::genMaxval(fir::FirOpBuilder &builder, else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in MAXVAL"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "MAXVAL"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -771,9 +767,7 @@ void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc, auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); auto eleTy = arrTy.cast().getEleTy(); fir::factory::CharacterExprHelper charHelper{builder, loc}; - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision MINLOC"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -794,7 +788,7 @@ void fir::runtime::genMinloc(fir::FirOpBuilder &builder, mlir::Location loc, else if (charHelper.isCharacterScalar(eleTy)) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in MINLOC"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "MINLOC"); genReduction4Args(func, builder, loc, resultBox, arrayBox, maskBox, kind, back); } @@ -846,9 +840,7 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision MINVAL"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -867,7 +859,7 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(16))) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in MINVAL"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "MINVAL"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -905,9 +897,7 @@ mlir::Value fir::runtime::genNorm2(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision NORM2"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -916,7 +906,7 @@ mlir::Value fir::runtime::genNorm2(fir::FirOpBuilder &builder, else if (eleTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in NORM2"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "NORM2"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -958,9 +948,7 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision PRODUCT"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -988,11 +976,8 @@ mlir::Value fir::runtime::genProduct(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || - eleTy == fir::ComplexType::get(builder.getContext(), 3)) - TODO(loc, "half-precision PRODUCT"); else - fir::emitFatalError(loc, "invalid type in PRODUCT"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "PRODUCT"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -1026,9 +1011,7 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, auto ty = resultBox.getType(); auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(ty); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision DOTPRODUCT"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -1048,9 +1031,6 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || - eleTy == fir::ComplexType::get(builder.getContext(), 3)) - TODO(loc, "half-precision DOTPRODUCT"); else if (eleTy.isInteger(builder.getKindMap().getIntegerBitsize(1))) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -1070,7 +1050,7 @@ mlir::Value fir::runtime::genDotProduct(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in DOTPRODUCT"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "DOTPRODUCT"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -1111,9 +1091,7 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, auto eleTy = arrTy.cast().getEleTy(); auto dim = builder.createIntegerConstant(loc, builder.getIndexType(), 0); - if (eleTy.isF16() || eleTy.isBF16()) - TODO(loc, "half-precision SUM"); - else if (eleTy.isF32()) + if (eleTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -1139,11 +1117,8 @@ mlir::Value fir::runtime::genSum(fir::FirOpBuilder &builder, mlir::Location loc, func = fir::runtime::getRuntimeFunc(loc, builder); else if (eleTy == fir::ComplexType::get(builder.getContext(), 16)) func = fir::runtime::getRuntimeFunc(loc, builder); - else if (eleTy == fir::ComplexType::get(builder.getContext(), 2) || - eleTy == fir::ComplexType::get(builder.getContext(), 3)) - TODO(loc, "half-precision SUM"); else - fir::emitFatalError(loc, "invalid type in SUM"); + fir::intrinsicTypeTODO(builder, eleTy, loc, "SUM"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); diff --git a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp index 3ae097743e3ad..6d3d85e8df69f 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp @@ -12,7 +12,7 @@ #include "flang/Optimizer/Builder/Character.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" -#include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Support/Utils.h" #include "flang/Runtime/matmul-transpose.h" #include "flang/Runtime/matmul.h" #include "flang/Runtime/transformational.h" @@ -160,9 +160,7 @@ void fir::runtime::genBesselJn(fir::FirOpBuilder &builder, mlir::Location loc, mlir::func::FuncOp func; auto xTy = x.getType(); - if (xTy.isF16() || xTy.isBF16()) - TODO(loc, "half-precision BESSEL_JN"); - else if (xTy.isF32()) + if (xTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (xTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -171,7 +169,7 @@ void fir::runtime::genBesselJn(fir::FirOpBuilder &builder, mlir::Location loc, else if (xTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in BESSEL_JN"); + fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -189,9 +187,7 @@ void fir::runtime::genBesselJnX0(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value n1, mlir::Value n2) { mlir::func::FuncOp func; - if (xTy.isF16() || xTy.isBF16()) - TODO(loc, "half-precision BESSEL_JN"); - else if (xTy.isF32()) + if (xTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (xTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -200,7 +196,7 @@ void fir::runtime::genBesselJnX0(fir::FirOpBuilder &builder, mlir::Location loc, else if (xTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in BESSEL_JN"); + fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_JN"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -219,9 +215,7 @@ void fir::runtime::genBesselYn(fir::FirOpBuilder &builder, mlir::Location loc, mlir::func::FuncOp func; auto xTy = x.getType(); - if (xTy.isF16() || xTy.isBF16()) - TODO(loc, "half-precision BESSEL_YN"); - else if (xTy.isF32()) + if (xTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (xTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -230,7 +224,7 @@ void fir::runtime::genBesselYn(fir::FirOpBuilder &builder, mlir::Location loc, else if (xTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in BESSEL_YN"); + fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); @@ -248,9 +242,7 @@ void fir::runtime::genBesselYnX0(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value n1, mlir::Value n2) { mlir::func::FuncOp func; - if (xTy.isF16() || xTy.isBF16()) - TODO(loc, "half-precision BESSEL_YN"); - else if (xTy.isF32()) + if (xTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (xTy.isF64()) func = fir::runtime::getRuntimeFunc(loc, builder); @@ -259,7 +251,7 @@ void fir::runtime::genBesselYnX0(fir::FirOpBuilder &builder, mlir::Location loc, else if (xTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); else - fir::emitFatalError(loc, "invalid type in BESSEL_YN"); + fir::intrinsicTypeTODO(builder, xTy, loc, "BESSEL_YN"); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index bb893277cb4d2..b136c8f7a9dd9 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -15,6 +15,7 @@ #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Dialect/Support/KindMapping.h" #include "flang/Optimizer/Support/FatalError.h" +#include "flang/Optimizer/Support/Utils.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/TypeRange.h" @@ -44,6 +45,19 @@ static const llvm::fltSemantics &floatToSemantics(const KindMapping &kindMap, return type.cast().getFloatSemantics(); } +static void typeTodo(const llvm::fltSemantics *sem, mlir::Location loc, + std::string context) { + if (sem == &llvm::APFloat::IEEEhalf()) { + TODO(loc, "COMPLEX(KIND=2): for " + context + " type"); + } else if (sem == &llvm::APFloat::BFloat()) { + TODO(loc, "COMPLEX(KIND=3): " + context + " type"); + } else if (sem == &llvm::APFloat::x87DoubleExtended()) { + TODO(loc, "COMPLEX(KIND=10): " + context + " type"); + } else { + TODO(loc, "complex for this precision for " + context + " type"); + } +} + namespace { template struct GenericTarget : public CodeGenSpecifics { @@ -163,7 +177,7 @@ struct TargetI386 : public GenericTarget { marshal.emplace_back(fir::ReferenceType::get(structTy), AT{/*alignment=*/4, /*byval=*/false, /*sret=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -222,7 +236,7 @@ struct TargetI386Win : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/4, /*byval=*/false, /*sret=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -258,7 +272,7 @@ struct TargetX86_64 : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/16, /*byval=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -284,7 +298,7 @@ struct TargetX86_64 : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/16, /*byval=*/false, /*sret=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -325,7 +339,7 @@ struct TargetX86_64Win : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/16, /*byval=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -354,7 +368,7 @@ struct TargetX86_64Win : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/16, /*byval=*/false, /*sret=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -380,7 +394,7 @@ struct TargetAArch64 : public GenericTarget { // [2 x t] array of 2 eleTy marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -397,7 +411,7 @@ struct TargetAArch64 : public GenericTarget { mlir::TypeRange{eleTy, eleTy}), AT{}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -532,7 +546,7 @@ struct TargetSparcV9 : public GenericTarget { eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})), AT{/*align=*/16, /*byval=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -570,7 +584,7 @@ struct TargetRISCV64 : public GenericTarget { marshal.emplace_back(eleTy, AT{}); marshal.emplace_back(eleTy, AT{}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -587,7 +601,7 @@ struct TargetRISCV64 : public GenericTarget { mlir::TypeRange{eleTy, eleTy}), AT{/*alignment=*/0, /*byval=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } @@ -668,7 +682,7 @@ struct TargetLoongArch64 : public GenericTarget { marshal.emplace_back(eleTy, AT{}); marshal.emplace_back(eleTy, AT{}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "argument"); } return marshal; } @@ -685,7 +699,7 @@ struct TargetLoongArch64 : public GenericTarget { mlir::TypeRange{eleTy, eleTy}), AT{/*alignment=*/0, /*byval=*/true}); } else { - TODO(loc, "complex for this precision"); + typeTodo(sem, loc, "return"); } return marshal; } diff --git a/flang/runtime/character.cpp b/flang/runtime/character.cpp index dd522f19a7ede..571f64ec42f42 100644 --- a/flang/runtime/character.cpp +++ b/flang/runtime/character.cpp @@ -256,7 +256,8 @@ static void LenTrimKind(Descriptor &result, const Descriptor &string, int kind, result, string, terminator); break; default: - terminator.Crash("not yet implemented: LEN_TRIM: KIND=%d", kind); + terminator.Crash( + "not yet implemented: CHARACTER(KIND=%d) in LEN_TRIM intrinsic", kind); } } @@ -457,7 +458,9 @@ static void GeneralCharFuncKind(Descriptor &result, const Descriptor &string, result, string, arg, back, terminator); break; default: - terminator.Crash("not yet implemented: INDEX/SCAN/VERIFY: KIND=%d", kind); + terminator.Crash("not yet implemented: CHARACTER(KIND=%d) in " + "INDEX/SCAN/VERIFY intrinsic", + kind); } } diff --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h index e20f31e9b4431..2b5bf8248aca2 100644 --- a/flang/runtime/descriptor-io.h +++ b/flang/runtime/descriptor-io.h @@ -483,8 +483,7 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, return FormattedIntegerIO<16, DIR>(io, descriptor); default: handler.Crash( - "DescriptorIO: Unimplemented INTEGER kind (%d) in descriptor", - kind); + "not yet implemented: INTEGER(KIND=%d) in formatted IO", kind); return false; } case TypeCategory::Real: @@ -504,7 +503,7 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, return FormattedRealIO<16, DIR>(io, descriptor); default: handler.Crash( - "DescriptorIO: Unimplemented REAL kind (%d) in descriptor", kind); + "not yet implemented: REAL(KIND=%d) in formatted IO", kind); return false; } case TypeCategory::Complex: @@ -524,8 +523,7 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, return FormattedComplexIO<16, DIR>(io, descriptor); default: handler.Crash( - "DescriptorIO: Unimplemented COMPLEX kind (%d) in descriptor", - kind); + "not yet implemented: COMPLEX(KIND=%d) in formatted IO", kind); return false; } case TypeCategory::Character: @@ -538,8 +536,7 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, return FormattedCharacterIO(io, descriptor); default: handler.Crash( - "DescriptorIO: Unimplemented CHARACTER kind (%d) in descriptor", - kind); + "not yet implemented: CHARACTER(KIND=%d) in formatted IO", kind); return false; } case TypeCategory::Logical: @@ -554,8 +551,7 @@ static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, return FormattedLogicalIO<8, DIR>(io, descriptor); default: handler.Crash( - "DescriptorIO: Unimplemented LOGICAL kind (%d) in descriptor", - kind); + "not yet implemented: LOGICAL(KIND=%d) in formatted IO", kind); return false; } case TypeCategory::Derived: diff --git a/flang/runtime/random.cpp b/flang/runtime/random.cpp index 8b00cfd1cac19..642091a06aff5 100644 --- a/flang/runtime/random.cpp +++ b/flang/runtime/random.cpp @@ -142,7 +142,8 @@ void RTNAME(RandomNumber)( } break; } - terminator.Crash("not yet implemented: RANDOM_NUMBER(): REAL kind %d", kind); + terminator.Crash( + "not yet implemented: intrinsic: REAL(KIND=%d) in RANDOM_NUMBER", kind); } void RTNAME(RandomSeedSize)( @@ -156,8 +157,8 @@ void RTNAME(RandomSeedSize)( RUNTIME_CHECK(terminator, size->rank() == 0 && typeCode && typeCode->first == TypeCategory::Integer); - int kind{typeCode->second}; - switch (kind) { + int sizeArg{typeCode->second}; + switch (sizeArg) { case 4: *size->OffsetElement>() = 1; break; @@ -166,7 +167,8 @@ void RTNAME(RandomSeedSize)( break; default: terminator.Crash( - "not yet implemented: RANDOM_SEED(SIZE=): kind %d\n", kind); + "not yet implemented: intrinsic: RANDOM_SEED(SIZE=): size %d\n", + sizeArg); } } @@ -182,9 +184,9 @@ void RTNAME(RandomSeedPut)( put->rank() == 1 && typeCode && typeCode->first == TypeCategory::Integer && put->GetDimension(0).Extent() >= 1); - int kind{typeCode->second}; + int putArg{typeCode->second}; GeneratedWord seed; - switch (kind) { + switch (putArg) { case 4: seed = *put->OffsetElement>(); break; @@ -192,7 +194,8 @@ void RTNAME(RandomSeedPut)( seed = *put->OffsetElement>(); break; default: - terminator.Crash("not yet implemented: RANDOM_SEED(PUT=): kind %d\n", kind); + terminator.Crash( + "not yet implemented: intrinsic: RANDOM_SEED(PUT=): put %d\n", putArg); } { CriticalSection critical{lock}; @@ -221,14 +224,14 @@ void RTNAME(RandomSeedGet)( get->rank() == 1 && typeCode && typeCode->first == TypeCategory::Integer && get->GetDimension(0).Extent() >= 1); - int kind{typeCode->second}; + int getArg{typeCode->second}; GeneratedWord seed; { CriticalSection critical{lock}; seed = GetNextValue(); nextValue = seed; } - switch (kind) { + switch (getArg) { case 4: *get->OffsetElement>() = seed; break; @@ -236,7 +239,8 @@ void RTNAME(RandomSeedGet)( *get->OffsetElement>() = seed; break; default: - terminator.Crash("not yet implemented: RANDOM_SEED(GET=): kind %d\n", kind); + terminator.Crash( + "not yet implemented: intrinsic: RANDOM_SEED(GET=): get %d\n", getArg); } } diff --git a/flang/runtime/tools.cpp b/flang/runtime/tools.cpp index a027559d9f4a7..b4e8f9bc890d5 100644 --- a/flang/runtime/tools.cpp +++ b/flang/runtime/tools.cpp @@ -109,8 +109,8 @@ RT_API_ATTRS void CheckConformability(const Descriptor &to, const Descriptor &x, RT_API_ATTRS void CheckIntegerKind( Terminator &terminator, int kind, const char *intrinsic) { if (kind < 1 || kind > 16 || (kind & (kind - 1)) != 0) { - terminator.Crash( - "not yet implemented: %s: KIND=%d argument", intrinsic, kind); + terminator.Crash("not yet implemented: INTEGER(KIND=%d) in %s intrinsic", + intrinsic, kind); } } diff --git a/flang/runtime/transformational.cpp b/flang/runtime/transformational.cpp index c93c3d65a0953..da8ec05c884fa 100644 --- a/flang/runtime/transformational.cpp +++ b/flang/runtime/transformational.cpp @@ -106,7 +106,8 @@ static RT_API_ATTRS void DefaultInitialize( static_cast(' ')); break; default: - terminator.Crash("not yet implemented: EOSHIFT: CHARACTER kind %d", kind); + terminator.Crash( + "not yet implemented: CHARACTER(KIND=%d) in EOSHIFT intrinsic", kind); } } else { std::memset(result.raw().base_addr, 0, bytes); diff --git a/flang/test/Lower/Intrinsics/missing-math-runtime.f90 b/flang/test/Lower/Intrinsics/missing-math-runtime.f90 index 89e383caaad6b..98d3abb17f3a8 100644 --- a/flang/test/Lower/Intrinsics/missing-math-runtime.f90 +++ b/flang/test/Lower/Intrinsics/missing-math-runtime.f90 @@ -4,7 +4,7 @@ complex(16) :: a real(16) :: b -! CHECK: not yet implemented: no math runtime available for 'abs(!fir.complex<16>)' +! CHECK: not yet implemented: no math runtime available for 'ABS(COMPLEX(KIND=16))' b = abs(a) end