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

Dan Bonachea via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 5 21:01:45 PST 2026


================
@@ -47,6 +54,239 @@ static mlir::Type getPRIFErrmsgType(fir::FirOpBuilder &builder) {
       builder.getContext(), 1, fir::CharacterType::unknownLen()));
 }
 
+static mlir::Type
+genBoxedSequenceType(mlir::Type eleTy,
+                     std::optional<int64_t> rank = std::nullopt) {
+  if (rank.has_value())
+    return fir::BoxType::get(fir::SequenceType::get({rank.value()}, eleTy));
+  return fir::BoxType::get(
+      fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, eleTy));
+}
+
+static mlir::Type getCoarrayHandleType(fir::FirOpBuilder &builder,
+                                       mlir::Location loc) {
+  // Defining the coarray handle type
+  std::string handleDTName =
+      fir::NameUniquer::doType({"prif"}, {}, 0, "prif_coarray_handle", {});
+  fir::RecordType handleTy =
+      fir::RecordType::get(builder.getContext(), handleDTName);
+  mlir::Type infoTy =
+      fir::BoxType::get(fir::PointerType::get(builder.getNoneType()));
+  handleTy.finalize({}, {{"info", infoTy}});
+
+  // Checking if the type information was generated
+  fir::TypeInfoOp dt;
+  fir::RecordType parentType{};
+  mlir::OpBuilder::InsertPoint insertPointIfCreated;
+  std::tie(dt, insertPointIfCreated) =
+      builder.createTypeInfoOp(loc, handleTy, parentType);
+  if (insertPointIfCreated.isSet()) {
+    // fir.type_info wasn't built in a previous call.
+    dt->setAttr(dt.getNoInitAttrName(), builder.getUnitAttr());
+    dt->setAttr(dt.getNoDestroyAttrName(), builder.getUnitAttr());
+    dt->setAttr(dt.getNoFinalAttrName(), builder.getUnitAttr());
+    builder.restoreInsertionPoint(insertPointIfCreated);
+    // Create global op
+    // FIXME: replace handleTy by the Derived type that describe handleTy
+    std::string globalName =
+        fir::NameUniquer::getTypeDescriptorName(handleDTName);
+    auto linkage = builder.createLinkOnceODRLinkage();
+    builder.createGlobal(loc, handleTy, globalName, linkage);
+  }
+  return handleTy;
+}
+
+mlir::Value getCoarrayHandle(fir::FirOpBuilder &builder, mlir::Location loc,
+                             mlir::Value coarray) {
+  mlir::Type boxTy = fir::BoxType::get(builder.getNoneType());
+  std::string uniqName = mif::getFullUniqName(coarray);
+  if (!uniqName.empty()) {
+    std::string globalName = uniqName + coarrayHandleSuffix.str();
+    mlir::SymbolRefAttr symAttr =
+        mlir::SymbolRefAttr::get(builder.getContext(), globalName);
+    mlir::Value coarrayHandle =
+        fir::AddrOfOp::create(builder, loc, builder.getRefType(boxTy), symAttr);
+    return fir::LoadOp::create(builder, loc, coarrayHandle);
+  }
+  mlir::emitError(coarray.getLoc(),
+                  "Unable to locate the coarray handle for this argument.");
+  return mlir::Value{};
+}
+
+// Function to generate the PRIF runtime function call to retrieve
+// the number of images in the current team
+static mlir::Value getNumImages(fir::FirOpBuilder &builder,
+                                mlir::Location loc) {
+  mlir::Type i32Ty = builder.getI32Type();
+  mlir::Value result = builder.createTemporary(loc, i32Ty);
+  mlir::FunctionType ftype = mlir::FunctionType::get(
+      builder.getContext(),
+      /*inputs*/ {builder.getRefType(i32Ty)}, /*results*/ {});
+  mlir::func::FuncOp funcOp =
+      builder.createFunction(loc, getPRIFProcName("num_images"), ftype);
+  llvm::SmallVector<mlir::Value> args =
+      fir::runtime::createArguments(builder, loc, ftype, result);
+  fir::CallOp::create(builder, loc, funcOp, args);
+  return fir::LoadOp::create(builder, loc, result);
+}
+
+static std::pair<mlir::Value, mlir::Value>
+genCoBounds(fir::FirOpBuilder &builder, mlir::Location loc,
+            mif::AllocCoarrayOp op) {
+  mlir::Value ucobounds, lcobounds;
+  mlir::DenseI64ArrayAttr lcbsAttr = op.getLcoboundsAttr();
+  mlir::DenseI64ArrayAttr ucbsAttr = op.getUcoboundsAttr();
+
+  size_t corank = lcbsAttr.size();
+  mlir::Type i64Ty = builder.getI64Type();
+  mlir::Type addrType = builder.getRefType(i64Ty);
+  mlir::Type arrayType = fir::SequenceType::get(
+      {static_cast<fir::SequenceType::Extent>(corank)}, i64Ty);
+  lcobounds = builder.createTemporary(loc, arrayType);
+  ucobounds = builder.createTemporary(loc, arrayType);
+
+  for (size_t i = 0; i < corank; i++) {
+    auto index = builder.createIntegerConstant(loc, builder.getIndexType(), i);
+    // Lower cobounds
+    auto lcovalue = builder.createIntegerConstant(loc, i64Ty, lcbsAttr[i]);
+    auto lcoaddr =
+        fir::CoordinateOp::create(builder, loc, addrType, lcobounds, index);
+    fir::StoreOp::create(builder, loc, lcovalue, lcoaddr);
+
+    // Upper cobounds
+    auto ucovalue = builder.createIntegerConstant(loc, i64Ty, ucbsAttr[i]);
+    auto ucoaddr =
+        fir::CoordinateOp::create(builder, loc, addrType, ucobounds, index);
+    fir::StoreOp::create(builder, loc, ucovalue, ucoaddr);
+  }
+
+  lcobounds = builder.createBox(loc, lcobounds);
+  ucobounds = builder.createBox(loc, ucobounds);
+
+  // Computing last ucobound
+  mlir::func::FuncOp func =
+      fir::runtime::getRuntimeFunc<mkRTKey(ComputeLastUcobound)>(loc, builder);
+  mlir::Value numImages = getNumImages(builder, loc);
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, func.getFunctionType(), numImages, lcobounds, ucobounds);
+  fir::CallOp::create(builder, loc, func, args);
----------------
bonachea wrote:

As mentioned in my previous comment in [flang-rt/lib/runtime/coarray.cpp](https://github.com/llvm/llvm-project/pull/182110/changes#diff-1de7f58af2d00b2528cead47a3eb5829a87227ce8c3c6eaaeb4928fcd65cf93c), the final element of `ucobounds` can now be removed (so it has `corank-1` elements), and then this block of code can be deleted, along with the definition of `ComputeLastUcobound`.



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


More information about the llvm-commits mailing list