| //===-- 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/SymbolMap.h" |
| #include "flang/Optimizer/Builder/FIRBuilder.h" |
| #include "flang/Optimizer/Builder/Todo.h" |
| #include "flang/Optimizer/Dialect/MIF/MIFOps.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"); |
| } |
| |
| void 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)); |
| |
| mif::ChangeTeamOp changeOp = mif::ChangeTeamOp::create( |
| builder, loc, team, statAddr, errMsgAddr, /*terminator*/ false); |
| builder.setInsertionPointToStart(changeOp.getBody()); |
| } |
| |
| 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 endOp = |
| mif::EndTeamOp::create(builder, loc, statAddr, errMsgAddr); |
| builder.setInsertionPointAfter(endOp.getParentOp()); |
| } |
| |
| 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 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"); |
| } |