[flang-commits] [flang] [llvm] [Flang] Adding lowering for the allocation and deallocation of coarrays (PR #182110)

via flang-commits flang-commits at lists.llvm.org
Wed Feb 18 11:48:01 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Jean-Didier PAILLEUX (JDPailleux)

<details>
<summary>Changes</summary>

This PR add support of coarray allocation and deallocation in Flang and adds two new operations to MIF:
- `mif::AllocaCoarrayOp` : Allocates a coarray using `prif_allocate_coarray` PRIF procedure.
- `mif::DeallocaCoarrayOp` : Deallocates a coarray using `prif_deallocate_coarray` PRIF procedure


However, allocation for coarrays with ALLOCATABLE and/or POINTER components is not yet supported because PRIF has procedures (`prif_(de)allocate`) for this. This will be added in a future PR.

Another PR which add support of some basic intrinsics with a coarray as an argument will follow after this one.

---

Patch is 164.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/182110.diff


22 Files Affected:

- (modified) flang-rt/lib/runtime/CMakeLists.txt (+1) 
- (added) flang-rt/lib/runtime/coarray.cpp (+38) 
- (modified) flang/include/flang/Lower/MultiImageFortran.h (+19) 
- (added) flang/include/flang/Optimizer/Builder/MIFCommon.h (+26) 
- (modified) flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td (+56) 
- (modified) flang/include/flang/Optimizer/Transforms/MIFOpConversion.h (+3-1) 
- (added) flang/include/flang/Runtime/coarray.h (+24) 
- (modified) flang/lib/Lower/Allocatable.cpp (+54-8) 
- (modified) flang/lib/Lower/ConvertVariable.cpp (+31) 
- (modified) flang/lib/Lower/MultiImageFortran.cpp (+130) 
- (modified) flang/lib/Optimizer/Builder/CMakeLists.txt (+1) 
- (added) flang/lib/Optimizer/Builder/MIFCommon.cpp (+63) 
- (modified) flang/lib/Optimizer/Dialect/MIF/CMakeLists.txt (+1) 
- (modified) flang/lib/Optimizer/Dialect/MIF/MIFOps.cpp (+63) 
- (modified) flang/lib/Optimizer/Transforms/MIFOpConversion.cpp (+387-11) 
- (modified) flang/test/Fir/MIF/change_team.mlir (+28-26) 
- (added) flang/test/Fir/MIF/coarray-alloc.mlir (+157) 
- (modified) flang/test/Fir/MIF/form_team.mlir (+33-30) 
- (modified) flang/test/Fir/MIF/get_team.mlir (+51-49) 
- (modified) flang/test/Fir/MIF/sync_team.mlir (+28-26) 
- (modified) flang/test/Fir/MIF/team_number.mlir (+19-17) 
- (added) flang/test/Lower/MIF/coarray_allocation.f90 (+63) 


``````````diff
diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt
index 787d0dbbfb5ca..ea1e671aaf5b7 100644
--- a/flang-rt/lib/runtime/CMakeLists.txt
+++ b/flang-rt/lib/runtime/CMakeLists.txt
@@ -23,6 +23,7 @@ set(supported_sources
   assign.cpp
   buffer.cpp
   character.cpp
+  coarray.cpp
   connection.cpp
   copy.cpp
   derived-api.cpp
diff --git a/flang-rt/lib/runtime/coarray.cpp b/flang-rt/lib/runtime/coarray.cpp
new file mode 100644
index 0000000000000..11589efc16b72
--- /dev/null
+++ b/flang-rt/lib/runtime/coarray.cpp
@@ -0,0 +1,38 @@
+//===-- runtime/coarray.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Runtime/coarray.h"
+#include "flang-rt/runtime/descriptor.h"
+#include "flang-rt/runtime/type-info.h"
+
+namespace Fortran::runtime {
+
+extern "C" {
+RT_EXT_API_GROUP_BEGIN
+
+void RTDEF(ComputeLastUcobound)(
+    int num_images, const Descriptor &lcobounds, const Descriptor &ucobounds) {
+  int corank = ucobounds.GetDimension(0).Extent();
+  int64_t *lcobounds_ptr = (int64_t *)lcobounds.raw().base_addr;
+  int64_t *ucobounds_ptr = (int64_t *)ucobounds.raw().base_addr;
+  int64_t index = 1;
+  for (int i = 0; i < corank - 1; i++) {
+    index *= ucobounds_ptr[i] - lcobounds_ptr[i] + 1;
+  }
+  if (corank == 1)
+    ucobounds_ptr[0] = num_images - lcobounds_ptr[0] + 1;
+  else if (index < num_images)
+    ucobounds_ptr[corank - 1] =
+        (num_images / index) + (num_images % index != 0);
+  else
+    ucobounds_ptr[corank - 1] = lcobounds_ptr[corank - 1];
+}
+
+RT_EXT_API_GROUP_END
+}
+} // namespace Fortran::runtime
diff --git a/flang/include/flang/Lower/MultiImageFortran.h b/flang/include/flang/Lower/MultiImageFortran.h
index 82d415a219ae9..f029133c046cd 100644
--- a/flang/include/flang/Lower/MultiImageFortran.h
+++ b/flang/include/flang/Lower/MultiImageFortran.h
@@ -59,6 +59,25 @@ void genEndChangeTeamStmt(AbstractConverter &, pft::Evaluation &eval,
 void genFormTeamStatement(AbstractConverter &, pft::Evaluation &eval,
                           const parser::FormTeamStmt &);
 
+//===----------------------------------------------------------------------===//
+// COARRAY utils
+//===----------------------------------------------------------------------===//
+
+mlir::DenseI64ArrayAttr genLowerCoBounds(AbstractConverter &converter,
+                                         mlir::Location loc,
+                                         const semantics::Symbol &sym);
+
+mlir::DenseI64ArrayAttr genUpperCoBounds(AbstractConverter &converter,
+                                         mlir::Location loc,
+                                         const semantics::Symbol &sym);
+
+mlir::Value genAllocateCoarray(
+    AbstractConverter &converter, mlir::Location loc,
+    const semantics::Symbol &sym, mlir::Value addr,
+    const std::optional<Fortran::parser::AllocateCoarraySpec> &allocSpec =
+        std::nullopt,
+    mlir::Value errMsg = {}, bool hasStat = false);
+
 //===----------------------------------------------------------------------===//
 // COARRAY expressions
 //===----------------------------------------------------------------------===//
diff --git a/flang/include/flang/Optimizer/Builder/MIFCommon.h b/flang/include/flang/Optimizer/Builder/MIFCommon.h
new file mode 100644
index 0000000000000..6339c3255d5d8
--- /dev/null
+++ b/flang/include/flang/Optimizer/Builder/MIFCommon.h
@@ -0,0 +1,26 @@
+//===-- MIFCommon.h -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_MIFCOMMON_H_
+#define FORTRAN_OPTIMIZER_TRANSFORMS_MIFCOMMON_H_
+
+#include "flang/Lower/AbstractConverter.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
+#include "flang/Runtime/coarray.h"
+#include "mlir/IR/BuiltinOps.h"
+
+static constexpr llvm::StringRef coarrayHandleSuffix = "_coarray_handle";
+
+namespace mif {
+
+std::string getFullUniqName(mlir::Value addr);
+
+} // namespace mif
+
+#endif // FORTRAN_OPTIMIZER_TRANSFORMS_MIFCOMMON_H_
diff --git a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
index 0d95123b0f9e5..5a432c04361d6 100644
--- a/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
+++ b/flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td
@@ -17,6 +17,7 @@
 include "flang/Optimizer/Dialect/MIF/MIFDialect.td"
 include "flang/Optimizer/Dialect/FIRTypes.td"
 include "flang/Optimizer/Dialect/FIRAttr.td"
+include "mlir/IR/BuiltinAttributes.td"
 
 class mif_Op<string mnemonic, list<Trait> traits>
     : Op<MIFDialect, mnemonic, traits>;
@@ -425,4 +426,59 @@ def mif_TeamNumberOp : mif_Op<"team_number", []> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// Allocation and Deallocation
+//===----------------------------------------------------------------------===//
+
+def mif_AllocCoarrayOp
+    : mif_Op<"alloc_coarray", [AttrSizedOperandSegments,
+                               MemoryEffects<[MemAlloc<DefaultResource>]>]> {
+  let summary = "Perform the allocation of a coarray and provide a "
+                "corresponding coarray descriptor";
+
+  let description = [{
+    This operation allocates a coarray and provides the corresponding 
+    coarray descriptor. This call is collective over the current team.
+  }];
+
+  let arguments = (ins StrAttr:$uniq_name,
+      Arg<fir_ReferenceType, "", [MemRead, MemWrite]>:$box,
+      DenseI64ArrayAttr:$lcobounds, DenseI64ArrayAttr:$ucobounds,
+      Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
+      Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
+
+  let builders = [OpBuilder<(ins "mlir::Value":$box, "llvm::StringRef":$symName,
+                      "mlir::DenseI64ArrayAttr":$lcobounds,
+                      "mlir::DenseI64ArrayAttr":$ucobounds, "mlir::Value":$stat,
+                      "mlir::Value":$errmsg)>,
+                  OpBuilder<(ins "mlir::Value":$box, "llvm::StringRef":$symName,
+                      "mlir::DenseI64ArrayAttr":$lcobounds,
+                      "mlir::DenseI64ArrayAttr":$ucobounds)>];
+
+  let hasVerifier = 1;
+  let assemblyFormat = [{
+    $box 
+    (`stat` $stat^ )?
+    (`errmsg` $errmsg^ )? 
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
+def mif_DeallocCoarrayOp
+    : mif_Op<"dealloc_coarray", [AttrSizedOperandSegments,
+                                 MemoryEffects<[MemFree<DefaultResource>]>]> {
+  let summary = "Perform the deallocation of a coarray";
+  let description = [{
+    This call releases memory allocated by `mif_AllocCoarrayOp` for a coarray.
+  }];
+  let arguments = (ins Arg<fir_ReferenceType, "", [MemFree]>:$coarray,
+      Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
+      Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
+
+  let assemblyFormat = [{
+    $coarray (`stat` $stat^ )?  (`errmsg` $errmsg^ )?
+    attr-dict `:` functional-type(operands, results)
+  }];
+}
+
 #endif // FORTRAN_DIALECT_MIF_MIF_OPS
diff --git a/flang/include/flang/Optimizer/Transforms/MIFOpConversion.h b/flang/include/flang/Optimizer/Transforms/MIFOpConversion.h
index 93c724748102c..6b9e71496e847 100644
--- a/flang/include/flang/Optimizer/Transforms/MIFOpConversion.h
+++ b/flang/include/flang/Optimizer/Transforms/MIFOpConversion.h
@@ -20,7 +20,9 @@ class LLVMTypeConverter;
 namespace mif {
 
 /// Patterns that convert MIF operations to runtime calls.
-void populateMIFOpConversionPatterns(mlir::RewritePatternSet &patterns);
+void populateMIFOpConversionPatterns(const fir::LLVMTypeConverter &converter,
+                                     mlir::DataLayout &dl,
+                                     mlir::RewritePatternSet &patterns);
 
 } // namespace mif
 
diff --git a/flang/include/flang/Runtime/coarray.h b/flang/include/flang/Runtime/coarray.h
new file mode 100644
index 0000000000000..4519179489147
--- /dev/null
+++ b/flang/include/flang/Runtime/coarray.h
@@ -0,0 +1,24 @@
+//===-- include/flang/Runtime/coarray.h --------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_RUNTIME_COARRAY_H
+#define FORTRAN_RUNTIME_COARRAY_H
+
+#include "flang/Runtime/descriptor-consts.h"
+#include "flang/Runtime/entry-names.h"
+
+namespace Fortran::runtime {
+// class Descriptor;
+extern "C" {
+
+void RTDECL(ComputeLastUcobound)(
+    int num_images, const Descriptor &lcobounds, const Descriptor &ucobounds);
+}
+} // namespace Fortran::runtime
+
+#endif // FORTRAN_RUNTIME_COARRAY_H
diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp
index 1912027f8742d..839a54c651e23 100644
--- a/flang/lib/Lower/Allocatable.cpp
+++ b/flang/lib/Lower/Allocatable.cpp
@@ -18,6 +18,7 @@
 #include "flang/Lower/ConvertVariable.h"
 #include "flang/Lower/IterationSpace.h"
 #include "flang/Lower/Mangler.h"
+#include "flang/Lower/MultiImageFortran.h"
 #include "flang/Lower/OpenACC.h"
 #include "flang/Lower/PFTBuilder.h"
 #include "flang/Lower/Runtime.h"
@@ -29,6 +30,7 @@
 #include "flang/Optimizer/Dialect/CUF/CUFOps.h"
 #include "flang/Optimizer/Dialect/FIROps.h"
 #include "flang/Optimizer/Dialect/FIROpsSupport.h"
+#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
 #include "flang/Optimizer/Support/FatalError.h"
 #include "flang/Optimizer/Support/InternalNames.h"
@@ -325,11 +327,12 @@ class AllocateStmtHelper {
   struct Allocation {
     const Fortran::parser::Allocation &alloc;
     const Fortran::semantics::DeclTypeSpec &type;
-    bool hasCoarraySpec() const {
+    const std::optional<Fortran::parser::AllocateCoarraySpec> &
+    getCoarraySpec() const {
       return std::get<std::optional<Fortran::parser::AllocateCoarraySpec>>(
-                 alloc.t)
-          .has_value();
+          alloc.t);
     }
+    bool hasCoarraySpec() const { return getCoarraySpec().has_value(); }
     const Fortran::parser::AllocateObject &getAllocObj() const {
       return std::get<Fortran::parser::AllocateObject>(alloc.t);
     }
@@ -478,6 +481,29 @@ class AllocateStmtHelper {
                             !box.isPointer();
     unsigned allocatorIdx = Fortran::lower::getAllocatorIdx(alloc.getSymbol());
 
+    const Fortran::lower::SomeExpr *expr =
+        Fortran::semantics::GetExpr(alloc.getAllocObj());
+    std::optional<Fortran::evaluate::DataRef> dataRef =
+        !expr ? std::nullopt : Fortran::evaluate::ExtractDataRef(expr);
+    bool isCoarrayAllocate = alloc.hasCoarraySpec();
+
+    if (isCoarrayAllocate) {
+      errorManager.genStatCheck(builder, loc);
+      genAllocateObjectInit(box, allocatorIdx);
+      Fortran::lower::StatementContext stmtCtx;
+      genSetType(alloc, box, loc);
+      genSetDeferredLengthParameters(alloc, box);
+      genAllocateObjectBounds(alloc, box);
+      mlir::Value stat;
+      stat = Fortran::lower::genAllocateCoarray(
+          converter, loc, alloc.getSymbol(), box.getAddr(),
+          alloc.getCoarraySpec(), errorManager.errMsgAddr);
+      fir::factory::syncMutableBoxFromIRBox(builder, loc, box);
+      postAllocationAction(alloc, box);
+      errorManager.assignStat(builder, loc, stat);
+      return;
+    }
+
     if (inlineAllocation &&
         ((isCudaAllocate && isCudaDeviceContext) || !isCudaAllocate)) {
       // Pointers must use PointerAllocate so that their deallocations
@@ -501,8 +527,6 @@ class AllocateStmtHelper {
     // Generate a sequence of runtime calls.
     errorManager.genStatCheck(builder, loc);
     genAllocateObjectInit(box, allocatorIdx);
-    if (alloc.hasCoarraySpec())
-      TODO(loc, "coarray: allocation of a coarray object");
     if (alloc.type.IsPolymorphic())
       genSetType(alloc, box, loc);
     genSetDeferredLengthParameters(alloc, box);
@@ -884,13 +908,32 @@ genDeallocate(fir::FirOpBuilder &builder,
               Fortran::lower::AbstractConverter &converter, mlir::Location loc,
               const fir::MutableBoxValue &box, ErrorManager &errorManager,
               mlir::Value declaredTypeDesc = {},
-              const Fortran::semantics::Symbol *symbol = nullptr) {
+              const Fortran::semantics::Symbol *symbol = nullptr,
+              const Fortran::lower::SomeExpr *allocExpr = nullptr) {
   bool isCudaSymbol = symbol && Fortran::semantics::HasCUDAAttr(*symbol);
   bool isCudaDeviceContext = cuf::isCUDADeviceContext(builder.getRegion());
   bool inlineDeallocation =
       !box.isDerived() && !box.isPolymorphic() && !box.hasAssumedRank() &&
       !box.isUnlimitedPolymorphic() && !errorManager.hasStatSpec() &&
       !useAllocateRuntime && !box.isPointer();
+
+  std::optional<Fortran::evaluate::DataRef> dataRef =
+      !allocExpr ? std::nullopt : Fortran::evaluate::ExtractDataRef(allocExpr);
+  bool isCoarraySymbol = symbol && Fortran::evaluate::IsCoarray(*symbol);
+
+  // Deallocate coarray
+  if (isCoarraySymbol) {
+    mlir::Value ret = builder.createTemporary(loc, builder.getI32Type());
+    mif::DeallocCoarrayOp::create(builder, loc, box.getAddr(), ret,
+                                  errorManager.errMsgAddr);
+    ret = fir::LoadOp::create(builder, loc, ret);
+    fir::factory::syncMutableBoxFromIRBox(builder, loc, box);
+    if (symbol)
+      postDeallocationAction(converter, builder, *symbol);
+    errorManager.assignStat(builder, loc, ret);
+    return ret;
+  }
+
   // Deallocate intrinsic types inline.
   if (inlineDeallocation &&
       ((isCudaSymbol && isCudaDeviceContext) || !isCudaSymbol)) {
@@ -975,6 +1018,8 @@ void Fortran::lower::genDeallocateStmt(
   for (const Fortran::parser::AllocateObject &allocateObject :
        std::get<std::list<Fortran::parser::AllocateObject>>(stmt.t)) {
     const Fortran::semantics::Symbol &symbol = unwrapSymbol(allocateObject);
+    const Fortran::lower::SomeExpr *allocExpr =
+        Fortran::semantics::GetExpr(allocateObject);
     fir::MutableBoxValue box =
         genMutableBoxValue(converter, loc, allocateObject);
     mlir::Value declaredTypeDesc = {};
@@ -987,8 +1032,9 @@ void Fortran::lower::genDeallocateStmt(
               Fortran::lower::getTypeDescAddr(converter, loc, *derivedTypeSpec);
         }
     }
-    mlir::Value beginOpValue = genDeallocate(
-        builder, converter, loc, box, errorManager, declaredTypeDesc, &symbol);
+    mlir::Value beginOpValue =
+        genDeallocate(builder, converter, loc, box, errorManager,
+                      declaredTypeDesc, &symbol, allocExpr);
     preDeallocationAction(converter, builder, beginOpValue, symbol);
   }
   builder.restoreInsertionPoint(insertPt);
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 0ededb364bfea..2e308324d09ae 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -21,6 +21,7 @@
 #include "flang/Lower/ConvertExprToHLFIR.h"
 #include "flang/Lower/ConvertProcedureDesignator.h"
 #include "flang/Lower/Mangler.h"
+#include "flang/Lower/MultiImageFortran.h"
 #include "flang/Lower/PFTBuilder.h"
 #include "flang/Lower/StatementContext.h"
 #include "flang/Lower/Support/Utils.h"
@@ -36,6 +37,7 @@
 #include "flang/Optimizer/Dialect/FIRAttr.h"
 #include "flang/Optimizer/Dialect/FIRDialect.h"
 #include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
 #include "flang/Optimizer/Support/FatalError.h"
@@ -1132,6 +1134,23 @@ static void instantiateLocal(Fortran::lower::AbstractConverter &converter,
       });
     }
   }
+  if (Fortran::evaluate::IsCoarray(var.getSymbol()) &&
+      !Fortran::semantics::IsAllocatableOrPointer(var.getSymbol()) &&
+      !Fortran::semantics::IsDummy(var.getSymbol())) {
+    mlir::Location loc = converter.getCurrentLocation();
+    fir::ExtendedValue exv =
+        converter.getSymbolExtendedValue(var.getSymbol(), &symMap);
+    auto *sym = &var.getSymbol();
+    const Fortran::semantics::Scope &owner = sym->owner();
+    if (owner.kind() != Fortran::semantics::Scope::Kind::MainProgram) {
+      auto *converterPtr = &converter;
+      converter.getFctCtx().attachCleanup([converterPtr, builder, loc, exv]() {
+        mif::DeallocCoarrayOp::create(*builder, loc, fir::getBase(exv),
+                                      /*stat*/ mlir::Value{},
+                                      /*errmsg*/ mlir::Value{});
+      });
+    }
+  }
   if (std::optional<VariableCleanUp> cleanup =
           needDeallocationOrFinalization(var)) {
     auto *builder = &converter.getFirOpBuilder();
@@ -2186,6 +2205,11 @@ void Fortran::lower::mapSymbolAttributes(
   }
 
   if (isDummy) {
+    if (Fortran::evaluate::IsCoarray(sym))
+      // Operation in MIF dialect to create an alias of the coarray not
+      // yet supported (by using the procedure provided by PRIF).
+      TODO(loc, "coarray dummy argument not yet supported.");
+
     mlir::Value dummyArg = symMap.lookupSymbol(sym).getAddr();
     if (lowerToBoxValue(sym, dummyArg, converter)) {
       llvm::SmallVector<mlir::Value> lbounds;
@@ -2480,6 +2504,13 @@ void Fortran::lower::mapSymbolAttributes(
     }
   }
 
+  if (Fortran::evaluate::IsCoarray(sym)) {
+    Fortran::lower::genAllocateCoarray(converter, loc, sym, addr);
+    ::genDeclareSymbol(converter, symMap, sym, addr, len, extents, lbounds,
+                       replace);
+    return;
+  }
+
   // Allocate or extract raw address for the entity
   if (!addr) {
     if (arg) {
diff --git a/flang/lib/Lower/MultiImageFortran.cpp b/flang/lib/Lower/MultiImageFortran.cpp
index 4f5b6a500d24f..a498a10f3e74b 100644
--- a/flang/lib/Lower/MultiImageFortran.cpp
+++ b/flang/lib/Lower/MultiImageFortran.cpp
@@ -15,6 +15,7 @@
 #include "flang/Lower/AbstractConverter.h"
 #include "flang/Lower/SymbolMap.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/MIFCommon.h"
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/expression.h"
@@ -257,6 +258,135 @@ void Fortran::lower::genFormTeamStatement(
                           errMsgAddr);
 }
 
+//===----------------------------------------------------------------------===//
+// COARRAY utils
+//===----------------------------------------------------------------------===//
+
+mlir::DenseI64ArrayAttr
+Fortran::lower::genLowerCoBounds(Fortran::lower::AbstractConverter &converter,
+                                 mlir::Location loc,
+                                 const Fortran::semantics::Symbol &sym) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  mlir::DenseI64ArrayAttr lcobounds;
+
+  if (Fortran::semantics::IsAllocatableOrObjectPointer(&sym))
+    return {};
+  if (const auto *object =
+          sym.GetUltimate()
+              .detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
+    llvm::SmallVector<std::int64_t> lcbs;
+    for (const Fortran::semantics::ShapeSpec &cobounds : object->coshape()) {
+      if (auto lb = cobounds.lbound().GetExplicit()) {
+        if (auto constant = Fortran::evaluate::ToInt64(*lb))
+          lcbs.push_back(*constant);
+        else
+          lcbs.push_back(1); // default lcobounds
+      }
+    }
+    lcobounds = mlir::DenseI64ArrayAttr::get(builder.getContext(), lcbs);
+  }
+  return lcobounds;
+}
+
+mlir::DenseI64ArrayAttr
+Fortran::lower::genUpperCoBounds(Fortran::lower::AbstractConverter &converter,
+                                 mlir::Location loc,
+                                 const Fortran::semantics::Symbol &sym) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder(...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/182110


More information about the flang-commits mailing list