9#ifndef FORTRAN_LOWER_INTRINSICCALL_H
10#define FORTRAN_LOWER_INTRINSICCALL_H
12#include "flang/Optimizer/Builder/BoxValue.h"
13#include "flang/Optimizer/Builder/FIRBuilder.h"
14#include "flang/Optimizer/Builder/Runtime/Character.h"
15#include "flang/Optimizer/Builder/Runtime/Numeric.h"
17#include "flang/Runtime/iostat-consts.h"
18#include "mlir/Dialect/Complex/IR/Complex.h"
19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
24class StatementContext;
40std::pair<fir::ExtendedValue, bool>
42 std::optional<mlir::Type> resultType,
49std::pair<fir::ExtendedValue, bool>
51 const IntrinsicHandlerEntry &,
52 std::optional<mlir::Type> resultType,
54 IntrinsicLoweringOptions options = {});
98struct IntrinsicLibrary {
103 : builder{builder}, loc{loc}, options{options} {}
104 IntrinsicLibrary() =
delete;
105 IntrinsicLibrary(
const IntrinsicLibrary &) =
delete;
110 std::pair<fir::ExtendedValue, bool>
111 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
124 using RuntimeCallGenerator = std::function<mlir::Value(
127 getRuntimeCallGenerator(llvm::StringRef name,
128 mlir::FunctionType soughtFuncType);
139 mlir::Value, mlir::Value)>
161 template <mlir::arith::CmpIPredicate pred>
162 mlir::Value genBitwiseCompare(mlir::Type resultType,
170 template <mlir::arith::CmpIPredicate pred>
184 mlir::Value genErfcScaled(mlir::Type resultType,
191 template <mlir::arith::CmpIPredicate pred>
211 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
213 mlir::ArrayRef<fir::ExtendedValue> args);
218 template <
bool isMax>
224 mlir::Value genFraction(mlir::Type resultType,
225 mlir::ArrayRef<mlir::Value> args);
226 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
228 mlir::ArrayRef<fir::ExtendedValue> args);
230 mlir::ArrayRef<fir::ExtendedValue> args);
233 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
234 mlir::Value genGetPID(mlir::Type resultType,
236 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
237 void genGetarg(mlir::ArrayRef<fir::ExtendedValue> args);
239 mlir::Value genGetGID(mlir::Type resultType,
242 mlir::Value genGetUID(mlir::Type resultType,
259 template <
bool isGet,
bool isModes>
268 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
269 template <
bool isMax,
bool isNum,
bool isMag>
271 template <mlir::arith::CmpFPredicate pred>
272 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
277 template <
bool isFlag>
281 template <mlir::arith::CmpFPredicate pred>
282 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
293 template <mlir::arith::CmpIPredicate pred>
307 template <Fortran::runtime::io::Iostat value>
321 template <
typename Shift>
336 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
337 template <NearestProc>
363 mlir::ArrayRef<fir::ExtendedValue>);
366 mlir::Value genRRSpacing(mlir::Type resultType,
376 mlir::ArrayRef<fir::ExtendedValue>);
382 mlir::Value genSetExponent(mlir::Type resultType,
386 template <
typename Shift>
395 mlir::Value genSpacing(mlir::Type resultType,
405 mlir::ArrayRef<fir::ExtendedValue> args);
439 template <
typename FN,
typename FD>
443 template <
typename FN,
typename FD,
typename FC>
446 llvm::StringRef errMsg,
447 mlir::Type resultType,
450 template <
typename FN,
typename FD>
452 mlir::Type resultType,
460 mlir::Value
genQNan(mlir::Type resultType);
465 using ExtendedGenerator =
decltype(&IntrinsicLibrary::genLenTrim);
466 using SubroutineGenerator =
decltype(&IntrinsicLibrary::genDateAndTime);
478 template <
typename GeneratorType>
480 mlir::Type resultType,
482 template <
typename GeneratorType>
484 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
485 std::optional<mlir::Type> resultType,
488 template <
typename GeneratorType>
489 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
491 bool loadRefArguments =
false);
494 template <
typename GeneratorType>
496 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
501 mlir::Type resultType,
504 mlir::Type resultType,
507 mlir::Type resultType,
520 mlir::FunctionType signature);
524 mlir::Type resultType,
525 llvm::StringRef errMsg);
527 void setResultMustBeFreed() { resultMustBeFreed =
true; }
531 bool resultMustBeFreed =
false;
536 const char *name =
nullptr;
538 bool handleDynamicOptional =
false;
545 constexpr bool hasDefaultRules()
const {
return args[0].name ==
nullptr; }
552 IntrinsicLibrary::Generator generator;
555 bool isElemental =
true;
563 using Key = std::string_view;
565 constexpr operator Key()
const {
return key; }
569 llvm::StringRef symbol;
570 fir::runtime::FuncTypeBuilderFunc typeGenerator;
581 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
585 using Key = std::string_view;
587 constexpr operator Key()
const {
return key; }
592 llvm::StringRef runtimeFunc;
593 FuncTypeBuilderFunc typeGenerator;
599 MathGeneratorTy funcGenerator;
603enum class ParamTypeId {
615static int getVecLen(mlir::Type eleTy) {
616 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
617 mlir::isa<mlir::FloatType>(eleTy)) &&
618 "unsupported vector element type");
619 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
622template <ParamTypeId t,
int k>
625 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
627 "Unsupported integer kind");
628 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
630 "Unsupported real kind");
631 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
632 k == 8 || k == 10 || k == 16,
633 "Unsupported complex kind");
635 static const ParamTypeId ty = t;
636 static const int kind = k;
661static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
663 ParamTypeId typeId,
int kind) {
667 case ParamTypeId::Void:
668 llvm::report_fatal_error(
"can not get type of void");
670 case ParamTypeId::Address:
672 assert(bits != 0 &&
"failed to convert address kind to integer bitsize");
673 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
675 case ParamTypeId::Integer:
676 case ParamTypeId::IntegerVector:
678 assert(bits != 0 &&
"failed to convert kind to integer bitsize");
679 r = mlir::IntegerType::get(context, bits);
681 case ParamTypeId::UnsignedVector:
683 assert(bits != 0 &&
"failed to convert kind to unsigned bitsize");
684 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
686 case ParamTypeId::Real:
687 case ParamTypeId::RealVector:
690 case ParamTypeId::Complex:
691 r = mlir::ComplexType::get(builder.
getRealType(kind));
696 case ParamTypeId::Void:
697 case ParamTypeId::Address:
698 case ParamTypeId::Integer:
699 case ParamTypeId::Real:
700 case ParamTypeId::Complex:
702 case ParamTypeId::IntegerVector:
703 case ParamTypeId::UnsignedVector:
704 case ParamTypeId::RealVector:
706 r = fir::VectorType::get(getVecLen(r), r);
713template <
typename TyR,
typename... ArgTys>
714static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
715 fir::FirOpBuilder &builder) {
716 llvm::SmallVector<ParamTypeId> argTys = {ArgTys::ty...};
717 llvm::SmallVector<int> argKinds = {ArgTys::kind...};
718 llvm::SmallVector<mlir::Type> argTypes;
720 for (
size_t i = 0; i < argTys.size(); ++i) {
721 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
724 if (TyR::ty == ParamTypeId::Void)
725 return mlir::FunctionType::get(context, argTypes, {});
727 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
728 return mlir::FunctionType::get(context, argTypes, {resType});
732struct IntrinsicHandlerEntry {
733 using RuntimeGeneratorRange =
734 std::pair<const MathOperation *, const MathOperation *>;
736 assert(handler &&
"handler must not be nullptr");
738 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
740 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
746static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
748 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
749 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
750 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
756static inline llvm::SmallVector<mlir::Value, 4>
757getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
758 llvm::SmallVector<mlir::Value, 4> baseVec;
759 for (
auto arg : args)
760 baseVec.push_back(
getBase(arg));
764static inline llvm::SmallVector<mlir::Type, 4>
765getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
766 llvm::SmallVector<mlir::Type, 4> typeVec;
767 for (
auto arg : args)
768 typeVec.push_back(arg.getType());
772mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
774 mlir::FunctionType libFuncType,
775 llvm::ArrayRef<mlir::Value> args);
778mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
780 mlir::FunctionType mathLibFuncType,
781 llvm::ArrayRef<mlir::Value> args);
784mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
786 mlir::FunctionType mathLibFuncType,
787 llvm::ArrayRef<mlir::Value> args);
789mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
792 mlir::FunctionType libFuncType,
793 llvm::ArrayRef<mlir::Value> args);
797std::optional<IntrinsicHandlerEntry>
799 std::optional<mlir::Type> resultType,
800 bool isBindcCall =
false);
823 llvm::StringRef name,
824 mlir::FunctionType signature);
833mlir::Value
genMax(fir::FirOpBuilder &, mlir::Location,
834 llvm::ArrayRef<mlir::Value> args);
837mlir::Value
genMin(fir::FirOpBuilder &, mlir::Location,
838 llvm::ArrayRef<mlir::Value> args);
842mlir::Value
genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
843 mlir::Type resultType, mlir::Value x, mlir::Value y);
847mlir::Value
genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
848 mlir::Value x, mlir::Value y);
850template <std::
size_t N>
855 for (
const auto &x : array) {
857 isSorted &= std::string_view{lastSeen->name} < std::string_view{x.name};
Definition BoxValue.h:475
Definition FIRBuilder.h:59
const fir::KindMapping & getKindMap()
Get a reference to the kind map.
Definition FIRBuilder.h:126
mlir::Type getRealType(int kind)
Get the mlir float type that implements Fortran REAL(kind).
Definition FIRBuilder.cpp:122
Bitsize getIntegerBitsize(KindTy kind) const
Get the size in bits of !fir.int<kind>
Definition KindMapping.cpp:283
Definition BoxValue.h:362
Definition AbstractConverter.h:37
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > args, IntrinsicLoweringOptions options={})
Definition IntrinsicCall.cpp:9430
const IntrinsicArgumentLoweringRules * getIntrinsicArgumentLowering(llvm::StringRef intrinsicName)
Definition IntrinsicCall.cpp:9385
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:9445
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9457
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9452
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition IntrinsicCall.cpp:91
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition IntrinsicCall.cpp:1958
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition IntrinsicCall.cpp:9417
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:9478
LowerIntrinsicArgAs
Definition IntrinsicCall.h:58
@ Addr
Definition IntrinsicCall.h:63
@ Inquired
Definition IntrinsicCall.h:69
@ Box
Lower argument to a box.
Definition IntrinsicCall.h:65
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition IntrinsicCall.h:60
std::optional< IntrinsicHandlerEntry > lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName, std::optional< mlir::Type > resultType, bool isBindcCall=false)
Definition IntrinsicCall.cpp:1924
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:9438
Define how a given intrinsic argument must be lowered.
Definition IntrinsicCall.h:73
bool handleDynamicOptional
Value:
Definition IntrinsicCall.h:85
This is shared by intrinsics and intrinsic module procedures.
Definition IntrinsicCall.h:542
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition IntrinsicCall.h:544
Definition IntrinsicCall.h:535
Entry into the tables describing how an intrinsic must be lowered.
Definition IntrinsicCall.h:732
Definition IntrinsicCall.h:550
bool outline
Definition IntrinsicCall.h:558
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition IntrinsicCall.cpp:2465
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:1970
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:4563
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition IntrinsicCall.cpp:2155
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition IntrinsicCall.h:468
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:2364
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2536
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition IntrinsicCall.cpp:4785
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2544
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2558
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:9297
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:2499
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition IntrinsicCall.h:464
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition IntrinsicCall.cpp:3203
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition IntrinsicCall.cpp:3196
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition IntrinsicCall.cpp:4792
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:2170
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:9216
Options controlling intrinsic lowering that depend on front-end state.
Definition IntrinsicCall.h:28
bool noPPCNativeVecElemOrder
Whether to avoid using the native vector element order on PPC targets.
Definition IntrinsicCall.h:32
bool coarrayEnabled
Whether multi-image (coarray) features are enabled (e.g. via -fcoarray).
Definition IntrinsicCall.h:30
Definition IntrinsicCall.h:573
Definition IntrinsicCall.h:623
Definition IntrinsicCall.h:561