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