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 This PR does not yet handle allocation for the following cases (which will be added in future PRs): - Coarrays with ALLOCATABLE and/or POINTER components (PRIF has procedures (`prif_(de)allocate`) for this). - Coarray dummy arguments (PRIF has also procedures for this) - Finalization of coarrays - non-ALLOCATABLE SAVE coarrays outside the scoping unit of the main program (e.g. non-ALLOCATABLE coarrays declared in a module or a procedure) Another PR which add support of some basic intrinsics with a coarray as an argument will follow after this one. --------- Co-authored-by: Dan Bonachea <dobonachea@lbl.gov>
467 lines
19 KiB
C++
467 lines
19 KiB
C++
//===-- MultiImageFortran.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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// Implementation of the lowering of image related constructs and expressions.
|
|
/// Fortran images can form teams, communicate via coarrays, etc.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Lower/MultiImageFortran.h"
|
|
#include "flang/Lower/AbstractConverter.h"
|
|
#include "flang/Lower/Support/Utils.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"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Synchronization statements
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void Fortran::lower::genSyncAllStatement(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
const Fortran::parser::SyncAllStmt &stmt) {
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
converter.checkCoarrayEnabled();
|
|
|
|
// Handle STAT and ERRMSG values
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;
|
|
auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);
|
|
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
mif::SyncAllOp::create(builder, loc, statAddr, errMsgAddr);
|
|
}
|
|
|
|
void Fortran::lower::genSyncImagesStatement(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
const Fortran::parser::SyncImagesStmt &stmt) {
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
converter.checkCoarrayEnabled();
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
|
|
// Handle STAT and ERRMSG values
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
|
|
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
|
|
auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);
|
|
|
|
// SYNC_IMAGES(*) is passed as count == -1 while SYNC IMAGES([]) has count
|
|
// == 0. Note further that SYNC IMAGES(*) is not semantically equivalent to
|
|
// SYNC ALL.
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
mlir::Value imageSet;
|
|
const Fortran::parser::SyncImagesStmt::ImageSet &imgSet =
|
|
std::get<Fortran::parser::SyncImagesStmt::ImageSet>(stmt.t);
|
|
std::visit(Fortran::common::visitors{
|
|
[&](const Fortran::parser::IntExpr &intExpr) {
|
|
const SomeExpr *expr = Fortran::semantics::GetExpr(intExpr);
|
|
imageSet =
|
|
fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));
|
|
},
|
|
[&](const Fortran::parser::Star &) {
|
|
// Image set is not set.
|
|
imageSet = mlir::Value{};
|
|
}},
|
|
imgSet.u);
|
|
|
|
mif::SyncImagesOp::create(builder, loc, imageSet, statAddr, errMsgAddr);
|
|
}
|
|
|
|
void Fortran::lower::genSyncMemoryStatement(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
const Fortran::parser::SyncMemoryStmt &stmt) {
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
converter.checkCoarrayEnabled();
|
|
|
|
// Handle STAT and ERRMSG values
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;
|
|
auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);
|
|
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
mif::SyncMemoryOp::create(builder, loc, statAddr, errMsgAddr);
|
|
}
|
|
|
|
void Fortran::lower::genSyncTeamStatement(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
const Fortran::parser::SyncTeamStmt &stmt) {
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
converter.checkCoarrayEnabled();
|
|
|
|
// Handle TEAM
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
const Fortran::parser::TeamValue &teamValue =
|
|
std::get<Fortran::parser::TeamValue>(stmt.t);
|
|
const SomeExpr *teamExpr = Fortran::semantics::GetExpr(teamValue);
|
|
mlir::Value team =
|
|
fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));
|
|
|
|
// Handle STAT and ERRMSG values
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
|
|
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
|
|
auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);
|
|
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
mif::SyncTeamOp::create(builder, loc, team, statAddr, errMsgAddr);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TEAM statements and constructs
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void Fortran::lower::genChangeTeamConstruct(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
Fortran::lower::pft::Evaluation &,
|
|
const Fortran::parser::ChangeTeamConstruct &) {
|
|
TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM construct");
|
|
}
|
|
|
|
mif::ChangeTeamOp
|
|
Fortran::lower::genChangeTeamStmt(Fortran::lower::AbstractConverter &converter,
|
|
Fortran::lower::pft::Evaluation &,
|
|
const Fortran::parser::ChangeTeamStmt &stmt) {
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
converter.checkCoarrayEnabled();
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
|
|
mlir::Value errMsgAddr, statAddr, team;
|
|
// Handle STAT and ERRMSG values
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
|
|
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
|
|
for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {
|
|
std::visit(Fortran::common::visitors{
|
|
[&](const Fortran::parser::StatVariable &statVar) {
|
|
const auto *expr = Fortran::semantics::GetExpr(statVar);
|
|
statAddr = fir::getBase(
|
|
converter.genExprAddr(loc, *expr, stmtCtx));
|
|
},
|
|
[&](const Fortran::parser::MsgVariable &errMsgVar) {
|
|
const auto *expr = Fortran::semantics::GetExpr(errMsgVar);
|
|
errMsgAddr = fir::getBase(
|
|
converter.genExprBox(loc, *expr, stmtCtx));
|
|
},
|
|
},
|
|
statOrErr.u);
|
|
}
|
|
|
|
// TODO: Manage the list of coarrays associated in
|
|
// `std::list<CoarrayAssociation>`. According to the PRIF specification, it is
|
|
// necessary to call `prif_alias_{create|destroy}` for each coarray defined in
|
|
// this list. Support will be added once lowering to this procedure is
|
|
// possible.
|
|
const std::list<Fortran::parser::CoarrayAssociation> &coarrayAssocList =
|
|
std::get<std::list<Fortran::parser::CoarrayAssociation>>(stmt.t);
|
|
if (coarrayAssocList.size())
|
|
TODO(loc, "Coarrays provided in the association list.");
|
|
|
|
// Handle TEAM-VALUE
|
|
const auto *teamExpr =
|
|
Fortran::semantics::GetExpr(std::get<Fortran::parser::TeamValue>(stmt.t));
|
|
team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));
|
|
|
|
return mif::ChangeTeamOp::create(builder, loc, team, statAddr, errMsgAddr);
|
|
}
|
|
|
|
void Fortran::lower::genEndChangeTeamStmt(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
Fortran::lower::pft::Evaluation &,
|
|
const Fortran::parser::EndChangeTeamStmt &stmt) {
|
|
converter.checkCoarrayEnabled();
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
|
|
mlir::Value errMsgAddr, statAddr;
|
|
// Handle STAT and ERRMSG values
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
|
|
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
|
|
for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {
|
|
std::visit(Fortran::common::visitors{
|
|
[&](const Fortran::parser::StatVariable &statVar) {
|
|
const auto *expr = Fortran::semantics::GetExpr(statVar);
|
|
statAddr = fir::getBase(
|
|
converter.genExprAddr(loc, *expr, stmtCtx));
|
|
},
|
|
[&](const Fortran::parser::MsgVariable &errMsgVar) {
|
|
const auto *expr = Fortran::semantics::GetExpr(errMsgVar);
|
|
errMsgAddr = fir::getBase(
|
|
converter.genExprBox(loc, *expr, stmtCtx));
|
|
},
|
|
},
|
|
statOrErr.u);
|
|
}
|
|
|
|
mif::EndTeamOp::create(builder, loc, statAddr, errMsgAddr);
|
|
}
|
|
|
|
void Fortran::lower::genFormTeamStatement(
|
|
Fortran::lower::AbstractConverter &converter,
|
|
Fortran::lower::pft::Evaluation &,
|
|
const Fortran::parser::FormTeamStmt &stmt) {
|
|
converter.checkCoarrayEnabled();
|
|
mlir::Location loc = converter.getCurrentLocation();
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
|
|
mlir::Value errMsgAddr, statAddr, newIndex, teamNumber, team;
|
|
// Handle NEW_INDEX, STAT and ERRMSG
|
|
std::list<Fortran::parser::StatOrErrmsg> statOrErrList{};
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
const auto &formSpecList =
|
|
std::get<std::list<Fortran::parser::FormTeamStmt::FormTeamSpec>>(stmt.t);
|
|
for (const Fortran::parser::FormTeamStmt::FormTeamSpec &formSpec :
|
|
formSpecList) {
|
|
std::visit(
|
|
Fortran::common::visitors{
|
|
[&](const Fortran::parser::StatOrErrmsg &statOrErr) {
|
|
std::visit(
|
|
Fortran::common::visitors{
|
|
[&](const Fortran::parser::StatVariable &statVar) {
|
|
const auto *expr = Fortran::semantics::GetExpr(statVar);
|
|
statAddr = fir::getBase(
|
|
converter.genExprAddr(loc, *expr, stmtCtx));
|
|
},
|
|
[&](const Fortran::parser::MsgVariable &errMsgVar) {
|
|
const auto *expr =
|
|
Fortran::semantics::GetExpr(errMsgVar);
|
|
errMsgAddr = fir::getBase(
|
|
converter.genExprBox(loc, *expr, stmtCtx));
|
|
},
|
|
},
|
|
statOrErr.u);
|
|
},
|
|
[&](const Fortran::parser::ScalarIntExpr &intExpr) {
|
|
fir::ExtendedValue newIndexExpr = converter.genExprValue(
|
|
loc, Fortran::semantics::GetExpr(intExpr), stmtCtx);
|
|
newIndex = fir::getBase(newIndexExpr);
|
|
},
|
|
},
|
|
formSpec.u);
|
|
}
|
|
|
|
// Handle TEAM-NUMBER
|
|
const auto *teamNumberExpr = Fortran::semantics::GetExpr(
|
|
std::get<Fortran::parser::ScalarIntExpr>(stmt.t));
|
|
teamNumber =
|
|
fir::getBase(converter.genExprValue(loc, *teamNumberExpr, stmtCtx));
|
|
|
|
// Handle TEAM-VARIABLE
|
|
const auto *teamExpr = Fortran::semantics::GetExpr(
|
|
std::get<Fortran::parser::TeamVariable>(stmt.t));
|
|
team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));
|
|
|
|
mif::FormTeamOp::create(builder, loc, teamNumber, team, newIndex, statAddr,
|
|
errMsgAddr);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// COARRAY utils
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
mlir::Value
|
|
Fortran::lower::genLowerCoBounds(Fortran::lower::AbstractConverter &converter,
|
|
mlir::Location loc,
|
|
const Fortran::semantics::Symbol &sym) {
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
mlir::Type i64Ty = builder.getI64Type();
|
|
mlir::Type addrType = builder.getRefType(i64Ty);
|
|
mlir::Value one = builder.createIntegerConstant(loc, i64Ty, 1);
|
|
mlir::Value lcobounds;
|
|
|
|
if (Fortran::semantics::IsAllocatableOrObjectPointer(&sym))
|
|
mlir::emitError(
|
|
loc,
|
|
"Unable to use genLowerCoBounds on ALLOCATABLE and POINTER symbol");
|
|
if (const auto *object =
|
|
sym.GetUltimate()
|
|
.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
|
|
size_t corank = object->coshape().size();
|
|
mlir::Type arrayType = fir::SequenceType::get(
|
|
{static_cast<fir::SequenceType::Extent>(corank)}, i64Ty);
|
|
lcobounds = builder.createTemporary(loc, arrayType);
|
|
mlir::Value lcovalue = one; // default lcobounds
|
|
for (size_t i = 0; i < corank; i++) {
|
|
if (auto lb = object->coshape()[i].lbound().GetExplicit()) {
|
|
auto lbExpr = ignoreEvConvert(*lb);
|
|
lcovalue = fir::getBase(converter.genExprValue(loc, lbExpr, stmtCtx));
|
|
}
|
|
|
|
if (lcovalue.getType() != i64Ty)
|
|
lcovalue = fir::ConvertOp::create(builder, loc, i64Ty, lcovalue);
|
|
mlir::Value index =
|
|
builder.createIntegerConstant(loc, builder.getIndexType(), i);
|
|
mlir::Value lcoaddr =
|
|
fir::CoordinateOp::create(builder, loc, addrType, lcobounds, index);
|
|
fir::StoreOp::create(builder, loc, lcovalue, lcoaddr);
|
|
}
|
|
lcobounds = builder.createBox(loc, lcobounds);
|
|
}
|
|
return lcobounds;
|
|
}
|
|
|
|
mlir::Value
|
|
Fortran::lower::genUpperCoBounds(Fortran::lower::AbstractConverter &converter,
|
|
mlir::Location loc,
|
|
const Fortran::semantics::Symbol &sym) {
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
mlir::Type i64Ty = builder.getI64Type();
|
|
mlir::Type addrType = builder.getRefType(i64Ty);
|
|
mlir::Value one = builder.createIntegerConstant(loc, i64Ty, 1);
|
|
mlir::Value ucobounds;
|
|
|
|
if (Fortran::semantics::IsAllocatableOrObjectPointer(&sym))
|
|
mlir::emitError(
|
|
loc,
|
|
"Unable to use genUpperCoBounds on ALLOCATABLE and POINTER symbol");
|
|
if (const auto *object =
|
|
sym.GetUltimate()
|
|
.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
|
|
size_t corank = object->coshape().size();
|
|
// PRIF take an array of size corank-1 for ucobound.
|
|
mlir::Type arrayType = fir::SequenceType::get(
|
|
{static_cast<fir::SequenceType::Extent>(corank - 1)}, i64Ty);
|
|
ucobounds = builder.createTemporary(loc, arrayType);
|
|
mlir::Value ucovalue;
|
|
for (size_t i = 0; i < corank - 1; i++) {
|
|
if (auto ub = object->coshape()[i].lbound().GetExplicit()) {
|
|
auto ubExpr = ignoreEvConvert(*ub);
|
|
ucovalue = fir::getBase(converter.genExprValue(loc, ubExpr, stmtCtx));
|
|
} else {
|
|
if (auto lb = object->coshape()[i].lbound().GetExplicit()) {
|
|
auto lbExpr = ignoreEvConvert(*lb);
|
|
ucovalue = fir::getBase(converter.genExprValue(
|
|
loc, lbExpr, stmtCtx)); // default value from lcobound
|
|
} else
|
|
ucovalue = one;
|
|
}
|
|
if (ucovalue.getType() != i64Ty)
|
|
ucovalue = fir::ConvertOp::create(builder, loc, i64Ty, ucovalue);
|
|
mlir::Value index =
|
|
builder.createIntegerConstant(loc, builder.getIndexType(), i);
|
|
mlir::Value ucoaddr =
|
|
fir::CoordinateOp::create(builder, loc, addrType, ucobounds, index);
|
|
fir::StoreOp::create(builder, loc, ucovalue, ucoaddr);
|
|
}
|
|
ucobounds = builder.createBox(loc, ucobounds);
|
|
}
|
|
return ucobounds;
|
|
}
|
|
|
|
static std::tuple<mlir::Value, mlir::Value>
|
|
genCoBounds(Fortran::lower::AbstractConverter &converter, mlir::Location loc,
|
|
const Fortran::parser::AllocateCoarraySpec &allocSpec) {
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
Fortran::lower::StatementContext stmtCtx;
|
|
llvm::SmallVector<std::int64_t> lcbs, ucbs;
|
|
mlir::Type i64Ty = builder.getI64Type();
|
|
mlir::Type addrType = builder.getRefType(i64Ty);
|
|
mlir::Value one = builder.createIntegerConstant(loc, i64Ty, 1);
|
|
|
|
const std::list<Fortran::parser::AllocateCoshapeSpec> &coshapeSpecs =
|
|
std::get<0>(allocSpec.t);
|
|
size_t corank = coshapeSpecs.size() + 1;
|
|
mlir::Type arrayType = fir::SequenceType::get(
|
|
{static_cast<fir::SequenceType::Extent>(corank)}, i64Ty);
|
|
mlir::Value lcobounds = builder.createTemporary(loc, arrayType);
|
|
mlir::Type arrayType2 = fir::SequenceType::get(
|
|
{static_cast<fir::SequenceType::Extent>(corank - 1)}, i64Ty);
|
|
mlir::Value ucobounds = builder.createTemporary(loc, arrayType2);
|
|
size_t i = 0;
|
|
for (const Fortran::parser::AllocateCoshapeSpec &coshapeSpec : coshapeSpecs) {
|
|
const std::optional<Fortran::parser::BoundExpr> &lbExpr =
|
|
std::get<0>(coshapeSpec.t);
|
|
const Fortran::parser::BoundExpr &ubExpr = std::get<1>(coshapeSpec.t);
|
|
mlir::Value lb = one;
|
|
if (lbExpr.has_value()) {
|
|
auto expr = Fortran::semantics::GetExpr(*lbExpr);
|
|
lb = fir::getBase(converter.genExprValue(loc, expr, stmtCtx));
|
|
if (lb.getType() != i64Ty)
|
|
lb = fir::ConvertOp::create(builder, loc, i64Ty, lb);
|
|
}
|
|
|
|
auto ube = Fortran::semantics::GetExpr(ubExpr);
|
|
mlir::Value ub = fir::getBase(converter.genExprValue(loc, ube, stmtCtx));
|
|
if (ub.getType() != i64Ty)
|
|
ub = fir::ConvertOp::create(builder, loc, i64Ty, ub);
|
|
|
|
mlir::Value index =
|
|
builder.createIntegerConstant(loc, builder.getIndexType(), i);
|
|
// Lcobound
|
|
mlir::Value lcoaddr =
|
|
fir::CoordinateOp::create(builder, loc, addrType, lcobounds, index);
|
|
fir::StoreOp::create(builder, loc, lb, lcoaddr);
|
|
// Ucobound
|
|
mlir::Value ucoaddr =
|
|
fir::CoordinateOp::create(builder, loc, addrType, ucobounds, index);
|
|
fir::StoreOp::create(builder, loc, ub, ucoaddr);
|
|
i++;
|
|
}
|
|
// Last lcobound;
|
|
{
|
|
mlir::Value lb = one;
|
|
if (const std::optional<Fortran::parser::BoundExpr> &lastCobound =
|
|
std::get<1>(allocSpec.t)) {
|
|
auto expr = Fortran::semantics::GetExpr(*lastCobound);
|
|
lb = fir::getBase(converter.genExprValue(loc, expr, stmtCtx));
|
|
}
|
|
mlir::Value index =
|
|
builder.createIntegerConstant(loc, builder.getIndexType(), i);
|
|
mlir::Value lcoaddr =
|
|
fir::CoordinateOp::create(builder, loc, addrType, lcobounds, index);
|
|
fir::StoreOp::create(builder, loc, lb, lcoaddr);
|
|
}
|
|
|
|
lcobounds = builder.createBox(loc, lcobounds);
|
|
ucobounds = builder.createBox(loc, ucobounds);
|
|
return {lcobounds, ucobounds};
|
|
}
|
|
|
|
mlir::Value Fortran::lower::genAllocateCoarray(
|
|
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
|
|
const Fortran::semantics::Symbol &sym, mlir::Value addr,
|
|
const std::optional<Fortran::parser::AllocateCoarraySpec> &allocSpec,
|
|
mlir::Value errmsg, bool hasStat) {
|
|
converter.checkCoarrayEnabled();
|
|
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
|
|
|
mlir::Value stat;
|
|
if (hasStat)
|
|
stat = builder.createTemporary(loc, builder.getI32Type());
|
|
|
|
mlir::Value lcobounds, ucobounds;
|
|
if (allocSpec.has_value()) {
|
|
std::tie(lcobounds, ucobounds) = genCoBounds(converter, loc, *allocSpec);
|
|
} else {
|
|
lcobounds = Fortran::lower::genLowerCoBounds(converter, loc, sym);
|
|
ucobounds = Fortran::lower::genUpperCoBounds(converter, loc, sym);
|
|
}
|
|
std::string uniqName = mif::getFullUniqName(addr);
|
|
if (uniqName.empty())
|
|
uniqName = converter.mangleName(sym);
|
|
mif::AllocCoarrayOp::create(builder, loc, addr, uniqName, lcobounds,
|
|
ucobounds, stat, errmsg);
|
|
return stat;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// COARRAY expressions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genAddr(
|
|
const Fortran::evaluate::CoarrayRef &expr) {
|
|
(void)symMap;
|
|
TODO(converter.getCurrentLocation(), "co-array address");
|
|
}
|
|
|
|
fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genValue(
|
|
const Fortran::evaluate::CoarrayRef &expr) {
|
|
TODO(converter.getCurrentLocation(), "co-array value");
|
|
}
|