xref: /llvm-project/flang/include/flang/Lower/ConvertVariable.h (revision 1fcb6a9754a8db057e18f629cb90011b638901e7)
1 //===- Lower/ConvertVariable.h -- lowering of variables to FIR --*- 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 /// Instantiation of pft::Variable in FIR/MLIR.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef FORTRAN_LOWER_CONVERT_VARIABLE_H
18 #define FORTRAN_LOWER_CONVERT_VARIABLE_H
19 
20 #include "flang/Lower/Support/Utils.h"
21 #include "flang/Optimizer/Dialect/FIRAttr.h"
22 #include "flang/Semantics/symbol.h"
23 #include "mlir/IR/Value.h"
24 #include "llvm/ADT/DenseMap.h"
25 
26 namespace cuf {
27 class DataAttributeAttr;
28 }
29 
30 namespace fir {
31 class ExtendedValue;
32 class FirOpBuilder;
33 class GlobalOp;
34 class FortranVariableFlagsAttr;
35 } // namespace fir
36 
37 namespace Fortran {
38 namespace semantics {
39 class Scope;
40 } // namespace semantics
41 
42 namespace lower {
43 class AbstractConverter;
44 class CallerInterface;
45 class StatementContext;
46 class SymMap;
47 namespace pft {
48 struct Variable;
49 }
50 
51 /// AggregateStoreMap is used to keep track of instantiated aggregate stores
52 /// when lowering a scope containing equivalences (aliases). It must only be
53 /// owned by the code lowering a scope and provided to instantiateVariable.
54 using AggregateStoreKey =
55     std::tuple<const Fortran::semantics::Scope *, std::size_t>;
56 using AggregateStoreMap = llvm::DenseMap<AggregateStoreKey, mlir::Value>;
57 
58 /// Instantiate variable \p var and add it to \p symMap.
59 /// The AbstractConverter builder must be set.
60 /// The AbstractConverter own symbol mapping is not used during the
61 /// instantiation and can be different form \p symMap.
62 void instantiateVariable(AbstractConverter &, const pft::Variable &var,
63                          SymMap &symMap, AggregateStoreMap &storeMap);
64 
65 /// Does this variable have a default initialization?
66 bool hasDefaultInitialization(const Fortran::semantics::Symbol &sym);
67 
68 /// Call default initialization runtime routine to initialize \p var.
69 void defaultInitializeAtRuntime(Fortran::lower::AbstractConverter &converter,
70                                 const Fortran::semantics::Symbol &sym,
71                                 Fortran::lower::SymMap &symMap);
72 
73 /// Call clone initialization runtime routine to initialize \p sym's value.
74 void initializeCloneAtRuntime(Fortran::lower::AbstractConverter &converter,
75                               const Fortran::semantics::Symbol &sym,
76                               Fortran::lower::SymMap &symMap);
77 
78 /// Create a fir::GlobalOp given a module variable definition. This is intended
79 /// to be used when lowering a module definition, not when lowering variables
80 /// used from a module. For used variables instantiateVariable must directly be
81 /// called.
82 void defineModuleVariable(AbstractConverter &, const pft::Variable &var);
83 
84 /// Create fir::GlobalOp for all common blocks, including their initial values
85 /// if they have one. This should be called before lowering any scopes so that
86 /// common block globals are available when a common appear in a scope.
87 void defineCommonBlocks(
88     AbstractConverter &,
89     const std::vector<std::pair<semantics::SymbolRef, std::size_t>>
90         &commonBlocks);
91 
92 /// The COMMON block is a global structure. \p commonValue is the base address
93 /// of the COMMON block. As the offset from the symbol \p sym, generate the
94 /// COMMON block member value (commonValue + offset) for the symbol.
95 mlir::Value genCommonBlockMember(AbstractConverter &converter,
96                                  mlir::Location loc,
97                                  const Fortran::semantics::Symbol &sym,
98                                  mlir::Value commonValue);
99 
100 /// Lower a symbol attributes given an optional storage \p and add it to the
101 /// provided symbol map. If \preAlloc is not provided, a temporary storage will
102 /// be allocated. This is a low level function that should only be used if
103 /// instantiateVariable cannot be called.
104 void mapSymbolAttributes(AbstractConverter &, const pft::Variable &, SymMap &,
105                          StatementContext &, mlir::Value preAlloc = {});
106 void mapSymbolAttributes(AbstractConverter &, const semantics::SymbolRef &,
107                          SymMap &, StatementContext &,
108                          mlir::Value preAlloc = {});
109 
110 /// Instantiate the variables that appear in the specification expressions
111 /// of the result of a function call. The instantiated variables are added
112 /// to \p symMap.
113 void mapCallInterfaceSymbolsForResult(
114     AbstractConverter &, const Fortran::lower::CallerInterface &caller,
115     SymMap &symMap);
116 
117 /// Instantiate the variables that appear in the specification expressions
118 /// of a dummy argument of a procedure call. The instantiated variables are
119 /// added to \p symMap.
120 void mapCallInterfaceSymbolsForDummyArgument(
121     AbstractConverter &, const Fortran::lower::CallerInterface &caller,
122     SymMap &symMap, const Fortran::semantics::Symbol &dummySymbol);
123 
124 // TODO: consider saving the initial expression symbol dependence analysis in
125 // in the PFT variable and dealing with the dependent symbols instantiation in
126 // the fir::GlobalOp body at the fir::GlobalOp creation point rather than by
127 // having genExtAddrInInitializer and genInitialDataTarget custom entry points
128 // here to deal with this while lowering the initial expression value.
129 
130 /// Create initial-data-target fir.box in a global initializer region.
131 /// This handles the local instantiation of the target variable.
132 mlir::Value genInitialDataTarget(Fortran::lower::AbstractConverter &,
133                                  mlir::Location, mlir::Type boxType,
134                                  const SomeExpr &initialTarget,
135                                  bool couldBeInEquivalence = false);
136 
137 /// Call \p genInit to generate code inside \p global initializer region.
138 void createGlobalInitialization(
139     fir::FirOpBuilder &builder, fir::GlobalOp global,
140     std::function<void(fir::FirOpBuilder &)> genInit);
141 
142 /// Generate address \p addr inside an initializer.
143 fir::ExtendedValue
144 genExtAddrInInitializer(Fortran::lower::AbstractConverter &converter,
145                         mlir::Location loc, const SomeExpr &addr);
146 
147 /// Create a global variable for an intrinsic module object.
148 void createIntrinsicModuleGlobal(Fortran::lower::AbstractConverter &converter,
149                                  const pft::Variable &);
150 
151 /// Create a global variable for a compiler generated object that describes a
152 /// derived type for the runtime.
153 void createRuntimeTypeInfoGlobal(Fortran::lower::AbstractConverter &converter,
154                                  const Fortran::semantics::Symbol &typeInfoSym);
155 
156 /// Translate the Fortran attributes of \p sym into the FIR variable attribute
157 /// representation.
158 fir::FortranVariableFlagsAttr
159 translateSymbolAttributes(mlir::MLIRContext *mlirContext,
160                           const Fortran::semantics::Symbol &sym,
161                           fir::FortranVariableFlagsEnum extraFlags =
162                               fir::FortranVariableFlagsEnum::None);
163 
164 /// Translate the CUDA Fortran attributes of \p sym into the FIR CUDA attribute
165 /// representation.
166 cuf::DataAttributeAttr
167 translateSymbolCUFDataAttribute(mlir::MLIRContext *mlirContext,
168                                 const Fortran::semantics::Symbol &sym);
169 
170 /// Map a symbol to a given fir::ExtendedValue. This will generate an
171 /// hlfir.declare when lowering to HLFIR and map the hlfir.declare result to the
172 /// symbol.
173 void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
174                       Fortran::lower::SymMap &symMap,
175                       const Fortran::semantics::Symbol &sym,
176                       const fir::ExtendedValue &exv,
177                       fir::FortranVariableFlagsEnum extraFlags =
178                           fir::FortranVariableFlagsEnum::None,
179                       bool force = false);
180 
181 /// Given the Fortran type of a Cray pointee, return the fir.box type used to
182 /// track the cray pointee as Fortran pointer.
183 mlir::Type getCrayPointeeBoxType(mlir::Type);
184 
185 } // namespace lower
186 } // namespace Fortran
187 #endif // FORTRAN_LOWER_CONVERT_VARIABLE_H
188