1 //===-- ConvertVariable.cpp -- bridge to lower to MLIR --------------------===//
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 #include "flang/Lower/ConvertVariable.h"
14 #include "flang/Lower/AbstractConverter.h"
15 #include "flang/Lower/Allocatable.h"
16 #include "flang/Lower/BoxAnalyzer.h"
17 #include "flang/Lower/CallInterface.h"
18 #include "flang/Lower/ConvertExpr.h"
19 #include "flang/Lower/IntrinsicCall.h"
20 #include "flang/Lower/Mangler.h"
21 #include "flang/Lower/PFTBuilder.h"
22 #include "flang/Lower/StatementContext.h"
23 #include "flang/Lower/Support/Utils.h"
24 #include "flang/Lower/SymbolMap.h"
25 #include "flang/Lower/Todo.h"
26 #include "flang/Optimizer/Builder/Character.h"
27 #include "flang/Optimizer/Builder/FIRBuilder.h"
28 #include "flang/Optimizer/Builder/Runtime/Derived.h"
29 #include "flang/Optimizer/Dialect/FIRAttr.h"
30 #include "flang/Optimizer/Dialect/FIRDialect.h"
31 #include "flang/Optimizer/Dialect/FIROps.h"
32 #include "flang/Optimizer/Support/FIRContext.h"
33 #include "flang/Optimizer/Support/FatalError.h"
34 #include "flang/Semantics/runtime-type-info.h"
35 #include "flang/Semantics/tools.h"
36 #include "llvm/Support/Debug.h"
37 
38 #define DEBUG_TYPE "flang-lower-variable"
39 
40 /// Helper to lower a scalar expression using a specific symbol mapping.
41 static mlir::Value genScalarValue(Fortran::lower::AbstractConverter &converter,
42                                   mlir::Location loc,
43                                   const Fortran::lower::SomeExpr &expr,
44                                   Fortran::lower::SymMap &symMap,
45                                   Fortran::lower::StatementContext &context) {
46   // This does not use the AbstractConverter member function to override the
47   // symbol mapping to be used expression lowering.
48   return fir::getBase(Fortran::lower::createSomeExtendedExpression(
49       loc, converter, expr, symMap, context));
50 }
51 
52 /// Does this variable have a default initialization?
53 static bool hasDefaultInitialization(const Fortran::semantics::Symbol &sym) {
54   if (sym.has<Fortran::semantics::ObjectEntityDetails>() && sym.size())
55     if (!Fortran::semantics::IsAllocatableOrPointer(sym))
56       if (const Fortran::semantics::DeclTypeSpec *declTypeSpec = sym.GetType())
57         if (const Fortran::semantics::DerivedTypeSpec *derivedTypeSpec =
58                 declTypeSpec->AsDerived())
59           return derivedTypeSpec->HasDefaultInitialization();
60   return false;
61 }
62 
63 //===----------------------------------------------------------------===//
64 // Global variables instantiation (not for alias and common)
65 //===----------------------------------------------------------------===//
66 
67 /// Helper to generate expression value inside global initializer.
68 static fir::ExtendedValue
69 genInitializerExprValue(Fortran::lower::AbstractConverter &converter,
70                         mlir::Location loc,
71                         const Fortran::lower::SomeExpr &expr,
72                         Fortran::lower::StatementContext &stmtCtx) {
73   // Data initializer are constant value and should not depend on other symbols
74   // given the front-end fold parameter references. In any case, the "current"
75   // map of the converter should not be used since it holds mapping to
76   // mlir::Value from another mlir region. If these value are used by accident
77   // in the initializer, this will lead to segfaults in mlir code.
78   Fortran::lower::SymMap emptyMap;
79   return Fortran::lower::createSomeInitializerExpression(loc, converter, expr,
80                                                          emptyMap, stmtCtx);
81 }
82 
83 /// Can this symbol constant be placed in read-only memory?
84 static bool isConstant(const Fortran::semantics::Symbol &sym) {
85   return sym.attrs().test(Fortran::semantics::Attr::PARAMETER) ||
86          sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
87 }
88 
89 /// Is this a compiler generated symbol to describe derived types ?
90 static bool isRuntimeTypeInfoData(const Fortran::semantics::Symbol &sym) {
91   // So far, use flags to detect if this symbol were generated during
92   // semantics::BuildRuntimeDerivedTypeTables(). Scope cannot be used since the
93   // symbols are injected in the user scopes defining the described derived
94   // types. A robustness improvement for this test could be to get hands on the
95   // semantics::RuntimeDerivedTypeTables and to check if the symbol names
96   // belongs to this structure.
97   return sym.test(Fortran::semantics::Symbol::Flag::CompilerCreated) &&
98          sym.test(Fortran::semantics::Symbol::Flag::ReadOnly);
99 }
100 
101 static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
102                                   const Fortran::lower::pft::Variable &var,
103                                   llvm::StringRef globalName,
104                                   mlir::StringAttr linkage);
105 
106 /// Create the global op declaration without any initializer
107 static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
108                                    const Fortran::lower::pft::Variable &var,
109                                    llvm::StringRef globalName,
110                                    mlir::StringAttr linkage) {
111   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
112   if (fir::GlobalOp global = builder.getNamedGlobal(globalName))
113     return global;
114   // Always define linkonce data since it may be optimized out from the module
115   // that actually owns the variable if it does not refers to it.
116   if (linkage == builder.createLinkOnceODRLinkage() ||
117       linkage == builder.createLinkOnceLinkage())
118     return defineGlobal(converter, var, globalName, linkage);
119   const Fortran::semantics::Symbol &sym = var.getSymbol();
120   mlir::Location loc = converter.genLocation(sym.name());
121   // Resolve potential host and module association before checking that this
122   // symbol is an object of a function pointer.
123   const Fortran::semantics::Symbol &ultimate = sym.GetUltimate();
124   if (!ultimate.has<Fortran::semantics::ObjectEntityDetails>() &&
125       !Fortran::semantics::IsProcedurePointer(ultimate))
126     mlir::emitError(loc, "lowering global declaration: symbol '")
127         << toStringRef(sym.name()) << "' has unexpected details\n";
128   return builder.createGlobal(loc, converter.genType(var), globalName, linkage,
129                               mlir::Attribute{}, isConstant(ultimate));
130 }
131 
132 /// Temporary helper to catch todos in initial data target lowering.
133 static bool
134 hasDerivedTypeWithLengthParameters(const Fortran::semantics::Symbol &sym) {
135   if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType())
136     if (const Fortran::semantics::DerivedTypeSpec *derived =
137             declTy->AsDerived())
138       return Fortran::semantics::CountLenParameters(*derived) > 0;
139   return false;
140 }
141 
142 static mlir::Type unwrapElementType(mlir::Type type) {
143   if (mlir::Type ty = fir::dyn_cast_ptrOrBoxEleTy(type))
144     type = ty;
145   if (auto seqType = type.dyn_cast<fir::SequenceType>())
146     type = seqType.getEleTy();
147   return type;
148 }
149 
150 fir::ExtendedValue Fortran::lower::genExtAddrInInitializer(
151     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
152     const Fortran::lower::SomeExpr &addr) {
153   Fortran::lower::SymMap globalOpSymMap;
154   Fortran::lower::AggregateStoreMap storeMap;
155   Fortran::lower::StatementContext stmtCtx;
156   if (const Fortran::semantics::Symbol *sym =
157           Fortran::evaluate::GetFirstSymbol(addr)) {
158     // Length parameters processing will need care in global initializer
159     // context.
160     if (hasDerivedTypeWithLengthParameters(*sym))
161       TODO(loc, "initial-data-target with derived type length parameters");
162 
163     auto var = Fortran::lower::pft::Variable(*sym, /*global=*/true);
164     Fortran::lower::instantiateVariable(converter, var, globalOpSymMap,
165                                         storeMap);
166   }
167   return Fortran::lower::createInitializerAddress(loc, converter, addr,
168                                                   globalOpSymMap, stmtCtx);
169 }
170 
171 /// create initial-data-target fir.box in a global initializer region.
172 mlir::Value Fortran::lower::genInitialDataTarget(
173     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
174     mlir::Type boxType, const Fortran::lower::SomeExpr &initialTarget) {
175   Fortran::lower::SymMap globalOpSymMap;
176   Fortran::lower::AggregateStoreMap storeMap;
177   Fortran::lower::StatementContext stmtCtx;
178   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
179   if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
180           initialTarget))
181     return fir::factory::createUnallocatedBox(builder, loc, boxType,
182                                               /*nonDeferredParams=*/llvm::None);
183   // Pointer initial data target, and NULL(mold).
184   if (const Fortran::semantics::Symbol *sym =
185           Fortran::evaluate::GetFirstSymbol(initialTarget)) {
186     // Length parameters processing will need care in global initializer
187     // context.
188     if (hasDerivedTypeWithLengthParameters(*sym))
189       TODO(loc, "initial-data-target with derived type length parameters");
190 
191     auto var = Fortran::lower::pft::Variable(*sym, /*global=*/true);
192     Fortran::lower::instantiateVariable(converter, var, globalOpSymMap,
193                                         storeMap);
194   }
195   mlir::Value box;
196   if (initialTarget.Rank() > 0) {
197     box = fir::getBase(Fortran::lower::createSomeArrayBox(
198         converter, initialTarget, globalOpSymMap, stmtCtx));
199   } else {
200     fir::ExtendedValue addr = Fortran::lower::createInitializerAddress(
201         loc, converter, initialTarget, globalOpSymMap, stmtCtx);
202     box = builder.createBox(loc, addr);
203   }
204   // box is a fir.box<T>, not a fir.box<fir.ptr<T>> as it should to be used
205   // for pointers. A fir.convert should not be used here, because it would
206   // not actually set the pointer attribute in the descriptor.
207   // In a normal context, fir.rebox would be used to set the pointer attribute
208   // while copying the projection from another fir.box. But fir.rebox cannot be
209   // used in initializer because its current codegen expects that the input
210   // fir.box is in memory, which is not the case in initializers.
211   // So, just replace the fir.embox that created addr with one with
212   // fir.box<fir.ptr<T>> result type.
213   // Note that the descriptor cannot have been created with fir.rebox because
214   // the initial-data-target cannot be a fir.box itself (it cannot be
215   // assumed-shape, deferred-shape, or polymorphic as per C765). However the
216   // case where the initial data target is a derived type with length parameters
217   // will most likely be a bit trickier, hence the TODO above.
218 
219   mlir::Operation *op = box.getDefiningOp();
220   if (!op || !mlir::isa<fir::EmboxOp>(*op))
221     fir::emitFatalError(
222         loc, "fir.box must be created with embox in global initializers");
223   mlir::Type targetEleTy = unwrapElementType(box.getType());
224   if (!fir::isa_char(targetEleTy))
225     return builder.create<fir::EmboxOp>(loc, boxType, op->getOperands(),
226                                         op->getAttrs());
227 
228   // Handle the character case length particularities: embox takes a length
229   // value argument when the result type has unknown length, but not when the
230   // result type has constant length. The type of the initial target must be
231   // constant length, but the one of the pointer may not be. In this case, a
232   // length operand must be added.
233   auto targetLen = targetEleTy.cast<fir::CharacterType>().getLen();
234   auto ptrLen = unwrapElementType(boxType).cast<fir::CharacterType>().getLen();
235   if (ptrLen == targetLen)
236     // Nothing to do
237     return builder.create<fir::EmboxOp>(loc, boxType, op->getOperands(),
238                                         op->getAttrs());
239   auto embox = mlir::cast<fir::EmboxOp>(*op);
240   auto ptrType = boxType.cast<fir::BoxType>().getEleTy();
241   mlir::Value memref = builder.createConvert(loc, ptrType, embox.getMemref());
242   if (targetLen == fir::CharacterType::unknownLen())
243     // Drop the length argument.
244     return builder.create<fir::EmboxOp>(loc, boxType, memref, embox.getShape(),
245                                         embox.getSlice());
246   // targetLen is constant and ptrLen is unknown. Add a length argument.
247   mlir::Value targetLenValue =
248       builder.createIntegerConstant(loc, builder.getIndexType(), targetLen);
249   return builder.create<fir::EmboxOp>(loc, boxType, memref, embox.getShape(),
250                                       embox.getSlice(),
251                                       mlir::ValueRange{targetLenValue});
252 }
253 
254 static mlir::Value genDefaultInitializerValue(
255     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
256     const Fortran::semantics::Symbol &sym, mlir::Type symTy,
257     Fortran::lower::StatementContext &stmtCtx) {
258   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
259   mlir::Type scalarType = symTy;
260   fir::SequenceType sequenceType;
261   if (auto ty = symTy.dyn_cast<fir::SequenceType>()) {
262     sequenceType = ty;
263     scalarType = ty.getEleTy();
264   }
265   // Build a scalar default value of the symbol type, looping through the
266   // components to build each component initial value.
267   auto recTy = scalarType.cast<fir::RecordType>();
268   auto fieldTy = fir::FieldType::get(scalarType.getContext());
269   mlir::Value initialValue = builder.create<fir::UndefOp>(loc, scalarType);
270   const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType();
271   assert(declTy && "var with default initialization must have a type");
272   Fortran::semantics::OrderedComponentIterator components(
273       declTy->derivedTypeSpec());
274   for (const auto &component : components) {
275     // Skip parent components, the sub-components of parent types are part of
276     // components and will be looped through right after.
277     if (component.test(Fortran::semantics::Symbol::Flag::ParentComp))
278       continue;
279     mlir::Value componentValue;
280     llvm::StringRef name = toStringRef(component.name());
281     mlir::Type componentTy = recTy.getType(name);
282     assert(componentTy && "component not found in type");
283     if (const auto *object{
284             component.detailsIf<Fortran::semantics::ObjectEntityDetails>()}) {
285       if (const auto &init = object->init()) {
286         // Component has explicit initialization.
287         if (Fortran::semantics::IsPointer(component))
288           // Initial data target.
289           componentValue =
290               genInitialDataTarget(converter, loc, componentTy, *init);
291         else
292           // Initial value.
293           componentValue = fir::getBase(
294               genInitializerExprValue(converter, loc, *init, stmtCtx));
295       } else if (Fortran::semantics::IsAllocatableOrPointer(component)) {
296         // Pointer or allocatable without initialization.
297         // Create deallocated/disassociated value.
298         // From a standard point of view, pointer without initialization do not
299         // need to be disassociated, but for sanity and simplicity, do it in
300         // global constructor since this has no runtime cost.
301         componentValue = fir::factory::createUnallocatedBox(
302             builder, loc, componentTy, llvm::None);
303       } else if (hasDefaultInitialization(component)) {
304         // Component type has default initialization.
305         componentValue = genDefaultInitializerValue(converter, loc, component,
306                                                     componentTy, stmtCtx);
307       } else {
308         // Component has no initial value.
309         componentValue = builder.create<fir::UndefOp>(loc, componentTy);
310       }
311     } else if (const auto *proc{
312                    component
313                        .detailsIf<Fortran::semantics::ProcEntityDetails>()}) {
314       if (proc->init().has_value())
315         TODO(loc, "procedure pointer component default initialization");
316       else
317         componentValue = builder.create<fir::UndefOp>(loc, componentTy);
318     }
319     assert(componentValue && "must have been computed");
320     componentValue = builder.createConvert(loc, componentTy, componentValue);
321     // FIXME: type parameters must come from the derived-type-spec
322     auto field = builder.create<fir::FieldIndexOp>(
323         loc, fieldTy, name, scalarType,
324         /*typeParams=*/mlir::ValueRange{} /*TODO*/);
325     initialValue = builder.create<fir::InsertValueOp>(
326         loc, recTy, initialValue, componentValue,
327         builder.getArrayAttr(field.getAttributes()));
328   }
329 
330   if (sequenceType) {
331     // For arrays, duplicate the scalar value to all elements with an
332     // fir.insert_range covering the whole array.
333     auto arrayInitialValue = builder.create<fir::UndefOp>(loc, sequenceType);
334     llvm::SmallVector<int64_t> rangeBounds;
335     for (int64_t extent : sequenceType.getShape()) {
336       if (extent == fir::SequenceType::getUnknownExtent())
337         TODO(loc,
338              "default initial value of array component with length parameters");
339       rangeBounds.push_back(0);
340       rangeBounds.push_back(extent - 1);
341     }
342     return builder.create<fir::InsertOnRangeOp>(
343         loc, sequenceType, arrayInitialValue, initialValue,
344         builder.getIndexVectorAttr(rangeBounds));
345   }
346   return initialValue;
347 }
348 
349 /// Does this global already have an initializer ?
350 static bool globalIsInitialized(fir::GlobalOp global) {
351   return !global.getRegion().empty() || global.getInitVal();
352 }
353 
354 /// Call \p genInit to generate code inside \p global initializer region.
355 static void
356 createGlobalInitialization(fir::FirOpBuilder &builder, fir::GlobalOp global,
357                            std::function<void(fir::FirOpBuilder &)> genInit) {
358   mlir::Region &region = global.getRegion();
359   region.push_back(new mlir::Block);
360   mlir::Block &block = region.back();
361   auto insertPt = builder.saveInsertionPoint();
362   builder.setInsertionPointToStart(&block);
363   genInit(builder);
364   builder.restoreInsertionPoint(insertPt);
365 }
366 
367 /// Create the global op and its init if it has one
368 static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
369                                   const Fortran::lower::pft::Variable &var,
370                                   llvm::StringRef globalName,
371                                   mlir::StringAttr linkage) {
372   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
373   const Fortran::semantics::Symbol &sym = var.getSymbol();
374   mlir::Location loc = converter.genLocation(sym.name());
375   bool isConst = isConstant(sym);
376   fir::GlobalOp global = builder.getNamedGlobal(globalName);
377   mlir::Type symTy = converter.genType(var);
378 
379   if (global && globalIsInitialized(global))
380     return global;
381 
382   if (Fortran::semantics::IsProcedurePointer(sym))
383     TODO(loc, "procedure pointer globals");
384 
385   // If this is an array, check to see if we can use a dense attribute
386   // with a tensor mlir type.  This optimization currently only supports
387   // rank-1 Fortran arrays of integer, real, or logical. The tensor
388   // type does not support nested structures which are needed for
389   // complex numbers.
390   // To get multidimensional arrays to work, we will have to use column major
391   // array ordering with the tensor type (so it matches column major ordering
392   // with the Fortran fir.array).  By default, tensor types assume row major
393   // ordering. How to create this tensor type is to be determined.
394   if (symTy.isa<fir::SequenceType>() && sym.Rank() == 1 &&
395       !Fortran::semantics::IsAllocatableOrPointer(sym)) {
396     mlir::Type eleTy = symTy.cast<fir::SequenceType>().getEleTy();
397     if (eleTy.isa<mlir::IntegerType, mlir::FloatType, fir::LogicalType>()) {
398       const auto *details =
399           sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
400       if (details->init()) {
401         global = Fortran::lower::createDenseGlobal(
402             loc, symTy, globalName, linkage, isConst, details->init().value(),
403             converter);
404         if (global) {
405           global.setVisibility(mlir::SymbolTable::Visibility::Public);
406           return global;
407         }
408       }
409     }
410   }
411   if (!global)
412     global = builder.createGlobal(loc, symTy, globalName, linkage,
413                                   mlir::Attribute{}, isConst);
414   if (Fortran::semantics::IsAllocatableOrPointer(sym)) {
415     const auto *details =
416         sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
417     if (details && details->init()) {
418       auto expr = *details->init();
419       createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
420         mlir::Value box =
421             Fortran::lower::genInitialDataTarget(converter, loc, symTy, expr);
422         b.create<fir::HasValueOp>(loc, box);
423       });
424     } else {
425       // Create unallocated/disassociated descriptor if no explicit init
426       createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
427         mlir::Value box =
428             fir::factory::createUnallocatedBox(b, loc, symTy, llvm::None);
429         b.create<fir::HasValueOp>(loc, box);
430       });
431     }
432 
433   } else if (const auto *details =
434                  sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
435     if (details->init()) {
436       createGlobalInitialization(
437           builder, global, [&](fir::FirOpBuilder &builder) {
438             Fortran::lower::StatementContext stmtCtx(
439                 /*cleanupProhibited=*/true);
440             fir::ExtendedValue initVal = genInitializerExprValue(
441                 converter, loc, details->init().value(), stmtCtx);
442             mlir::Value castTo =
443                 builder.createConvert(loc, symTy, fir::getBase(initVal));
444             builder.create<fir::HasValueOp>(loc, castTo);
445           });
446     } else if (hasDefaultInitialization(sym)) {
447       createGlobalInitialization(
448           builder, global, [&](fir::FirOpBuilder &builder) {
449             Fortran::lower::StatementContext stmtCtx(
450                 /*cleanupProhibited=*/true);
451             mlir::Value initVal =
452                 genDefaultInitializerValue(converter, loc, sym, symTy, stmtCtx);
453             mlir::Value castTo = builder.createConvert(loc, symTy, initVal);
454             builder.create<fir::HasValueOp>(loc, castTo);
455           });
456     }
457   } else if (sym.has<Fortran::semantics::CommonBlockDetails>()) {
458     mlir::emitError(loc, "COMMON symbol processed elsewhere");
459   } else {
460     TODO(loc, "global"); // Procedure pointer or something else
461   }
462   // Creates undefined initializer for globals without initializers
463   if (!globalIsInitialized(global))
464     createGlobalInitialization(
465         builder, global, [&](fir::FirOpBuilder &builder) {
466           builder.create<fir::HasValueOp>(
467               loc, builder.create<fir::UndefOp>(loc, symTy));
468         });
469   // Set public visibility to prevent global definition to be optimized out
470   // even if they have no initializer and are unused in this compilation unit.
471   global.setVisibility(mlir::SymbolTable::Visibility::Public);
472   return global;
473 }
474 
475 /// Return linkage attribute for \p var.
476 static mlir::StringAttr
477 getLinkageAttribute(fir::FirOpBuilder &builder,
478                     const Fortran::lower::pft::Variable &var) {
479   // Runtime type info for a same derived type is identical in each compilation
480   // unit. It desired to avoid having to link against module that only define a
481   // type. Therefore the runtime type info is generated everywhere it is needed
482   // with `linkonce_odr` LLVM linkage.
483   if (var.hasSymbol() && isRuntimeTypeInfoData(var.getSymbol()))
484     return builder.createLinkOnceODRLinkage();
485   if (var.isModuleVariable())
486     return {}; // external linkage
487   // Otherwise, the variable is owned by a procedure and must not be visible in
488   // other compilation units.
489   return builder.createInternalLinkage();
490 }
491 
492 /// Instantiate a global variable. If it hasn't already been processed, add
493 /// the global to the ModuleOp as a new uniqued symbol and initialize it with
494 /// the correct value. It will be referenced on demand using `fir.addr_of`.
495 static void instantiateGlobal(Fortran::lower::AbstractConverter &converter,
496                               const Fortran::lower::pft::Variable &var,
497                               Fortran::lower::SymMap &symMap) {
498   const Fortran::semantics::Symbol &sym = var.getSymbol();
499   assert(!var.isAlias() && "must be handled in instantiateAlias");
500   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
501   std::string globalName = Fortran::lower::mangle::mangleName(sym);
502   mlir::Location loc = converter.genLocation(sym.name());
503   fir::GlobalOp global = builder.getNamedGlobal(globalName);
504   mlir::StringAttr linkage = getLinkageAttribute(builder, var);
505   if (var.isModuleVariable()) {
506     // A module global was or will be defined when lowering the module. Emit
507     // only a declaration if the global does not exist at that point.
508     global = declareGlobal(converter, var, globalName, linkage);
509   } else {
510     global = defineGlobal(converter, var, globalName, linkage);
511   }
512   auto addrOf = builder.create<fir::AddrOfOp>(loc, global.resultType(),
513                                               global.getSymbol());
514   Fortran::lower::StatementContext stmtCtx;
515   mapSymbolAttributes(converter, var, symMap, stmtCtx, addrOf);
516 }
517 
518 //===----------------------------------------------------------------===//
519 // Local variables instantiation (not for alias)
520 //===----------------------------------------------------------------===//
521 
522 /// Create a stack slot for a local variable. Precondition: the insertion
523 /// point of the builder must be in the entry block, which is currently being
524 /// constructed.
525 static mlir::Value createNewLocal(Fortran::lower::AbstractConverter &converter,
526                                   mlir::Location loc,
527                                   const Fortran::lower::pft::Variable &var,
528                                   mlir::Value preAlloc,
529                                   llvm::ArrayRef<mlir::Value> shape = {},
530                                   llvm::ArrayRef<mlir::Value> lenParams = {}) {
531   if (preAlloc)
532     return preAlloc;
533   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
534   std::string nm = Fortran::lower::mangle::mangleName(var.getSymbol());
535   mlir::Type ty = converter.genType(var);
536   const Fortran::semantics::Symbol &ultimateSymbol =
537       var.getSymbol().GetUltimate();
538   llvm::StringRef symNm = toStringRef(ultimateSymbol.name());
539   bool isTarg = var.isTarget();
540   // Let the builder do all the heavy lifting.
541   return builder.allocateLocal(loc, ty, nm, symNm, shape, lenParams, isTarg);
542 }
543 
544 /// Must \p var be default initialized at runtime when entering its scope.
545 static bool
546 mustBeDefaultInitializedAtRuntime(const Fortran::lower::pft::Variable &var) {
547   if (!var.hasSymbol())
548     return false;
549   const Fortran::semantics::Symbol &sym = var.getSymbol();
550   if (var.isGlobal())
551     // Global variables are statically initialized.
552     return false;
553   if (Fortran::semantics::IsDummy(sym) && !Fortran::semantics::IsIntentOut(sym))
554     return false;
555   // Local variables (including function results), and intent(out) dummies must
556   // be default initialized at runtime if their type has default initialization.
557   return hasDefaultInitialization(sym);
558 }
559 
560 /// Call default initialization runtime routine to initialize \p var.
561 static void
562 defaultInitializeAtRuntime(Fortran::lower::AbstractConverter &converter,
563                            const Fortran::lower::pft::Variable &var,
564                            Fortran::lower::SymMap &symMap) {
565   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
566   mlir::Location loc = converter.getCurrentLocation();
567   const Fortran::semantics::Symbol &sym = var.getSymbol();
568   fir::ExtendedValue exv = symMap.lookupSymbol(sym).toExtendedValue();
569   if (Fortran::semantics::IsOptional(sym)) {
570     // 15.5.2.12 point 3, absent optional dummies are not initialized.
571     // Creating descriptor/passing null descriptor to the runtime would
572     // create runtime crashes.
573     auto isPresent = builder.create<fir::IsPresentOp>(loc, builder.getI1Type(),
574                                                       fir::getBase(exv));
575     builder.genIfThen(loc, isPresent)
576         .genThen([&]() {
577           auto box = builder.createBox(loc, exv);
578           fir::runtime::genDerivedTypeInitialize(builder, loc, box);
579         })
580         .end();
581   } else {
582     mlir::Value box = builder.createBox(loc, exv);
583     fir::runtime::genDerivedTypeInitialize(builder, loc, box);
584   }
585 }
586 
587 /// Instantiate a local variable. Precondition: Each variable will be visited
588 /// such that if its properties depend on other variables, the variables upon
589 /// which its properties depend will already have been visited.
590 static void instantiateLocal(Fortran::lower::AbstractConverter &converter,
591                              const Fortran::lower::pft::Variable &var,
592                              Fortran::lower::SymMap &symMap) {
593   assert(!var.isAlias());
594   Fortran::lower::StatementContext stmtCtx;
595   mapSymbolAttributes(converter, var, symMap, stmtCtx);
596   if (mustBeDefaultInitializedAtRuntime(var))
597     defaultInitializeAtRuntime(converter, var, symMap);
598 }
599 
600 //===----------------------------------------------------------------===//
601 // Aliased (EQUIVALENCE) variables instantiation
602 //===----------------------------------------------------------------===//
603 
604 /// Insert \p aggregateStore instance into an AggregateStoreMap.
605 static void insertAggregateStore(Fortran::lower::AggregateStoreMap &storeMap,
606                                  const Fortran::lower::pft::Variable &var,
607                                  mlir::Value aggregateStore) {
608   std::size_t off = var.getAggregateStore().getOffset();
609   Fortran::lower::AggregateStoreKey key = {var.getOwningScope(), off};
610   storeMap[key] = aggregateStore;
611 }
612 
613 /// Retrieve the aggregate store instance of \p alias from an
614 /// AggregateStoreMap.
615 static mlir::Value
616 getAggregateStore(Fortran::lower::AggregateStoreMap &storeMap,
617                   const Fortran::lower::pft::Variable &alias) {
618   Fortran::lower::AggregateStoreKey key = {alias.getOwningScope(),
619                                            alias.getAlias()};
620   auto iter = storeMap.find(key);
621   assert(iter != storeMap.end());
622   return iter->second;
623 }
624 
625 /// Build the name for the storage of a global equivalence.
626 static std::string mangleGlobalAggregateStore(
627     const Fortran::lower::pft::Variable::AggregateStore &st) {
628   return Fortran::lower::mangle::mangleName(st.getNamingSymbol());
629 }
630 
631 /// Build the type for the storage of an equivalence.
632 static mlir::Type
633 getAggregateType(Fortran::lower::AbstractConverter &converter,
634                  const Fortran::lower::pft::Variable::AggregateStore &st) {
635   if (const Fortran::semantics::Symbol *initSym = st.getInitialValueSymbol())
636     return converter.genType(*initSym);
637   mlir::IntegerType byteTy = converter.getFirOpBuilder().getIntegerType(8);
638   return fir::SequenceType::get(std::get<1>(st.interval), byteTy);
639 }
640 
641 /// Define a GlobalOp for the storage of a global equivalence described
642 /// by \p aggregate. The global is named \p aggName and is created with
643 /// the provided \p linkage.
644 /// If any of the equivalence members are initialized, an initializer is
645 /// created for the equivalence.
646 /// This is to be used when lowering the scope that owns the equivalence
647 /// (as opposed to simply using it through host or use association).
648 /// This is not to be used for equivalence of common block members (they
649 /// already have the common block GlobalOp for them, see defineCommonBlock).
650 static fir::GlobalOp defineGlobalAggregateStore(
651     Fortran::lower::AbstractConverter &converter,
652     const Fortran::lower::pft::Variable::AggregateStore &aggregate,
653     llvm::StringRef aggName, mlir::StringAttr linkage) {
654   assert(aggregate.isGlobal() && "not a global interval");
655   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
656   fir::GlobalOp global = builder.getNamedGlobal(aggName);
657   if (global && globalIsInitialized(global))
658     return global;
659   mlir::Location loc = converter.getCurrentLocation();
660   mlir::Type aggTy = getAggregateType(converter, aggregate);
661   if (!global)
662     global = builder.createGlobal(loc, aggTy, aggName, linkage);
663 
664   if (const Fortran::semantics::Symbol *initSym =
665           aggregate.getInitialValueSymbol())
666     if (const auto *objectDetails =
667             initSym->detailsIf<Fortran::semantics::ObjectEntityDetails>())
668       if (objectDetails->init()) {
669         createGlobalInitialization(
670             builder, global, [&](fir::FirOpBuilder &builder) {
671               Fortran::lower::StatementContext stmtCtx;
672               mlir::Value initVal = fir::getBase(genInitializerExprValue(
673                   converter, loc, objectDetails->init().value(), stmtCtx));
674               builder.create<fir::HasValueOp>(loc, initVal);
675             });
676         return global;
677       }
678   // Equivalence has no Fortran initial value. Create an undefined FIR initial
679   // value to ensure this is consider an object definition in the IR regardless
680   // of the linkage.
681   createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &builder) {
682     Fortran::lower::StatementContext stmtCtx;
683     mlir::Value initVal = builder.create<fir::UndefOp>(loc, aggTy);
684     builder.create<fir::HasValueOp>(loc, initVal);
685   });
686   return global;
687 }
688 
689 /// Declare a GlobalOp for the storage of a global equivalence described
690 /// by \p aggregate. The global is named \p aggName and is created with
691 /// the provided \p linkage.
692 /// No initializer is built for the created GlobalOp.
693 /// This is to be used when lowering the scope that uses members of an
694 /// equivalence it through host or use association.
695 /// This is not to be used for equivalence of common block members (they
696 /// already have the common block GlobalOp for them, see defineCommonBlock).
697 static fir::GlobalOp declareGlobalAggregateStore(
698     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
699     const Fortran::lower::pft::Variable::AggregateStore &aggregate,
700     llvm::StringRef aggName, mlir::StringAttr linkage) {
701   assert(aggregate.isGlobal() && "not a global interval");
702   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
703   if (fir::GlobalOp global = builder.getNamedGlobal(aggName))
704     return global;
705   mlir::Type aggTy = getAggregateType(converter, aggregate);
706   return builder.createGlobal(loc, aggTy, aggName, linkage);
707 }
708 
709 /// This is an aggregate store for a set of EQUIVALENCED variables. Create the
710 /// storage on the stack or global memory and add it to the map.
711 static void
712 instantiateAggregateStore(Fortran::lower::AbstractConverter &converter,
713                           const Fortran::lower::pft::Variable &var,
714                           Fortran::lower::AggregateStoreMap &storeMap) {
715   assert(var.isAggregateStore() && "not an interval");
716   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
717   mlir::IntegerType i8Ty = builder.getIntegerType(8);
718   mlir::Location loc = converter.getCurrentLocation();
719   std::string aggName = mangleGlobalAggregateStore(var.getAggregateStore());
720   if (var.isGlobal()) {
721     fir::GlobalOp global;
722     auto &aggregate = var.getAggregateStore();
723     mlir::StringAttr linkage = getLinkageAttribute(builder, var);
724     if (var.isModuleVariable()) {
725       // A module global was or will be defined when lowering the module. Emit
726       // only a declaration if the global does not exist at that point.
727       global = declareGlobalAggregateStore(converter, loc, aggregate, aggName,
728                                            linkage);
729     } else {
730       global =
731           defineGlobalAggregateStore(converter, aggregate, aggName, linkage);
732     }
733     auto addr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
734                                               global.getSymbol());
735     auto size = std::get<1>(var.getInterval());
736     fir::SequenceType::Shape shape(1, size);
737     auto seqTy = fir::SequenceType::get(shape, i8Ty);
738     mlir::Type refTy = builder.getRefType(seqTy);
739     mlir::Value aggregateStore = builder.createConvert(loc, refTy, addr);
740     insertAggregateStore(storeMap, var, aggregateStore);
741     return;
742   }
743   // This is a local aggregate, allocate an anonymous block of memory.
744   auto size = std::get<1>(var.getInterval());
745   fir::SequenceType::Shape shape(1, size);
746   auto seqTy = fir::SequenceType::get(shape, i8Ty);
747   mlir::Value local =
748       builder.allocateLocal(loc, seqTy, aggName, "", llvm::None, llvm::None,
749                             /*target=*/false);
750   insertAggregateStore(storeMap, var, local);
751 }
752 
753 /// Cast an alias address (variable part of an equivalence) to fir.ptr so that
754 /// the optimizer is conservative and avoids doing copy elision in assignment
755 /// involving equivalenced variables.
756 /// TODO: Represent the equivalence aliasing constraint in another way to avoid
757 /// pessimizing array assignments involving equivalenced variables.
758 static mlir::Value castAliasToPointer(fir::FirOpBuilder &builder,
759                                       mlir::Location loc, mlir::Type aliasType,
760                                       mlir::Value aliasAddr) {
761   return builder.createConvert(loc, fir::PointerType::get(aliasType),
762                                aliasAddr);
763 }
764 
765 /// Instantiate a member of an equivalence. Compute its address in its
766 /// aggregate storage and lower its attributes.
767 static void instantiateAlias(Fortran::lower::AbstractConverter &converter,
768                              const Fortran::lower::pft::Variable &var,
769                              Fortran::lower::SymMap &symMap,
770                              Fortran::lower::AggregateStoreMap &storeMap) {
771   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
772   assert(var.isAlias());
773   const Fortran::semantics::Symbol &sym = var.getSymbol();
774   const mlir::Location loc = converter.genLocation(sym.name());
775   mlir::IndexType idxTy = builder.getIndexType();
776   std::size_t aliasOffset = var.getAlias();
777   mlir::Value store = getAggregateStore(storeMap, var);
778   mlir::IntegerType i8Ty = builder.getIntegerType(8);
779   mlir::Type i8Ptr = builder.getRefType(i8Ty);
780   mlir::Value offset = builder.createIntegerConstant(
781       loc, idxTy, sym.GetUltimate().offset() - aliasOffset);
782   auto ptr = builder.create<fir::CoordinateOp>(loc, i8Ptr, store,
783                                                mlir::ValueRange{offset});
784   mlir::Value preAlloc =
785       castAliasToPointer(builder, loc, converter.genType(sym), ptr);
786   Fortran::lower::StatementContext stmtCtx;
787   mapSymbolAttributes(converter, var, symMap, stmtCtx, preAlloc);
788   // Default initialization is possible for equivalence members: see
789   // F2018 19.5.3.4. Note that if several equivalenced entities have
790   // default initialization, they must have the same type, and the standard
791   // allows the storage to be default initialized several times (this has
792   // no consequences other than wasting some execution time). For now,
793   // do not try optimizing this to single default initializations of
794   // the equivalenced storages. Keep lowering simple.
795   if (mustBeDefaultInitializedAtRuntime(var))
796     defaultInitializeAtRuntime(converter, var, symMap);
797 }
798 
799 //===--------------------------------------------------------------===//
800 // COMMON blocks instantiation
801 //===--------------------------------------------------------------===//
802 
803 /// Does any member of the common block has an initializer ?
804 static bool
805 commonBlockHasInit(const Fortran::semantics::MutableSymbolVector &cmnBlkMems) {
806   for (const Fortran::semantics::MutableSymbolRef &mem : cmnBlkMems) {
807     if (const auto *memDet =
808             mem->detailsIf<Fortran::semantics::ObjectEntityDetails>())
809       if (memDet->init())
810         return true;
811   }
812   return false;
813 }
814 
815 /// Build a tuple type for a common block based on the common block
816 /// members and the common block size.
817 /// This type is only needed to build common block initializers where
818 /// the initial value is the collection of the member initial values.
819 static mlir::TupleType getTypeOfCommonWithInit(
820     Fortran::lower::AbstractConverter &converter,
821     const Fortran::semantics::MutableSymbolVector &cmnBlkMems,
822     std::size_t commonSize) {
823   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
824   llvm::SmallVector<mlir::Type> members;
825   std::size_t counter = 0;
826   for (const Fortran::semantics::MutableSymbolRef &mem : cmnBlkMems) {
827     if (const auto *memDet =
828             mem->detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
829       if (mem->offset() > counter) {
830         fir::SequenceType::Shape len = {
831             static_cast<fir::SequenceType::Extent>(mem->offset() - counter)};
832         mlir::IntegerType byteTy = builder.getIntegerType(8);
833         auto memTy = fir::SequenceType::get(len, byteTy);
834         members.push_back(memTy);
835         counter = mem->offset();
836       }
837       if (memDet->init()) {
838         mlir::Type memTy = converter.genType(*mem);
839         members.push_back(memTy);
840         counter = mem->offset() + mem->size();
841       }
842     }
843   }
844   if (counter < commonSize) {
845     fir::SequenceType::Shape len = {
846         static_cast<fir::SequenceType::Extent>(commonSize - counter)};
847     mlir::IntegerType byteTy = builder.getIntegerType(8);
848     auto memTy = fir::SequenceType::get(len, byteTy);
849     members.push_back(memTy);
850   }
851   return mlir::TupleType::get(builder.getContext(), members);
852 }
853 
854 /// Common block members may have aliases. They are not in the common block
855 /// member list from the symbol. We need to know about these aliases if they
856 /// have initializer to generate the common initializer.
857 /// This function takes care of adding aliases with initializer to the member
858 /// list.
859 static Fortran::semantics::MutableSymbolVector
860 getCommonMembersWithInitAliases(const Fortran::semantics::Symbol &common) {
861   const auto &commonDetails =
862       common.get<Fortran::semantics::CommonBlockDetails>();
863   auto members = commonDetails.objects();
864 
865   // The number and size of equivalence and common is expected to be small, so
866   // no effort is given to optimize this loop of complexity equivalenced
867   // common members * common members
868   for (const Fortran::semantics::EquivalenceSet &set :
869        common.owner().equivalenceSets())
870     for (const Fortran::semantics::EquivalenceObject &obj : set) {
871       if (!obj.symbol.test(Fortran::semantics::Symbol::Flag::CompilerCreated)) {
872         if (const auto &details =
873                 obj.symbol
874                     .detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
875           const Fortran::semantics::Symbol *com =
876               FindCommonBlockContaining(obj.symbol);
877           if (!details->init() || com != &common)
878             continue;
879           // This is an alias with an init that belongs to the list
880           if (std::find(members.begin(), members.end(), obj.symbol) ==
881               members.end())
882             members.emplace_back(obj.symbol);
883         }
884       }
885     }
886   return members;
887 }
888 
889 /// Return the fir::GlobalOp that was created of COMMON block \p common.
890 /// It is an error if the fir::GlobalOp was not created before this is
891 /// called (it cannot be created on the flight because it is not known here
892 /// what mlir type the GlobalOp should have to satisfy all the
893 /// appearances in the program).
894 static fir::GlobalOp
895 getCommonBlockGlobal(Fortran::lower::AbstractConverter &converter,
896                      const Fortran::semantics::Symbol &common) {
897   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
898   std::string commonName = Fortran::lower::mangle::mangleName(common);
899   fir::GlobalOp global = builder.getNamedGlobal(commonName);
900   // Common blocks are lowered before any subprograms to deal with common
901   // whose size may not be the same in every subprograms.
902   if (!global)
903     fir::emitFatalError(converter.genLocation(common.name()),
904                         "COMMON block was not lowered before its usage");
905   return global;
906 }
907 
908 /// Create the fir::GlobalOp for COMMON block \p common. If \p common has an
909 /// initial value, it is not created yet. Instead, the common block list
910 /// members is returned to later create the initial value in
911 /// finalizeCommonBlockDefinition.
912 static std::optional<std::tuple<
913     fir::GlobalOp, Fortran::semantics::MutableSymbolVector, mlir::Location>>
914 declareCommonBlock(Fortran::lower::AbstractConverter &converter,
915                    const Fortran::semantics::Symbol &common,
916                    std::size_t commonSize) {
917   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
918   std::string commonName = Fortran::lower::mangle::mangleName(common);
919   fir::GlobalOp global = builder.getNamedGlobal(commonName);
920   if (global)
921     return std::nullopt;
922   Fortran::semantics::MutableSymbolVector cmnBlkMems =
923       getCommonMembersWithInitAliases(common);
924   mlir::Location loc = converter.genLocation(common.name());
925   mlir::StringAttr linkage = builder.createCommonLinkage();
926   if (!commonBlockHasInit(cmnBlkMems)) {
927     // A COMMON block sans initializers is initialized to zero.
928     // mlir::Vector types must have a strictly positive size, so at least
929     // temporarily, force a zero size COMMON block to have one byte.
930     const auto sz =
931         static_cast<fir::SequenceType::Extent>(commonSize > 0 ? commonSize : 1);
932     fir::SequenceType::Shape shape = {sz};
933     mlir::IntegerType i8Ty = builder.getIntegerType(8);
934     auto commonTy = fir::SequenceType::get(shape, i8Ty);
935     auto vecTy = mlir::VectorType::get(sz, i8Ty);
936     mlir::Attribute zero = builder.getIntegerAttr(i8Ty, 0);
937     auto init = mlir::DenseElementsAttr::get(vecTy, llvm::makeArrayRef(zero));
938     builder.createGlobal(loc, commonTy, commonName, linkage, init);
939     // No need to add any initial value later.
940     return std::nullopt;
941   }
942   // COMMON block with initializer (note that initialized blank common are
943   // accepted as an extension by semantics). Sort members by offset before
944   // generating the type and initializer.
945   std::sort(cmnBlkMems.begin(), cmnBlkMems.end(),
946             [](auto &s1, auto &s2) { return s1->offset() < s2->offset(); });
947   mlir::TupleType commonTy =
948       getTypeOfCommonWithInit(converter, cmnBlkMems, commonSize);
949   // Create the global object, the initial value will be added later.
950   global = builder.createGlobal(loc, commonTy, commonName);
951   return std::make_tuple(global, std::move(cmnBlkMems), loc);
952 }
953 
954 /// Add initial value to a COMMON block fir::GlobalOp \p global given the list
955 /// \p cmnBlkMems of the common block member symbols that contains symbols with
956 /// an initial value.
957 static void finalizeCommonBlockDefinition(
958     mlir::Location loc, Fortran::lower::AbstractConverter &converter,
959     fir::GlobalOp global,
960     const Fortran::semantics::MutableSymbolVector &cmnBlkMems) {
961   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
962   mlir::TupleType commonTy = global.getType().cast<mlir::TupleType>();
963   auto initFunc = [&](fir::FirOpBuilder &builder) {
964     mlir::IndexType idxTy = builder.getIndexType();
965     mlir::Value cb = builder.create<fir::UndefOp>(loc, commonTy);
966     unsigned tupIdx = 0;
967     std::size_t offset = 0;
968     LLVM_DEBUG(llvm::dbgs() << "block {\n");
969     for (const Fortran::semantics::MutableSymbolRef &mem : cmnBlkMems) {
970       if (const auto *memDet =
971               mem->detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
972         if (mem->offset() > offset) {
973           ++tupIdx;
974           offset = mem->offset();
975         }
976         if (memDet->init()) {
977           LLVM_DEBUG(llvm::dbgs()
978                      << "offset: " << mem->offset() << " is " << *mem << '\n');
979           Fortran::lower::StatementContext stmtCtx;
980           auto initExpr = memDet->init().value();
981           fir::ExtendedValue initVal =
982               Fortran::semantics::IsPointer(*mem)
983                   ? Fortran::lower::genInitialDataTarget(
984                         converter, loc, converter.genType(*mem), initExpr)
985                   : genInitializerExprValue(converter, loc, initExpr, stmtCtx);
986           mlir::IntegerAttr offVal = builder.getIntegerAttr(idxTy, tupIdx);
987           mlir::Value castVal = builder.createConvert(
988               loc, commonTy.getType(tupIdx), fir::getBase(initVal));
989           cb = builder.create<fir::InsertValueOp>(loc, commonTy, cb, castVal,
990                                                   builder.getArrayAttr(offVal));
991           ++tupIdx;
992           offset = mem->offset() + mem->size();
993         }
994       }
995     }
996     LLVM_DEBUG(llvm::dbgs() << "}\n");
997     builder.create<fir::HasValueOp>(loc, cb);
998   };
999   createGlobalInitialization(builder, global, initFunc);
1000 }
1001 
1002 void Fortran::lower::defineCommonBlocks(
1003     Fortran::lower::AbstractConverter &converter,
1004     const Fortran::semantics::CommonBlockList &commonBlocks) {
1005   // Common blocks may depend on another common block address (if they contain
1006   // pointers with initial targets). To cover this case, create all common block
1007   // fir::Global before creating the initial values (if any).
1008   std::vector<std::tuple<fir::GlobalOp, Fortran::semantics::MutableSymbolVector,
1009                          mlir::Location>>
1010       delayedInitializations;
1011   for (const auto &[common, size] : commonBlocks)
1012     if (auto delayedInit = declareCommonBlock(converter, common, size))
1013       delayedInitializations.emplace_back(std::move(*delayedInit));
1014   for (auto &[global, cmnBlkMems, loc] : delayedInitializations)
1015     finalizeCommonBlockDefinition(loc, converter, global, cmnBlkMems);
1016 }
1017 
1018 /// The COMMON block is a global structure. `var` will be at some offset
1019 /// within the COMMON block. Adds the address of `var` (COMMON + offset) to
1020 /// the symbol map.
1021 static void instantiateCommon(Fortran::lower::AbstractConverter &converter,
1022                               const Fortran::semantics::Symbol &common,
1023                               const Fortran::lower::pft::Variable &var,
1024                               Fortran::lower::SymMap &symMap) {
1025   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1026   const Fortran::semantics::Symbol &varSym = var.getSymbol();
1027   mlir::Location loc = converter.genLocation(varSym.name());
1028 
1029   mlir::Value commonAddr;
1030   if (Fortran::lower::SymbolBox symBox = symMap.lookupSymbol(common))
1031     commonAddr = symBox.getAddr();
1032   if (!commonAddr) {
1033     // introduce a local AddrOf and add it to the map
1034     fir::GlobalOp global = getCommonBlockGlobal(converter, common);
1035     commonAddr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
1036                                                global.getSymbol());
1037 
1038     symMap.addSymbol(common, commonAddr);
1039   }
1040   std::size_t byteOffset = varSym.GetUltimate().offset();
1041   mlir::IntegerType i8Ty = builder.getIntegerType(8);
1042   mlir::Type i8Ptr = builder.getRefType(i8Ty);
1043   mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(i8Ty));
1044   mlir::Value base = builder.createConvert(loc, seqTy, commonAddr);
1045   mlir::Value offs =
1046       builder.createIntegerConstant(loc, builder.getIndexType(), byteOffset);
1047   auto varAddr = builder.create<fir::CoordinateOp>(loc, i8Ptr, base,
1048                                                    mlir::ValueRange{offs});
1049   mlir::Type symType = converter.genType(var.getSymbol());
1050   mlir::Value local;
1051   if (Fortran::semantics::FindEquivalenceSet(var.getSymbol()) != nullptr)
1052     local = castAliasToPointer(builder, loc, symType, varAddr);
1053   else
1054     local = builder.createConvert(loc, builder.getRefType(symType), varAddr);
1055   Fortran::lower::StatementContext stmtCtx;
1056   mapSymbolAttributes(converter, var, symMap, stmtCtx, local);
1057 }
1058 
1059 //===--------------------------------------------------------------===//
1060 // Lower Variables specification expressions and attributes
1061 //===--------------------------------------------------------------===//
1062 
1063 /// Helper to decide if a dummy argument must be tracked in an BoxValue.
1064 static bool lowerToBoxValue(const Fortran::semantics::Symbol &sym,
1065                             mlir::Value dummyArg) {
1066   // Only dummy arguments coming as fir.box can be tracked in an BoxValue.
1067   if (!dummyArg || !dummyArg.getType().isa<fir::BoxType>())
1068     return false;
1069   // Non contiguous arrays must be tracked in an BoxValue.
1070   if (sym.Rank() > 0 && !sym.attrs().test(Fortran::semantics::Attr::CONTIGUOUS))
1071     return true;
1072   // Assumed rank and optional fir.box cannot yet be read while lowering the
1073   // specifications.
1074   if (Fortran::evaluate::IsAssumedRank(sym) ||
1075       Fortran::semantics::IsOptional(sym))
1076     return true;
1077   // Polymorphic entity should be tracked through a fir.box that has the
1078   // dynamic type info.
1079   if (const Fortran::semantics::DeclTypeSpec *type = sym.GetType())
1080     if (type->IsPolymorphic())
1081       return true;
1082   return false;
1083 }
1084 
1085 /// Compute extent from lower and upper bound.
1086 static mlir::Value computeExtent(fir::FirOpBuilder &builder, mlir::Location loc,
1087                                  mlir::Value lb, mlir::Value ub) {
1088   mlir::IndexType idxTy = builder.getIndexType();
1089   // Let the folder deal with the common `ub - <const> + 1` case.
1090   auto diff = builder.create<mlir::arith::SubIOp>(loc, idxTy, ub, lb);
1091   mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
1092   auto rawExtent = builder.create<mlir::arith::AddIOp>(loc, idxTy, diff, one);
1093   return Fortran::lower::genMaxWithZero(builder, loc, rawExtent);
1094 }
1095 
1096 /// Lower explicit lower bounds into \p result. Does nothing if this is not an
1097 /// array, or if the lower bounds are deferred, or all implicit or one.
1098 static void lowerExplicitLowerBounds(
1099     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
1100     const Fortran::lower::BoxAnalyzer &box,
1101     llvm::SmallVectorImpl<mlir::Value> &result, Fortran::lower::SymMap &symMap,
1102     Fortran::lower::StatementContext &stmtCtx) {
1103   if (!box.isArray() || box.lboundIsAllOnes())
1104     return;
1105   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1106   mlir::IndexType idxTy = builder.getIndexType();
1107   if (box.isStaticArray()) {
1108     for (int64_t lb : box.staticLBound())
1109       result.emplace_back(builder.createIntegerConstant(loc, idxTy, lb));
1110     return;
1111   }
1112   for (const Fortran::semantics::ShapeSpec *spec : box.dynamicBound()) {
1113     if (auto low = spec->lbound().GetExplicit()) {
1114       auto expr = Fortran::lower::SomeExpr{*low};
1115       mlir::Value lb = builder.createConvert(
1116           loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx));
1117       result.emplace_back(lb);
1118     }
1119   }
1120   assert(result.empty() || result.size() == box.dynamicBound().size());
1121 }
1122 
1123 /// Lower explicit extents into \p result if this is an explicit-shape or
1124 /// assumed-size array. Does nothing if this is not an explicit-shape or
1125 /// assumed-size array.
1126 static void
1127 lowerExplicitExtents(Fortran::lower::AbstractConverter &converter,
1128                      mlir::Location loc, const Fortran::lower::BoxAnalyzer &box,
1129                      llvm::SmallVectorImpl<mlir::Value> &lowerBounds,
1130                      llvm::SmallVectorImpl<mlir::Value> &result,
1131                      Fortran::lower::SymMap &symMap,
1132                      Fortran::lower::StatementContext &stmtCtx) {
1133   if (!box.isArray())
1134     return;
1135   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1136   mlir::IndexType idxTy = builder.getIndexType();
1137   if (box.isStaticArray()) {
1138     for (int64_t extent : box.staticShape())
1139       result.emplace_back(builder.createIntegerConstant(loc, idxTy, extent));
1140     return;
1141   }
1142   for (const auto &spec : llvm::enumerate(box.dynamicBound())) {
1143     if (auto up = spec.value()->ubound().GetExplicit()) {
1144       auto expr = Fortran::lower::SomeExpr{*up};
1145       mlir::Value ub = builder.createConvert(
1146           loc, idxTy, genScalarValue(converter, loc, expr, symMap, stmtCtx));
1147       if (lowerBounds.empty())
1148         result.emplace_back(Fortran::lower::genMaxWithZero(builder, loc, ub));
1149       else
1150         result.emplace_back(
1151             computeExtent(builder, loc, lowerBounds[spec.index()], ub));
1152     } else if (spec.value()->ubound().isStar()) {
1153       // Assumed extent is undefined. Must be provided by user's code.
1154       result.emplace_back(builder.create<fir::UndefOp>(loc, idxTy));
1155     }
1156   }
1157   assert(result.empty() || result.size() == box.dynamicBound().size());
1158 }
1159 
1160 /// Lower explicit character length if any. Return empty mlir::Value if no
1161 /// explicit length.
1162 static mlir::Value
1163 lowerExplicitCharLen(Fortran::lower::AbstractConverter &converter,
1164                      mlir::Location loc, const Fortran::lower::BoxAnalyzer &box,
1165                      Fortran::lower::SymMap &symMap,
1166                      Fortran::lower::StatementContext &stmtCtx) {
1167   if (!box.isChar())
1168     return mlir::Value{};
1169   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1170   mlir::Type lenTy = builder.getCharacterLengthType();
1171   if (llvm::Optional<int64_t> len = box.getCharLenConst())
1172     return builder.createIntegerConstant(loc, lenTy, *len);
1173   if (llvm::Optional<Fortran::lower::SomeExpr> lenExpr = box.getCharLenExpr())
1174     // If the length expression is negative, the length is zero. See F2018
1175     // 7.4.4.2 point 5.
1176     return Fortran::lower::genMaxWithZero(
1177         builder, loc,
1178         genScalarValue(converter, loc, *lenExpr, symMap, stmtCtx));
1179   return mlir::Value{};
1180 }
1181 
1182 /// Treat negative values as undefined. Assumed size arrays will return -1 from
1183 /// the front end for example. Using negative values can produce hard to find
1184 /// bugs much further along in the compilation.
1185 static mlir::Value genExtentValue(fir::FirOpBuilder &builder,
1186                                   mlir::Location loc, mlir::Type idxTy,
1187                                   long frontEndExtent) {
1188   if (frontEndExtent >= 0)
1189     return builder.createIntegerConstant(loc, idxTy, frontEndExtent);
1190   return builder.create<fir::UndefOp>(loc, idxTy);
1191 }
1192 
1193 /// Lower specification expressions and attributes of variable \p var and
1194 /// add it to the symbol map.  For a global or an alias, the address must be
1195 /// pre-computed and provided in \p preAlloc.  A dummy argument for the current
1196 /// entry point has already been mapped to an mlir block argument in
1197 /// mapDummiesAndResults.  Its mapping may be updated here.
1198 void Fortran::lower::mapSymbolAttributes(
1199     AbstractConverter &converter, const Fortran::lower::pft::Variable &var,
1200     Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
1201     mlir::Value preAlloc) {
1202   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1203   const Fortran::semantics::Symbol &sym = var.getSymbol();
1204   const mlir::Location loc = converter.genLocation(sym.name());
1205   mlir::IndexType idxTy = builder.getIndexType();
1206   const bool isDeclaredDummy = Fortran::semantics::IsDummy(sym);
1207   // An active dummy from the current entry point.
1208   const bool isDummy = isDeclaredDummy && symMap.lookupSymbol(sym).getAddr();
1209   // An unused dummy from another entry point.
1210   const bool isUnusedEntryDummy = isDeclaredDummy && !isDummy;
1211   const bool isResult = Fortran::semantics::IsFunctionResult(sym);
1212   const bool replace = isDummy || isResult;
1213   fir::factory::CharacterExprHelper charHelp{builder, loc};
1214 
1215   if (Fortran::semantics::IsProcedure(sym)) {
1216     if (isUnusedEntryDummy) {
1217       // Additional discussion below.
1218       mlir::Type dummyProcType =
1219           Fortran::lower::getDummyProcedureType(sym, converter);
1220       mlir::Value undefOp = builder.create<fir::UndefOp>(loc, dummyProcType);
1221       symMap.addSymbol(sym, undefOp);
1222     }
1223     if (Fortran::semantics::IsPointer(sym))
1224       TODO(loc, "procedure pointers");
1225     return;
1226   }
1227 
1228   Fortran::lower::BoxAnalyzer ba;
1229   ba.analyze(sym);
1230 
1231   // First deal with pointers and allocatables, because their handling here
1232   // is the same regardless of their rank.
1233   if (Fortran::semantics::IsAllocatableOrPointer(sym)) {
1234     // Get address of fir.box describing the entity.
1235     // global
1236     mlir::Value boxAlloc = preAlloc;
1237     // dummy or passed result
1238     if (!boxAlloc)
1239       if (Fortran::lower::SymbolBox symbox = symMap.lookupSymbol(sym))
1240         boxAlloc = symbox.getAddr();
1241     // local
1242     if (!boxAlloc)
1243       boxAlloc = createNewLocal(converter, loc, var, preAlloc);
1244     // Lower non deferred parameters.
1245     llvm::SmallVector<mlir::Value> nonDeferredLenParams;
1246     if (ba.isChar()) {
1247       if (mlir::Value len =
1248               lowerExplicitCharLen(converter, loc, ba, symMap, stmtCtx))
1249         nonDeferredLenParams.push_back(len);
1250       else if (Fortran::semantics::IsAssumedLengthCharacter(sym))
1251         TODO(loc, "assumed length character allocatable");
1252     } else if (const Fortran::semantics::DeclTypeSpec *declTy = sym.GetType()) {
1253       if (const Fortran::semantics::DerivedTypeSpec *derived =
1254               declTy->AsDerived())
1255         if (Fortran::semantics::CountLenParameters(*derived) != 0)
1256           TODO(loc,
1257                "derived type allocatable or pointer with length parameters");
1258     }
1259     fir::MutableBoxValue box = Fortran::lower::createMutableBox(
1260         converter, loc, var, boxAlloc, nonDeferredLenParams);
1261     symMap.addAllocatableOrPointer(var.getSymbol(), box, replace);
1262     return;
1263   }
1264 
1265   if (isDummy) {
1266     mlir::Value dummyArg = symMap.lookupSymbol(sym).getAddr();
1267     if (lowerToBoxValue(sym, dummyArg)) {
1268       llvm::SmallVector<mlir::Value> lbounds;
1269       llvm::SmallVector<mlir::Value> explicitExtents;
1270       llvm::SmallVector<mlir::Value> explicitParams;
1271       // Lower lower bounds, explicit type parameters and explicit
1272       // extents if any.
1273       if (ba.isChar())
1274         if (mlir::Value len =
1275                 lowerExplicitCharLen(converter, loc, ba, symMap, stmtCtx))
1276           explicitParams.push_back(len);
1277       // TODO: derived type length parameters.
1278       lowerExplicitLowerBounds(converter, loc, ba, lbounds, symMap, stmtCtx);
1279       lowerExplicitExtents(converter, loc, ba, lbounds, explicitExtents, symMap,
1280                            stmtCtx);
1281       symMap.addBoxSymbol(sym, dummyArg, lbounds, explicitParams,
1282                           explicitExtents, replace);
1283       return;
1284     }
1285   }
1286 
1287   // A dummy from another entry point that is not declared in the current
1288   // entry point requires a skeleton definition.  Most such "unused" dummies
1289   // will not survive into final generated code, but some will.  It is illegal
1290   // to reference one at run time if it does.  Such a dummy is mapped to a
1291   // value in one of three ways:
1292   //
1293   //  - Generate a fir::UndefOp value.  This is lightweight, easy to clean up,
1294   //    and often valid, but it may fail for a dummy with dynamic bounds,
1295   //    or a dummy used to define another dummy.  Information to distinguish
1296   //    valid cases is not generally available here, with the exception of
1297   //    dummy procedures.  See the first function exit above.
1298   //
1299   //  - Allocate an uninitialized stack slot.  This is an intermediate-weight
1300   //    solution that is harder to clean up.  It is often valid, but may fail
1301   //    for an object with dynamic bounds.  This option is "automatically"
1302   //    used by default for cases that do not use one of the other options.
1303   //
1304   //  - Allocate a heap box/descriptor, initialized to zero.  This always
1305   //    works, but is more heavyweight and harder to clean up.  It is used
1306   //    for dynamic objects via calls to genUnusedEntryPointBox.
1307 
1308   auto genUnusedEntryPointBox = [&]() {
1309     if (isUnusedEntryDummy) {
1310       assert(!Fortran::semantics::IsAllocatableOrPointer(sym) &&
1311              "handled above");
1312       // The box is read right away because lowering code does not expect
1313       // a non pointer/allocatable symbol to be mapped to a MutableBox.
1314       symMap.addSymbol(sym, fir::factory::genMutableBoxRead(
1315                                 builder, loc,
1316                                 fir::factory::createTempMutableBox(
1317                                     builder, loc, converter.genType(var))));
1318       return true;
1319     }
1320     return false;
1321   };
1322 
1323   // Helper to generate scalars for the symbol properties.
1324   auto genValue = [&](const Fortran::lower::SomeExpr &expr) {
1325     return genScalarValue(converter, loc, expr, symMap, stmtCtx);
1326   };
1327 
1328   // For symbols reaching this point, all properties are constant and can be
1329   // read/computed already into ssa values.
1330 
1331   // The origin must be \vec{1}.
1332   auto populateShape = [&](auto &shapes, const auto &bounds, mlir::Value box) {
1333     for (auto iter : llvm::enumerate(bounds)) {
1334       auto *spec = iter.value();
1335       assert(spec->lbound().GetExplicit() &&
1336              "lbound must be explicit with constant value 1");
1337       if (auto high = spec->ubound().GetExplicit()) {
1338         Fortran::lower::SomeExpr highEx{*high};
1339         mlir::Value ub = genValue(highEx);
1340         ub = builder.createConvert(loc, idxTy, ub);
1341         shapes.emplace_back(genMaxWithZero(builder, loc, ub));
1342       } else if (spec->ubound().isColon()) {
1343         assert(box && "assumed bounds require a descriptor");
1344         mlir::Value dim =
1345             builder.createIntegerConstant(loc, idxTy, iter.index());
1346         auto dimInfo =
1347             builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
1348         shapes.emplace_back(dimInfo.getResult(1));
1349       } else if (spec->ubound().isStar()) {
1350         shapes.emplace_back(builder.create<fir::UndefOp>(loc, idxTy));
1351       } else {
1352         llvm::report_fatal_error("unknown bound category");
1353       }
1354     }
1355   };
1356 
1357   // The origin is not \vec{1}.
1358   auto populateLBoundsExtents = [&](auto &lbounds, auto &extents,
1359                                     const auto &bounds, mlir::Value box) {
1360     for (auto iter : llvm::enumerate(bounds)) {
1361       auto *spec = iter.value();
1362       fir::BoxDimsOp dimInfo;
1363       mlir::Value ub, lb;
1364       if (spec->lbound().isColon() || spec->ubound().isColon()) {
1365         // This is an assumed shape because allocatables and pointers extents
1366         // are not constant in the scope and are not read here.
1367         assert(box && "deferred bounds require a descriptor");
1368         mlir::Value dim =
1369             builder.createIntegerConstant(loc, idxTy, iter.index());
1370         dimInfo =
1371             builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
1372         extents.emplace_back(dimInfo.getResult(1));
1373         if (auto low = spec->lbound().GetExplicit()) {
1374           auto expr = Fortran::lower::SomeExpr{*low};
1375           mlir::Value lb = builder.createConvert(loc, idxTy, genValue(expr));
1376           lbounds.emplace_back(lb);
1377         } else {
1378           // Implicit lower bound is 1 (Fortran 2018 section 8.5.8.3 point 3.)
1379           lbounds.emplace_back(builder.createIntegerConstant(loc, idxTy, 1));
1380         }
1381       } else {
1382         if (auto low = spec->lbound().GetExplicit()) {
1383           auto expr = Fortran::lower::SomeExpr{*low};
1384           lb = builder.createConvert(loc, idxTy, genValue(expr));
1385         } else {
1386           TODO(loc, "assumed rank lowering");
1387         }
1388         lbounds.emplace_back(lb);
1389 
1390         if (auto high = spec->ubound().GetExplicit()) {
1391           auto expr = Fortran::lower::SomeExpr{*high};
1392           ub = builder.createConvert(loc, idxTy, genValue(expr));
1393           extents.emplace_back(computeExtent(builder, loc, lb, ub));
1394         } else {
1395           // An assumed size array. The extent is not computed.
1396           assert(spec->ubound().isStar() && "expected assumed size");
1397           extents.emplace_back(builder.create<fir::UndefOp>(loc, idxTy));
1398         }
1399       }
1400     }
1401   };
1402 
1403   // Lower length expression for non deferred and non dummy assumed length
1404   // characters.
1405   auto genExplicitCharLen =
1406       [&](llvm::Optional<Fortran::lower::SomeExpr> charLen) -> mlir::Value {
1407     if (!charLen)
1408       fir::emitFatalError(loc, "expected explicit character length");
1409     mlir::Value rawLen = genValue(*charLen);
1410     // If the length expression is negative, the length is zero. See
1411     // F2018 7.4.4.2 point 5.
1412     return genMaxWithZero(builder, loc, rawLen);
1413   };
1414 
1415   ba.match(
1416       //===--------------------------------------------------------------===//
1417       // Trivial case.
1418       //===--------------------------------------------------------------===//
1419       [&](const Fortran::lower::details::ScalarSym &) {
1420         if (isDummy) {
1421           // This is an argument.
1422           if (!symMap.lookupSymbol(sym))
1423             mlir::emitError(loc, "symbol \"")
1424                 << toStringRef(sym.name()) << "\" must already be in map";
1425           return;
1426         } else if (isResult) {
1427           // Some Fortran results may be passed by argument (e.g. derived
1428           // types)
1429           if (symMap.lookupSymbol(sym))
1430             return;
1431         }
1432         // Otherwise, it's a local variable or function result.
1433         mlir::Value local = createNewLocal(converter, loc, var, preAlloc);
1434         symMap.addSymbol(sym, local);
1435       },
1436 
1437       //===--------------------------------------------------------------===//
1438       // The non-trivial cases are when we have an argument or local that has
1439       // a repetition value. Arguments might be passed as simple pointers and
1440       // need to be cast to a multi-dimensional array with constant bounds
1441       // (possibly with a missing column), bounds computed in the callee
1442       // (here), or with bounds from the caller (boxed somewhere else). Locals
1443       // have the same properties except they are never boxed arguments from
1444       // the caller and never having a missing column size.
1445       //===--------------------------------------------------------------===//
1446 
1447       [&](const Fortran::lower::details::ScalarStaticChar &x) {
1448         // type is a CHARACTER, determine the LEN value
1449         auto charLen = x.charLen();
1450         if (replace) {
1451           Fortran::lower::SymbolBox symBox = symMap.lookupSymbol(sym);
1452           std::pair<mlir::Value, mlir::Value> unboxchar =
1453               charHelp.createUnboxChar(symBox.getAddr());
1454           mlir::Value boxAddr = unboxchar.first;
1455           // Set/override LEN with a constant
1456           mlir::Value len = builder.createIntegerConstant(loc, idxTy, charLen);
1457           symMap.addCharSymbol(sym, boxAddr, len, true);
1458           return;
1459         }
1460         mlir::Value len = builder.createIntegerConstant(loc, idxTy, charLen);
1461         if (preAlloc) {
1462           symMap.addCharSymbol(sym, preAlloc, len);
1463           return;
1464         }
1465         mlir::Value local = createNewLocal(converter, loc, var, preAlloc);
1466         symMap.addCharSymbol(sym, local, len);
1467       },
1468 
1469       //===--------------------------------------------------------------===//
1470 
1471       [&](const Fortran::lower::details::ScalarDynamicChar &x) {
1472         if (genUnusedEntryPointBox())
1473           return;
1474         // type is a CHARACTER, determine the LEN value
1475         auto charLen = x.charLen();
1476         if (replace) {
1477           Fortran::lower::SymbolBox symBox = symMap.lookupSymbol(sym);
1478           mlir::Value boxAddr = symBox.getAddr();
1479           mlir::Value len;
1480           mlir::Type addrTy = boxAddr.getType();
1481           if (addrTy.isa<fir::BoxCharType>() || addrTy.isa<fir::BoxType>())
1482             std::tie(boxAddr, len) = charHelp.createUnboxChar(symBox.getAddr());
1483           // Override LEN with an expression
1484           if (charLen)
1485             len = genExplicitCharLen(charLen);
1486           symMap.addCharSymbol(sym, boxAddr, len, true);
1487           return;
1488         }
1489         // local CHARACTER variable
1490         mlir::Value len = genExplicitCharLen(charLen);
1491         if (preAlloc) {
1492           symMap.addCharSymbol(sym, preAlloc, len);
1493           return;
1494         }
1495         llvm::SmallVector<mlir::Value> lengths = {len};
1496         mlir::Value local =
1497             createNewLocal(converter, loc, var, preAlloc, llvm::None, lengths);
1498         symMap.addCharSymbol(sym, local, len);
1499       },
1500 
1501       //===--------------------------------------------------------------===//
1502 
1503       [&](const Fortran::lower::details::StaticArray &x) {
1504         // object shape is constant, not a character
1505         mlir::Type castTy = builder.getRefType(converter.genType(var));
1506         mlir::Value addr = symMap.lookupSymbol(sym).getAddr();
1507         if (addr)
1508           addr = builder.createConvert(loc, castTy, addr);
1509         if (x.lboundAllOnes()) {
1510           // if lower bounds are all ones, build simple shaped object
1511           llvm::SmallVector<mlir::Value> shape;
1512           for (int64_t i : x.shapes)
1513             shape.push_back(genExtentValue(builder, loc, idxTy, i));
1514           mlir::Value local =
1515               isDummy ? addr : createNewLocal(converter, loc, var, preAlloc);
1516           symMap.addSymbolWithShape(sym, local, shape, isDummy);
1517           return;
1518         }
1519         // If object is an array process the lower bound and extent values by
1520         // constructing constants and populating the lbounds and extents.
1521         llvm::SmallVector<mlir::Value> extents;
1522         llvm::SmallVector<mlir::Value> lbounds;
1523         for (auto [fst, snd] : llvm::zip(x.lbounds, x.shapes)) {
1524           lbounds.emplace_back(builder.createIntegerConstant(loc, idxTy, fst));
1525           extents.emplace_back(genExtentValue(builder, loc, idxTy, snd));
1526         }
1527         mlir::Value local =
1528             isDummy ? addr
1529                     : createNewLocal(converter, loc, var, preAlloc, extents);
1530         assert(isDummy || Fortran::lower::isExplicitShape(sym));
1531         symMap.addSymbolWithBounds(sym, local, extents, lbounds, isDummy);
1532       },
1533 
1534       //===--------------------------------------------------------------===//
1535 
1536       [&](const Fortran::lower::details::DynamicArray &x) {
1537         if (genUnusedEntryPointBox())
1538           return;
1539         // cast to the known constant parts from the declaration
1540         mlir::Type varType = converter.genType(var);
1541         mlir::Value addr = symMap.lookupSymbol(sym).getAddr();
1542         mlir::Value argBox;
1543         mlir::Type castTy = builder.getRefType(varType);
1544         if (addr) {
1545           if (auto boxTy = addr.getType().dyn_cast<fir::BoxType>()) {
1546             argBox = addr;
1547             mlir::Type refTy = builder.getRefType(boxTy.getEleTy());
1548             addr = builder.create<fir::BoxAddrOp>(loc, refTy, argBox);
1549           }
1550           addr = builder.createConvert(loc, castTy, addr);
1551         }
1552         if (x.lboundAllOnes()) {
1553           // if lower bounds are all ones, build simple shaped object
1554           llvm::SmallVector<mlir::Value> shapes;
1555           populateShape(shapes, x.bounds, argBox);
1556           if (isDummy) {
1557             symMap.addSymbolWithShape(sym, addr, shapes, true);
1558             return;
1559           }
1560           // local array with computed bounds
1561           assert(Fortran::lower::isExplicitShape(sym) ||
1562                  Fortran::semantics::IsAllocatableOrPointer(sym));
1563           mlir::Value local =
1564               createNewLocal(converter, loc, var, preAlloc, shapes);
1565           symMap.addSymbolWithShape(sym, local, shapes);
1566           return;
1567         }
1568         // if object is an array process the lower bound and extent values
1569         llvm::SmallVector<mlir::Value> extents;
1570         llvm::SmallVector<mlir::Value> lbounds;
1571         populateLBoundsExtents(lbounds, extents, x.bounds, argBox);
1572         if (isDummy) {
1573           symMap.addSymbolWithBounds(sym, addr, extents, lbounds, true);
1574           return;
1575         }
1576         // local array with computed bounds
1577         assert(Fortran::lower::isExplicitShape(sym));
1578         mlir::Value local =
1579             createNewLocal(converter, loc, var, preAlloc, extents);
1580         symMap.addSymbolWithBounds(sym, local, extents, lbounds);
1581       },
1582 
1583       //===--------------------------------------------------------------===//
1584 
1585       [&](const Fortran::lower::details::StaticArrayStaticChar &x) {
1586         // if element type is a CHARACTER, determine the LEN value
1587         auto charLen = x.charLen();
1588         mlir::Value addr;
1589         mlir::Value len;
1590         if (isDummy) {
1591           Fortran::lower::SymbolBox symBox = symMap.lookupSymbol(sym);
1592           std::pair<mlir::Value, mlir::Value> unboxchar =
1593               charHelp.createUnboxChar(symBox.getAddr());
1594           addr = unboxchar.first;
1595           // Set/override LEN with a constant
1596           len = builder.createIntegerConstant(loc, idxTy, charLen);
1597         } else {
1598           // local CHARACTER variable
1599           len = builder.createIntegerConstant(loc, idxTy, charLen);
1600         }
1601 
1602         // object shape is constant
1603         mlir::Type castTy = builder.getRefType(converter.genType(var));
1604         if (addr)
1605           addr = builder.createConvert(loc, castTy, addr);
1606 
1607         if (x.lboundAllOnes()) {
1608           // if lower bounds are all ones, build simple shaped object
1609           llvm::SmallVector<mlir::Value> shape;
1610           for (int64_t i : x.shapes)
1611             shape.push_back(genExtentValue(builder, loc, idxTy, i));
1612           mlir::Value local =
1613               isDummy ? addr : createNewLocal(converter, loc, var, preAlloc);
1614           symMap.addCharSymbolWithShape(sym, local, len, shape, isDummy);
1615           return;
1616         }
1617 
1618         // if object is an array process the lower bound and extent values
1619         llvm::SmallVector<mlir::Value> extents;
1620         llvm::SmallVector<mlir::Value> lbounds;
1621         // construct constants and populate `bounds`
1622         for (auto [fst, snd] : llvm::zip(x.lbounds, x.shapes)) {
1623           lbounds.emplace_back(builder.createIntegerConstant(loc, idxTy, fst));
1624           extents.emplace_back(genExtentValue(builder, loc, idxTy, snd));
1625         }
1626 
1627         if (isDummy) {
1628           symMap.addCharSymbolWithBounds(sym, addr, len, extents, lbounds,
1629                                          true);
1630           return;
1631         }
1632         // local CHARACTER array with computed bounds
1633         assert(Fortran::lower::isExplicitShape(sym));
1634         mlir::Value local =
1635             createNewLocal(converter, loc, var, preAlloc, extents);
1636         symMap.addCharSymbolWithBounds(sym, local, len, extents, lbounds);
1637       },
1638 
1639       //===--------------------------------------------------------------===//
1640 
1641       [&](const Fortran::lower::details::StaticArrayDynamicChar &x) {
1642         if (genUnusedEntryPointBox())
1643           return;
1644         mlir::Value addr;
1645         mlir::Value len;
1646         [[maybe_unused]] bool mustBeDummy = false;
1647         auto charLen = x.charLen();
1648         // if element type is a CHARACTER, determine the LEN value
1649         if (isDummy) {
1650           Fortran::lower::SymbolBox symBox = symMap.lookupSymbol(sym);
1651           std::pair<mlir::Value, mlir::Value> unboxchar =
1652               charHelp.createUnboxChar(symBox.getAddr());
1653           addr = unboxchar.first;
1654           if (charLen) {
1655             // Set/override LEN with an expression
1656             len = genExplicitCharLen(charLen);
1657           } else {
1658             // LEN is from the boxchar
1659             len = unboxchar.second;
1660             mustBeDummy = true;
1661           }
1662         } else {
1663           // local CHARACTER variable
1664           len = genExplicitCharLen(charLen);
1665         }
1666         llvm::SmallVector<mlir::Value> lengths = {len};
1667 
1668         // cast to the known constant parts from the declaration
1669         mlir::Type castTy = builder.getRefType(converter.genType(var));
1670         if (addr)
1671           addr = builder.createConvert(loc, castTy, addr);
1672 
1673         if (x.lboundAllOnes()) {
1674           // if lower bounds are all ones, build simple shaped object
1675           llvm::SmallVector<mlir::Value> shape;
1676           for (int64_t i : x.shapes)
1677             shape.push_back(genExtentValue(builder, loc, idxTy, i));
1678           if (isDummy) {
1679             symMap.addCharSymbolWithShape(sym, addr, len, shape, true);
1680             return;
1681           }
1682           // local CHARACTER array with constant size
1683           mlir::Value local = createNewLocal(converter, loc, var, preAlloc,
1684                                              llvm::None, lengths);
1685           symMap.addCharSymbolWithShape(sym, local, len, shape);
1686           return;
1687         }
1688 
1689         // if object is an array process the lower bound and extent values
1690         llvm::SmallVector<mlir::Value> extents;
1691         llvm::SmallVector<mlir::Value> lbounds;
1692 
1693         // construct constants and populate `bounds`
1694         for (auto [fst, snd] : llvm::zip(x.lbounds, x.shapes)) {
1695           lbounds.emplace_back(builder.createIntegerConstant(loc, idxTy, fst));
1696           extents.emplace_back(genExtentValue(builder, loc, idxTy, snd));
1697         }
1698         if (isDummy) {
1699           symMap.addCharSymbolWithBounds(sym, addr, len, extents, lbounds,
1700                                          true);
1701           return;
1702         }
1703         // local CHARACTER array with computed bounds
1704         assert((!mustBeDummy) && (Fortran::lower::isExplicitShape(sym)));
1705         mlir::Value local =
1706             createNewLocal(converter, loc, var, preAlloc, llvm::None, lengths);
1707         symMap.addCharSymbolWithBounds(sym, local, len, extents, lbounds);
1708       },
1709 
1710       //===--------------------------------------------------------------===//
1711 
1712       [&](const Fortran::lower::details::DynamicArrayStaticChar &x) {
1713         if (genUnusedEntryPointBox())
1714           return;
1715         mlir::Value addr;
1716         mlir::Value len;
1717         mlir::Value argBox;
1718         auto charLen = x.charLen();
1719         // if element type is a CHARACTER, determine the LEN value
1720         if (isDummy) {
1721           mlir::Value actualArg = symMap.lookupSymbol(sym).getAddr();
1722           if (auto boxTy = actualArg.getType().dyn_cast<fir::BoxType>()) {
1723             argBox = actualArg;
1724             mlir::Type refTy = builder.getRefType(boxTy.getEleTy());
1725             addr = builder.create<fir::BoxAddrOp>(loc, refTy, argBox);
1726           } else {
1727             addr = charHelp.createUnboxChar(actualArg).first;
1728           }
1729           // Set/override LEN with a constant
1730           len = builder.createIntegerConstant(loc, idxTy, charLen);
1731         } else {
1732           // local CHARACTER variable
1733           len = builder.createIntegerConstant(loc, idxTy, charLen);
1734         }
1735 
1736         // cast to the known constant parts from the declaration
1737         mlir::Type castTy = builder.getRefType(converter.genType(var));
1738         if (addr)
1739           addr = builder.createConvert(loc, castTy, addr);
1740         if (x.lboundAllOnes()) {
1741           // if lower bounds are all ones, build simple shaped object
1742           llvm::SmallVector<mlir::Value> shape;
1743           populateShape(shape, x.bounds, argBox);
1744           if (isDummy) {
1745             symMap.addCharSymbolWithShape(sym, addr, len, shape, true);
1746             return;
1747           }
1748           // local CHARACTER array
1749           mlir::Value local =
1750               createNewLocal(converter, loc, var, preAlloc, shape);
1751           symMap.addCharSymbolWithShape(sym, local, len, shape);
1752           return;
1753         }
1754         // if object is an array process the lower bound and extent values
1755         llvm::SmallVector<mlir::Value> extents;
1756         llvm::SmallVector<mlir::Value> lbounds;
1757         populateLBoundsExtents(lbounds, extents, x.bounds, argBox);
1758         if (isDummy) {
1759           symMap.addCharSymbolWithBounds(sym, addr, len, extents, lbounds,
1760                                          true);
1761           return;
1762         }
1763         // local CHARACTER array with computed bounds
1764         assert(Fortran::lower::isExplicitShape(sym));
1765         mlir::Value local =
1766             createNewLocal(converter, loc, var, preAlloc, extents);
1767         symMap.addCharSymbolWithBounds(sym, local, len, extents, lbounds);
1768       },
1769 
1770       //===--------------------------------------------------------------===//
1771 
1772       [&](const Fortran::lower::details::DynamicArrayDynamicChar &x) {
1773         if (genUnusedEntryPointBox())
1774           return;
1775         mlir::Value addr;
1776         mlir::Value len;
1777         mlir::Value argBox;
1778         auto charLen = x.charLen();
1779         // if element type is a CHARACTER, determine the LEN value
1780         if (isDummy) {
1781           mlir::Value actualArg = symMap.lookupSymbol(sym).getAddr();
1782           if (auto boxTy = actualArg.getType().dyn_cast<fir::BoxType>()) {
1783             argBox = actualArg;
1784             mlir::Type refTy = builder.getRefType(boxTy.getEleTy());
1785             addr = builder.create<fir::BoxAddrOp>(loc, refTy, argBox);
1786             if (charLen)
1787               // Set/override LEN with an expression.
1788               len = genExplicitCharLen(charLen);
1789             else
1790               // Get the length from the actual arguments.
1791               len = charHelp.readLengthFromBox(argBox);
1792           } else {
1793             std::pair<mlir::Value, mlir::Value> unboxchar =
1794                 charHelp.createUnboxChar(actualArg);
1795             addr = unboxchar.first;
1796             if (charLen) {
1797               // Set/override LEN with an expression
1798               len = genExplicitCharLen(charLen);
1799             } else {
1800               // Get the length from the actual arguments.
1801               len = unboxchar.second;
1802             }
1803           }
1804         } else {
1805           // local CHARACTER variable
1806           len = genExplicitCharLen(charLen);
1807         }
1808         llvm::SmallVector<mlir::Value> lengths = {len};
1809 
1810         // cast to the known constant parts from the declaration
1811         mlir::Type castTy = builder.getRefType(converter.genType(var));
1812         if (addr)
1813           addr = builder.createConvert(loc, castTy, addr);
1814         if (x.lboundAllOnes()) {
1815           // if lower bounds are all ones, build simple shaped object
1816           llvm::SmallVector<mlir::Value> shape;
1817           populateShape(shape, x.bounds, argBox);
1818           if (isDummy) {
1819             symMap.addCharSymbolWithShape(sym, addr, len, shape, true);
1820             return;
1821           }
1822           // local CHARACTER array
1823           mlir::Value local =
1824               createNewLocal(converter, loc, var, preAlloc, shape, lengths);
1825           symMap.addCharSymbolWithShape(sym, local, len, shape);
1826           return;
1827         }
1828         // Process the lower bound and extent values.
1829         llvm::SmallVector<mlir::Value> extents;
1830         llvm::SmallVector<mlir::Value> lbounds;
1831         populateLBoundsExtents(lbounds, extents, x.bounds, argBox);
1832         if (isDummy) {
1833           symMap.addCharSymbolWithBounds(sym, addr, len, extents, lbounds,
1834                                          true);
1835           return;
1836         }
1837         // local CHARACTER array with computed bounds
1838         assert(Fortran::lower::isExplicitShape(sym));
1839         mlir::Value local =
1840             createNewLocal(converter, loc, var, preAlloc, extents, lengths);
1841         symMap.addCharSymbolWithBounds(sym, local, len, extents, lbounds);
1842       },
1843 
1844       //===--------------------------------------------------------------===//
1845 
1846       [&](const Fortran::lower::BoxAnalyzer::None &) {
1847         mlir::emitError(loc, "symbol analysis failed on ")
1848             << toStringRef(sym.name());
1849       });
1850 }
1851 
1852 void Fortran::lower::defineModuleVariable(
1853     AbstractConverter &converter, const Fortran::lower::pft::Variable &var) {
1854   // Use empty linkage for module variables, which makes them available
1855   // for use in another unit.
1856   mlir::StringAttr linkage =
1857       getLinkageAttribute(converter.getFirOpBuilder(), var);
1858   if (!var.isGlobal())
1859     fir::emitFatalError(converter.getCurrentLocation(),
1860                         "attempting to lower module variable as local");
1861   // Define aggregate storages for equivalenced objects.
1862   if (var.isAggregateStore()) {
1863     const Fortran::lower::pft::Variable::AggregateStore &aggregate =
1864         var.getAggregateStore();
1865     std::string aggName = mangleGlobalAggregateStore(aggregate);
1866     defineGlobalAggregateStore(converter, aggregate, aggName, linkage);
1867     return;
1868   }
1869   const Fortran::semantics::Symbol &sym = var.getSymbol();
1870   if (const Fortran::semantics::Symbol *common =
1871           Fortran::semantics::FindCommonBlockContaining(var.getSymbol())) {
1872     // Nothing to do, common block are generated before everything. Ensure
1873     // this was done by calling getCommonBlockGlobal.
1874     getCommonBlockGlobal(converter, *common);
1875   } else if (var.isAlias()) {
1876     // Do nothing. Mapping will be done on user side.
1877   } else {
1878     std::string globalName = Fortran::lower::mangle::mangleName(sym);
1879     defineGlobal(converter, var, globalName, linkage);
1880   }
1881 }
1882 
1883 void Fortran::lower::instantiateVariable(AbstractConverter &converter,
1884                                          const pft::Variable &var,
1885                                          Fortran::lower::SymMap &symMap,
1886                                          AggregateStoreMap &storeMap) {
1887   if (var.isAggregateStore()) {
1888     instantiateAggregateStore(converter, var, storeMap);
1889   } else if (const Fortran::semantics::Symbol *common =
1890                  Fortran::semantics::FindCommonBlockContaining(
1891                      var.getSymbol().GetUltimate())) {
1892     instantiateCommon(converter, *common, var, symMap);
1893   } else if (var.isAlias()) {
1894     instantiateAlias(converter, var, symMap, storeMap);
1895   } else if (var.isGlobal()) {
1896     instantiateGlobal(converter, var, symMap);
1897   } else {
1898     instantiateLocal(converter, var, symMap);
1899   }
1900 }
1901 
1902 void Fortran::lower::mapCallInterfaceSymbols(
1903     AbstractConverter &converter, const Fortran::lower::CallerInterface &caller,
1904     SymMap &symMap) {
1905   Fortran::lower::AggregateStoreMap storeMap;
1906   const Fortran::semantics::Symbol &result = caller.getResultSymbol();
1907   for (Fortran::lower::pft::Variable var :
1908        Fortran::lower::pft::buildFuncResultDependencyList(result)) {
1909     if (var.isAggregateStore()) {
1910       instantiateVariable(converter, var, symMap, storeMap);
1911     } else {
1912       const Fortran::semantics::Symbol &sym = var.getSymbol();
1913       const auto *hostDetails =
1914           sym.detailsIf<Fortran::semantics::HostAssocDetails>();
1915       if (hostDetails && !var.isModuleVariable()) {
1916         // The callee is an internal procedure `A` whose result properties
1917         // depend on host variables. The caller may be the host, or another
1918         // internal procedure `B` contained in the same host.  In the first
1919         // case, the host symbol is obviously mapped, in the second case, it
1920         // must also be mapped because
1921         // HostAssociations::internalProcedureBindings that was called when
1922         // lowering `B` will have mapped all host symbols of captured variables
1923         // to the tuple argument containing the composite of all host associated
1924         // variables, whether or not the host symbol is actually referred to in
1925         // `B`. Hence it is possible to simply lookup the variable associated to
1926         // the host symbol without having to go back to the tuple argument.
1927         Fortran::lower::SymbolBox hostValue =
1928             symMap.lookupSymbol(hostDetails->symbol());
1929         assert(hostValue && "callee host symbol must be mapped on caller side");
1930         symMap.addSymbol(sym, hostValue.toExtendedValue());
1931         // The SymbolBox associated to the host symbols is complete, skip
1932         // instantiateVariable that would try to allocate a new storage.
1933         continue;
1934       }
1935       if (Fortran::semantics::IsDummy(sym) && sym.owner() == result.owner()) {
1936         // Get the argument for the dummy argument symbols of the current call.
1937         symMap.addSymbol(sym, caller.getArgumentValue(sym));
1938         // All the properties of the dummy variable may not come from the actual
1939         // argument, let instantiateVariable handle this.
1940       }
1941       // If this is neither a host associated or dummy symbol, it must be a
1942       // module or common block variable to satisfy specification expression
1943       // requirements in 10.1.11, instantiateVariable will get its address and
1944       // properties.
1945       instantiateVariable(converter, var, symMap, storeMap);
1946     }
1947   }
1948 }
1949 
1950 void Fortran::lower::createRuntimeTypeInfoGlobal(
1951     Fortran::lower::AbstractConverter &converter, mlir::Location loc,
1952     const Fortran::semantics::Symbol &typeInfoSym) {
1953   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1954   std::string globalName = Fortran::lower::mangle::mangleName(typeInfoSym);
1955   auto var = Fortran::lower::pft::Variable(typeInfoSym, /*global=*/true);
1956   mlir::StringAttr linkage = getLinkageAttribute(builder, var);
1957   defineGlobal(converter, var, globalName, linkage);
1958 }
1959