xref: /llvm-project/flang/include/flang/Lower/AbstractConverter.h (revision a0406ce823e8f1c1993b565d08b045c0104c3a5a)
1 //===-- Lower/AbstractConverter.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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef FORTRAN_LOWER_ABSTRACTCONVERTER_H
14 #define FORTRAN_LOWER_ABSTRACTCONVERTER_H
15 
16 #include "flang/Common/Fortran.h"
17 #include "flang/Lower/LoweringOptions.h"
18 #include "flang/Lower/PFTDefs.h"
19 #include "flang/Optimizer/Builder/BoxValue.h"
20 #include "flang/Optimizer/Dialect/FIRAttr.h"
21 #include "flang/Semantics/symbol.h"
22 #include "mlir/IR/Builders.h"
23 #include "mlir/IR/BuiltinOps.h"
24 #include "mlir/IR/Operation.h"
25 #include "llvm/ADT/ArrayRef.h"
26 
27 namespace mlir {
28 class SymbolTable;
29 }
30 
31 namespace fir {
32 class KindMapping;
33 class FirOpBuilder;
34 } // namespace fir
35 
36 namespace Fortran {
37 namespace common {
38 template <typename>
39 class Reference;
40 }
41 
42 namespace evaluate {
43 struct DataRef;
44 template <typename>
45 class Expr;
46 class FoldingContext;
47 struct SomeType;
48 } // namespace evaluate
49 
50 namespace parser {
51 class CharBlock;
52 }
53 namespace semantics {
54 class Symbol;
55 class Scope;
56 class DerivedTypeSpec;
57 } // namespace semantics
58 
59 namespace lower {
60 class SymMap;
61 struct SymbolBox;
62 namespace pft {
63 struct Variable;
64 struct FunctionLikeUnit;
65 } // namespace pft
66 
67 using SomeExpr = Fortran::evaluate::Expr<Fortran::evaluate::SomeType>;
68 using SymbolRef = Fortran::common::Reference<const Fortran::semantics::Symbol>;
69 using TypeConstructionStack =
70     llvm::DenseMap<const Fortran::semantics::Scope *, mlir::Type>;
71 class StatementContext;
72 
73 using ExprToValueMap = llvm::DenseMap<const SomeExpr *, mlir::Value>;
74 
75 //===----------------------------------------------------------------------===//
76 // AbstractConverter interface
77 //===----------------------------------------------------------------------===//
78 
79 /// The abstract interface for converter implementations to lower Fortran
80 /// front-end fragments such as expressions, types, etc. to the FIR dialect of
81 /// MLIR.
82 class AbstractConverter {
83 public:
84   //===--------------------------------------------------------------------===//
85   // Symbols
86   //===--------------------------------------------------------------------===//
87 
88   /// Get the mlir instance of a symbol.
89   virtual mlir::Value getSymbolAddress(SymbolRef sym) = 0;
90 
91   virtual fir::ExtendedValue
92   symBoxToExtendedValue(const Fortran::lower::SymbolBox &symBox) = 0;
93 
94   virtual fir::ExtendedValue
95   getSymbolExtendedValue(const Fortran::semantics::Symbol &sym,
96                          Fortran::lower::SymMap *symMap = nullptr) = 0;
97 
98   /// Get the binding of an implied do variable by name.
99   virtual mlir::Value impliedDoBinding(llvm::StringRef name) = 0;
100 
101   /// Copy the binding of src to target symbol.
102   virtual void copySymbolBinding(SymbolRef src, SymbolRef target) = 0;
103 
104   /// Binds the symbol to an fir extended value. The symbol binding will be
105   /// added or replaced at the inner-most level of the local symbol map.
106   virtual void bindSymbol(SymbolRef sym, const fir::ExtendedValue &exval) = 0;
107 
108   /// Override lowering of expression with pre-lowered values.
109   /// Associate mlir::Value to evaluate::Expr. All subsequent call to
110   /// genExprXXX() will replace any occurrence of an overridden
111   /// expression in the expression tree by the pre-lowered values.
112   virtual void overrideExprValues(const ExprToValueMap *) = 0;
113   void resetExprOverrides() { overrideExprValues(nullptr); }
114   virtual const ExprToValueMap *getExprOverrides() = 0;
115 
116   /// Get the label set associated with a symbol.
117   virtual bool lookupLabelSet(SymbolRef sym, pft::LabelSet &labelSet) = 0;
118 
119   /// Get the code defined by a label
120   virtual pft::Evaluation *lookupLabel(pft::Label label) = 0;
121 
122   /// For a given symbol which is host-associated, create a clone using
123   /// parameters from the host-associated symbol.
124   /// The clone is default initialized if its type has any default
125   /// initialization unless `skipDefaultInit` is set.
126   virtual bool
127   createHostAssociateVarClone(const Fortran::semantics::Symbol &sym,
128                               bool skipDefaultInit) = 0;
129 
130   virtual void
131   createHostAssociateVarCloneDealloc(const Fortran::semantics::Symbol &sym) = 0;
132 
133   /// For a host-associated symbol (a symbol associated with another symbol from
134   /// an enclosing scope), either:
135   ///
136   /// * if \p hostIsSource == true: copy \p sym's value *from* its corresponding
137   /// host symbol,
138   ///
139   /// * if \p hostIsSource == false: copy \p sym's value *to* its corresponding
140   /// host symbol.
141   virtual void
142   copyHostAssociateVar(const Fortran::semantics::Symbol &sym,
143                        mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr,
144                        bool hostIsSource = true) = 0;
145 
146   virtual void copyVar(mlir::Location loc, mlir::Value dst, mlir::Value src,
147                        fir::FortranVariableFlagsEnum attrs) = 0;
148 
149   /// For a given symbol, check if it is present in the inner-most
150   /// level of the symbol map.
151   virtual bool
152   isPresentShallowLookup(const Fortran::semantics::Symbol &sym) = 0;
153 
154   /// Collect the set of symbols with \p flag in \p eval
155   /// region if \p collectSymbols is true. Otherwise, collect the
156   /// set of the host symbols with \p flag of the associated symbols in \p eval
157   /// region if collectHostAssociatedSymbols is true. This allows gathering
158   /// host association details of symbols particularly in nested directives
159   /// irrespective of \p flag \p, and can be useful where host
160   /// association details are needed in flag-agnostic manner.
161   virtual void collectSymbolSet(
162       pft::Evaluation &eval,
163       llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet,
164       Fortran::semantics::Symbol::Flag flag, bool collectSymbols = true,
165       bool collectHostAssociatedSymbols = false) = 0;
166 
167   /// For the given literal constant \p expression, returns a unique name
168   /// that can be used to create a global object to represent this
169   /// literal constant. It will return the same name for equivalent
170   /// literal constant expressions. \p eleTy specifies the data type
171   /// of the constant elements. For array constants it specifies
172   /// the array's element type.
173   virtual llvm::StringRef
174   getUniqueLitName(mlir::Location loc,
175                    std::unique_ptr<Fortran::lower::SomeExpr> expression,
176                    mlir::Type eleTy) = 0;
177 
178   //===--------------------------------------------------------------------===//
179   // Expressions
180   //===--------------------------------------------------------------------===//
181 
182   /// Generate the address of the location holding the expression, \p expr.
183   /// If \p expr is a Designator that is not compile time contiguous, the
184   /// address returned is the one of a contiguous temporary storage holding the
185   /// expression value. The clean-up for this temporary is added to \p context.
186   virtual fir::ExtendedValue genExprAddr(const SomeExpr &expr,
187                                          StatementContext &context,
188                                          mlir::Location *locPtr = nullptr) = 0;
189 
190   /// Generate the address of the location holding the expression, \p expr.
191   fir::ExtendedValue genExprAddr(mlir::Location loc, const SomeExpr *expr,
192                                  StatementContext &stmtCtx) {
193     return genExprAddr(*expr, stmtCtx, &loc);
194   }
195   fir::ExtendedValue genExprAddr(mlir::Location loc, const SomeExpr &expr,
196                                  StatementContext &stmtCtx) {
197     return genExprAddr(expr, stmtCtx, &loc);
198   }
199 
200   /// Generate the computations of the expression to produce a value.
201   virtual fir::ExtendedValue genExprValue(const SomeExpr &expr,
202                                           StatementContext &context,
203                                           mlir::Location *locPtr = nullptr) = 0;
204 
205   /// Generate the computations of the expression, \p expr, to produce a value.
206   fir::ExtendedValue genExprValue(mlir::Location loc, const SomeExpr *expr,
207                                   StatementContext &stmtCtx) {
208     return genExprValue(*expr, stmtCtx, &loc);
209   }
210   fir::ExtendedValue genExprValue(mlir::Location loc, const SomeExpr &expr,
211                                   StatementContext &stmtCtx) {
212     return genExprValue(expr, stmtCtx, &loc);
213   }
214 
215   /// Generate or get a fir.box describing the expression. If SomeExpr is
216   /// a Designator, the fir.box describes an entity over the Designator base
217   /// storage without making a temporary.
218   virtual fir::ExtendedValue genExprBox(mlir::Location loc,
219                                         const SomeExpr &expr,
220                                         StatementContext &stmtCtx) = 0;
221 
222   /// Generate the address of the box describing the variable designated
223   /// by the expression. The expression must be an allocatable or pointer
224   /// designator.
225   virtual fir::MutableBoxValue genExprMutableBox(mlir::Location loc,
226                                                  const SomeExpr &expr) = 0;
227 
228   /// Get FoldingContext that is required for some expression
229   /// analysis.
230   virtual Fortran::evaluate::FoldingContext &getFoldingContext() = 0;
231 
232   /// Host associated variables are grouped as a tuple. This returns that value,
233   /// which is itself a reference. Use bindTuple() to set this value.
234   virtual mlir::Value hostAssocTupleValue() = 0;
235 
236   /// Record a binding for the ssa-value of the host assoications tuple for this
237   /// function.
238   virtual void bindHostAssocTuple(mlir::Value val) = 0;
239 
240   /// Returns fir.dummy_scope operation's result value to be used
241   /// as dummy_scope operand of hlfir.declare operations for the dummy
242   /// arguments of this function.
243   virtual mlir::Value dummyArgsScopeValue() const = 0;
244 
245   /// Returns true if the given symbol is a dummy argument of this function.
246   /// Note that it returns false for all the symbols after all the variables
247   /// are instantiated for this function, i.e. it can only be used reliably
248   /// during the instatiation of the variables.
249   virtual bool
250   isRegisteredDummySymbol(Fortran::semantics::SymbolRef symRef) const = 0;
251 
252   /// Returns the FunctionLikeUnit being lowered, if any.
253   virtual const Fortran::lower::pft::FunctionLikeUnit *
254   getCurrentFunctionUnit() const = 0;
255 
256   //===--------------------------------------------------------------------===//
257   // Types
258   //===--------------------------------------------------------------------===//
259 
260   /// Generate the type of an Expr
261   virtual mlir::Type genType(const SomeExpr &) = 0;
262   /// Generate the type of a Symbol
263   virtual mlir::Type genType(SymbolRef) = 0;
264   /// Generate the type from a category
265   virtual mlir::Type genType(Fortran::common::TypeCategory tc) = 0;
266   /// Generate the type from a category and kind and length parameters.
267   virtual mlir::Type
268   genType(Fortran::common::TypeCategory tc, int kind,
269           llvm::ArrayRef<std::int64_t> lenParameters = std::nullopt) = 0;
270   /// Generate the type from a DerivedTypeSpec.
271   virtual mlir::Type genType(const Fortran::semantics::DerivedTypeSpec &) = 0;
272   /// Generate the type from a Variable
273   virtual mlir::Type genType(const pft::Variable &) = 0;
274 
275   /// Register a runtime derived type information object symbol to ensure its
276   /// object will be generated as a global.
277   virtual void
278   registerTypeInfo(mlir::Location loc, SymbolRef typeInfoSym,
279                    const Fortran::semantics::DerivedTypeSpec &typeSpec,
280                    fir::RecordType type) = 0;
281 
282   /// Get stack of derived type in construction. This is an internal entry point
283   /// for the type conversion utility to allow lowering recursive derived types.
284   virtual TypeConstructionStack &getTypeConstructionStack() = 0;
285 
286   //===--------------------------------------------------------------------===//
287   // Locations
288   //===--------------------------------------------------------------------===//
289 
290   /// Get the converter's current location
291   virtual mlir::Location getCurrentLocation() = 0;
292   /// Generate a dummy location
293   virtual mlir::Location genUnknownLocation() = 0;
294   /// Generate the location as converted from a CharBlock
295   virtual mlir::Location genLocation(const Fortran::parser::CharBlock &) = 0;
296 
297   /// Get the converter's current scope
298   virtual const Fortran::semantics::Scope &getCurrentScope() = 0;
299 
300   //===--------------------------------------------------------------------===//
301   // FIR/MLIR
302   //===--------------------------------------------------------------------===//
303 
304   /// Get the OpBuilder
305   virtual fir::FirOpBuilder &getFirOpBuilder() = 0;
306   /// Get the ModuleOp
307   virtual mlir::ModuleOp getModuleOp() = 0;
308   /// Get the MLIRContext
309   virtual mlir::MLIRContext &getMLIRContext() = 0;
310   /// Unique a symbol (add a containing scope specific prefix)
311   virtual std::string mangleName(const Fortran::semantics::Symbol &) = 0;
312   /// Unique a derived type (add a containing scope specific prefix)
313   virtual std::string
314   mangleName(const Fortran::semantics::DerivedTypeSpec &) = 0;
315   /// Unique a compiler generated name (add a containing scope specific prefix)
316   virtual std::string mangleName(std::string &) = 0;
317   /// Return the field name for a derived type component inside a fir.record
318   /// type.
319   virtual std::string
320   getRecordTypeFieldName(const Fortran::semantics::Symbol &component) = 0;
321 
322   /// Get the KindMap.
323   virtual const fir::KindMapping &getKindMap() = 0;
324 
325   virtual Fortran::lower::StatementContext &getFctCtx() = 0;
326 
327   AbstractConverter(const Fortran::lower::LoweringOptions &loweringOptions)
328       : loweringOptions(loweringOptions) {}
329   virtual ~AbstractConverter() = default;
330 
331   //===--------------------------------------------------------------------===//
332   // Miscellaneous
333   //===--------------------------------------------------------------------===//
334 
335   /// Generate IR for Evaluation \p eval.
336   virtual void genEval(pft::Evaluation &eval,
337                        bool unstructuredContext = true) = 0;
338 
339   /// Return options controlling lowering behavior.
340   const Fortran::lower::LoweringOptions &getLoweringOptions() const {
341     return loweringOptions;
342   }
343 
344   /// Find the symbol in one level up of symbol map such as for host-association
345   /// in OpenMP code or return null.
346   virtual Fortran::lower::SymbolBox
347   lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0;
348 
349   /// Return the mlir::SymbolTable associated to the ModuleOp.
350   /// Look-ups are faster using it than using module.lookup<>,
351   /// but the module op should be queried in case of failure
352   /// because this symbol table is not guaranteed to contain
353   /// all the symbols from the ModuleOp (the symbol table should
354   /// always be provided to the builder helper creating globals and
355   /// functions in order to be in sync).
356   virtual mlir::SymbolTable *getMLIRSymbolTable() = 0;
357 
358 private:
359   /// Options controlling lowering behavior.
360   const Fortran::lower::LoweringOptions &loweringOptions;
361 };
362 
363 } // namespace lower
364 } // namespace Fortran
365 
366 #endif // FORTRAN_LOWER_ABSTRACTCONVERTER_H
367