1 //===-- include/flang/Evaluate/intrinsics.h ---------------------*- 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_EVALUATE_INTRINSICS_H_
10 #define FORTRAN_EVALUATE_INTRINSICS_H_
11
12 #include "call.h"
13 #include "characteristics.h"
14 #include "type.h"
15 #include "flang/Common/default-kinds.h"
16 #include "flang/Parser/char-block.h"
17 #include "flang/Parser/message.h"
18 #include <memory>
19 #include <optional>
20 #include <string>
21
22 namespace llvm {
23 class raw_ostream;
24 }
25
26 namespace Fortran::evaluate {
27
28 class FoldingContext;
29
30 // Utility for checking for missing, excess, and duplicated arguments,
31 // and rearranging the actual arguments into dummy argument order.
32 bool CheckAndRearrangeArguments(ActualArguments &, parser::ContextualMessages &,
33 const char *const dummyKeywords[] /* null terminated */,
34 std::size_t trailingOptionals = 0);
35
36 struct CallCharacteristics {
37 std::string name;
38 bool isSubroutineCall{false};
39 };
40
41 struct SpecificCall {
SpecificCallSpecificCall42 SpecificCall(SpecificIntrinsic &&si, ActualArguments &&as)
43 : specificIntrinsic{std::move(si)}, arguments{std::move(as)} {}
44 SpecificIntrinsic specificIntrinsic;
45 ActualArguments arguments;
46 };
47
48 struct SpecificIntrinsicFunctionInterface : public characteristics::Procedure {
SpecificIntrinsicFunctionInterfaceSpecificIntrinsicFunctionInterface49 SpecificIntrinsicFunctionInterface(
50 characteristics::Procedure &&p, std::string n, bool isRestrictedSpecific)
51 : characteristics::Procedure{std::move(p)}, genericName{n},
52 isRestrictedSpecific{isRestrictedSpecific} {}
53 std::string genericName;
54 bool isRestrictedSpecific;
55 // N.B. If there are multiple arguments, they all have the same type.
56 // All argument and result types are intrinsic types with default kinds.
57 };
58
59 // Generic intrinsic classes from table 16.1
ENUM_CLASS(IntrinsicClass,atomicSubroutine,collectiveSubroutine,elementalFunction,elementalSubroutine,inquiryFunction,pureSubroutine,impureSubroutine,transformationalFunction,noClass)60 ENUM_CLASS(IntrinsicClass, atomicSubroutine, collectiveSubroutine,
61 elementalFunction, elementalSubroutine, inquiryFunction, pureSubroutine,
62 impureSubroutine, transformationalFunction, noClass)
63
64 class IntrinsicProcTable {
65 private:
66 class Implementation;
67
68 IntrinsicProcTable() = default;
69
70 public:
71 ~IntrinsicProcTable();
72 IntrinsicProcTable(IntrinsicProcTable &&) = default;
73
74 static IntrinsicProcTable Configure(
75 const common::IntrinsicTypeDefaultKinds &);
76
77 // Check whether a name should be allowed to appear on an INTRINSIC
78 // statement.
79 bool IsIntrinsic(const std::string &) const;
80 bool IsIntrinsicFunction(const std::string &) const;
81 bool IsIntrinsicSubroutine(const std::string &) const;
82
83 // Inquiry intrinsics are defined in section 16.7, table 16.1
84 IntrinsicClass GetIntrinsicClass(const std::string &) const;
85
86 // Return the generic name of a specific intrinsic name.
87 // The name provided is returned if it is a generic intrinsic name or is
88 // not known to be an intrinsic.
89 std::string GetGenericIntrinsicName(const std::string &) const;
90
91 // Probe the intrinsics for a match against a specific call.
92 // On success, the actual arguments are transferred to the result
93 // in dummy argument order; on failure, the actual arguments remain
94 // untouched.
95 std::optional<SpecificCall> Probe(
96 const CallCharacteristics &, ActualArguments &, FoldingContext &) const;
97
98 // Probe the intrinsics with the name of a potential specific intrinsic.
99 std::optional<SpecificIntrinsicFunctionInterface> IsSpecificIntrinsicFunction(
100 const std::string &) const;
101
102 // Illegal name for an intrinsic used to avoid cascading error messages when
103 // constant folding.
104 static const inline std::string InvalidName{
105 "(invalid intrinsic function call)"};
106
107 llvm::raw_ostream &Dump(llvm::raw_ostream &) const;
108
109 private:
110 std::unique_ptr<Implementation> impl_;
111 };
112
113 // Check if an intrinsic explicitly allows its INTENT(OUT) arguments to be
114 // allocatable coarrays.
115 bool AcceptsIntentOutAllocatableCoarray(const std::string &);
116 } // namespace Fortran::evaluate
117 #endif // FORTRAN_EVALUATE_INTRINSICS_H_
118