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/LLVMIR/NVVMDialect.h"
23#include "mlir/Dialect/Math/IR/Math.h"
28class StatementContext;
36std::pair<fir::ExtendedValue, bool>
38 std::optional<mlir::Type> resultType,
39 llvm::ArrayRef<fir::ExtendedValue> args,
40 Fortran::lower::AbstractConverter *converter =
nullptr);
45std::pair<fir::ExtendedValue, bool>
48 std::optional<mlir::Type> resultType,
49 llvm::ArrayRef<fir::ExtendedValue> args,
50 Fortran::lower::AbstractConverter *converter =
nullptr);
58enum class ExtremumBehavior {
137struct IntrinsicLibrary {
140 explicit IntrinsicLibrary(
143 : builder{builder}, loc{loc}, converter{converter} {}
144 IntrinsicLibrary() =
delete;
145 IntrinsicLibrary(
const IntrinsicLibrary &) =
delete;
150 std::pair<fir::ExtendedValue, bool>
151 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
164 using RuntimeCallGenerator = std::function<mlir::Value(
167 getRuntimeCallGenerator(llvm::StringRef name,
168 mlir::FunctionType soughtFuncType);
179 mlir::Value, mlir::Value)>
218 template <mlir::arith::CmpIPredicate pred>
219 mlir::Value genBitwiseCompare(mlir::Type resultType,
227 template <mlir::arith::CmpIPredicate pred>
235 template <const
char *fctName,
int extent>
243 mlir::Value genErfcScaled(mlir::Type resultType,
249 template <mlir::arith::CmpIPredicate pred>
269 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
271 mlir::ArrayRef<fir::ExtendedValue> args);
275 template <Extremum, ExtremumBehavior>
279 mlir::Value genFraction(mlir::Type resultType,
280 mlir::ArrayRef<mlir::Value> args);
281 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
283 mlir::ArrayRef<fir::ExtendedValue> args);
285 mlir::ArrayRef<fir::ExtendedValue> args);
288 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
289 mlir::Value genGetPID(mlir::Type resultType,
291 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
293 mlir::Value genGetGID(mlir::Type resultType,
295 mlir::Value genGetUID(mlir::Type resultType,
311 template <
bool isGet,
bool isModes>
320 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
321 template <
bool isMax,
bool isNum,
bool isMag>
323 template <mlir::arith::CmpFPredicate pred>
324 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
329 template <
bool isFlag>
333 template <mlir::arith::CmpFPredicate pred>
334 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
345 template <mlir::arith::CmpIPredicate pred>
355 template <Fortran::runtime::io::Iostat value>
367 template <
typename Shift>
384 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
385 template <NearestProc>
393 template <
typename OpTy>
411 mlir::ArrayRef<fir::ExtendedValue>);
414 mlir::Value genRRSpacing(mlir::Type resultType,
423 mlir::ArrayRef<fir::ExtendedValue>);
429 mlir::Value genSetExponent(mlir::Type resultType,
433 template <
typename Shift>
441 mlir::Value genSpacing(mlir::Type resultType,
455 mlir::ArrayRef<fir::ExtendedValue> args);
483 template <mlir::NVVM::VoteSyncKind kind>
496 template <
typename FN,
typename FD>
500 template <
typename FN,
typename FD,
typename FC>
503 llvm::StringRef errMsg,
504 mlir::Type resultType,
507 template <
typename FN,
typename FD>
509 mlir::Type resultType,
517 mlir::Value
genQNan(mlir::Type resultType);
522 using ExtendedGenerator =
decltype(&IntrinsicLibrary::genLenTrim);
523 using SubroutineGenerator =
decltype(&IntrinsicLibrary::genDateAndTime);
535 template <
typename GeneratorType>
537 mlir::Type resultType,
539 template <
typename GeneratorType>
541 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
542 std::optional<mlir::Type> resultType,
545 template <
typename GeneratorType>
546 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
548 bool loadRefArguments =
false);
551 template <
typename GeneratorType>
553 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
558 mlir::Type resultType,
561 mlir::Type resultType,
564 mlir::Type resultType,
577 mlir::FunctionType signature);
581 mlir::Type resultType,
582 llvm::StringRef errMsg);
584 void setResultMustBeFreed() { resultMustBeFreed =
true; }
588 bool resultMustBeFreed =
false;
593 const char *name =
nullptr;
595 bool handleDynamicOptional =
false;
602 constexpr bool hasDefaultRules()
const {
return args[0].name ==
nullptr; }
609 IntrinsicLibrary::Generator generator;
612 bool isElemental =
true;
620 using Key = std::string_view;
622 constexpr operator Key()
const {
return key; }
626 llvm::StringRef symbol;
627 fir::runtime::FuncTypeBuilderFunc typeGenerator;
638 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
642 using Key = std::string_view;
644 constexpr operator Key()
const {
return key; }
649 llvm::StringRef runtimeFunc;
650 FuncTypeBuilderFunc typeGenerator;
656 MathGeneratorTy funcGenerator;
660enum class ParamTypeId {
672static int getVecLen(mlir::Type eleTy) {
673 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
674 mlir::isa<mlir::FloatType>(eleTy)) &&
675 "unsupported vector element type");
676 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
679template <ParamTypeId t,
int k>
682 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
684 "Unsupported integer kind");
685 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
687 "Unsupported real kind");
688 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
689 k == 8 || k == 10 || k == 16,
690 "Unsupported complex kind");
692 static const ParamTypeId ty = t;
693 static const int kind = k;
718static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
720 ParamTypeId typeId,
int kind) {
724 case ParamTypeId::Void:
725 llvm::report_fatal_error(
"can not get type of void");
727 case ParamTypeId::Address:
729 assert(bits != 0 &&
"failed to convert address kind to integer bitsize");
730 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
732 case ParamTypeId::Integer:
733 case ParamTypeId::IntegerVector:
735 assert(bits != 0 &&
"failed to convert kind to integer bitsize");
736 r = mlir::IntegerType::get(context, bits);
738 case ParamTypeId::UnsignedVector:
740 assert(bits != 0 &&
"failed to convert kind to unsigned bitsize");
741 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
743 case ParamTypeId::Real:
744 case ParamTypeId::RealVector:
747 case ParamTypeId::Complex:
748 r = mlir::ComplexType::get(builder.
getRealType(kind));
753 case ParamTypeId::Void:
754 case ParamTypeId::Address:
755 case ParamTypeId::Integer:
756 case ParamTypeId::Real:
757 case ParamTypeId::Complex:
759 case ParamTypeId::IntegerVector:
760 case ParamTypeId::UnsignedVector:
761 case ParamTypeId::RealVector:
763 r = fir::VectorType::get(getVecLen(r), r);
770template <
typename TyR,
typename... ArgTys>
771static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
772 fir::FirOpBuilder &builder) {
773 llvm::SmallVector<ParamTypeId> argTys = {ArgTys::ty...};
774 llvm::SmallVector<int> argKinds = {ArgTys::kind...};
775 llvm::SmallVector<mlir::Type> argTypes;
777 for (
size_t i = 0; i < argTys.size(); ++i) {
778 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
781 if (TyR::ty == ParamTypeId::Void)
782 return mlir::FunctionType::get(context, argTypes, {});
784 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
785 return mlir::FunctionType::get(context, argTypes, {resType});
789struct IntrinsicHandlerEntry {
790 using RuntimeGeneratorRange =
791 std::pair<const MathOperation *, const MathOperation *>;
793 assert(handler &&
"handler must not be nullptr");
795 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
797 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
803static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
805 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
806 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
807 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
813static inline llvm::SmallVector<mlir::Value, 4>
814getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
815 llvm::SmallVector<mlir::Value, 4> baseVec;
816 for (
auto arg : args)
817 baseVec.push_back(
getBase(arg));
821static inline llvm::SmallVector<mlir::Type, 4>
822getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
823 llvm::SmallVector<mlir::Type, 4> typeVec;
824 for (
auto arg : args)
825 typeVec.push_back(arg.getType());
829mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
831 mlir::FunctionType libFuncType,
832 llvm::ArrayRef<mlir::Value> args);
835mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
837 mlir::FunctionType mathLibFuncType,
838 llvm::ArrayRef<mlir::Value> args);
841mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
843 mlir::FunctionType mathLibFuncType,
844 llvm::ArrayRef<mlir::Value> args);
846mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
849 mlir::FunctionType libFuncType,
850 llvm::ArrayRef<mlir::Value> args);
854std::optional<IntrinsicHandlerEntry>
856 std::optional<mlir::Type> resultType);
879 llvm::StringRef name,
880 mlir::FunctionType signature);
889mlir::Value
genMax(fir::FirOpBuilder &, mlir::Location,
890 llvm::ArrayRef<mlir::Value> args);
893mlir::Value
genMin(fir::FirOpBuilder &, mlir::Location,
894 llvm::ArrayRef<mlir::Value> args);
898mlir::Value
genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
899 mlir::Type resultType, mlir::Value x, mlir::Value y);
903mlir::Value
genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
904 mlir::Value x, mlir::Value y);
Definition AbstractConverter.h:85
Definition BoxValue.h:478
Definition FIRBuilder.h:55
const fir::KindMapping & getKindMap()
Get a reference to the kind map.
Definition FIRBuilder.h:122
mlir::Type getRealType(int kind)
Get the mlir float type that implements Fortran REAL(kind).
Definition FIRBuilder.cpp:118
Bitsize getIntegerBitsize(KindTy kind) const
Get the size in bits of !fir.int<kind>
Definition KindMapping.cpp:283
Definition BoxValue.h:360
Definition AbstractConverter.h:34
std::optional< IntrinsicHandlerEntry > lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName, std::optional< mlir::Type > resultType)
Definition IntrinsicCall.cpp:2116
Extremum
Enums used to templatize and share lowering of MIN and MAX.
Definition IntrinsicCall.h:53
const IntrinsicArgumentLoweringRules * getIntrinsicArgumentLowering(llvm::StringRef intrinsicName)
Definition IntrinsicCall.cpp:9659
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:9713
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9726
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9721
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition IntrinsicCall.cpp:78
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition IntrinsicCall.cpp:2138
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition IntrinsicCall.cpp:9684
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:9747
LowerIntrinsicArgAs
Definition IntrinsicCall.h:97
@ Addr
Definition IntrinsicCall.h:102
@ Inquired
Definition IntrinsicCall.h:108
@ Box
Lower argument to a box.
Definition IntrinsicCall.h:104
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition IntrinsicCall.h:99
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:9697
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:9705
Define how a given intrinsic argument must be lowered.
Definition IntrinsicCall.h:112
bool handleDynamicOptional
Value:
Definition IntrinsicCall.h:124
This is shared by intrinsics and intrinsic module procedures.
Definition IntrinsicCall.h:599
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition IntrinsicCall.h:601
Definition IntrinsicCall.h:592
Entry into the tables describing how an intrinsic must be lowered.
Definition IntrinsicCall.h:789
Definition IntrinsicCall.h:607
bool outline
Definition IntrinsicCall.h:615
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition IntrinsicCall.cpp:2644
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:2150
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:4822
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition IntrinsicCall.cpp:2334
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition IntrinsicCall.h:525
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:2543
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2715
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition IntrinsicCall.cpp:5035
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2723
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2737
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:9568
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:2678
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition IntrinsicCall.h:521
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition IntrinsicCall.cpp:3581
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition IntrinsicCall.cpp:3574
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition IntrinsicCall.cpp:5042
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:2349
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:9487
Definition IntrinsicCall.h:630
Definition IntrinsicCall.h:680
Definition IntrinsicCall.h:618