12c2e5a5dSValentin Clement //===-- ConvertVariable.cpp -- bridge to lower to MLIR --------------------===// 22c2e5a5dSValentin Clement // 32c2e5a5dSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42c2e5a5dSValentin Clement // See https://llvm.org/LICENSE.txt for license information. 52c2e5a5dSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c2e5a5dSValentin Clement // 72c2e5a5dSValentin Clement //===----------------------------------------------------------------------===// 82c2e5a5dSValentin Clement // 92c2e5a5dSValentin Clement // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 102c2e5a5dSValentin Clement // 112c2e5a5dSValentin Clement //===----------------------------------------------------------------------===// 122c2e5a5dSValentin Clement 132c2e5a5dSValentin Clement #include "flang/Lower/ConvertVariable.h" 142c2e5a5dSValentin Clement #include "flang/Lower/AbstractConverter.h" 152a59ead1SValentin Clement #include "flang/Lower/Allocatable.h" 162a59ead1SValentin Clement #include "flang/Lower/BoxAnalyzer.h" 172c2e5a5dSValentin Clement #include "flang/Lower/CallInterface.h" 182c2e5a5dSValentin Clement #include "flang/Lower/ConvertExpr.h" 192c2e5a5dSValentin Clement #include "flang/Lower/Mangler.h" 202c2e5a5dSValentin Clement #include "flang/Lower/PFTBuilder.h" 212a59ead1SValentin Clement #include "flang/Lower/StatementContext.h" 222c2e5a5dSValentin Clement #include "flang/Lower/Support/Utils.h" 232c2e5a5dSValentin Clement #include "flang/Lower/SymbolMap.h" 242c2e5a5dSValentin Clement #include "flang/Lower/Todo.h" 252c2e5a5dSValentin Clement #include "flang/Optimizer/Builder/Character.h" 262c2e5a5dSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 272c2e5a5dSValentin Clement #include "flang/Optimizer/Builder/Runtime/Derived.h" 282c2e5a5dSValentin Clement #include "flang/Optimizer/Dialect/FIRAttr.h" 292c2e5a5dSValentin Clement #include "flang/Optimizer/Dialect/FIRDialect.h" 302c2e5a5dSValentin Clement #include "flang/Optimizer/Dialect/FIROps.h" 312c2e5a5dSValentin Clement #include "flang/Optimizer/Support/FIRContext.h" 322c2e5a5dSValentin Clement #include "flang/Optimizer/Support/FatalError.h" 332c2e5a5dSValentin Clement #include "flang/Semantics/tools.h" 342c2e5a5dSValentin Clement #include "llvm/Support/Debug.h" 352c2e5a5dSValentin Clement 362c2e5a5dSValentin Clement #define DEBUG_TYPE "flang-lower-variable" 372c2e5a5dSValentin Clement 382a59ead1SValentin Clement /// Helper to lower a scalar expression using a specific symbol mapping. 392a59ead1SValentin Clement static mlir::Value genScalarValue(Fortran::lower::AbstractConverter &converter, 402a59ead1SValentin Clement mlir::Location loc, 412a59ead1SValentin Clement const Fortran::lower::SomeExpr &expr, 422a59ead1SValentin Clement Fortran::lower::SymMap &symMap, 432a59ead1SValentin Clement Fortran::lower::StatementContext &context) { 442a59ead1SValentin Clement // This does not use the AbstractConverter member function to override the 452a59ead1SValentin Clement // symbol mapping to be used expression lowering. 462a59ead1SValentin Clement return fir::getBase(Fortran::lower::createSomeExtendedExpression( 472a59ead1SValentin Clement loc, converter, expr, symMap, context)); 482a59ead1SValentin Clement } 492a59ead1SValentin Clement 502c2e5a5dSValentin Clement //===----------------------------------------------------------------===// 512c2e5a5dSValentin Clement // Local variables instantiation (not for alias) 522c2e5a5dSValentin Clement //===----------------------------------------------------------------===// 532c2e5a5dSValentin Clement 542c2e5a5dSValentin Clement /// Create a stack slot for a local variable. Precondition: the insertion 552c2e5a5dSValentin Clement /// point of the builder must be in the entry block, which is currently being 562c2e5a5dSValentin Clement /// constructed. 572c2e5a5dSValentin Clement static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter, 582c2e5a5dSValentin Clement mlir::Location loc, 592c2e5a5dSValentin Clement const Fortran::lower::pft::Variable &var, 602c2e5a5dSValentin Clement mlir::Value preAlloc, 612c2e5a5dSValentin Clement llvm::ArrayRef<mlir::Value> shape = {}, 622c2e5a5dSValentin Clement llvm::ArrayRef<mlir::Value> lenParams = {}) { 632c2e5a5dSValentin Clement if (preAlloc) 642c2e5a5dSValentin Clement return preAlloc; 652c2e5a5dSValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 662c2e5a5dSValentin Clement std::string nm = Fortran::lower::mangle::mangleName(var.getSymbol()); 672c2e5a5dSValentin Clement mlir::Type ty = converter.genType(var); 682c2e5a5dSValentin Clement const Fortran::semantics::Symbol &ultimateSymbol = 692c2e5a5dSValentin Clement var.getSymbol().GetUltimate(); 702c2e5a5dSValentin Clement llvm::StringRef symNm = toStringRef(ultimateSymbol.name()); 712c2e5a5dSValentin Clement bool isTarg = var.isTarget(); 722c2e5a5dSValentin Clement // Let the builder do all the heavy lifting. 732c2e5a5dSValentin Clement return builder.allocateLocal(loc, ty, nm, symNm, shape, lenParams, isTarg); 742c2e5a5dSValentin Clement } 752c2e5a5dSValentin Clement 762c2e5a5dSValentin Clement /// Instantiate a local variable. Precondition: Each variable will be visited 772c2e5a5dSValentin Clement /// such that if its properties depend on other variables, the variables upon 782c2e5a5dSValentin Clement /// which its properties depend will already have been visited. 792c2e5a5dSValentin Clement static void instantiateLocal(Fortran::lower::AbstractConverter &converter, 802c2e5a5dSValentin Clement const Fortran::lower::pft::Variable &var, 812c2e5a5dSValentin Clement Fortran::lower::SymMap &symMap) { 822c2e5a5dSValentin Clement assert(!var.isAlias()); 832a59ead1SValentin Clement Fortran::lower::StatementContext stmtCtx; 842a59ead1SValentin Clement mapSymbolAttributes(converter, var, symMap, stmtCtx); 852a59ead1SValentin Clement } 862a59ead1SValentin Clement 872a59ead1SValentin Clement /// Helper to decide if a dummy argument must be tracked in an BoxValue. 882a59ead1SValentin Clement static bool lowerToBoxValue(const Fortran::semantics::Symbol &sym, 892a59ead1SValentin Clement mlir::Value dummyArg) { 902a59ead1SValentin Clement // Only dummy arguments coming as fir.box can be tracked in an BoxValue. 912a59ead1SValentin Clement if (!dummyArg || !dummyArg.getType().isa<fir::BoxType>()) 922a59ead1SValentin Clement return false; 932a59ead1SValentin Clement // Non contiguous arrays must be tracked in an BoxValue. 942a59ead1SValentin Clement if (sym.Rank() > 0 && !sym.attrs().test(Fortran::semantics::Attr::CONTIGUOUS)) 952a59ead1SValentin Clement return true; 962a59ead1SValentin Clement // Assumed rank and optional fir.box cannot yet be read while lowering the 972a59ead1SValentin Clement // specifications. 982a59ead1SValentin Clement if (Fortran::evaluate::IsAssumedRank(sym) || 992a59ead1SValentin Clement Fortran::semantics::IsOptional(sym)) 1002a59ead1SValentin Clement return true; 1012a59ead1SValentin Clement // Polymorphic entity should be tracked through a fir.box that has the 1022a59ead1SValentin Clement // dynamic type info. 1032a59ead1SValentin Clement if (const Fortran::semantics::DeclTypeSpec *type = sym.GetType()) 1042a59ead1SValentin Clement if (type->IsPolymorphic()) 1052a59ead1SValentin Clement return true; 1062a59ead1SValentin Clement return false; 1072a59ead1SValentin Clement } 1082a59ead1SValentin Clement 1092a59ead1SValentin Clement /// Compute extent from lower and upper bound. 1102a59ead1SValentin Clement static mlir::Value computeExtent(fir::FirOpBuilder &builder, mlir::Location loc, 1112a59ead1SValentin Clement mlir::Value lb, mlir::Value ub) { 1122a59ead1SValentin Clement mlir::IndexType idxTy = builder.getIndexType(); 1132a59ead1SValentin Clement // Let the folder deal with the common `ub - <const> + 1` case. 1142a59ead1SValentin Clement auto diff = builder.create<mlir::arith::SubIOp>(loc, idxTy, ub, lb); 1152a59ead1SValentin Clement mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); 1162a59ead1SValentin Clement return builder.create<mlir::arith::AddIOp>(loc, idxTy, diff, one); 1172a59ead1SValentin Clement } 1182a59ead1SValentin Clement 1192a59ead1SValentin Clement /// Lower explicit lower bounds into \p result. Does nothing if this is not an 1202a59ead1SValentin Clement /// array, or if the lower bounds are deferred, or all implicit or one. 1212a59ead1SValentin Clement static void lowerExplicitLowerBounds( 1222a59ead1SValentin Clement Fortran::lower::AbstractConverter &converter, mlir::Location loc, 1232a59ead1SValentin Clement const Fortran::lower::BoxAnalyzer &box, 1242a59ead1SValentin Clement llvm::SmallVectorImpl<mlir::Value> &result, Fortran::lower::SymMap &symMap, 1252a59ead1SValentin Clement Fortran::lower::StatementContext &stmtCtx) { 1262a59ead1SValentin Clement if (!box.isArray() || box.lboundIsAllOnes()) 1272a59ead1SValentin Clement return; 1282a59ead1SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 1292a59ead1SValentin Clement mlir::IndexType idxTy = builder.getIndexType(); 1302a59ead1SValentin Clement if (box.isStaticArray()) { 1312a59ead1SValentin Clement for (int64_t lb : box.staticLBound()) 1322a59ead1SValentin Clement result.emplace_back(builder.createIntegerConstant(loc, idxTy, lb)); 1332a59ead1SValentin Clement return; 1342a59ead1SValentin Clement } 1352a59ead1SValentin Clement for (const Fortran::semantics::ShapeSpec *spec : box.dynamicBound()) { 1362a59ead1SValentin Clement if (auto low = spec->lbound().GetExplicit()) { 1372a59ead1SValentin Clement auto expr = Fortran::lower::SomeExpr{*low}; 1382a59ead1SValentin Clement mlir::Value lb = builder.createConvert( 1392a59ead1SValentin Clement loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx)); 1402a59ead1SValentin Clement result.emplace_back(lb); 1412a59ead1SValentin Clement } else if (!spec->lbound().isColon()) { 1422a59ead1SValentin Clement // Implicit lower bound is 1 (Fortran 2018 section 8.5.8.3 point 3.) 1432a59ead1SValentin Clement result.emplace_back(builder.createIntegerConstant(loc, idxTy, 1)); 1442a59ead1SValentin Clement } 1452a59ead1SValentin Clement } 1462a59ead1SValentin Clement assert(result.empty() || result.size() == box.dynamicBound().size()); 1472a59ead1SValentin Clement } 1482a59ead1SValentin Clement 1492a59ead1SValentin Clement /// Lower explicit extents into \p result if this is an explicit-shape or 1502a59ead1SValentin Clement /// assumed-size array. Does nothing if this is not an explicit-shape or 1512a59ead1SValentin Clement /// assumed-size array. 1522a59ead1SValentin Clement static void lowerExplicitExtents(Fortran::lower::AbstractConverter &converter, 1532a59ead1SValentin Clement mlir::Location loc, 1542a59ead1SValentin Clement const Fortran::lower::BoxAnalyzer &box, 1552a59ead1SValentin Clement llvm::ArrayRef<mlir::Value> lowerBounds, 1562a59ead1SValentin Clement llvm::SmallVectorImpl<mlir::Value> &result, 1572a59ead1SValentin Clement Fortran::lower::SymMap &symMap, 1582a59ead1SValentin Clement Fortran::lower::StatementContext &stmtCtx) { 1592a59ead1SValentin Clement if (!box.isArray()) 1602a59ead1SValentin Clement return; 1612a59ead1SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 1622a59ead1SValentin Clement mlir::IndexType idxTy = builder.getIndexType(); 1632a59ead1SValentin Clement if (box.isStaticArray()) { 1642a59ead1SValentin Clement for (int64_t extent : box.staticShape()) 1652a59ead1SValentin Clement result.emplace_back(builder.createIntegerConstant(loc, idxTy, extent)); 1662a59ead1SValentin Clement return; 1672a59ead1SValentin Clement } 1682a59ead1SValentin Clement for (const auto &spec : llvm::enumerate(box.dynamicBound())) { 1692a59ead1SValentin Clement if (auto up = spec.value()->ubound().GetExplicit()) { 1702a59ead1SValentin Clement auto expr = Fortran::lower::SomeExpr{*up}; 1712a59ead1SValentin Clement mlir::Value ub = builder.createConvert( 1722a59ead1SValentin Clement loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx)); 1732a59ead1SValentin Clement if (lowerBounds.empty()) 1742a59ead1SValentin Clement result.emplace_back(ub); 1752a59ead1SValentin Clement else 1762a59ead1SValentin Clement result.emplace_back( 1772a59ead1SValentin Clement computeExtent(builder, loc, lowerBounds[spec.index()], ub)); 1782a59ead1SValentin Clement } else if (spec.value()->ubound().isStar()) { 1792a59ead1SValentin Clement // Assumed extent is undefined. Must be provided by user's code. 1802a59ead1SValentin Clement result.emplace_back(builder.create<fir::UndefOp>(loc, idxTy)); 1812a59ead1SValentin Clement } 1822a59ead1SValentin Clement } 1832a59ead1SValentin Clement assert(result.empty() || result.size() == box.dynamicBound().size()); 1842a59ead1SValentin Clement } 1852a59ead1SValentin Clement 1862a59ead1SValentin Clement /// Treat negative values as undefined. Assumed size arrays will return -1 from 1872a59ead1SValentin Clement /// the front end for example. Using negative values can produce hard to find 1882a59ead1SValentin Clement /// bugs much further along in the compilation. 1892a59ead1SValentin Clement static mlir::Value genExtentValue(fir::FirOpBuilder &builder, 1902a59ead1SValentin Clement mlir::Location loc, mlir::Type idxTy, 1912a59ead1SValentin Clement long frontEndExtent) { 1922a59ead1SValentin Clement if (frontEndExtent >= 0) 1932a59ead1SValentin Clement return builder.createIntegerConstant(loc, idxTy, frontEndExtent); 1942a59ead1SValentin Clement return builder.create<fir::UndefOp>(loc, idxTy); 1952a59ead1SValentin Clement } 1962a59ead1SValentin Clement 1972a59ead1SValentin Clement /// Lower specification expressions and attributes of variable \p var and 1982a59ead1SValentin Clement /// add it to the symbol map. 1992a59ead1SValentin Clement /// For global and aliases, the address must be pre-computed and provided 2002a59ead1SValentin Clement /// in \p preAlloc. 2012a59ead1SValentin Clement /// Dummy arguments must have already been mapped to mlir block arguments 2022a59ead1SValentin Clement /// their mapping may be updated here. 2032a59ead1SValentin Clement void Fortran::lower::mapSymbolAttributes( 2042a59ead1SValentin Clement AbstractConverter &converter, const Fortran::lower::pft::Variable &var, 2052a59ead1SValentin Clement Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx, 2062a59ead1SValentin Clement mlir::Value preAlloc) { 2072a59ead1SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 2082c2e5a5dSValentin Clement const Fortran::semantics::Symbol &sym = var.getSymbol(); 2092a59ead1SValentin Clement const mlir::Location loc = converter.genLocation(sym.name()); 2102a59ead1SValentin Clement mlir::IndexType idxTy = builder.getIndexType(); 211da7c77b8SValentin Clement const bool isDummy = Fortran::semantics::IsDummy(sym); 212da7c77b8SValentin Clement const bool isResult = Fortran::semantics::IsFunctionResult(sym); 2132a59ead1SValentin Clement const bool replace = isDummy || isResult; 2142a59ead1SValentin Clement fir::factory::CharacterExprHelper charHelp{builder, loc}; 2152a59ead1SValentin Clement Fortran::lower::BoxAnalyzer ba; 2162a59ead1SValentin Clement ba.analyze(sym); 217da7c77b8SValentin Clement 2182a59ead1SValentin Clement // First deal with pointers an allocatables, because their handling here 2192a59ead1SValentin Clement // is the same regardless of their rank. 2202a59ead1SValentin Clement if (Fortran::semantics::IsAllocatableOrPointer(sym)) { 2212a59ead1SValentin Clement // Get address of fir.box describing the entity. 2222a59ead1SValentin Clement // global 2232a59ead1SValentin Clement mlir::Value boxAlloc = preAlloc; 2242a59ead1SValentin Clement // dummy or passed result 2252a59ead1SValentin Clement if (!boxAlloc) 2262a59ead1SValentin Clement if (Fortran::lower::SymbolBox symbox = symMap.lookupSymbol(sym)) 2272a59ead1SValentin Clement boxAlloc = symbox.getAddr(); 2282a59ead1SValentin Clement // local 2292a59ead1SValentin Clement if (!boxAlloc) 2302a59ead1SValentin Clement boxAlloc = createNewLocal(converter, loc, var, preAlloc); 2312a59ead1SValentin Clement // Lower non deferred parameters. 2322a59ead1SValentin Clement llvm::SmallVector<mlir::Value> nonDeferredLenParams; 2332a59ead1SValentin Clement if (ba.isChar()) { 2342a59ead1SValentin Clement TODO(loc, "mapSymbolAttributes allocatble or pointer char"); 2352a59ead1SValentin Clement } else if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType()) { 2362a59ead1SValentin Clement if (const Fortran::semantics::DerivedTypeSpec *derived = 2372a59ead1SValentin Clement declTy->AsDerived()) 2382a59ead1SValentin Clement if (Fortran::semantics::CountLenParameters(*derived) != 0) 2392a59ead1SValentin Clement TODO(loc, 2402a59ead1SValentin Clement "derived type allocatable or pointer with length parameters"); 2412a59ead1SValentin Clement } 2422a59ead1SValentin Clement fir::MutableBoxValue box = Fortran::lower::createMutableBox( 2432a59ead1SValentin Clement converter, loc, var, boxAlloc, nonDeferredLenParams); 2442a59ead1SValentin Clement symMap.addAllocatableOrPointer(var.getSymbol(), box, replace); 2452a59ead1SValentin Clement return; 2462a59ead1SValentin Clement } 2472a59ead1SValentin Clement 2482a59ead1SValentin Clement if (isDummy) { 2492a59ead1SValentin Clement mlir::Value dummyArg = symMap.lookupSymbol(sym).getAddr(); 2502a59ead1SValentin Clement if (lowerToBoxValue(sym, dummyArg)) { 2512a59ead1SValentin Clement llvm::SmallVector<mlir::Value> lbounds; 2522a59ead1SValentin Clement llvm::SmallVector<mlir::Value> extents; 2532a59ead1SValentin Clement llvm::SmallVector<mlir::Value> explicitParams; 2542a59ead1SValentin Clement // Lower lower bounds, explicit type parameters and explicit 2552a59ead1SValentin Clement // extents if any. 2562a59ead1SValentin Clement if (ba.isChar()) 2572a59ead1SValentin Clement TODO(loc, "lowerToBoxValue character"); 2582a59ead1SValentin Clement // TODO: derived type length parameters. 2592a59ead1SValentin Clement lowerExplicitLowerBounds(converter, loc, ba, lbounds, symMap, stmtCtx); 2602a59ead1SValentin Clement lowerExplicitExtents(converter, loc, ba, lbounds, extents, symMap, 2612a59ead1SValentin Clement stmtCtx); 2622a59ead1SValentin Clement symMap.addBoxSymbol(sym, dummyArg, lbounds, explicitParams, extents, 2632a59ead1SValentin Clement replace); 2642a59ead1SValentin Clement return; 2652a59ead1SValentin Clement } 2662a59ead1SValentin Clement } 2672a59ead1SValentin Clement 2682a59ead1SValentin Clement // For symbols reaching this point, all properties are constant and can be 2692a59ead1SValentin Clement // read/computed already into ssa values. 2702a59ead1SValentin Clement 2712a59ead1SValentin Clement ba.match( 2722a59ead1SValentin Clement //===--------------------------------------------------------------===// 2732a59ead1SValentin Clement // Trivial case. 2742a59ead1SValentin Clement //===--------------------------------------------------------------===// 2752a59ead1SValentin Clement [&](const Fortran::lower::details::ScalarSym &) { 276da7c77b8SValentin Clement if (isDummy) { 277da7c77b8SValentin Clement // This is an argument. 278da7c77b8SValentin Clement if (!symMap.lookupSymbol(sym)) 279da7c77b8SValentin Clement mlir::emitError(loc, "symbol \"") 280da7c77b8SValentin Clement << toStringRef(sym.name()) << "\" must already be in map"; 281da7c77b8SValentin Clement return; 282da7c77b8SValentin Clement } else if (isResult) { 283da7c77b8SValentin Clement // Some Fortran results may be passed by argument (e.g. derived 284da7c77b8SValentin Clement // types) 285da7c77b8SValentin Clement if (symMap.lookupSymbol(sym)) 286da7c77b8SValentin Clement return; 287da7c77b8SValentin Clement } 288da7c77b8SValentin Clement // Otherwise, it's a local variable or function result. 2892a59ead1SValentin Clement mlir::Value local = createNewLocal(converter, loc, var, preAlloc); 2902c2e5a5dSValentin Clement symMap.addSymbol(sym, local); 2912a59ead1SValentin Clement }, 2922a59ead1SValentin Clement 2932a59ead1SValentin Clement //===--------------------------------------------------------------===// 2942a59ead1SValentin Clement // The non-trivial cases are when we have an argument or local that has 2952a59ead1SValentin Clement // a repetition value. Arguments might be passed as simple pointers and 2962a59ead1SValentin Clement // need to be cast to a multi-dimensional array with constant bounds 2972a59ead1SValentin Clement // (possibly with a missing column), bounds computed in the callee 2982a59ead1SValentin Clement // (here), or with bounds from the caller (boxed somewhere else). Locals 2992a59ead1SValentin Clement // have the same properties except they are never boxed arguments from 3002a59ead1SValentin Clement // the caller and never having a missing column size. 3012a59ead1SValentin Clement //===--------------------------------------------------------------===// 3022a59ead1SValentin Clement 3032a59ead1SValentin Clement [&](const Fortran::lower::details::ScalarStaticChar &x) { 304*f9704f0cSValentin Clement TODO(loc, "ScalarStaticChar variable lowering"); 3052a59ead1SValentin Clement }, 3062a59ead1SValentin Clement 3072a59ead1SValentin Clement //===--------------------------------------------------------------===// 3082a59ead1SValentin Clement 3092a59ead1SValentin Clement [&](const Fortran::lower::details::ScalarDynamicChar &x) { 310*f9704f0cSValentin Clement TODO(loc, "ScalarDynamicChar variable lowering"); 3112a59ead1SValentin Clement }, 3122a59ead1SValentin Clement 3132a59ead1SValentin Clement //===--------------------------------------------------------------===// 3142a59ead1SValentin Clement 3152a59ead1SValentin Clement [&](const Fortran::lower::details::StaticArray &x) { 3162a59ead1SValentin Clement // object shape is constant, not a character 3172a59ead1SValentin Clement mlir::Type castTy = builder.getRefType(converter.genType(var)); 3182a59ead1SValentin Clement mlir::Value addr = symMap.lookupSymbol(sym).getAddr(); 3192a59ead1SValentin Clement if (addr) 3202a59ead1SValentin Clement addr = builder.createConvert(loc, castTy, addr); 3212a59ead1SValentin Clement if (x.lboundAllOnes()) { 3222a59ead1SValentin Clement // if lower bounds are all ones, build simple shaped object 3232a59ead1SValentin Clement llvm::SmallVector<mlir::Value> shape; 3242a59ead1SValentin Clement for (int64_t i : x.shapes) 3252a59ead1SValentin Clement shape.push_back(genExtentValue(builder, loc, idxTy, i)); 3262a59ead1SValentin Clement mlir::Value local = 3272a59ead1SValentin Clement isDummy ? addr : createNewLocal(converter, loc, var, preAlloc); 3282a59ead1SValentin Clement symMap.addSymbolWithShape(sym, local, shape, isDummy); 3292a59ead1SValentin Clement return; 3302a59ead1SValentin Clement } 3312a59ead1SValentin Clement // If object is an array process the lower bound and extent values by 3322a59ead1SValentin Clement // constructing constants and populating the lbounds and extents. 3332a59ead1SValentin Clement llvm::SmallVector<mlir::Value> extents; 3342a59ead1SValentin Clement llvm::SmallVector<mlir::Value> lbounds; 3352a59ead1SValentin Clement for (auto [fst, snd] : llvm::zip(x.lbounds, x.shapes)) { 3362a59ead1SValentin Clement lbounds.emplace_back(builder.createIntegerConstant(loc, idxTy, fst)); 3372a59ead1SValentin Clement extents.emplace_back(genExtentValue(builder, loc, idxTy, snd)); 3382a59ead1SValentin Clement } 3392a59ead1SValentin Clement mlir::Value local = 3402a59ead1SValentin Clement isDummy ? addr 3412a59ead1SValentin Clement : createNewLocal(converter, loc, var, preAlloc, extents); 3422a59ead1SValentin Clement assert(isDummy || Fortran::lower::isExplicitShape(sym)); 3432a59ead1SValentin Clement symMap.addSymbolWithBounds(sym, local, extents, lbounds, isDummy); 3442a59ead1SValentin Clement }, 3452a59ead1SValentin Clement 3462a59ead1SValentin Clement //===--------------------------------------------------------------===// 3472a59ead1SValentin Clement 3482a59ead1SValentin Clement [&](const Fortran::lower::details::DynamicArray &x) { 349*f9704f0cSValentin Clement TODO(loc, "DynamicArray variable lowering"); 3502a59ead1SValentin Clement }, 3512a59ead1SValentin Clement 3522a59ead1SValentin Clement //===--------------------------------------------------------------===// 3532a59ead1SValentin Clement 3542a59ead1SValentin Clement [&](const Fortran::lower::details::StaticArrayStaticChar &x) { 355*f9704f0cSValentin Clement TODO(loc, "StaticArrayStaticChar variable lowering"); 3562a59ead1SValentin Clement }, 3572a59ead1SValentin Clement 3582a59ead1SValentin Clement //===--------------------------------------------------------------===// 3592a59ead1SValentin Clement 3602a59ead1SValentin Clement [&](const Fortran::lower::details::StaticArrayDynamicChar &x) { 361*f9704f0cSValentin Clement TODO(loc, "StaticArrayDynamicChar variable lowering"); 3622a59ead1SValentin Clement }, 3632a59ead1SValentin Clement 3642a59ead1SValentin Clement //===--------------------------------------------------------------===// 3652a59ead1SValentin Clement 3662a59ead1SValentin Clement [&](const Fortran::lower::details::DynamicArrayStaticChar &x) { 367*f9704f0cSValentin Clement TODO(loc, "DynamicArrayStaticChar variable lowering"); 3682a59ead1SValentin Clement }, 3692a59ead1SValentin Clement 3702a59ead1SValentin Clement //===--------------------------------------------------------------===// 3712a59ead1SValentin Clement 3722a59ead1SValentin Clement [&](const Fortran::lower::details::DynamicArrayDynamicChar &x) { 373*f9704f0cSValentin Clement TODO(loc, "DynamicArrayDynamicChar variable lowering"); 3742a59ead1SValentin Clement }, 3752a59ead1SValentin Clement 3762a59ead1SValentin Clement //===--------------------------------------------------------------===// 3772a59ead1SValentin Clement 3782a59ead1SValentin Clement [&](const Fortran::lower::BoxAnalyzer::None &) { 3792a59ead1SValentin Clement mlir::emitError(loc, "symbol analysis failed on ") 3802a59ead1SValentin Clement << toStringRef(sym.name()); 3812a59ead1SValentin Clement }); 3822c2e5a5dSValentin Clement } 3832c2e5a5dSValentin Clement 3842c2e5a5dSValentin Clement void Fortran::lower::instantiateVariable(AbstractConverter &converter, 3852c2e5a5dSValentin Clement const pft::Variable &var, 3862c2e5a5dSValentin Clement SymMap &symMap) { 3872c2e5a5dSValentin Clement const Fortran::semantics::Symbol &sym = var.getSymbol(); 3882c2e5a5dSValentin Clement const mlir::Location loc = converter.genLocation(sym.name()); 3892c2e5a5dSValentin Clement if (var.isAggregateStore()) { 3902c2e5a5dSValentin Clement TODO(loc, "instantiateVariable AggregateStore"); 3912c2e5a5dSValentin Clement } else if (Fortran::semantics::FindCommonBlockContaining( 3922c2e5a5dSValentin Clement var.getSymbol().GetUltimate())) { 3932c2e5a5dSValentin Clement TODO(loc, "instantiateVariable Common"); 3942c2e5a5dSValentin Clement } else if (var.isAlias()) { 3952c2e5a5dSValentin Clement TODO(loc, "instantiateVariable Alias"); 3962c2e5a5dSValentin Clement } else if (var.isGlobal()) { 3972c2e5a5dSValentin Clement TODO(loc, "instantiateVariable Global"); 3982c2e5a5dSValentin Clement } else { 3992c2e5a5dSValentin Clement instantiateLocal(converter, var, symMap); 4002c2e5a5dSValentin Clement } 4012c2e5a5dSValentin Clement } 402d0b70a07SValentin Clement 403d0b70a07SValentin Clement void Fortran::lower::mapCallInterfaceSymbols( 404d0b70a07SValentin Clement AbstractConverter &converter, const Fortran::lower::CallerInterface &caller, 405d0b70a07SValentin Clement SymMap &symMap) { 406d0b70a07SValentin Clement const Fortran::semantics::Symbol &result = caller.getResultSymbol(); 407d0b70a07SValentin Clement for (Fortran::lower::pft::Variable var : 408d0b70a07SValentin Clement Fortran::lower::pft::buildFuncResultDependencyList(result)) { 409d0b70a07SValentin Clement if (var.isAggregateStore()) { 410d0b70a07SValentin Clement instantiateVariable(converter, var, symMap); 411d0b70a07SValentin Clement } else { 412d0b70a07SValentin Clement const Fortran::semantics::Symbol &sym = var.getSymbol(); 413d0b70a07SValentin Clement const auto *hostDetails = 414d0b70a07SValentin Clement sym.detailsIf<Fortran::semantics::HostAssocDetails>(); 415d0b70a07SValentin Clement if (hostDetails && !var.isModuleVariable()) { 416d0b70a07SValentin Clement // The callee is an internal procedure `A` whose result properties 417d0b70a07SValentin Clement // depend on host variables. The caller may be the host, or another 418d0b70a07SValentin Clement // internal procedure `B` contained in the same host. In the first 419d0b70a07SValentin Clement // case, the host symbol is obviously mapped, in the second case, it 420d0b70a07SValentin Clement // must also be mapped because 421d0b70a07SValentin Clement // HostAssociations::internalProcedureBindings that was called when 422d0b70a07SValentin Clement // lowering `B` will have mapped all host symbols of captured variables 423d0b70a07SValentin Clement // to the tuple argument containing the composite of all host associated 424d0b70a07SValentin Clement // variables, whether or not the host symbol is actually referred to in 425d0b70a07SValentin Clement // `B`. Hence it is possible to simply lookup the variable associated to 426d0b70a07SValentin Clement // the host symbol without having to go back to the tuple argument. 427d0b70a07SValentin Clement Fortran::lower::SymbolBox hostValue = 428d0b70a07SValentin Clement symMap.lookupSymbol(hostDetails->symbol()); 429d0b70a07SValentin Clement assert(hostValue && "callee host symbol must be mapped on caller side"); 430d0b70a07SValentin Clement symMap.addSymbol(sym, hostValue.toExtendedValue()); 431d0b70a07SValentin Clement // The SymbolBox associated to the host symbols is complete, skip 432d0b70a07SValentin Clement // instantiateVariable that would try to allocate a new storage. 433d0b70a07SValentin Clement continue; 434d0b70a07SValentin Clement } 435d0b70a07SValentin Clement if (Fortran::semantics::IsDummy(sym) && sym.owner() == result.owner()) { 436d0b70a07SValentin Clement // Get the argument for the dummy argument symbols of the current call. 437d0b70a07SValentin Clement symMap.addSymbol(sym, caller.getArgumentValue(sym)); 438d0b70a07SValentin Clement // All the properties of the dummy variable may not come from the actual 439d0b70a07SValentin Clement // argument, let instantiateVariable handle this. 440d0b70a07SValentin Clement } 441d0b70a07SValentin Clement // If this is neither a host associated or dummy symbol, it must be a 442d0b70a07SValentin Clement // module or common block variable to satisfy specification expression 443d0b70a07SValentin Clement // requirements in 10.1.11, instantiateVariable will get its address and 444d0b70a07SValentin Clement // properties. 445d0b70a07SValentin Clement instantiateVariable(converter, var, symMap); 446d0b70a07SValentin Clement } 447d0b70a07SValentin Clement } 448d0b70a07SValentin Clement } 449