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 fir {
25
26class StatementContext;
28
36
42std::pair<fir::ExtendedValue, bool>
43genIntrinsicCall(fir::FirOpBuilder &, mlir::Location, llvm::StringRef name,
44 std::optional<mlir::Type> resultType,
46 IntrinsicLoweringOptions options = {});
47
51std::pair<fir::ExtendedValue, bool>
52genIntrinsicCall(fir::FirOpBuilder &, mlir::Location,
53 const IntrinsicHandlerEntry &,
54 std::optional<mlir::Type> resultType,
56 IntrinsicLoweringOptions options = {});
57
73
76 LowerIntrinsicArgAs lowerAs;
78 // - Numerical: 0
79 // - Logical : false
80 // - Derived/character: not possible. Need custom intrinsic lowering.
81 // Addr:
82 // - nullptr
83 // Box:
84 // - absent box
85 // AsInquired:
86 // - no-op
88};
89
90constexpr auto asValue = fir::LowerIntrinsicArgAs::Value;
91constexpr auto asAddr = fir::LowerIntrinsicArgAs::Addr;
92constexpr auto asBox = fir::LowerIntrinsicArgAs::Box;
93constexpr auto asInquired = fir::LowerIntrinsicArgAs::Inquired;
94
98
99// TODO error handling -> return a code or directly emit messages ?
100struct IntrinsicLibrary {
101
102 // Constructors.
103 explicit IntrinsicLibrary(fir::FirOpBuilder &builder, mlir::Location loc,
104 IntrinsicLoweringOptions options = {})
105 : builder{builder}, loc{loc}, options{options} {}
106 IntrinsicLibrary() = delete;
107 IntrinsicLibrary(const IntrinsicLibrary &) = delete;
108
112 std::pair<fir::ExtendedValue, bool>
113 genIntrinsicCall(llvm::StringRef name, std::optional<mlir::Type> resultType,
115
123 mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type,
125
126 using RuntimeCallGenerator = std::function<mlir::Value(
128 RuntimeCallGenerator
129 getRuntimeCallGenerator(llvm::StringRef name,
130 mlir::FunctionType soughtFuncType);
131
137 mlir::Value genAbs(mlir::Type, llvm::ArrayRef<mlir::Value>);
138 mlir::Value genAcosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
139 mlir::Value genAcospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
140 template <void (*CallRuntime)(fir::FirOpBuilder &, mlir::Location loc,
141 mlir::Value, mlir::Value)>
142 fir::ExtendedValue genAdjustRtCall(mlir::Type,
144 mlir::Value genAimag(mlir::Type, llvm::ArrayRef<mlir::Value>);
145 mlir::Value genAint(mlir::Type, llvm::ArrayRef<mlir::Value>);
147 fir::ExtendedValue genAllocated(mlir::Type,
149 mlir::Value genAnint(mlir::Type, llvm::ArrayRef<mlir::Value>);
151 mlir::Value genAtanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
153 genCommandArgumentCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
154 mlir::Value genAsind(mlir::Type, llvm::ArrayRef<mlir::Value>);
155 mlir::Value genAsinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
156 fir::ExtendedValue genAssociated(mlir::Type,
158 mlir::Value genAtand(mlir::Type, llvm::ArrayRef<mlir::Value>);
159 fir::ExtendedValue genBesselJn(mlir::Type,
161 fir::ExtendedValue genBesselYn(mlir::Type,
163 template <mlir::arith::CmpIPredicate pred>
164 mlir::Value genBitwiseCompare(mlir::Type resultType,
166
167 mlir::Value genBtest(mlir::Type, llvm::ArrayRef<mlir::Value>);
168 mlir::Value genCeiling(mlir::Type, llvm::ArrayRef<mlir::Value>);
170 fir::ExtendedValue genChdir(std::optional<mlir::Type> resultType,
172 template <mlir::arith::CmpIPredicate pred>
173 fir::ExtendedValue genCharacterCompare(mlir::Type,
175 mlir::Value genCmplx(mlir::Type, llvm::ArrayRef<mlir::Value>);
176 mlir::Value genConjg(mlir::Type, llvm::ArrayRef<mlir::Value>);
179 void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>);
186 mlir::Value genErfcScaled(mlir::Type resultType,
188 void genCFPointer(llvm::ArrayRef<fir::ExtendedValue>);
189 void genCFProcPointer(llvm::ArrayRef<fir::ExtendedValue>);
190 void genCFStrPointer(llvm::ArrayRef<fir::ExtendedValue>);
193 template <mlir::arith::CmpIPredicate pred>
194 fir::ExtendedValue genCPtrCompare(mlir::Type,
196 void genCoBroadcast(llvm::ArrayRef<fir::ExtendedValue>);
200 mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>);
201 mlir::Value genCospi(mlir::Type, llvm::ArrayRef<mlir::Value>);
202 void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
203 fir::ExtendedValue genDsecnds(mlir::Type resultType,
205 mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>);
206 fir::ExtendedValue genDotProduct(mlir::Type,
208 mlir::Value genDprod(mlir::Type, llvm::ArrayRef<mlir::Value>);
209 mlir::Value genDshiftl(mlir::Type, llvm::ArrayRef<mlir::Value>);
210 mlir::Value genDshiftr(mlir::Type, llvm::ArrayRef<mlir::Value>);
213 void genExecuteCommandLine(mlir::ArrayRef<fir::ExtendedValue> args);
214 fir::ExtendedValue genEtime(std::optional<mlir::Type>,
215 mlir::ArrayRef<fir::ExtendedValue> args);
216 mlir::Value genTimef(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
217 mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
218 fir::ExtendedValue genExtendsTypeOf(mlir::Type,
220 template <bool isMax>
221 mlir::Value genExtremum(mlir::Type, llvm::ArrayRef<mlir::Value>);
222 fir::ExtendedValue genFCString(mlir::Type,
224 mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
226 mlir::Value genFraction(mlir::Type resultType,
227 mlir::ArrayRef<mlir::Value> args);
228 void genFree(mlir::ArrayRef<fir::ExtendedValue> args);
229 fir::ExtendedValue genFseek(std::optional<mlir::Type>,
230 mlir::ArrayRef<fir::ExtendedValue> args);
231 fir::ExtendedValue genFtell(std::optional<mlir::Type>,
232 mlir::ArrayRef<fir::ExtendedValue> args);
233 fir::ExtendedValue genGetCwd(std::optional<mlir::Type> resultType,
235 void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
236 mlir::Value genGetPID(mlir::Type resultType,
238 void genGetCommandArgument(mlir::ArrayRef<fir::ExtendedValue> args);
239 void genGetarg(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>);
252 mlir::Value genIbclr(mlir::Type, llvm::ArrayRef<mlir::Value>);
253 mlir::Value genIbits(mlir::Type, llvm::ArrayRef<mlir::Value>);
254 mlir::Value genIbset(mlir::Type, llvm::ArrayRef<mlir::Value>);
257 mlir::Value genIeeeClass(mlir::Type, llvm::ArrayRef<mlir::Value>);
258 mlir::Value genIeeeCopySign(mlir::Type, llvm::ArrayRef<mlir::Value>);
259 void genIeeeGetFlag(llvm::ArrayRef<fir::ExtendedValue>);
260 void genIeeeGetHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
261 template <bool isGet, bool isModes>
262 void genIeeeGetOrSetModesOrStatus(llvm::ArrayRef<fir::ExtendedValue>);
263 void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
264 void genIeeeGetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
265 mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);
266 mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
267 mlir::Value genIeeeIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
268 mlir::Value genIeeeIsNegative(mlir::Type, llvm::ArrayRef<mlir::Value>);
269 mlir::Value genIeeeIsNormal(mlir::Type, llvm::ArrayRef<mlir::Value>);
270 mlir::Value genIeeeLogb(mlir::Type, mlir::ArrayRef<mlir::Value>);
271 template <bool isMax, bool isNum, bool isMag>
272 mlir::Value genIeeeMaxMin(mlir::Type, llvm::ArrayRef<mlir::Value>);
273 template <mlir::arith::CmpFPredicate pred>
274 mlir::Value genIeeeQuietCompare(mlir::Type resultType,
276 mlir::Value genIeeeReal(mlir::Type, llvm::ArrayRef<mlir::Value>);
277 mlir::Value genIeeeRem(mlir::Type, llvm::ArrayRef<mlir::Value>);
278 mlir::Value genIeeeRint(mlir::Type, llvm::ArrayRef<mlir::Value>);
279 template <bool isFlag>
280 void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
281 void genIeeeSetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
282 void genIeeeSetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
283 template <mlir::arith::CmpFPredicate pred>
284 mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
286 mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
287 fir::ExtendedValue genIeeeSupportFlag(mlir::Type,
289 fir::ExtendedValue genIeeeSupportHalting(mlir::Type,
291 fir::ExtendedValue genIeeeSupportRounding(mlir::Type,
293 fir::ExtendedValue genIeeeSupportStandard(mlir::Type,
295 template <mlir::arith::CmpIPredicate pred>
296 mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
297 mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
298 mlir::Value genIeeeValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
299 mlir::Value genIeor(mlir::Type, llvm::ArrayRef<mlir::Value>);
300 fir::ExtendedValue genImageIndex(mlir::Type,
303 mlir::Value genIor(mlir::Type, llvm::ArrayRef<mlir::Value>);
305 fir::ExtendedValue genIrand(mlir::Type resultType,
307 fir::ExtendedValue genIsContiguous(mlir::Type,
309 template <Fortran::runtime::io::Iostat value>
310 mlir::Value genIsIostatValue(mlir::Type, llvm::ArrayRef<mlir::Value>);
311 mlir::Value genIsFPClass(mlir::Type, llvm::ArrayRef<mlir::Value>,
312 int fpclass);
313 mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
314 mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
316 fir::ExtendedValue genLcobound(mlir::Type,
318 mlir::Value genLeadz(mlir::Type, llvm::ArrayRef<mlir::Value>);
322 mlir::Value genMalloc(mlir::Type, llvm::ArrayRef<mlir::Value>);
323 template <typename Shift>
324 mlir::Value genMask(mlir::Type, llvm::ArrayRef<mlir::Value>);
326 fir::ExtendedValue genMatmulTranspose(mlir::Type,
331 mlir::Value genMergeBits(mlir::Type, llvm::ArrayRef<mlir::Value>);
334 mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
335 mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
336 void genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue>);
338 enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
339 template <NearestProc>
340 mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
341 mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
343 mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
345 fir::ExtendedValue genNumImages(mlir::Type,
350 mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
351 mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
354 fir::ExtendedValue genPutenv(std::optional<mlir::Type>,
356 fir::ExtendedValue genRand(mlir::Type resultType,
358 void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
359 void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
360 void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
362 fir::ExtendedValue genReduceDim(mlir::Type,
364 fir::ExtendedValue genRename(std::optional<mlir::Type>,
365 mlir::ArrayRef<fir::ExtendedValue>);
368 mlir::Value genRRSpacing(mlir::Type resultType,
370 mlir::Value genRtc(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args);
371 fir::ExtendedValue genSameTypeAs(mlir::Type,
373 mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
375 fir::ExtendedValue genSecnds(mlir::Type resultType,
377 fir::ExtendedValue genSecond(std::optional<mlir::Type>,
378 mlir::ArrayRef<fir::ExtendedValue>);
379 fir::ExtendedValue genSelectedCharKind(mlir::Type,
381 mlir::Value genSelectedIntKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
382 mlir::Value genSelectedLogicalKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
383 mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
384 mlir::Value genSetExponent(mlir::Type resultType,
386 fir::ExtendedValue genShape(mlir::Type resultType,
388 template <typename Shift>
389 mlir::Value genShift(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
390 mlir::Value genShiftA(mlir::Type resultType, llvm::ArrayRef<mlir::Value>);
391 void genShowDescriptor(llvm::ArrayRef<fir::ExtendedValue>);
392 mlir::Value genSign(mlir::Type, llvm::ArrayRef<mlir::Value>);
393 mlir::Value genSind(mlir::Type, llvm::ArrayRef<mlir::Value>);
394 mlir::Value genSinpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
397 mlir::Value genSpacing(mlir::Type resultType,
401 fir::ExtendedValue genStorageSize(mlir::Type,
404 void genSignalSubroutine(llvm::ArrayRef<fir::ExtendedValue>);
406 fir::ExtendedValue genSystem(std::optional<mlir::Type>,
407 mlir::ArrayRef<fir::ExtendedValue> args);
408 void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
409 mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
410 mlir::Value genTanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
411 fir::ExtendedValue genTeamNumber(mlir::Type,
413 mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
414 void genTokenize(llvm::ArrayRef<fir::ExtendedValue>);
415 mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
416 fir::ExtendedValue genTransfer(mlir::Type,
418 fir::ExtendedValue genTranspose(mlir::Type,
420 fir::ExtendedValue genThisImage(mlir::Type,
424 fir::ExtendedValue genUcobound(mlir::Type,
426 fir::ExtendedValue genUnlink(std::optional<mlir::Type> resultType,
430
434 mlir::Value genConversion(mlir::Type, llvm::ArrayRef<mlir::Value>);
435
441 template <typename FN, typename FD>
442 fir::ExtendedValue genExtremumloc(FN func, FD funcDim, llvm::StringRef errMsg,
443 mlir::Type,
445 template <typename FN, typename FD, typename FC>
447 fir::ExtendedValue genExtremumVal(FN func, FD funcDim, FC funcChar,
448 llvm::StringRef errMsg,
449 mlir::Type resultType,
452 template <typename FN, typename FD>
453 fir::ExtendedValue genReduction(FN func, FD funcDim, llvm::StringRef errMsg,
454 mlir::Type resultType,
456
459 void genRaiseExcept(int excepts, mlir::Value cond = {});
460
462 mlir::Value genQNan(mlir::Type resultType);
463
467 using ExtendedGenerator = decltype(&IntrinsicLibrary::genLenTrim);
468 using SubroutineGenerator = decltype(&IntrinsicLibrary::genDateAndTime);
470 using DualGenerator = decltype(&IntrinsicLibrary::genEtime);
471 using Generator = std::variant<ElementalGenerator, ExtendedGenerator,
472 SubroutineGenerator, DualGenerator>;
473
480 template <typename GeneratorType>
481 mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name,
482 mlir::Type resultType,
484 template <typename GeneratorType>
486 outlineInExtendedWrapper(GeneratorType, llvm::StringRef name,
487 std::optional<mlir::Type> resultType,
489
490 template <typename GeneratorType>
491 mlir::func::FuncOp getWrapper(GeneratorType, llvm::StringRef name,
492 mlir::FunctionType,
493 bool loadRefArguments = false);
494
496 template <typename GeneratorType>
498 genElementalCall(GeneratorType, llvm::StringRef name, mlir::Type resultType,
499 llvm::ArrayRef<fir::ExtendedValue> args, bool outline);
500
502 mlir::Value invokeGenerator(ElementalGenerator generator,
503 mlir::Type resultType,
505 mlir::Value invokeGenerator(RuntimeCallGenerator generator,
506 mlir::Type resultType,
508 mlir::Value invokeGenerator(ExtendedGenerator generator,
509 mlir::Type resultType,
511 mlir::Value invokeGenerator(SubroutineGenerator generator,
513 mlir::Value invokeGenerator(DualGenerator generator,
515 mlir::Value invokeGenerator(DualGenerator generator, mlir::Type resultType,
517
520 mlir::SymbolRefAttr
521 getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name,
522 mlir::FunctionType signature);
523
526 mlir::Type resultType,
527 llvm::StringRef errMsg);
528
529 void setResultMustBeFreed() { resultMustBeFreed = true; }
530
531 fir::FirOpBuilder &builder;
532 mlir::Location loc;
533 bool resultMustBeFreed = false;
535};
536
538 const char *name = nullptr;
540 bool handleDynamicOptional = false;
541};
542
547 constexpr bool hasDefaultRules() const { return args[0].name == nullptr; }
548};
549
553 const char *name;
554 IntrinsicLibrary::Generator generator;
555 // The following may be omitted in the table below.
556 fir::IntrinsicArgumentLoweringRules argLoweringRules = {};
557 bool isElemental = true;
560 bool outline = false;
561};
562
564 // llvm::StringRef comparison operator are not constexpr, so use string_view.
565 using Key = std::string_view;
566 // Needed for implicit compare with keys.
567 constexpr operator Key() const { return key; }
568 Key key; // intrinsic name
569
570 // Name of a runtime function that implements the operation.
571 llvm::StringRef symbol;
572 fir::runtime::FuncTypeBuilderFunc typeGenerator;
573};
574
576 // Callback type for generating lowering for a math operation.
577 using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
578 const MathOperation &,
579 mlir::FunctionType,
581
582 // Overrides fir::runtime::FuncTypeBuilderFunc to add FirOpBuilder argument.
583 using FuncTypeBuilderFunc = mlir::FunctionType (*)(mlir::MLIRContext *,
585
586 // llvm::StringRef comparison operator are not constexpr, so use string_view.
587 using Key = std::string_view;
588 // Needed for implicit compare with keys.
589 constexpr operator Key() const { return key; }
590 // Intrinsic name.
591 Key key;
592
593 // Name of a runtime function that implements the operation.
594 llvm::StringRef runtimeFunc;
595 FuncTypeBuilderFunc typeGenerator;
596
597 // A callback to generate FIR for the intrinsic defined by 'key'.
598 // A callback may generate either dedicated MLIR operation(s) or
599 // a function call to a runtime function with name defined by
600 // 'runtimeFunc'.
601 MathGeneratorTy funcGenerator;
602};
603
604// Enum of most supported intrinsic argument or return types.
605enum class ParamTypeId {
606 Void,
607 Address, // pointer (to an [array of] Integers of some kind)
608 Integer,
609 Real,
610 Complex,
611 IntegerVector,
612 UnsignedVector,
613 RealVector,
614};
615
616// Helper function to get length of a 16-byte vector of element type eleTy.
617static int getVecLen(mlir::Type eleTy) {
618 assert((mlir::isa<mlir::IntegerType>(eleTy) ||
619 mlir::isa<mlir::FloatType>(eleTy)) &&
620 "unsupported vector element type");
621 return 16 / (eleTy.getIntOrFloatBitWidth() / 8);
622}
623
624template <ParamTypeId t, int k>
625struct ParamType {
626 // Supported kinds can be checked with static asserts at compile time.
627 static_assert(t != ParamTypeId::Integer || k == 1 || k == 2 || k == 4 ||
628 k == 8,
629 "Unsupported integer kind");
630 static_assert(t != ParamTypeId::Real || k == 4 || k == 8 || k == 10 ||
631 k == 16,
632 "Unsupported real kind");
633 static_assert(t != ParamTypeId::Complex || k == 2 || k == 3 || k == 4 ||
634 k == 8 || k == 10 || k == 16,
635 "Unsupported complex kind");
636
637 static const ParamTypeId ty = t;
638 static const int kind = k;
639};
640
641// Namespace encapsulating type definitions for parameter types.
642namespace Ty {
644template <int k>
646template <int k>
648template <int k>
650template <int k>
652template <int k>
653using IntegerVector = ParamType<ParamTypeId::IntegerVector, k>;
654template <int k>
655using UnsignedVector = ParamType<ParamTypeId::UnsignedVector, k>;
656template <int k>
658} // namespace Ty
659
660// Helper function that generates most types that are supported for intrinsic
661// arguments and return type. Used by `genFuncType` to generate function
662// types for most of the intrinsics.
663static inline mlir::Type getTypeHelper(mlir::MLIRContext *context,
664 fir::FirOpBuilder &builder,
665 ParamTypeId typeId, int kind) {
666 mlir::Type r;
667 unsigned bits{0};
668 switch (typeId) {
669 case ParamTypeId::Void:
670 llvm::report_fatal_error("can not get type of void");
671 break;
672 case ParamTypeId::Address:
673 bits = builder.getKindMap().getIntegerBitsize(kind);
674 assert(bits != 0 && "failed to convert address kind to integer bitsize");
675 r = fir::ReferenceType::get(mlir::IntegerType::get(context, bits));
676 break;
677 case ParamTypeId::Integer:
678 case ParamTypeId::IntegerVector:
679 bits = builder.getKindMap().getIntegerBitsize(kind);
680 assert(bits != 0 && "failed to convert kind to integer bitsize");
681 r = mlir::IntegerType::get(context, bits);
682 break;
683 case ParamTypeId::UnsignedVector:
684 bits = builder.getKindMap().getIntegerBitsize(kind);
685 assert(bits != 0 && "failed to convert kind to unsigned bitsize");
686 r = mlir::IntegerType::get(context, bits, mlir::IntegerType::Unsigned);
687 break;
688 case ParamTypeId::Real:
689 case ParamTypeId::RealVector:
690 r = builder.getRealType(kind);
691 break;
692 case ParamTypeId::Complex:
693 r = mlir::ComplexType::get(builder.getRealType(kind));
694 break;
695 }
696
697 switch (typeId) {
698 case ParamTypeId::Void:
699 case ParamTypeId::Address:
700 case ParamTypeId::Integer:
701 case ParamTypeId::Real:
702 case ParamTypeId::Complex:
703 break;
704 case ParamTypeId::IntegerVector:
705 case ParamTypeId::UnsignedVector:
706 case ParamTypeId::RealVector:
707 // convert to vector type
708 r = fir::VectorType::get(getVecLen(r), r);
709 }
710 return r;
711}
712
713// Generic function type generator that supports most of the function types
714// used by intrinsics.
715template <typename TyR, typename... ArgTys>
716static inline mlir::FunctionType genFuncType(mlir::MLIRContext *context,
717 fir::FirOpBuilder &builder) {
718 llvm::SmallVector<ParamTypeId> argTys = {ArgTys::ty...};
719 llvm::SmallVector<int> argKinds = {ArgTys::kind...};
720 llvm::SmallVector<mlir::Type> argTypes;
721
722 for (size_t i = 0; i < argTys.size(); ++i) {
723 argTypes.push_back(getTypeHelper(context, builder, argTys[i], argKinds[i]));
724 }
725
726 if (TyR::ty == ParamTypeId::Void)
727 return mlir::FunctionType::get(context, argTypes, {});
728
729 auto resType = getTypeHelper(context, builder, TyR::ty, TyR::kind);
730 return mlir::FunctionType::get(context, argTypes, {resType});
731}
732
734struct IntrinsicHandlerEntry {
735 using RuntimeGeneratorRange =
736 std::pair<const MathOperation *, const MathOperation *>;
737 IntrinsicHandlerEntry(const IntrinsicHandler *handler) : entry{handler} {
738 assert(handler && "handler must not be nullptr");
739 };
740 IntrinsicHandlerEntry(RuntimeGeneratorRange rt) : entry{rt} {};
741 const IntrinsicArgumentLoweringRules *getArgumentLoweringRules() const;
742 std::variant<const IntrinsicHandler *, RuntimeGeneratorRange> entry;
743};
744
745//===----------------------------------------------------------------------===//
746// Helper functions for argument handling.
747//===----------------------------------------------------------------------===//
748static inline mlir::Type getConvertedElementType(mlir::MLIRContext *context,
749 mlir::Type eleTy) {
750 if (mlir::isa<mlir::IntegerType>(eleTy) && !eleTy.isSignlessInteger()) {
751 const auto intTy{mlir::dyn_cast<mlir::IntegerType>(eleTy)};
752 auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())};
753 return newEleTy;
754 }
755 return eleTy;
756}
757
758static inline llvm::SmallVector<mlir::Value, 4>
759getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
760 llvm::SmallVector<mlir::Value, 4> baseVec;
761 for (auto arg : args)
762 baseVec.push_back(getBase(arg));
763 return baseVec;
764}
765
766static inline llvm::SmallVector<mlir::Type, 4>
767getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
768 llvm::SmallVector<mlir::Type, 4> typeVec;
769 for (auto arg : args)
770 typeVec.push_back(arg.getType());
771 return typeVec;
772}
773
774mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
775 const MathOperation &mathOp,
776 mlir::FunctionType libFuncType,
777 llvm::ArrayRef<mlir::Value> args);
778
779template <typename T>
780mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
781 const MathOperation &mathOp,
782 mlir::FunctionType mathLibFuncType,
783 llvm::ArrayRef<mlir::Value> args);
784
785template <typename T>
786mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
787 const MathOperation &mathOp,
788 mlir::FunctionType mathLibFuncType,
789 llvm::ArrayRef<mlir::Value> args);
790
791mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
792 mlir::Location loc,
793 const MathOperation &mathOp,
794 mlir::FunctionType libFuncType,
795 llvm::ArrayRef<mlir::Value> args);
796
799std::optional<IntrinsicHandlerEntry>
800lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName,
801 std::optional<mlir::Type> resultType);
802
804void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name);
805
809getIntrinsicArgumentLowering(llvm::StringRef intrinsicName);
810
814 unsigned position);
815
817fir::ExtendedValue getAbsentIntrinsicArgument();
818
820// implementation) of an unrestricted intrinsic (defined by its signature
821// and generic name)
822mlir::SymbolRefAttr
823getUnrestrictedIntrinsicSymbolRefAttr(fir::FirOpBuilder &, mlir::Location,
824 llvm::StringRef name,
825 mlir::FunctionType signature);
826
827//===----------------------------------------------------------------------===//
828// Direct access to intrinsics that may be used by lowering outside
829// of intrinsic call lowering.
830//===----------------------------------------------------------------------===//
831
834mlir::Value genMax(fir::FirOpBuilder &, mlir::Location,
835 llvm::ArrayRef<mlir::Value> args);
836
838mlir::Value genMin(fir::FirOpBuilder &, mlir::Location,
839 llvm::ArrayRef<mlir::Value> args);
840
843mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc,
844 mlir::Type resultType, mlir::Value x, mlir::Value y);
845
848mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType,
849 mlir::Value x, mlir::Value y);
850
851} // namespace fir
852
853#endif // FORTRAN_LOWER_INTRINSICCALL_H
Definition BoxValue.h:480
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:119
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::optional< IntrinsicHandlerEntry > lookupIntrinsicHandler(fir::FirOpBuilder &, llvm::StringRef intrinsicName, std::optional< mlir::Type > resultType)
Definition IntrinsicCall.cpp:1932
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:9414
const IntrinsicArgumentLoweringRules * getIntrinsicArgumentLowering(llvm::StringRef intrinsicName)
Definition IntrinsicCall.cpp:9373
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:9429
mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9441
mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, mlir::Value x, mlir::Value y)
Definition IntrinsicCall.cpp:9436
fir::ExtendedValue getAbsentIntrinsicArgument()
Return place-holder for absent intrinsic arguments.
Definition IntrinsicCall.cpp:89
void crashOnMissingIntrinsic(mlir::Location loc, llvm::StringRef name)
Generate a TODO error message for an as yet unimplemented intrinsic.
Definition IntrinsicCall.cpp:1957
ArgLoweringRule lowerIntrinsicArgumentAs(const IntrinsicArgumentLoweringRules &, unsigned position)
Definition IntrinsicCall.cpp:9401
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:9462
LowerIntrinsicArgAs
Definition IntrinsicCall.h:60
@ Addr
Definition IntrinsicCall.h:65
@ Inquired
Definition IntrinsicCall.h:71
@ Box
Lower argument to a box.
Definition IntrinsicCall.h:67
@ Value
Lower argument to a value. Mainly intended for scalar arguments.
Definition IntrinsicCall.h:62
mlir::Value genMax(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:9422
Define how a given intrinsic argument must be lowered.
Definition IntrinsicCall.h:75
bool handleDynamicOptional
Value:
Definition IntrinsicCall.h:87
This is shared by intrinsics and intrinsic module procedures.
Definition IntrinsicCall.h:544
IntrinsicDummyArgument args[7]
There is no more than 7 non repeated arguments in Fortran intrinsics.
Definition IntrinsicCall.h:546
Definition IntrinsicCall.h:537
Entry into the tables describing how an intrinsic must be lowered.
Definition IntrinsicCall.h:734
Definition IntrinsicCall.h:552
bool outline
Definition IntrinsicCall.h:560
mlir::SymbolRefAttr getUnrestrictedIntrinsicSymbolRefAttr(llvm::StringRef name, mlir::FunctionType signature)
Definition IntrinsicCall.cpp:2464
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:1969
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:4556
std::pair< fir::ExtendedValue, bool > genIntrinsicCall(llvm::StringRef name, std::optional< mlir::Type > resultType, llvm::ArrayRef< fir::ExtendedValue > arg)
Definition IntrinsicCall.cpp:2154
decltype(&IntrinsicLibrary::genEtime) DualGenerator
The generator for intrinsic that has both function and subroutine form.
Definition IntrinsicCall.h:470
mlir::Value outlineInWrapper(GeneratorType, llvm::StringRef name, mlir::Type resultType, llvm::ArrayRef< mlir::Value > args)
Definition IntrinsicCall.cpp:2363
mlir::Value genRuntimeCall(llvm::StringRef name, mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2535
mlir::Value genQNan(mlir::Type resultType)
Generate a quiet NaN of a given floating point type.
Definition IntrinsicCall.cpp:4778
mlir::Value genConversion(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2543
mlir::Value genAbs(mlir::Type, llvm::ArrayRef< mlir::Value >)
Definition IntrinsicCall.cpp:2557
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:9285
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:2498
decltype(&IntrinsicLibrary::genAbs) ElementalGenerator
Definition IntrinsicCall.h:466
fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_PTR [, C_PTR])
Definition IntrinsicCall.cpp:3202
fir::ExtendedValue genCAssociatedCFunPtr(mlir::Type, llvm::ArrayRef< fir::ExtendedValue >)
C_ASSOCIATED (C_FUNPTR [, C_FUNPTR])
Definition IntrinsicCall.cpp:3195
void genRaiseExcept(int excepts, mlir::Value cond={})
Definition IntrinsicCall.cpp:4785
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:2169
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:9204
Options controlling intrinsic lowering that depend on front-end state.
Definition IntrinsicCall.h:30
bool noPPCNativeVecElemOrder
Whether to avoid using the native vector element order on PPC targets.
Definition IntrinsicCall.h:34
bool coarrayEnabled
Whether multi-image (coarray) features are enabled (e.g. via -fcoarray).
Definition IntrinsicCall.h:32
Definition IntrinsicCall.h:575
Definition IntrinsicCall.h:625
Definition IntrinsicCall.h:563