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;
35std::pair<fir::ExtendedValue, bool>
37 std::optional<mlir::Type> resultType,
38 llvm::ArrayRef<fir::ExtendedValue> args,
39 Fortran::lower::AbstractConverter *converter =
nullptr);
44std::pair<fir::ExtendedValue, bool>
47 std::optional<mlir::Type> resultType,
48 llvm::ArrayRef<fir::ExtendedValue> args,
49 Fortran::lower::AbstractConverter *converter =
nullptr);
57enum class ExtremumBehavior {
136struct IntrinsicLibrary {
139 explicit IntrinsicLibrary(
142 : builder{builder}, loc{loc}, converter{converter} {}
143 IntrinsicLibrary() =
delete;
144 IntrinsicLibrary(
const IntrinsicLibrary &) =
delete;
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);
178 mlir::Value, mlir::Value)>
200 template <mlir::arith::CmpIPredicate pred>
201 mlir::Value genBitwiseCompare(mlir::Type resultType,
209 template <mlir::arith::CmpIPredicate pred>
222 mlir::Value genErfcScaled(mlir::Type resultType,
228 template <mlir::arith::CmpIPredicate pred>
248 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
250 mlir::ArrayRef<fir::ExtendedValue> args);
254 template <Extremum, ExtremumBehavior>
257 mlir::Value genFraction(mlir::Type resultType,
258 mlir::ArrayRef<mlir::Value> args);
259 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
261 mlir::ArrayRef<fir::ExtendedValue> args);
263 mlir::ArrayRef<fir::ExtendedValue> args);
266 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
267 mlir::Value genGetPID(mlir::Type resultType,
269 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
271 mlir::Value genGetGID(mlir::Type resultType,
273 mlir::Value genGetUID(mlir::Type resultType,
289 template <
bool isGet,
bool isModes>
298 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
299 template <
bool isMax,
bool isNum,
bool isMag>
301 template <mlir::arith::CmpFPredicate pred>
302 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
307 template <
bool isFlag>
311 template <mlir::arith::CmpFPredicate pred>
312 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
323 template <mlir::arith::CmpIPredicate pred>
333 template <Fortran::runtime::io::Iostat value>
345 template <
typename Shift>
360 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
361 template <NearestProc>
385 mlir::ArrayRef<fir::ExtendedValue>);
388 mlir::Value genRRSpacing(mlir::Type resultType,
397 mlir::ArrayRef<fir::ExtendedValue>);
403 mlir::Value genSetExponent(mlir::Type resultType,
407 template <
typename Shift>
415 mlir::Value genSpacing(mlir::Type resultType,
424 mlir::ArrayRef<fir::ExtendedValue> args);
453 template <
typename FN,
typename FD>
457 template <
typename FN,
typename FD,
typename FC>
460 llvm::StringRef errMsg,
461 mlir::Type resultType,
464 template <
typename FN,
typename FD>
466 mlir::Type resultType,
474 mlir::Value
genQNan(mlir::Type resultType);
479 using ExtendedGenerator =
decltype(&IntrinsicLibrary::genLenTrim);
480 using SubroutineGenerator =
decltype(&IntrinsicLibrary::genDateAndTime);
492 template <
typename GeneratorType>
494 mlir::Type resultType,
496 template <
typename GeneratorType>
498 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
499 std::optional<mlir::Type> resultType,
502 template <
typename GeneratorType>
503 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
505 bool loadRefArguments =
false);
508 template <
typename GeneratorType>
510 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
515 mlir::Type resultType,
518 mlir::Type resultType,
521 mlir::Type resultType,
534 mlir::FunctionType signature);
538 mlir::Type resultType,
539 llvm::StringRef errMsg);
541 void setResultMustBeFreed() { resultMustBeFreed =
true; }
545 bool resultMustBeFreed =
false;
550 const char *name =
nullptr;
552 bool handleDynamicOptional =
false;
559 constexpr bool hasDefaultRules()
const {
return args[0].name ==
nullptr; }
566 IntrinsicLibrary::Generator generator;
569 bool isElemental =
true;
577 using Key = std::string_view;
579 constexpr operator Key()
const {
return key; }
583 llvm::StringRef symbol;
584 fir::runtime::FuncTypeBuilderFunc typeGenerator;
595 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
599 using Key = std::string_view;
601 constexpr operator Key()
const {
return key; }
606 llvm::StringRef runtimeFunc;
607 FuncTypeBuilderFunc typeGenerator;
613 MathGeneratorTy funcGenerator;
617enum class ParamTypeId {
629static int getVecLen(mlir::Type eleTy) {
630 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
631 mlir::isa<mlir::FloatType>(eleTy)) &&
632 "unsupported vector element type");
633 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
636template <ParamTypeId t,
int k>
639 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
641 "Unsupported integer kind");
642 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
644 "Unsupported real kind");
645 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
646 k == 8 || k == 10 || k == 16,
647 "Unsupported complex kind");
649 static const ParamTypeId ty = t;
650 static const int kind = k;
675static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
677 ParamTypeId typeId,
int kind) {
681 case ParamTypeId::Void:
682 llvm::report_fatal_error(
"can not get type of void");
684 case ParamTypeId::Address:
686 assert(bits != 0 &&
"failed to convert address kind to integer bitsize");
687 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
689 case ParamTypeId::Integer:
690 case ParamTypeId::IntegerVector:
692 assert(bits != 0 &&
"failed to convert kind to integer bitsize");
693 r = mlir::IntegerType::get(context, bits);
695 case ParamTypeId::UnsignedVector:
697 assert(bits != 0 &&
"failed to convert kind to unsigned bitsize");
698 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
700 case ParamTypeId::Real:
701 case ParamTypeId::RealVector:
704 case ParamTypeId::Complex:
705 r = mlir::ComplexType::get(builder.
getRealType(kind));
710 case ParamTypeId::Void:
711 case ParamTypeId::Address:
712 case ParamTypeId::Integer:
713 case ParamTypeId::Real:
714 case ParamTypeId::Complex:
716 case ParamTypeId::IntegerVector:
717 case ParamTypeId::UnsignedVector:
718 case ParamTypeId::RealVector:
720 r = fir::VectorType::get(getVecLen(r), r);
727template <
typename TyR,
typename... ArgTys>
728static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
729 fir::FirOpBuilder &builder) {
730 llvm::SmallVector<ParamTypeId> argTys = {ArgTys::ty...};
731 llvm::SmallVector<int> argKinds = {ArgTys::kind...};
732 llvm::SmallVector<mlir::Type> argTypes;
734 for (
size_t i = 0; i < argTys.size(); ++i) {
735 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
738 if (TyR::ty == ParamTypeId::Void)
739 return mlir::FunctionType::get(context, argTypes, {});
741 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
742 return mlir::FunctionType::get(context, argTypes, {resType});
746struct IntrinsicHandlerEntry {
747 using RuntimeGeneratorRange =
748 std::pair<const MathOperation *, const MathOperation *>;
750 assert(handler &&
"handler must not be nullptr");
752 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
754 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
760static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
762 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
763 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
764 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
770static inline llvm::SmallVector<mlir::Value, 4>
771getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
772 llvm::SmallVector<mlir::Value, 4> baseVec;
773 for (
auto arg : args)
774 baseVec.push_back(
getBase(arg));
778static inline llvm::SmallVector<mlir::Type, 4>
779getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
780 llvm::SmallVector<mlir::Type, 4> typeVec;
781 for (
auto arg : args)
782 typeVec.push_back(arg.getType());
786mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
788 mlir::FunctionType libFuncType,
789 llvm::ArrayRef<mlir::Value> args);
792mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
794 mlir::FunctionType mathLibFuncType,
795 llvm::ArrayRef<mlir::Value> args);
798mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
800 mlir::FunctionType mathLibFuncType,
801 llvm::ArrayRef<mlir::Value> args);
803mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
806 mlir::FunctionType libFuncType,
807 llvm::ArrayRef<mlir::Value> args);
811std::optional<IntrinsicHandlerEntry>
813 std::optional<mlir::Type> resultType);
836 llvm::StringRef name,
837 mlir::FunctionType signature);
846mlir::Value
genMax(fir::FirOpBuilder &, mlir::Location,
847 llvm::ArrayRef<mlir::Value> args);
850mlir::Value
genMin(fir::FirOpBuilder &, mlir::Location,
851 llvm::ArrayRef<mlir::Value> args);
855mlir::Value
genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
856 mlir::Type resultType, mlir::Value x, mlir::Value y);
860mlir::Value
genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
861 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:1839
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:8737
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:8794
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:8807
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:8802
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition IntrinsicCall.cpp:79
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition IntrinsicCall.cpp:1864
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition IntrinsicCall.cpp:8765
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:8828
LowerIntrinsicArgAs
Definition IntrinsicCall.h:96
@ Addr
Definition IntrinsicCall.h:101
@ Inquired
Definition IntrinsicCall.h:107
@ Box
Lower argument to a box.
Definition IntrinsicCall.h:103
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition IntrinsicCall.h:98
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:8778
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:8786
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:556
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition IntrinsicCall.h:558
Definition IntrinsicCall.h:549
Entry into the tables describing how an intrinsic must be lowered.
Definition IntrinsicCall.h:746
Definition IntrinsicCall.h:564
bool outline
Definition IntrinsicCall.h:572
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition IntrinsicCall.cpp:2371
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:1876
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:4279
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition IntrinsicCall.cpp:2061
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition IntrinsicCall.h:482
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:2270
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2442
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition IntrinsicCall.cpp:4492
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2450
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2464
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:8646
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:2405
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition IntrinsicCall.h:478
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition IntrinsicCall.cpp:3112
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition IntrinsicCall.cpp:3105
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition IntrinsicCall.cpp:4499
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:2076
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:8565
Definition IntrinsicCall.h:587
Definition IntrinsicCall.h:637
Definition IntrinsicCall.h:575