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/iostat-consts.h"
18#include "mlir/Dialect/Complex/IR/Complex.h"
19#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
20#include <optional>
21
22namespace fir {
23
24class StatementContext;
26
34
40std::pair<fir::ExtendedValue, bool>
41genIntrinsicCall(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name,
42 std::optional<mlir::Type> resultType,
44 IntrinsicLoweringOptions options = {});
45
49std::pair<fir::ExtendedValue, bool>
50genIntrinsicCall(fir::FirOpBuilder &, mlir::Location,
51 const IntrinsicHandlerEntry &,
52 std::optional<mlir::Type> resultType,
54 IntrinsicLoweringOptions options = {});
55
71
74 LowerIntrinsicArgAs lowerAs;
76 // - Numerical: 0
77 // - Logical : false
78 // - Derived/character: not possible. Need custom intrinsic lowering.
79 // Addr:
80 // - nullptr
81 // Box:
82 // - absent box
83 // AsInquired:
84 // - no-op
86};
87
88constexpr auto asValue = fir::LowerIntrinsicArgAs::Value;
89constexpr auto asAddr = fir::LowerIntrinsicArgAs::Addr;
90constexpr auto asBox = fir::LowerIntrinsicArgAs::Box;
91constexpr auto asInquired = fir::LowerIntrinsicArgAs::Inquired;
92
96
97// TODO error handling -> return a code or directly emit messages ?
98struct IntrinsicLibrary {
99
100 // Constructors.
101 explicit IntrinsicLibrary(fir::FirOpBuilder &builder, mlir::Location loc,
102 IntrinsicLoweringOptions options = {})
103 : builder{builder}, loc{loc}, options{options} {}
104 IntrinsicLibrary() = delete;
105 IntrinsicLibrary(const IntrinsicLibrary &) = delete;
106
110 std::pair<fir::ExtendedValue, bool>
111 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
113
121 mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type,
123
124 using RuntimeCallGenerator = std::function<mlir::Value(
126 RuntimeCallGenerator
127 getRuntimeCallGenerator(llvm::StringRef name,
128 mlir::FunctionType soughtFuncType);
129
135 mlir::Value genAbs(mlir::Type, llvm::ArrayRef<mlir::Value>);
136 mlir::Value genAcosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
137 mlir::Value genAcospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
138 template <void (*CallRuntime)(fir::FirOpBuilder &, mlir::Location loc,
139 mlir::Value, mlir::Value)>
140 fir::ExtendedValue genAdjustRtCall(mlir::Type,
142 mlir::Value genAimag(mlir::Type, llvm::ArrayRef<mlir::Value>);
143 mlir::Value genAint(mlir::Type, llvm::ArrayRef<mlir::Value>);
145 fir::ExtendedValue genAllocated(mlir::Type,
147 mlir::Value genAnint(mlir::Type, llvm::ArrayRef<mlir::Value>);
149 mlir::Value genAtanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
151 genCommandArgumentCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
152 mlir::Value genAsind(mlir::Type, llvm::ArrayRef<mlir::Value>);
153 mlir::Value genAsinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
154 fir::ExtendedValue genAssociated(mlir::Type,
156 mlir::Value genAtand(mlir::Type, llvm::ArrayRef<mlir::Value>);
157 fir::ExtendedValue genBesselJn(mlir::Type,
159 fir::ExtendedValue genBesselYn(mlir::Type,
161 template <mlir::arith::CmpIPredicate pred>
162 mlir::Value genBitwiseCompare(mlir::Type resultType,
164
165 mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
166 mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
168 fir::ExtendedValue genChdir(std::optional<mlir::Type> resultType,
170 template <mlir::arith::CmpIPredicate pred>
171 fir::ExtendedValue genCharacterCompare(mlir::Type,
173 mlir::Value genCmplx(mlir::Type, llvm::ArrayRef<mlir::Value>);
174 mlir::Value genConjg(mlir::Type, llvm::ArrayRef<mlir::Value>);
177 void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>);
184 mlir::Value genErfcScaled(mlir::Type resultType,
186 void genCFPointer(llvm::ArrayRef<fir::ExtendedValue>);
187 void genCFProcPointer(llvm::ArrayRef<fir::ExtendedValue>);
188 void genCFStrPointer(llvm::ArrayRef<fir::ExtendedValue>);
191 template <mlir::arith::CmpIPredicate pred>
192 fir::ExtendedValue genCPtrCompare(mlir::Type,
194 void genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue>);
198 mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
199 mlir::Value genCospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
200 void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
201 fir::ExtendedValue genDsecnds(mlir::Type resultType,
203 mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>);
204 fir::ExtendedValue genDotProduct(mlir::Type,
206 mlir::Value genDprod(mlir::Type, llvm::ArrayRef<mlir::Value>);
207 mlir::Value genDshiftl(mlir::Type, llvm::ArrayRef<mlir::Value>);
208 mlir::Value genDshiftr(mlir::Type, llvm::ArrayRef<mlir::Value>);
211 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
212 fir::ExtendedValue genEtime(std::optional<mlir::Type>,
213 mlir::ArrayRef<fir::ExtendedValue> args);
214 mlir::Value genTimef(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
215 mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
216 fir::ExtendedValue genExtendsTypeOf(mlir::Type,
218 template <bool isMax>
219 mlir::Value genExtremum(mlir::Type, llvm::ArrayRef<mlir::Value>);
220 fir::ExtendedValue genFCString(mlir::Type,
222 mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
224 mlir::Value genFraction(mlir::Type resultType,
225 mlir::ArrayRef<mlir::Value> args);
226 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
227 fir::ExtendedValue genFseek(std::optional<mlir::Type>,
228 mlir::ArrayRef<fir::ExtendedValue> args);
229 fir::ExtendedValue genFtell(std::optional<mlir::Type>,
230 mlir::ArrayRef<fir::ExtendedValue> args);
231 fir::ExtendedValue genGetCwd(std::optional<mlir::Type> resultType,
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);
238 void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
239 mlir::Value genGetGID(mlir::Type resultType,
241 mlir::Value genGetTeam(mlir::Type, llvm::ArrayRef<mlir::Value>);
242 mlir::Value genGetUID(mlir::Type resultType,
244 fir::ExtendedValue genHostnm(std::optional<mlir::Type> resultType,
247 mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
250 mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
251 mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
252 mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
255 mlir::Value genIeeeClass(mlir::Type, llvm::ArrayRef<mlir::Value>);
256 mlir::Value genIeeeCopySign(mlir::Type, llvm::ArrayRef<mlir::Value>);
257 void genIeeeGetFlag(llvm::ArrayRef<fir::ExtendedValue>);
258 void genIeeeGetHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
259 template <bool isGet, bool isModes>
260 void genIeeeGetOrSetModesOrStatus(llvm::ArrayRef<fir::ExtendedValue>);
261 void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
262 void genIeeeGetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
263 mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);
264 mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
265 mlir::Value genIeeeIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
266 mlir::Value genIeeeIsNegative(mlir::Type, llvm::ArrayRef<mlir::Value>);
267 mlir::Value genIeeeIsNormal(mlir::Type, llvm::ArrayRef<mlir::Value>);
268 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
269 template <bool isMax, bool isNum, bool isMag>
270 mlir::Value genIeeeMaxMin(mlir::Type, llvm::ArrayRef<mlir::Value>);
271 template <mlir::arith::CmpFPredicate pred>
272 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
274 mlir::Value genIeeeReal(mlir::Type, llvm::ArrayRef<mlir::Value>);
275 mlir::Value genIeeeRem(mlir::Type, llvm::ArrayRef<mlir::Value>);
276 mlir::Value genIeeeRint(mlir::Type, llvm::ArrayRef<mlir::Value>);
277 template <bool isFlag>
278 void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
279 void genIeeeSetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
280 void genIeeeSetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
281 template <mlir::arith::CmpFPredicate pred>
282 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
284 mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
285 fir::ExtendedValue genIeeeSupportFlag(mlir::Type,
287 fir::ExtendedValue genIeeeSupportHalting(mlir::Type,
289 fir::ExtendedValue genIeeeSupportRounding(mlir::Type,
291 fir::ExtendedValue genIeeeSupportStandard(mlir::Type,
293 template <mlir::arith::CmpIPredicate pred>
294 mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
295 mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
296 mlir::Value genIeeeValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
297 mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
298 fir::ExtendedValue genImageIndex(mlir::Type,
301 mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
303 fir::ExtendedValue genIrand(mlir::Type resultType,
305 fir::ExtendedValue genIsContiguous(mlir::Type,
307 template <Fortran::runtime::io::Iostat value>
308 mlir::Value genIsIostatValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
309 mlir::Value genIsFPClass(mlir::Type, llvm::ArrayRef<mlir::Value>,
310 int fpclass);
311 mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
312 mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
314 fir::ExtendedValue genLcobound(mlir::Type,
316 mlir::Value genLeadz(mlir::Type, llvm::ArrayRef<mlir::Value>);
320 mlir::Value genMalloc(mlir::Type, llvm::ArrayRef<mlir::Value>);
321 template <typename Shift>
322 mlir::Value genMask(mlir::Type, llvm::ArrayRef<mlir::Value>);
324 fir::ExtendedValue genMatmulTranspose(mlir::Type,
329 mlir::Value genMergeBits(mlir::Type, llvm::ArrayRef<mlir::Value>);
332 mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
333 mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
334 void genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue>);
336 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
337 template <NearestProc>
338 mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
339 mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
341 mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
343 fir::ExtendedValue genNumImages(mlir::Type,
348 mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
349 mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
352 fir::ExtendedValue genPutenv(std::optional<mlir::Type>,
354 fir::ExtendedValue genRand(mlir::Type resultType,
356 void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
357 void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
358 void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
360 fir::ExtendedValue genReduceDim(mlir::Type,
362 fir::ExtendedValue genRename(std::optional<mlir::Type>,
363 mlir::ArrayRef<fir::ExtendedValue>);
366 mlir::Value genRRSpacing(mlir::Type resultType,
368 mlir::Value genRtc(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
369 fir::ExtendedValue genSameTypeAs(mlir::Type,
371 mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
373 fir::ExtendedValue genSecnds(mlir::Type resultType,
375 fir::ExtendedValue genSecond(std::optional<mlir::Type>,
376 mlir::ArrayRef<fir::ExtendedValue>);
377 fir::ExtendedValue genSelectedCharKind(mlir::Type,
379 mlir::Value genSelectedIntKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
380 mlir::Value genSelectedLogicalKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
381 mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
382 mlir::Value genSetExponent(mlir::Type resultType,
384 fir::ExtendedValue genShape(mlir::Type resultType,
386 template <typename Shift>
387 mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
388 mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
389 void genShowDescriptor(llvm::ArrayRef<fir::ExtendedValue>);
390 mlir::Value genSign(mlir::Type, llvm::ArrayRef<mlir::Value>);
391 mlir::Value genSind(mlir::Type, llvm::ArrayRef<mlir::Value>);
392 mlir::Value genSinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
395 mlir::Value genSpacing(mlir::Type resultType,
399 fir::ExtendedValue genStorageSize(mlir::Type,
402 void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>);
404 fir::ExtendedValue genSystem(std::optional<mlir::Type>,
405 mlir::ArrayRef<fir::ExtendedValue> args);
406 void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
407 mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
408 mlir::Value genTanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
409 fir::ExtendedValue genTeamNumber(mlir::Type,
411 mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
412 void genTokenize(llvm::ArrayRef<fir::ExtendedValue>);
413 mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
414 fir::ExtendedValue genTransfer(mlir::Type,
416 fir::ExtendedValue genTranspose(mlir::Type,
418 fir::ExtendedValue genThisImage(mlir::Type,
422 fir::ExtendedValue genUcobound(mlir::Type,
424 fir::ExtendedValue genUnlink(std::optional<mlir::Type> resultType,
428
432 mlir::Value genConversion(mlir::Type, llvm::ArrayRef<mlir::Value>);
433
439 template <typename FN, typename FD>
440 fir::ExtendedValue genExtremumloc(FN func, FD funcDim, llvm::StringRef errMsg,
441 mlir::Type,
443 template <typename FN, typename FD, typename FC>
445 fir::ExtendedValue genExtremumVal(FN func, FD funcDim, FC funcChar,
446 llvm::StringRef errMsg,
447 mlir::Type resultType,
450 template <typename FN, typename FD>
451 fir::ExtendedValue genReduction(FN func, FD funcDim, llvm::StringRef errMsg,
452 mlir::Type resultType,
454
457 void genRaiseExcept(int excepts, mlir::Value cond = {});
458
460 mlir::Value genQNan(mlir::Type resultType);
461
465 using ExtendedGenerator = decltype(&IntrinsicLibrary::genLenTrim);
466 using SubroutineGenerator = decltype(&IntrinsicLibrary::genDateAndTime);
468 using DualGenerator = decltype(&IntrinsicLibrary::genEtime);
469 using Generator = std::variant<ElementalGenerator, ExtendedGenerator,
470 SubroutineGenerator, DualGenerator>;
471
478 template <typename GeneratorType>
479 mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name,
480 mlir::Type resultType,
482 template <typename GeneratorType>
484 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
485 std::optional<mlir::Type> resultType,
487
488 template <typename GeneratorType>
489 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
490 mlir::FunctionType,
491 bool loadRefArguments = false);
492
494 template <typename GeneratorType>
496 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
497 llvm::ArrayRef<fir::ExtendedValue> args, bool outline);
498
500 mlir::Value invokeGenerator(ElementalGenerator generator,
501 mlir::Type resultType,
503 mlir::Value invokeGenerator(RuntimeCallGenerator generator,
504 mlir::Type resultType,
506 mlir::Value invokeGenerator(ExtendedGenerator generator,
507 mlir::Type resultType,
509 mlir::Value invokeGenerator(SubroutineGenerator generator,
511 mlir::Value invokeGenerator(DualGenerator generator,
513 mlir::Value invokeGenerator(DualGenerator generator, mlir::Type resultType,
515
518 mlir::SymbolRefAttr
519 getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name,
520 mlir::FunctionType signature);
521
524 mlir::Type resultType,
525 llvm::StringRef errMsg);
526
527 void setResultMustBeFreed() { resultMustBeFreed = true; }
528
529 fir::FirOpBuilder &builder;
530 mlir::Location loc;
531 bool resultMustBeFreed = false;
533};
534
536 const char *name = nullptr;
538 bool handleDynamicOptional = false;
539};
540
545 constexpr bool hasDefaultRules() const { return args[0].name == nullptr; }
546};
547
551 const char *name;
552 IntrinsicLibrary::Generator generator;
553 // The following may be omitted in the table below.
554 fir::IntrinsicArgumentLoweringRules argLoweringRules = {};
555 bool isElemental = true;
558 bool outline = false;
559};
560
562 // llvm::StringRef comparison operator are not constexpr, so use string_view.
563 using Key = std::string_view;
564 // Needed for implicit compare with keys.
565 constexpr operator Key() const { return key; }
566 Key key; // intrinsic name
567
568 // Name of a runtime function that implements the operation.
569 llvm::StringRef symbol;
570 fir::runtime::FuncTypeBuilderFunc typeGenerator;
571};
572
574 // Callback type for generating lowering for a math operation.
575 using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
576 const MathOperation &,
577 mlir::FunctionType,
579
580 // Overrides fir::runtime::FuncTypeBuilderFunc to add FirOpBuilder argument.
581 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
583
584 // llvm::StringRef comparison operator are not constexpr, so use string_view.
585 using Key = std::string_view;
586 // Needed for implicit compare with keys.
587 constexpr operator Key() const { return key; }
588 // Intrinsic name.
589 Key key;
590
591 // Name of a runtime function that implements the operation.
592 llvm::StringRef runtimeFunc;
593 FuncTypeBuilderFunc typeGenerator;
594
595 // A callback to generate FIR for the intrinsic defined by 'key'.
596 // A callback may generate either dedicated MLIR operation(s) or
597 // a function call to a runtime function with name defined by
598 // 'runtimeFunc'.
599 MathGeneratorTy funcGenerator;
600};
601
602// Enum of most supported intrinsic argument or return types.
603enum class ParamTypeId {
604 Void,
605 Address, // pointer (to an [array of] Integers of some kind)
606 Integer,
607 Real,
608 Complex,
609 IntegerVector,
610 UnsignedVector,
611 RealVector,
612};
613
614// Helper function to get length of a 16-byte vector of element type eleTy.
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);
620}
621
622template <ParamTypeId t, int k>
623struct ParamType {
624 // Supported kinds can be checked with static asserts at compile time.
625 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
626 k == 8,
627 "Unsupported integer kind");
628 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
629 k == 16,
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");
634
635 static const ParamTypeId ty = t;
636 static const int kind = k;
637};
638
639// Namespace encapsulating type definitions for parameter types.
640namespace Ty {
642template <int k>
644template <int k>
646template <int k>
648template <int k>
650template <int k>
651using IntegerVector = ParamType<ParamTypeId::IntegerVector, k>;
652template <int k>
653using UnsignedVector = ParamType<ParamTypeId::UnsignedVector, k>;
654template <int k>
656} // namespace Ty
657
658// Helper function that generates most types that are supported for intrinsic
659// arguments and return type. Used by `genFuncType` to generate function
660// types for most of the intrinsics.
661static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
662 fir::FirOpBuilder &builder,
663 ParamTypeId typeId, int kind) {
664 mlir::Type r;
665 unsigned bits{0};
666 switch (typeId) {
667 case ParamTypeId::Void:
668 llvm::report_fatal_error("can not get type of void");
669 break;
670 case ParamTypeId::Address:
671 bits = builder.getKindMap().getIntegerBitsize(kind);
672 assert(bits != 0 && "failed to convert address kind to integer bitsize");
673 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
674 break;
675 case ParamTypeId::Integer:
676 case ParamTypeId::IntegerVector:
677 bits = builder.getKindMap().getIntegerBitsize(kind);
678 assert(bits != 0 && "failed to convert kind to integer bitsize");
679 r = mlir::IntegerType::get(context, bits);
680 break;
681 case ParamTypeId::UnsignedVector:
682 bits = builder.getKindMap().getIntegerBitsize(kind);
683 assert(bits != 0 && "failed to convert kind to unsigned bitsize");
684 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
685 break;
686 case ParamTypeId::Real:
687 case ParamTypeId::RealVector:
688 r = builder.getRealType(kind);
689 break;
690 case ParamTypeId::Complex:
691 r = mlir::ComplexType::get(builder.getRealType(kind));
692 break;
693 }
694
695 switch (typeId) {
696 case ParamTypeId::Void:
697 case ParamTypeId::Address:
698 case ParamTypeId::Integer:
699 case ParamTypeId::Real:
700 case ParamTypeId::Complex:
701 break;
702 case ParamTypeId::IntegerVector:
703 case ParamTypeId::UnsignedVector:
704 case ParamTypeId::RealVector:
705 // convert to vector type
706 r = fir::VectorType::get(getVecLen(r), r);
707 }
708 return r;
709}
710
711// Generic function type generator that supports most of the function types
712// used by intrinsics.
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;
719
720 for (size_t i = 0; i < argTys.size(); ++i) {
721 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
722 }
723
724 if (TyR::ty == ParamTypeId::Void)
725 return mlir::FunctionType::get(context, argTypes, {});
726
727 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
728 return mlir::FunctionType::get(context, argTypes, {resType});
729}
730
732struct IntrinsicHandlerEntry {
733 using RuntimeGeneratorRange =
734 std::pair<const MathOperation *, const MathOperation *>;
735 IntrinsicHandlerEntry(const IntrinsicHandler *handler) : entry{handler} {
736 assert(handler && "handler must not be nullptr");
737 };
738 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
739 const IntrinsicArgumentLoweringRules *getArgumentLoweringRules() const;
740 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
741};
742
743//===----------------------------------------------------------------------===//
744// Helper functions for argument handling.
745//===----------------------------------------------------------------------===//
746static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
747 mlir::Type eleTy) {
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())};
751 return newEleTy;
752 }
753 return eleTy;
754}
755
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));
761 return baseVec;
762}
763
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());
769 return typeVec;
770}
771
772mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
773 const MathOperation &mathOp,
774 mlir::FunctionType libFuncType,
775 llvm::ArrayRef<mlir::Value> args);
776
777template <typename T>
778mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
779 const MathOperation &mathOp,
780 mlir::FunctionType mathLibFuncType,
781 llvm::ArrayRef<mlir::Value> args);
782
783template <typename T>
784mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
785 const MathOperation &mathOp,
786 mlir::FunctionType mathLibFuncType,
787 llvm::ArrayRef<mlir::Value> args);
788
789mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
790 mlir::Location loc,
791 const MathOperation &mathOp,
792 mlir::FunctionType libFuncType,
793 llvm::ArrayRef<mlir::Value> args);
794
797std::optional<IntrinsicHandlerEntry>
798lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName,
799 std::optional<mlir::Type> resultType,
800 bool isBindcCall = false);
801
803void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name);
804
808getIntrinsicArgumentLowering(llvm::StringRef intrinsicName);
809
813 unsigned position);
814
816fir::ExtendedValue getAbsentIntrinsicArgument();
817
819// implementation) of an unrestricted intrinsic (defined by its signature
820// and generic name)
821mlir::SymbolRefAttr
822getUnrestrictedIntrinsicSymbolRefAttr(fir::FirOpBuilder &, mlir::Location,
823 llvm::StringRef name,
824 mlir::FunctionType signature);
825
826//===----------------------------------------------------------------------===//
827// Direct access to intrinsics that may be used by lowering outside
828// of intrinsic call lowering.
829//===----------------------------------------------------------------------===//
830
833mlir::Value genMax(fir::FirOpBuilder &, mlir::Location,
834 llvm::ArrayRef<mlir::Value> args);
835
837mlir::Value genMin(fir::FirOpBuilder &, mlir::Location,
838 llvm::ArrayRef<mlir::Value> args);
839
842mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
843 mlir::Type resultType, mlir::Value x, mlir::Value y);
844
847mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
848 mlir::Value x, mlir::Value y);
849
850template <std::size_t N>
851static constexpr bool isSorted(const IntrinsicHandler (&array)[N]) {
852 // Replace by std::sorted when C++20 is default (will be constexpr).
853 const IntrinsicHandler *lastSeen{nullptr};
854 bool isSorted{true};
855 for (const auto &x : array) {
856 if (lastSeen)
857 isSorted &= std::string_view{lastSeen->name} < std::string_view{x.name};
858 lastSeen = &x;
859 }
860 return isSorted;
861}
862
863} // namespace fir
864
865#endif // FORTRAN_LOWER_INTRINSICCALL_H
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 FIRType.h:106
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