FLANG
IntrinsicCall.h
1//===-- Builder/IntrinsicCall.h -- lowering of intrinsics -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_LOWER_INTRINSICCALL_H
10#define FORTRAN_LOWER_INTRINSICCALL_H
11
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/entry-names.h"
18#include "flang/Runtime/iostat-consts.h"
19#include "mlir/Dialect/Complex/IR/Complex.h"
20#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
21#include "mlir/Dialect/Math/IR/Math.h"
22#include <optional>
23
24namespace Fortran {
25namespace lower {
26// TODO: remove the usage of AbstractConverter to avoid making IntrinsicCall.cpp
27// depend upon Lower/Evaluate and use a data structure to pass options to
28// IntrinsicLibrary.
30} // namespace lower
31} // namespace Fortran
32
33namespace fir {
34
35class StatementContext;
37
43std::pair<fir::ExtendedValue, bool>
44genIntrinsicCall(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name,
45 std::optional<mlir::Type> resultType,
46 llvm::ArrayRef<fir::ExtendedValue> args,
47 Fortran::lower::AbstractConverter *converter = nullptr);
48
52std::pair<fir::ExtendedValue, bool>
53genIntrinsicCall(fir::FirOpBuilder &, mlir::Location,
55 std::optional<mlir::Type> resultType,
56 llvm::ArrayRef<fir::ExtendedValue> args,
57 Fortran::lower::AbstractConverter *converter = nullptr);
58
74
77 LowerIntrinsicArgAs lowerAs;
79 // - Numerical: 0
80 // - Logical : false
81 // - Derived/character: not possible. Need custom intrinsic lowering.
82 // Addr:
83 // - nullptr
84 // Box:
85 // - absent box
86 // AsInquired:
87 // - no-op
89};
90
91constexpr auto asValue = fir::LowerIntrinsicArgAs::Value;
92constexpr auto asAddr = fir::LowerIntrinsicArgAs::Addr;
93constexpr auto asBox = fir::LowerIntrinsicArgAs::Box;
94constexpr auto asInquired = fir::LowerIntrinsicArgAs::Inquired;
95
99
100// TODO error handling -> return a code or directly emit messages ?
101struct IntrinsicLibrary {
102
103 // Constructors.
104 explicit IntrinsicLibrary(
105 fir::FirOpBuilder &builder, mlir::Location loc,
106 Fortran::lower::AbstractConverter *converter = nullptr)
107 : builder{builder}, loc{loc}, converter{converter} {}
108 IntrinsicLibrary() = delete;
109 IntrinsicLibrary(const IntrinsicLibrary &) = delete;
110
114 std::pair<fir::ExtendedValue, bool>
115 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
117
125 mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type,
127
128 using RuntimeCallGenerator = std::function<mlir::Value(
130 RuntimeCallGenerator
131 getRuntimeCallGenerator(llvm::StringRef name,
132 mlir::FunctionType soughtFuncType);
133
139 mlir::Value genAbs(mlir::Type, llvm::ArrayRef<mlir::Value>);
140 mlir::Value genAcosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
141 mlir::Value genAcospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
142 template <void (*CallRuntime)(fir::FirOpBuilder &, mlir::Location loc,
143 mlir::Value, mlir::Value)>
144 fir::ExtendedValue genAdjustRtCall(mlir::Type,
146 mlir::Value genAimag(mlir::Type, llvm::ArrayRef<mlir::Value>);
147 mlir::Value genAint(mlir::Type, llvm::ArrayRef<mlir::Value>);
149 fir::ExtendedValue genAllocated(mlir::Type,
151 mlir::Value genAnint(mlir::Type, llvm::ArrayRef<mlir::Value>);
153 mlir::Value genAtanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
155 genCommandArgumentCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
156 mlir::Value genAsind(mlir::Type, llvm::ArrayRef<mlir::Value>);
157 mlir::Value genAsinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
158 fir::ExtendedValue genAssociated(mlir::Type,
160 mlir::Value genAtand(mlir::Type, llvm::ArrayRef<mlir::Value>);
161 fir::ExtendedValue genBesselJn(mlir::Type,
163 fir::ExtendedValue genBesselYn(mlir::Type,
165 template <mlir::arith::CmpIPredicate pred>
166 mlir::Value genBitwiseCompare(mlir::Type resultType,
168
169 mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
170 mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
172 fir::ExtendedValue genChdir(std::optional<mlir::Type> resultType,
174 template <mlir::arith::CmpIPredicate pred>
175 fir::ExtendedValue genCharacterCompare(mlir::Type,
177 mlir::Value genCmplx(mlir::Type, llvm::ArrayRef<mlir::Value>);
178 mlir::Value genConjg(mlir::Type, llvm::ArrayRef<mlir::Value>);
180 void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>);
187 mlir::Value genErfcScaled(mlir::Type resultType,
189 void genCFPointer(llvm::ArrayRef<fir::ExtendedValue>);
190 void genCFProcPointer(llvm::ArrayRef<fir::ExtendedValue>);
191 void genCFStrPointer(llvm::ArrayRef<fir::ExtendedValue>);
194 template <mlir::arith::CmpIPredicate pred>
195 fir::ExtendedValue genCPtrCompare(mlir::Type,
197 void genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue>);
201 mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
202 mlir::Value genCospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
203 void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
204 fir::ExtendedValue genDsecnds(mlir::Type resultType,
206 mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>);
207 fir::ExtendedValue genDotProduct(mlir::Type,
209 mlir::Value genDprod(mlir::Type, llvm::ArrayRef<mlir::Value>);
210 mlir::Value genDshiftl(mlir::Type, llvm::ArrayRef<mlir::Value>);
211 mlir::Value genDshiftr(mlir::Type, llvm::ArrayRef<mlir::Value>);
214 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
215 fir::ExtendedValue genEtime(std::optional<mlir::Type>,
216 mlir::ArrayRef<fir::ExtendedValue> args);
217 mlir::Value genTimef(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
218 mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
219 fir::ExtendedValue genExtendsTypeOf(mlir::Type,
221 template <bool isMax>
222 mlir::Value genExtremum(mlir::Type, llvm::ArrayRef<mlir::Value>);
223 fir::ExtendedValue genFCString(mlir::Type,
225 mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
227 mlir::Value genFraction(mlir::Type resultType,
228 mlir::ArrayRef<mlir::Value> args);
229 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
230 fir::ExtendedValue genFseek(std::optional<mlir::Type>,
231 mlir::ArrayRef<fir::ExtendedValue> args);
232 fir::ExtendedValue genFtell(std::optional<mlir::Type>,
233 mlir::ArrayRef<fir::ExtendedValue> args);
234 fir::ExtendedValue genGetCwd(std::optional<mlir::Type> resultType,
236 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
237 mlir::Value genGetPID(mlir::Type resultType,
239 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
240 void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
241 mlir::Value genGetGID(mlir::Type resultType,
243 mlir::Value genGetTeam(mlir::Type, llvm::ArrayRef<mlir::Value>);
244 mlir::Value genGetUID(mlir::Type resultType,
246 fir::ExtendedValue genHostnm(std::optional<mlir::Type> resultType,
249 mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
251 mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
252 mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
253 mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
256 mlir::Value genIeeeClass(mlir::Type, llvm::ArrayRef<mlir::Value>);
257 mlir::Value genIeeeCopySign(mlir::Type, llvm::ArrayRef<mlir::Value>);
258 void genIeeeGetFlag(llvm::ArrayRef<fir::ExtendedValue>);
259 void genIeeeGetHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
260 template <bool isGet, bool isModes>
261 void genIeeeGetOrSetModesOrStatus(llvm::ArrayRef<fir::ExtendedValue>);
262 void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
263 void genIeeeGetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
264 mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);
265 mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
266 mlir::Value genIeeeIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
267 mlir::Value genIeeeIsNegative(mlir::Type, llvm::ArrayRef<mlir::Value>);
268 mlir::Value genIeeeIsNormal(mlir::Type, llvm::ArrayRef<mlir::Value>);
269 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
270 template <bool isMax, bool isNum, bool isMag>
271 mlir::Value genIeeeMaxMin(mlir::Type, llvm::ArrayRef<mlir::Value>);
272 template <mlir::arith::CmpFPredicate pred>
273 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
275 mlir::Value genIeeeReal(mlir::Type, llvm::ArrayRef<mlir::Value>);
276 mlir::Value genIeeeRem(mlir::Type, llvm::ArrayRef<mlir::Value>);
277 mlir::Value genIeeeRint(mlir::Type, llvm::ArrayRef<mlir::Value>);
278 template <bool isFlag>
279 void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
280 void genIeeeSetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
281 void genIeeeSetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
282 template <mlir::arith::CmpFPredicate pred>
283 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
285 mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
286 fir::ExtendedValue genIeeeSupportFlag(mlir::Type,
288 fir::ExtendedValue genIeeeSupportHalting(mlir::Type,
290 fir::ExtendedValue genIeeeSupportRounding(mlir::Type,
292 fir::ExtendedValue genIeeeSupportStandard(mlir::Type,
294 template <mlir::arith::CmpIPredicate pred>
295 mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
296 mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
297 mlir::Value genIeeeValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
298 mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
300 mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
302 fir::ExtendedValue genIrand(mlir::Type resultType,
304 fir::ExtendedValue genIsContiguous(mlir::Type,
306 template <Fortran::runtime::io::Iostat value>
307 mlir::Value genIsIostatValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
308 mlir::Value genIsFPClass(mlir::Type, llvm::ArrayRef<mlir::Value>,
309 int fpclass);
310 mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
311 mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
313 mlir::Value genLeadz(mlir::Type, llvm::ArrayRef<mlir::Value>);
317 mlir::Value genMalloc(mlir::Type, llvm::ArrayRef<mlir::Value>);
318 template <typename Shift>
319 mlir::Value genMask(mlir::Type, llvm::ArrayRef<mlir::Value>);
321 fir::ExtendedValue genMatmulTranspose(mlir::Type,
326 mlir::Value genMergeBits(mlir::Type, llvm::ArrayRef<mlir::Value>);
329 mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
330 mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
331 void genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue>);
333 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
334 template <NearestProc>
335 mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
336 mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
338 mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
340 fir::ExtendedValue genNumImages(mlir::Type,
345 mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
346 mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
349 fir::ExtendedValue genPutenv(std::optional<mlir::Type>,
351 fir::ExtendedValue genRand(mlir::Type resultType,
353 void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
354 void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
355 void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
357 fir::ExtendedValue genReduceDim(mlir::Type,
359 fir::ExtendedValue genRename(std::optional<mlir::Type>,
360 mlir::ArrayRef<fir::ExtendedValue>);
363 mlir::Value genRRSpacing(mlir::Type resultType,
365 mlir::Value genRtc(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
366 fir::ExtendedValue genSameTypeAs(mlir::Type,
368 mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
370 fir::ExtendedValue genSecnds(mlir::Type resultType,
372 fir::ExtendedValue genSecond(std::optional<mlir::Type>,
373 mlir::ArrayRef<fir::ExtendedValue>);
374 fir::ExtendedValue genSelectedCharKind(mlir::Type,
376 mlir::Value genSelectedIntKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
377 mlir::Value genSelectedLogicalKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
378 mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
379 mlir::Value genSetExponent(mlir::Type resultType,
381 fir::ExtendedValue genShape(mlir::Type resultType,
383 template <typename Shift>
384 mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
385 mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
386 void genShowDescriptor(llvm::ArrayRef<fir::ExtendedValue>);
387 mlir::Value genSign(mlir::Type, llvm::ArrayRef<mlir::Value>);
388 mlir::Value genSind(mlir::Type, llvm::ArrayRef<mlir::Value>);
389 mlir::Value genSinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
392 mlir::Value genSpacing(mlir::Type resultType,
396 fir::ExtendedValue genStorageSize(mlir::Type,
399 void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>);
401 fir::ExtendedValue genSystem(std::optional<mlir::Type>,
402 mlir::ArrayRef<fir::ExtendedValue> args);
403 void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
404 mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
405 mlir::Value genTanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
406 fir::ExtendedValue genTeamNumber(mlir::Type,
408 mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
409 void genTokenize(llvm::ArrayRef<fir::ExtendedValue>);
410 mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
411 fir::ExtendedValue genTransfer(mlir::Type,
413 fir::ExtendedValue genTranspose(mlir::Type,
415 fir::ExtendedValue genThisImage(mlir::Type,
419 fir::ExtendedValue genUnlink(std::optional<mlir::Type> resultType,
423
427 mlir::Value genConversion(mlir::Type, llvm::ArrayRef<mlir::Value>);
428
434 template <typename FN, typename FD>
435 fir::ExtendedValue genExtremumloc(FN func, FD funcDim, llvm::StringRef errMsg,
436 mlir::Type,
438 template <typename FN, typename FD, typename FC>
440 fir::ExtendedValue genExtremumVal(FN func, FD funcDim, FC funcChar,
441 llvm::StringRef errMsg,
442 mlir::Type resultType,
445 template <typename FN, typename FD>
446 fir::ExtendedValue genReduction(FN func, FD funcDim, llvm::StringRef errMsg,
447 mlir::Type resultType,
449
452 void genRaiseExcept(int excepts, mlir::Value cond = {});
453
455 mlir::Value genQNan(mlir::Type resultType);
456
460 using ExtendedGenerator = decltype(&IntrinsicLibrary::genLenTrim);
461 using SubroutineGenerator = decltype(&IntrinsicLibrary::genDateAndTime);
463 using DualGenerator = decltype(&IntrinsicLibrary::genEtime);
464 using Generator = std::variant<ElementalGenerator, ExtendedGenerator,
465 SubroutineGenerator, DualGenerator>;
466
473 template <typename GeneratorType>
474 mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name,
475 mlir::Type resultType,
477 template <typename GeneratorType>
479 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
480 std::optional<mlir::Type> resultType,
482
483 template <typename GeneratorType>
484 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
485 mlir::FunctionType,
486 bool loadRefArguments = false);
487
489 template <typename GeneratorType>
491 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
492 llvm::ArrayRef<fir::ExtendedValue> args, bool outline);
493
495 mlir::Value invokeGenerator(ElementalGenerator generator,
496 mlir::Type resultType,
498 mlir::Value invokeGenerator(RuntimeCallGenerator generator,
499 mlir::Type resultType,
501 mlir::Value invokeGenerator(ExtendedGenerator generator,
502 mlir::Type resultType,
504 mlir::Value invokeGenerator(SubroutineGenerator generator,
506 mlir::Value invokeGenerator(DualGenerator generator,
508 mlir::Value invokeGenerator(DualGenerator generator, mlir::Type resultType,
510
513 mlir::SymbolRefAttr
514 getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name,
515 mlir::FunctionType signature);
516
519 mlir::Type resultType,
520 llvm::StringRef errMsg);
521
522 void setResultMustBeFreed() { resultMustBeFreed = true; }
523
524 fir::FirOpBuilder &builder;
525 mlir::Location loc;
526 bool resultMustBeFreed = false;
527 Fortran::lower::AbstractConverter *converter = nullptr;
528};
529
531 const char *name = nullptr;
533 bool handleDynamicOptional = false;
534};
535
540 constexpr bool hasDefaultRules() const { return args[0].name == nullptr; }
541};
542
546 const char *name;
547 IntrinsicLibrary::Generator generator;
548 // The following may be omitted in the table below.
549 fir::IntrinsicArgumentLoweringRules argLoweringRules = {};
550 bool isElemental = true;
553 bool outline = false;
554};
555
557 // llvm::StringRef comparison operator are not constexpr, so use string_view.
558 using Key = std::string_view;
559 // Needed for implicit compare with keys.
560 constexpr operator Key() const { return key; }
561 Key key; // intrinsic name
562
563 // Name of a runtime function that implements the operation.
564 llvm::StringRef symbol;
565 fir::runtime::FuncTypeBuilderFunc typeGenerator;
566};
567
569 // Callback type for generating lowering for a math operation.
570 using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
571 const MathOperation &,
572 mlir::FunctionType,
574
575 // Overrides fir::runtime::FuncTypeBuilderFunc to add FirOpBuilder argument.
576 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
578
579 // llvm::StringRef comparison operator are not constexpr, so use string_view.
580 using Key = std::string_view;
581 // Needed for implicit compare with keys.
582 constexpr operator Key() const { return key; }
583 // Intrinsic name.
584 Key key;
585
586 // Name of a runtime function that implements the operation.
587 llvm::StringRef runtimeFunc;
588 FuncTypeBuilderFunc typeGenerator;
589
590 // A callback to generate FIR for the intrinsic defined by 'key'.
591 // A callback may generate either dedicated MLIR operation(s) or
592 // a function call to a runtime function with name defined by
593 // 'runtimeFunc'.
594 MathGeneratorTy funcGenerator;
595};
596
597// Enum of most supported intrinsic argument or return types.
598enum class ParamTypeId {
599 Void,
600 Address, // pointer (to an [array of] Integers of some kind)
601 Integer,
602 Real,
603 Complex,
604 IntegerVector,
605 UnsignedVector,
606 RealVector,
607};
608
609// Helper function to get length of a 16-byte vector of element type eleTy.
610static int getVecLen(mlir::Type eleTy) {
611 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
612 mlir::isa<mlir::FloatType>(eleTy)) &&
613 "unsupported vector element type");
614 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
615}
616
617template <ParamTypeId t, int k>
618struct ParamType {
619 // Supported kinds can be checked with static asserts at compile time.
620 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
621 k == 8,
622 "Unsupported integer kind");
623 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
624 k == 16,
625 "Unsupported real kind");
626 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
627 k == 8 || k == 10 || k == 16,
628 "Unsupported complex kind");
629
630 static const ParamTypeId ty = t;
631 static const int kind = k;
632};
633
634// Namespace encapsulating type definitions for parameter types.
635namespace Ty {
637template <int k>
639template <int k>
641template <int k>
643template <int k>
645template <int k>
646using IntegerVector = ParamType<ParamTypeId::IntegerVector, k>;
647template <int k>
648using UnsignedVector = ParamType<ParamTypeId::UnsignedVector, k>;
649template <int k>
651} // namespace Ty
652
653// Helper function that generates most types that are supported for intrinsic
654// arguments and return type. Used by `genFuncType` to generate function
655// types for most of the intrinsics.
656static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
657 fir::FirOpBuilder &builder,
658 ParamTypeId typeId, int kind) {
659 mlir::Type r;
660 unsigned bits{0};
661 switch (typeId) {
662 case ParamTypeId::Void:
663 llvm::report_fatal_error("can not get type of void");
664 break;
665 case ParamTypeId::Address:
666 bits = builder.getKindMap().getIntegerBitsize(kind);
667 assert(bits != 0 && "failed to convert address kind to integer bitsize");
668 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
669 break;
670 case ParamTypeId::Integer:
671 case ParamTypeId::IntegerVector:
672 bits = builder.getKindMap().getIntegerBitsize(kind);
673 assert(bits != 0 && "failed to convert kind to integer bitsize");
674 r = mlir::IntegerType::get(context, bits);
675 break;
676 case ParamTypeId::UnsignedVector:
677 bits = builder.getKindMap().getIntegerBitsize(kind);
678 assert(bits != 0 && "failed to convert kind to unsigned bitsize");
679 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
680 break;
681 case ParamTypeId::Real:
682 case ParamTypeId::RealVector:
683 r = builder.getRealType(kind);
684 break;
685 case ParamTypeId::Complex:
686 r = mlir::ComplexType::get(builder.getRealType(kind));
687 break;
688 }
689
690 switch (typeId) {
691 case ParamTypeId::Void:
692 case ParamTypeId::Address:
693 case ParamTypeId::Integer:
694 case ParamTypeId::Real:
695 case ParamTypeId::Complex:
696 break;
697 case ParamTypeId::IntegerVector:
698 case ParamTypeId::UnsignedVector:
699 case ParamTypeId::RealVector:
700 // convert to vector type
701 r = fir::VectorType::get(getVecLen(r), r);
702 }
703 return r;
704}
705
706// Generic function type generator that supports most of the function types
707// used by intrinsics.
708template <typename TyR, typename... ArgTys>
709static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
710 fir::FirOpBuilder &builder) {
711 llvm::SmallVector<ParamTypeId> argTys = {ArgTys::ty...};
712 llvm::SmallVector<int> argKinds = {ArgTys::kind...};
713 llvm::SmallVector<mlir::Type> argTypes;
714
715 for (size_t i = 0; i < argTys.size(); ++i) {
716 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
717 }
718
719 if (TyR::ty == ParamTypeId::Void)
720 return mlir::FunctionType::get(context, argTypes, {});
721
722 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
723 return mlir::FunctionType::get(context, argTypes, {resType});
724}
725
727struct IntrinsicHandlerEntry {
728 using RuntimeGeneratorRange =
729 std::pair<const MathOperation *, const MathOperation *>;
730 IntrinsicHandlerEntry(const IntrinsicHandler *handler) : entry{handler} {
731 assert(handler && "handler must not be nullptr");
732 };
733 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
734 const IntrinsicArgumentLoweringRules *getArgumentLoweringRules() const;
735 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
736};
737
738//===----------------------------------------------------------------------===//
739// Helper functions for argument handling.
740//===----------------------------------------------------------------------===//
741static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
742 mlir::Type eleTy) {
743 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
744 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
745 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
746 return newEleTy;
747 }
748 return eleTy;
749}
750
751static inline llvm::SmallVector<mlir::Value, 4>
752getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
753 llvm::SmallVector<mlir::Value, 4> baseVec;
754 for (auto arg : args)
755 baseVec.push_back(getBase(arg));
756 return baseVec;
757}
758
759static inline llvm::SmallVector<mlir::Type, 4>
760getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
761 llvm::SmallVector<mlir::Type, 4> typeVec;
762 for (auto arg : args)
763 typeVec.push_back(arg.getType());
764 return typeVec;
765}
766
767mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
768 const MathOperation &mathOp,
769 mlir::FunctionType libFuncType,
770 llvm::ArrayRef<mlir::Value> args);
771
772template <typename T>
773mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
774 const MathOperation &mathOp,
775 mlir::FunctionType mathLibFuncType,
776 llvm::ArrayRef<mlir::Value> args);
777
778template <typename T>
779mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
780 const MathOperation &mathOp,
781 mlir::FunctionType mathLibFuncType,
782 llvm::ArrayRef<mlir::Value> args);
783
784mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
785 mlir::Location loc,
786 const MathOperation &mathOp,
787 mlir::FunctionType libFuncType,
788 llvm::ArrayRef<mlir::Value> args);
789
792std::optional<IntrinsicHandlerEntry>
793lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName,
794 std::optional<mlir::Type> resultType);
795
797void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name);
798
802getIntrinsicArgumentLowering(llvm::StringRef intrinsicName);
803
807 unsigned position);
808
810fir::ExtendedValue getAbsentIntrinsicArgument();
811
813// implementation) of an unrestricted intrinsic (defined by its signature
814// and generic name)
815mlir::SymbolRefAttr
816getUnrestrictedIntrinsicSymbolRefAttr(fir::FirOpBuilder &, mlir::Location,
817 llvm::StringRef name,
818 mlir::FunctionType signature);
819
820//===----------------------------------------------------------------------===//
821// Direct access to intrinsics that may be used by lowering outside
822// of intrinsic call lowering.
823//===----------------------------------------------------------------------===//
824
827mlir::Value genMax(fir::FirOpBuilder &, mlir::Location,
828 llvm::ArrayRef<mlir::Value> args);
829
831mlir::Value genMin(fir::FirOpBuilder &, mlir::Location,
832 llvm::ArrayRef<mlir::Value> args);
833
836mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
837 mlir::Type resultType, mlir::Value x, mlir::Value y);
838
841mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
842 mlir::Value x, mlir::Value y);
843
844} // namespace fir
845
846#endif // FORTRAN_LOWER_INTRINSICCALL_H
Definition AbstractConverter.h:87
Definition BoxValue.h:478
Definition FIRBuilder.h:56
const fir::KindMapping & getKindMap()
Get a reference to the kind map.
Definition FIRBuilder.h:123
mlir::Type getRealType(int kind)
Get the mlir float type that implements Fortran REAL(kind).
Definition FIRBuilder.cpp:119
Bitsize getIntegerBitsize(KindTy kind) const
Get the size in bits of !fir.int<kind>
Definition KindMapping.cpp:283
Definition BoxValue.h:360
Definition FIRType.h:103
Definition ParserActions.h:24
Definition bit-population-count.h:20
Definition AbstractConverter.h:37
std::optional< IntrinsicHandlerEntry > lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName, std::optional< mlir::Type > resultType)
Definition IntrinsicCall.cpp:1899
const IntrinsicArgumentLoweringRules * getIntrinsicArgumentLowering(llvm::StringRef intrinsicName)
Definition IntrinsicCall.cpp:9211
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:9267
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9279
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9274
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition IntrinsicCall.cpp:80
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition IntrinsicCall.cpp:1924
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition IntrinsicCall.cpp:9239
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:9300
LowerIntrinsicArgAs
Definition IntrinsicCall.h:61
@ Addr
Definition IntrinsicCall.h:66
@ Inquired
Definition IntrinsicCall.h:72
@ Box
Lower argument to a box.
Definition IntrinsicCall.h:68
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition IntrinsicCall.h:63
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:9252
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:9260
Define how a given intrinsic argument must be lowered.
Definition IntrinsicCall.h:76
bool handleDynamicOptional
Value:
Definition IntrinsicCall.h:88
This is shared by intrinsics and intrinsic module procedures.
Definition IntrinsicCall.h:537
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition IntrinsicCall.h:539
Definition IntrinsicCall.h:530
Entry into the tables describing how an intrinsic must be lowered.
Definition IntrinsicCall.h:727
Definition IntrinsicCall.h:545
bool outline
Definition IntrinsicCall.h:553
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition IntrinsicCall.cpp:2431
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:1936
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:4498
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition IntrinsicCall.cpp:2121
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition IntrinsicCall.h:463
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:2330
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2502
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition IntrinsicCall.cpp:4711
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2510
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2524
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:9123
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:2465
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition IntrinsicCall.h:459
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition IntrinsicCall.cpp:3172
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition IntrinsicCall.cpp:3165
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition IntrinsicCall.cpp:4718
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:2136
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:9042
Definition IntrinsicCall.h:568
Definition IntrinsicCall.h:618
Definition IntrinsicCall.h:556