279 lines · cpp
1//===-- MultiImageFortran.cpp ---------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8///9/// Implementation of the lowering of image related constructs and expressions.10/// Fortran images can form teams, communicate via coarrays, etc.11///12//===----------------------------------------------------------------------===//13 14#include "flang/Lower/MultiImageFortran.h"15#include "flang/Lower/AbstractConverter.h"16#include "flang/Lower/SymbolMap.h"17#include "flang/Optimizer/Builder/FIRBuilder.h"18#include "flang/Optimizer/Builder/Todo.h"19#include "flang/Optimizer/Dialect/MIF/MIFOps.h"20#include "flang/Parser/parse-tree.h"21#include "flang/Semantics/expression.h"22 23//===----------------------------------------------------------------------===//24// Synchronization statements25//===----------------------------------------------------------------------===//26 27void Fortran::lower::genSyncAllStatement(28 Fortran::lower::AbstractConverter &converter,29 const Fortran::parser::SyncAllStmt &stmt) {30 mlir::Location loc = converter.getCurrentLocation();31 converter.checkCoarrayEnabled();32 33 // Handle STAT and ERRMSG values34 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;35 auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);36 37 fir::FirOpBuilder &builder = converter.getFirOpBuilder();38 mif::SyncAllOp::create(builder, loc, statAddr, errMsgAddr);39}40 41void Fortran::lower::genSyncImagesStatement(42 Fortran::lower::AbstractConverter &converter,43 const Fortran::parser::SyncImagesStmt &stmt) {44 mlir::Location loc = converter.getCurrentLocation();45 converter.checkCoarrayEnabled();46 fir::FirOpBuilder &builder = converter.getFirOpBuilder();47 48 // Handle STAT and ERRMSG values49 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =50 std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);51 auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);52 53 // SYNC_IMAGES(*) is passed as count == -1 while SYNC IMAGES([]) has count54 // == 0. Note further that SYNC IMAGES(*) is not semantically equivalent to55 // SYNC ALL.56 Fortran::lower::StatementContext stmtCtx;57 mlir::Value imageSet;58 const Fortran::parser::SyncImagesStmt::ImageSet &imgSet =59 std::get<Fortran::parser::SyncImagesStmt::ImageSet>(stmt.t);60 std::visit(Fortran::common::visitors{61 [&](const Fortran::parser::IntExpr &intExpr) {62 const SomeExpr *expr = Fortran::semantics::GetExpr(intExpr);63 imageSet =64 fir::getBase(converter.genExprBox(loc, *expr, stmtCtx));65 },66 [&](const Fortran::parser::Star &) {67 // Image set is not set.68 imageSet = mlir::Value{};69 }},70 imgSet.u);71 72 mif::SyncImagesOp::create(builder, loc, imageSet, statAddr, errMsgAddr);73}74 75void Fortran::lower::genSyncMemoryStatement(76 Fortran::lower::AbstractConverter &converter,77 const Fortran::parser::SyncMemoryStmt &stmt) {78 mlir::Location loc = converter.getCurrentLocation();79 converter.checkCoarrayEnabled();80 81 // Handle STAT and ERRMSG values82 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList = stmt.v;83 auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);84 85 fir::FirOpBuilder &builder = converter.getFirOpBuilder();86 mif::SyncMemoryOp::create(builder, loc, statAddr, errMsgAddr);87}88 89void Fortran::lower::genSyncTeamStatement(90 Fortran::lower::AbstractConverter &converter,91 const Fortran::parser::SyncTeamStmt &stmt) {92 mlir::Location loc = converter.getCurrentLocation();93 converter.checkCoarrayEnabled();94 95 // Handle TEAM96 Fortran::lower::StatementContext stmtCtx;97 const Fortran::parser::TeamValue &teamValue =98 std::get<Fortran::parser::TeamValue>(stmt.t);99 const SomeExpr *teamExpr = Fortran::semantics::GetExpr(teamValue);100 mlir::Value team =101 fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));102 103 // Handle STAT and ERRMSG values104 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =105 std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);106 auto [statAddr, errMsgAddr] = converter.genStatAndErrmsg(loc, statOrErrList);107 108 fir::FirOpBuilder &builder = converter.getFirOpBuilder();109 mif::SyncTeamOp::create(builder, loc, team, statAddr, errMsgAddr);110}111 112//===----------------------------------------------------------------------===//113// TEAM statements and constructs114//===----------------------------------------------------------------------===//115 116void Fortran::lower::genChangeTeamConstruct(117 Fortran::lower::AbstractConverter &converter,118 Fortran::lower::pft::Evaluation &,119 const Fortran::parser::ChangeTeamConstruct &) {120 TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM construct");121}122 123void Fortran::lower::genChangeTeamStmt(124 Fortran::lower::AbstractConverter &converter,125 Fortran::lower::pft::Evaluation &,126 const Fortran::parser::ChangeTeamStmt &stmt) {127 mlir::Location loc = converter.getCurrentLocation();128 converter.checkCoarrayEnabled();129 fir::FirOpBuilder &builder = converter.getFirOpBuilder();130 131 mlir::Value errMsgAddr, statAddr, team;132 // Handle STAT and ERRMSG values133 Fortran::lower::StatementContext stmtCtx;134 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =135 std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);136 for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {137 std::visit(Fortran::common::visitors{138 [&](const Fortran::parser::StatVariable &statVar) {139 const auto *expr = Fortran::semantics::GetExpr(statVar);140 statAddr = fir::getBase(141 converter.genExprAddr(loc, *expr, stmtCtx));142 },143 [&](const Fortran::parser::MsgVariable &errMsgVar) {144 const auto *expr = Fortran::semantics::GetExpr(errMsgVar);145 errMsgAddr = fir::getBase(146 converter.genExprBox(loc, *expr, stmtCtx));147 },148 },149 statOrErr.u);150 }151 152 // TODO: Manage the list of coarrays associated in153 // `std::list<CoarrayAssociation>`. According to the PRIF specification, it is154 // necessary to call `prif_alias_{create|destroy}` for each coarray defined in155 // this list. Support will be added once lowering to this procedure is156 // possible.157 const std::list<Fortran::parser::CoarrayAssociation> &coarrayAssocList =158 std::get<std::list<Fortran::parser::CoarrayAssociation>>(stmt.t);159 if (coarrayAssocList.size())160 TODO(loc, "Coarrays provided in the association list.");161 162 // Handle TEAM-VALUE163 const auto *teamExpr =164 Fortran::semantics::GetExpr(std::get<Fortran::parser::TeamValue>(stmt.t));165 team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));166 167 mif::ChangeTeamOp changeOp = mif::ChangeTeamOp::create(168 builder, loc, team, statAddr, errMsgAddr, /*terminator*/ false);169 builder.setInsertionPointToStart(changeOp.getBody());170}171 172void Fortran::lower::genEndChangeTeamStmt(173 Fortran::lower::AbstractConverter &converter,174 Fortran::lower::pft::Evaluation &,175 const Fortran::parser::EndChangeTeamStmt &stmt) {176 converter.checkCoarrayEnabled();177 mlir::Location loc = converter.getCurrentLocation();178 fir::FirOpBuilder &builder = converter.getFirOpBuilder();179 180 mlir::Value errMsgAddr, statAddr;181 // Handle STAT and ERRMSG values182 Fortran::lower::StatementContext stmtCtx;183 const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =184 std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);185 for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {186 std::visit(Fortran::common::visitors{187 [&](const Fortran::parser::StatVariable &statVar) {188 const auto *expr = Fortran::semantics::GetExpr(statVar);189 statAddr = fir::getBase(190 converter.genExprAddr(loc, *expr, stmtCtx));191 },192 [&](const Fortran::parser::MsgVariable &errMsgVar) {193 const auto *expr = Fortran::semantics::GetExpr(errMsgVar);194 errMsgAddr = fir::getBase(195 converter.genExprBox(loc, *expr, stmtCtx));196 },197 },198 statOrErr.u);199 }200 201 mif::EndTeamOp endOp =202 mif::EndTeamOp::create(builder, loc, statAddr, errMsgAddr);203 builder.setInsertionPointAfter(endOp.getParentOp());204}205 206void Fortran::lower::genFormTeamStatement(207 Fortran::lower::AbstractConverter &converter,208 Fortran::lower::pft::Evaluation &,209 const Fortran::parser::FormTeamStmt &stmt) {210 converter.checkCoarrayEnabled();211 mlir::Location loc = converter.getCurrentLocation();212 fir::FirOpBuilder &builder = converter.getFirOpBuilder();213 214 mlir::Value errMsgAddr, statAddr, newIndex, teamNumber, team;215 // Handle NEW_INDEX, STAT and ERRMSG216 std::list<Fortran::parser::StatOrErrmsg> statOrErrList{};217 Fortran::lower::StatementContext stmtCtx;218 const auto &formSpecList =219 std::get<std::list<Fortran::parser::FormTeamStmt::FormTeamSpec>>(stmt.t);220 for (const Fortran::parser::FormTeamStmt::FormTeamSpec &formSpec :221 formSpecList) {222 std::visit(223 Fortran::common::visitors{224 [&](const Fortran::parser::StatOrErrmsg &statOrErr) {225 std::visit(226 Fortran::common::visitors{227 [&](const Fortran::parser::StatVariable &statVar) {228 const auto *expr = Fortran::semantics::GetExpr(statVar);229 statAddr = fir::getBase(230 converter.genExprAddr(loc, *expr, stmtCtx));231 },232 [&](const Fortran::parser::MsgVariable &errMsgVar) {233 const auto *expr =234 Fortran::semantics::GetExpr(errMsgVar);235 errMsgAddr = fir::getBase(236 converter.genExprBox(loc, *expr, stmtCtx));237 },238 },239 statOrErr.u);240 },241 [&](const Fortran::parser::ScalarIntExpr &intExpr) {242 fir::ExtendedValue newIndexExpr = converter.genExprValue(243 loc, Fortran::semantics::GetExpr(intExpr), stmtCtx);244 newIndex = fir::getBase(newIndexExpr);245 },246 },247 formSpec.u);248 }249 250 // Handle TEAM-NUMBER251 const auto *teamNumberExpr = Fortran::semantics::GetExpr(252 std::get<Fortran::parser::ScalarIntExpr>(stmt.t));253 teamNumber =254 fir::getBase(converter.genExprValue(loc, *teamNumberExpr, stmtCtx));255 256 // Handle TEAM-VARIABLE257 const auto *teamExpr = Fortran::semantics::GetExpr(258 std::get<Fortran::parser::TeamVariable>(stmt.t));259 team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));260 261 mif::FormTeamOp::create(builder, loc, teamNumber, team, newIndex, statAddr,262 errMsgAddr);263}264 265//===----------------------------------------------------------------------===//266// COARRAY expressions267//===----------------------------------------------------------------------===//268 269fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genAddr(270 const Fortran::evaluate::CoarrayRef &expr) {271 (void)symMap;272 TODO(converter.getCurrentLocation(), "co-array address");273}274 275fir::ExtendedValue Fortran::lower::CoarrayExprHelper::genValue(276 const Fortran::evaluate::CoarrayRef &expr) {277 TODO(converter.getCurrentLocation(), "co-array value");278}279