9#ifndef FORTRAN_LOWER_INTRINSICCALL_H
10#define FORTRAN_LOWER_INTRINSICCALL_H
12#include "flang/Lower/AbstractConverter.h"
13#include "flang/Optimizer/Builder/BoxValue.h"
14#include "flang/Optimizer/Builder/FIRBuilder.h"
15#include "flang/Optimizer/Builder/Runtime/Character.h"
16#include "flang/Optimizer/Builder/Runtime/Numeric.h"
18#include "flang/Runtime/entry-names.h"
19#include "flang/Runtime/iostat-consts.h"
20#include "mlir/Dialect/Complex/IR/Complex.h"
21#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
22#include "mlir/Dialect/Math/IR/Math.h"
27class StatementContext;
28struct IntrinsicHandlerEntry;
35std::pair<fir::ExtendedValue, bool>
37 std::optional<mlir::Type> resultType,
44std::pair<fir::ExtendedValue, bool>
46 const IntrinsicHandlerEntry &,
47 std::optional<mlir::Type> resultType,
57enum class ExtremumBehavior {
142 : builder{builder}, loc{loc}, converter{converter} {}
149 std::pair<fir::ExtendedValue, bool>
150 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
163 using RuntimeCallGenerator = std::function<mlir::Value(
166 getRuntimeCallGenerator(llvm::StringRef name,
167 mlir::FunctionType soughtFuncType);
177 mlir::Value, mlir::Value)>
198 template <mlir::arith::CmpIPredicate pred>
199 mlir::Value genBitwiseCompare(mlir::Type resultType,
205 template <mlir::arith::CmpIPredicate pred>
218 mlir::Value genErfcScaled(mlir::Type resultType,
224 template <mlir::arith::CmpIPredicate pred>
237 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
239 mlir::ArrayRef<fir::ExtendedValue> args);
243 template <Extremum, ExtremumBehavior>
246 mlir::Value genFraction(mlir::Type resultType,
247 mlir::ArrayRef<mlir::Value> args);
248 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
251 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
252 mlir::Value genGetPID(mlir::Type resultType,
254 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
256 mlir::Value genGetGID(mlir::Type resultType,
258 mlir::Value genGetUID(mlir::Type resultType,
272 template <
bool isGet,
bool isModes>
281 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
282 template <
bool isMax,
bool isNum,
bool isMag>
284 template <mlir::arith::CmpFPredicate pred>
285 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
290 template <
bool isFlag>
294 template <mlir::arith::CmpFPredicate pred>
295 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
303 template <mlir::arith::CmpIPredicate pred>
313 template <Fortran::runtime::io::Iostat value>
325 template <
typename Shift>
340 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
341 template <NearestProc>
360 mlir::ArrayRef<fir::ExtendedValue>);
363 mlir::Value genRRSpacing(mlir::Type resultType,
370 mlir::ArrayRef<fir::ExtendedValue>);
376 mlir::Value genSetExponent(mlir::Type resultType,
380 template <
typename Shift>
387 mlir::Value genSpacing(mlir::Type resultType,
400 mlir::ArrayRef<fir::ExtendedValue> args);
426 template <
typename FN,
typename FD>
430 template <
typename FN,
typename FD,
typename FC>
433 llvm::StringRef errMsg,
434 mlir::Type resultType,
437 template <
typename FN,
typename FD>
439 mlir::Type resultType,
447 mlir::Value
genQNan(mlir::Type resultType);
452 using ExtendedGenerator =
decltype(&IntrinsicLibrary::genLenTrim);
453 using SubroutineGenerator =
decltype(&IntrinsicLibrary::genDateAndTime);
465 template <
typename GeneratorType>
467 mlir::Type resultType,
469 template <
typename GeneratorType>
471 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
472 std::optional<mlir::Type> resultType,
475 template <
typename GeneratorType>
476 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
478 bool loadRefArguments =
false);
481 template <
typename GeneratorType>
483 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
488 mlir::Type resultType,
491 mlir::Type resultType,
494 mlir::Type resultType,
507 mlir::FunctionType signature);
511 mlir::Type resultType,
512 llvm::StringRef errMsg);
514 void setResultMustBeFreed() { resultMustBeFreed =
true; }
518 bool resultMustBeFreed =
false;
523 const char *name =
nullptr;
525 bool handleDynamicOptional =
false;
532 constexpr bool hasDefaultRules()
const {
return args[0].name ==
nullptr; }
539 IntrinsicLibrary::Generator generator;
542 bool isElemental =
true;
550 using Key = std::string_view;
552 constexpr operator Key()
const {
return key; }
556 llvm::StringRef symbol;
557 fir::runtime::FuncTypeBuilderFunc typeGenerator;
568 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
572 using Key = std::string_view;
574 constexpr operator Key()
const {
return key; }
579 llvm::StringRef runtimeFunc;
580 FuncTypeBuilderFunc typeGenerator;
586 MathGeneratorTy funcGenerator;
590enum class ParamTypeId {
602static int getVecLen(mlir::Type eleTy) {
603 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
604 mlir::isa<mlir::FloatType>(eleTy)) &&
605 "unsupported vector element type");
606 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
609template <ParamTypeId t,
int k>
612 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
614 "Unsupported integer kind");
615 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
617 "Unsupported real kind");
618 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
619 k == 8 || k == 10 || k == 16,
620 "Unsupported complex kind");
622 static const ParamTypeId ty = t;
623 static const int kind = k;
648static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
650 ParamTypeId typeId,
int kind) {
654 case ParamTypeId::Void:
655 llvm::report_fatal_error(
"can not get type of void");
657 case ParamTypeId::Address:
659 assert(bits != 0 &&
"failed to convert address kind to integer bitsize");
660 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
662 case ParamTypeId::Integer:
663 case ParamTypeId::IntegerVector:
665 assert(bits != 0 &&
"failed to convert kind to integer bitsize");
666 r = mlir::IntegerType::get(context, bits);
668 case ParamTypeId::UnsignedVector:
670 assert(bits != 0 &&
"failed to convert kind to unsigned bitsize");
671 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
673 case ParamTypeId::Real:
674 case ParamTypeId::RealVector:
677 case ParamTypeId::Complex:
678 r = mlir::ComplexType::get(builder.
getRealType(kind));
683 case ParamTypeId::Void:
684 case ParamTypeId::Address:
685 case ParamTypeId::Integer:
686 case ParamTypeId::Real:
687 case ParamTypeId::Complex:
689 case ParamTypeId::IntegerVector:
690 case ParamTypeId::UnsignedVector:
691 case ParamTypeId::RealVector:
693 r = fir::VectorType::get(getVecLen(r), r);
700template <
typename TyR,
typename... ArgTys>
701static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
707 for (
size_t i = 0; i < argTys.size(); ++i) {
708 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
711 if (TyR::ty == ParamTypeId::Void)
712 return mlir::FunctionType::get(context, argTypes, std::nullopt);
714 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
715 return mlir::FunctionType::get(context, argTypes, {resType});
720 using RuntimeGeneratorRange =
721 std::pair<const MathOperation *, const MathOperation *>;
723 assert(handler &&
"handler must not be nullptr");
727 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
733static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
735 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
736 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
737 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
746 for (
auto arg : args)
747 baseVec.push_back(
getBase(arg));
754 for (
auto arg : args)
755 typeVec.push_back(arg.getType());
760 const MathOperation &mathOp,
761 mlir::FunctionType libFuncType,
766 const MathOperation &mathOp,
767 mlir::FunctionType mathLibFuncType,
772 const MathOperation &mathOp,
773 mlir::FunctionType mathLibFuncType,
778 const MathOperation &mathOp,
779 mlir::FunctionType libFuncType,
784std::optional<IntrinsicHandlerEntry>
786 std::optional<mlir::Type> resultType);
793const IntrinsicArgumentLoweringRules *
809 llvm::StringRef name,
810 mlir::FunctionType signature);
829 mlir::Type resultType, mlir::Value x, mlir::Value y);
834 mlir::Value x, mlir::Value y);
Definition: AbstractConverter.h:82
Definition: BoxValue.h:478
Definition: FIRBuilder.h:55
const fir::KindMapping & getKindMap()
Get a reference to the kind map.
Definition: FIRBuilder.h:116
mlir::Type getRealType(int kind)
Get the mlir float type that implements Fortran REAL(kind).
Definition: FIRBuilder.cpp:105
Bitsize getIntegerBitsize(KindTy kind) const
Get the size in bits of !fir.int<kind>
Definition: KindMapping.cpp:282
Definition: BoxValue.h:360
Definition: AbstractConverter.h:31
std::optional< IntrinsicHandlerEntry > lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName, std::optional< mlir::Type > resultType)
Definition: IntrinsicCall.cpp:1718
Extremum
Enums used to templatize and share lowering of MIN and MAX.
Definition: IntrinsicCall.h:52
const IntrinsicArgumentLoweringRules * getIntrinsicArgumentLowering(llvm::StringRef intrinsicName)
Definition: IntrinsicCall.cpp:8095
mlir::Value getBase(const ExtendedValue &exv)
Definition: BoxValue.cpp:21
mlir::Value genMin(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Generate minimum. Same constraints as genMax.
Definition: IntrinsicCall.cpp:8149
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition: IntrinsicCall.cpp:8162
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition: IntrinsicCall.cpp:8157
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition: IntrinsicCall.cpp:74
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition: IntrinsicCall.cpp:1740
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition: IntrinsicCall.cpp:8120
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name, mlir::FunctionType signature)
Get SymbolRefAttr of runtime (or wrapper function containing inlined.
Definition: IntrinsicCall.cpp:8175
LowerIntrinsicArgAs
Definition: IntrinsicCall.h:96
@ Box
Lower argument to a box.
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > args, Fortran::lower::AbstractConverter *converter=nullptr)
Definition: IntrinsicCall.cpp:8133
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition: IntrinsicCall.cpp:8141
Define how a given intrinsic argument must be lowered.
Definition: IntrinsicCall.h:111
bool handleDynamicOptional
Value:
Definition: IntrinsicCall.h:123
This is shared by intrinsics and intrinsic module procedures.
Definition: IntrinsicCall.h:529
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition: IntrinsicCall.h:531
Definition: IntrinsicCall.h:522
Entry into the tables describing how an intrinsic must be lowered.
Definition: IntrinsicCall.h:719
Definition: IntrinsicCall.h:537
bool outline
Definition: IntrinsicCall.h:545
Definition: IntrinsicCall.h:136
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition: IntrinsicCall.cpp:2246
fir::ExtendedValue genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< fir::ExtendedValue > args, bool outline)
Generate calls to ElementalGenerator, handling the elemental aspects.
Definition: IntrinsicCall.cpp:1752
fir::ExtendedValue genReduction(FN func, FD funcDim, llvm::StringRef errMsg, mlir::Type resultType, llvm::ArrayRef< fir::ExtendedValue > args)
Process calls to Product, Sum, IAll, IAny, IParity intrinsic functions.
Definition: IntrinsicCall.cpp:3878
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition: IntrinsicCall.cpp:1936
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition: IntrinsicCall.h:455
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition: IntrinsicCall.cpp:2145
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition: IntrinsicCall.cpp:2317
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition: IntrinsicCall.cpp:4091
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition: IntrinsicCall.cpp:2325
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition: IntrinsicCall.cpp:2339
fir::ExtendedValue genExtremumVal(FN func, FD funcDim, FC funcChar, llvm::StringRef errMsg, mlir::Type resultType, llvm::ArrayRef< fir::ExtendedValue > args)
Helper for MinVal/MaxVal.
Definition: IntrinsicCall.cpp:8004
fir::ExtendedValue readAndAddCleanUp(fir::MutableBoxValue resultMutableBox, mlir::Type resultType, llvm::StringRef errMsg)
Helper function for generating code clean-up for result descriptors.
Definition: IntrinsicCall.cpp:2280
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition: IntrinsicCall.h:451
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition: IntrinsicCall.cpp:2937
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition: IntrinsicCall.cpp:2930
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition: IntrinsicCall.cpp:4098
mlir::Value invokeGenerator(ElementalGenerator generator, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Helper to invoke code generator for the intrinsics given arguments.
Definition: IntrinsicCall.cpp:1951
fir::ExtendedValue genExtremumloc(FN func, FD funcDim, llvm::StringRef errMsg, mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
Process calls to Minloc, Maxloc intrinsic functions.
Definition: IntrinsicCall.cpp:7923
Definition: IntrinsicCall.h:560
Definition: IntrinsicCall.h:610
Definition: IntrinsicCall.h:548