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