1aab4263aSValentin Clement //===-- Runtime.cpp -------------------------------------------------------===// 2aab4263aSValentin Clement // 3aab4263aSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4aab4263aSValentin Clement // See https://llvm.org/LICENSE.txt for license information. 5aab4263aSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6aab4263aSValentin Clement // 7aab4263aSValentin Clement //===----------------------------------------------------------------------===// 8aab4263aSValentin Clement 9aab4263aSValentin Clement #include "flang/Lower/Runtime.h" 10aab4263aSValentin Clement #include "flang/Lower/Bridge.h" 11b171849aSValentin Clement (バレンタイン クレメン) #include "flang/Lower/OpenACC.h" 12ed27d28fSPeixin Qiao #include "flang/Lower/OpenMP.h" 13d0b70a07SValentin Clement #include "flang/Lower/StatementContext.h" 14aab4263aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 15aab4263aSValentin Clement #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" 165b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h" 1770ade047Svdonaldson #include "flang/Optimizer/Dialect/FIROpsSupport.h" 18aab4263aSValentin Clement #include "flang/Parser/parse-tree.h" 19a16eddb2SValentin Clement #include "flang/Runtime/misc-intrinsic.h" 2072276bdaSValentin Clement #include "flang/Runtime/pointer.h" 21a1918fdfSValentin Clement #include "flang/Runtime/random.h" 22aab4263aSValentin Clement #include "flang/Runtime/stop.h" 239daf5765SValentin Clement #include "flang/Runtime/time-intrinsic.h" 24aab4263aSValentin Clement #include "flang/Semantics/tools.h" 25b171849aSValentin Clement (バレンタイン クレメン) #include "mlir/Dialect/OpenACC/OpenACC.h" 26ed27d28fSPeixin Qiao #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 27aab4263aSValentin Clement #include "llvm/Support/Debug.h" 284d4d4785SKazu Hirata #include <optional> 29aab4263aSValentin Clement 30aab4263aSValentin Clement #define DEBUG_TYPE "flang-lower-runtime" 31aab4263aSValentin Clement 32aab4263aSValentin Clement using namespace Fortran::runtime; 33aab4263aSValentin Clement 34aab4263aSValentin Clement /// Runtime calls that do not return to the caller indicate this condition by 35aab4263aSValentin Clement /// terminating the current basic block with an unreachable op. 36aab4263aSValentin Clement static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { 37ed27d28fSPeixin Qiao mlir::Block *curBlock = builder.getBlock(); 38ed27d28fSPeixin Qiao mlir::Operation *parentOp = curBlock->getParentOp(); 39ed27d28fSPeixin Qiao if (parentOp->getDialect()->getNamespace() == 40ed27d28fSPeixin Qiao mlir::omp::OpenMPDialect::getDialectNamespace()) 41ed27d28fSPeixin Qiao Fortran::lower::genOpenMPTerminator(builder, parentOp, loc); 42b171849aSValentin Clement (バレンタイン クレメン) else if (parentOp->getDialect()->getNamespace() == 43b171849aSValentin Clement (バレンタイン クレメン) mlir::acc::OpenACCDialect::getDialectNamespace()) 44b171849aSValentin Clement (バレンタイン クレメン) Fortran::lower::genOpenACCTerminator(builder, parentOp, loc); 45ed27d28fSPeixin Qiao else 46aab4263aSValentin Clement builder.create<fir::UnreachableOp>(loc); 47ed27d28fSPeixin Qiao mlir::Block *newBlock = curBlock->splitBlock(builder.getInsertionPoint()); 48aab4263aSValentin Clement builder.setInsertionPointToStart(newBlock); 49aab4263aSValentin Clement } 50aab4263aSValentin Clement 51aab4263aSValentin Clement //===----------------------------------------------------------------------===// 52aab4263aSValentin Clement // Misc. Fortran statements that lower to runtime calls 53aab4263aSValentin Clement //===----------------------------------------------------------------------===// 54aab4263aSValentin Clement 55aab4263aSValentin Clement void Fortran::lower::genStopStatement( 56aab4263aSValentin Clement Fortran::lower::AbstractConverter &converter, 57aab4263aSValentin Clement const Fortran::parser::StopStmt &stmt) { 58ea88bb16SjeanPerier const bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) == 59ea88bb16SjeanPerier Fortran::parser::StopStmt::Kind::ErrorStop; 60aab4263aSValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 61aab4263aSValentin Clement mlir::Location loc = converter.getCurrentLocation(); 62d0b70a07SValentin Clement Fortran::lower::StatementContext stmtCtx; 63aab4263aSValentin Clement llvm::SmallVector<mlir::Value> operands; 6458ceae95SRiver Riddle mlir::func::FuncOp callee; 65aab4263aSValentin Clement mlir::FunctionType calleeType; 66aab4263aSValentin Clement // First operand is stop code (zero if absent) 67ca53e049SValentin Clement if (const auto &code = 68ca53e049SValentin Clement std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) { 69d0b70a07SValentin Clement auto expr = 70d0b70a07SValentin Clement converter.genExprValue(*Fortran::semantics::GetExpr(*code), stmtCtx); 71ca53e049SValentin Clement LLVM_DEBUG(llvm::dbgs() << "stop expression: "; expr.dump(); 72ca53e049SValentin Clement llvm::dbgs() << '\n'); 73ca53e049SValentin Clement expr.match( 74ca53e049SValentin Clement [&](const fir::CharBoxValue &x) { 75a8d48fe0SValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatementText)>( 76a8d48fe0SValentin Clement loc, builder); 774a3460a7SRiver Riddle calleeType = callee.getFunctionType(); 78a8d48fe0SValentin Clement // Creates a pair of operands for the CHARACTER and its LEN. 79a8d48fe0SValentin Clement operands.push_back( 80a8d48fe0SValentin Clement builder.createConvert(loc, calleeType.getInput(0), x.getAddr())); 81a8d48fe0SValentin Clement operands.push_back( 82a8d48fe0SValentin Clement builder.createConvert(loc, calleeType.getInput(1), x.getLen())); 83ca53e049SValentin Clement }, 84ca53e049SValentin Clement [&](fir::UnboxedValue x) { 85ca53e049SValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>( 86ca53e049SValentin Clement loc, builder); 874a3460a7SRiver Riddle calleeType = callee.getFunctionType(); 88ca53e049SValentin Clement mlir::Value cast = 89ca53e049SValentin Clement builder.createConvert(loc, calleeType.getInput(0), x); 90ca53e049SValentin Clement operands.push_back(cast); 91ca53e049SValentin Clement }, 92ca53e049SValentin Clement [&](auto) { 93ca53e049SValentin Clement mlir::emitError(loc, "unhandled expression in STOP"); 94ca53e049SValentin Clement std::exit(1); 95ca53e049SValentin Clement }); 96aab4263aSValentin Clement } else { 97aab4263aSValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); 984a3460a7SRiver Riddle calleeType = callee.getFunctionType(); 99ea88bb16SjeanPerier // Default to values are advised in F'2023 11.4 p2. 100ea88bb16SjeanPerier operands.push_back(builder.createIntegerConstant( 101ea88bb16SjeanPerier loc, calleeType.getInput(0), isError ? 1 : 0)); 102aab4263aSValentin Clement } 103aab4263aSValentin Clement 104aab4263aSValentin Clement // Second operand indicates ERROR STOP 105aab4263aSValentin Clement operands.push_back(builder.createIntegerConstant( 106aab4263aSValentin Clement loc, calleeType.getInput(operands.size()), isError)); 107aab4263aSValentin Clement 108aab4263aSValentin Clement // Third operand indicates QUIET (default to false). 109cc306740SValentin Clement if (const auto &quiet = 110cc306740SValentin Clement std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) { 111cc306740SValentin Clement const SomeExpr *expr = Fortran::semantics::GetExpr(*quiet); 112cc306740SValentin Clement assert(expr && "failed getting typed expression"); 113d0b70a07SValentin Clement mlir::Value q = fir::getBase(converter.genExprValue(*expr, stmtCtx)); 114cc306740SValentin Clement operands.push_back( 115cc306740SValentin Clement builder.createConvert(loc, calleeType.getInput(operands.size()), q)); 116aab4263aSValentin Clement } else { 117aab4263aSValentin Clement operands.push_back(builder.createIntegerConstant( 118aab4263aSValentin Clement loc, calleeType.getInput(operands.size()), 0)); 119aab4263aSValentin Clement } 120aab4263aSValentin Clement 121aab4263aSValentin Clement builder.create<fir::CallOp>(loc, callee, operands); 122ed27d28fSPeixin Qiao auto blockIsUnterminated = [&builder]() { 123ed27d28fSPeixin Qiao mlir::Block *currentBlock = builder.getBlock(); 124ed27d28fSPeixin Qiao return currentBlock->empty() || 125ed27d28fSPeixin Qiao !currentBlock->back().hasTrait<mlir::OpTrait::IsTerminator>(); 126ed27d28fSPeixin Qiao }; 127ed27d28fSPeixin Qiao if (blockIsUnterminated()) 128aab4263aSValentin Clement genUnreachable(builder, loc); 129aab4263aSValentin Clement } 130db01b123SValentin Clement 131534b2283SValentin Clement void Fortran::lower::genFailImageStatement( 132534b2283SValentin Clement Fortran::lower::AbstractConverter &converter) { 133534b2283SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 134534b2283SValentin Clement mlir::Location loc = converter.getCurrentLocation(); 13558ceae95SRiver Riddle mlir::func::FuncOp callee = 136534b2283SValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(FailImageStatement)>(loc, builder); 1379a417395SKazu Hirata builder.create<fir::CallOp>(loc, callee, std::nullopt); 138534b2283SValentin Clement genUnreachable(builder, loc); 139534b2283SValentin Clement } 140534b2283SValentin Clement 141a2d7af75SKatherine Rasmussen void Fortran::lower::genNotifyWaitStatement( 142a2d7af75SKatherine Rasmussen Fortran::lower::AbstractConverter &converter, 143a2d7af75SKatherine Rasmussen const Fortran::parser::NotifyWaitStmt &) { 144a2d7af75SKatherine Rasmussen TODO(converter.getCurrentLocation(), "coarray: NOTIFY WAIT runtime"); 145a2d7af75SKatherine Rasmussen } 146a2d7af75SKatherine Rasmussen 147534b2283SValentin Clement void Fortran::lower::genEventPostStatement( 148534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 149534b2283SValentin Clement const Fortran::parser::EventPostStmt &) { 1505db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: EVENT POST runtime"); 151534b2283SValentin Clement } 152534b2283SValentin Clement 153534b2283SValentin Clement void Fortran::lower::genEventWaitStatement( 154534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 155534b2283SValentin Clement const Fortran::parser::EventWaitStmt &) { 1565db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: EVENT WAIT runtime"); 157534b2283SValentin Clement } 158534b2283SValentin Clement 159534b2283SValentin Clement void Fortran::lower::genLockStatement( 160534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 161534b2283SValentin Clement const Fortran::parser::LockStmt &) { 1625db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: LOCK runtime"); 163534b2283SValentin Clement } 164534b2283SValentin Clement 165534b2283SValentin Clement void Fortran::lower::genUnlockStatement( 166534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 167534b2283SValentin Clement const Fortran::parser::UnlockStmt &) { 1685db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: UNLOCK runtime"); 169534b2283SValentin Clement } 170534b2283SValentin Clement 171534b2283SValentin Clement void Fortran::lower::genSyncAllStatement( 172534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 173534b2283SValentin Clement const Fortran::parser::SyncAllStmt &) { 1745db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: SYNC ALL runtime"); 175534b2283SValentin Clement } 176534b2283SValentin Clement 177534b2283SValentin Clement void Fortran::lower::genSyncImagesStatement( 178534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 179534b2283SValentin Clement const Fortran::parser::SyncImagesStmt &) { 1805db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: SYNC IMAGES runtime"); 181534b2283SValentin Clement } 182534b2283SValentin Clement 183534b2283SValentin Clement void Fortran::lower::genSyncMemoryStatement( 184534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 185534b2283SValentin Clement const Fortran::parser::SyncMemoryStmt &) { 1865db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: SYNC MEMORY runtime"); 187534b2283SValentin Clement } 188534b2283SValentin Clement 189534b2283SValentin Clement void Fortran::lower::genSyncTeamStatement( 190534b2283SValentin Clement Fortran::lower::AbstractConverter &converter, 191534b2283SValentin Clement const Fortran::parser::SyncTeamStmt &) { 1925db4779cSPete Steinfeld TODO(converter.getCurrentLocation(), "coarray: SYNC TEAM runtime"); 193534b2283SValentin Clement } 194534b2283SValentin Clement 195db01b123SValentin Clement void Fortran::lower::genPauseStatement( 196db01b123SValentin Clement Fortran::lower::AbstractConverter &converter, 197db01b123SValentin Clement const Fortran::parser::PauseStmt &) { 198db01b123SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 199db01b123SValentin Clement mlir::Location loc = converter.getCurrentLocation(); 20058ceae95SRiver Riddle mlir::func::FuncOp callee = 201db01b123SValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); 2029a417395SKazu Hirata builder.create<fir::CallOp>(loc, callee, std::nullopt); 203db01b123SValentin Clement } 20472276bdaSValentin Clement 205abefd87eSValentin Clement void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder, 206abefd87eSValentin Clement mlir::Location loc, 207abefd87eSValentin Clement mlir::Value pointer, 208abefd87eSValentin Clement mlir::Value target) { 209abefd87eSValentin Clement mlir::func::FuncOp func = 210abefd87eSValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(PointerAssociate)>(loc, builder); 211abefd87eSValentin Clement llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( 212abefd87eSValentin Clement builder, loc, func.getFunctionType(), pointer, target); 213*12ba74e1SValentin Clement (バレンタイン クレメン) builder.create<fir::CallOp>(loc, func, args); 214abefd87eSValentin Clement } 215abefd87eSValentin Clement 21642b21ddaSValentin Clement void Fortran::lower::genPointerAssociateRemapping(fir::FirOpBuilder &builder, 21742b21ddaSValentin Clement mlir::Location loc, 21842b21ddaSValentin Clement mlir::Value pointer, 21942b21ddaSValentin Clement mlir::Value target, 22042b21ddaSValentin Clement mlir::Value bounds) { 22142b21ddaSValentin Clement mlir::func::FuncOp func = 22242b21ddaSValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(PointerAssociateRemapping)>(loc, 22342b21ddaSValentin Clement builder); 22442b21ddaSValentin Clement auto fTy = func.getFunctionType(); 22542b21ddaSValentin Clement auto sourceFile = fir::factory::locationToFilename(builder, loc); 22642b21ddaSValentin Clement auto sourceLine = 22742b21ddaSValentin Clement fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); 22842b21ddaSValentin Clement llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( 22942b21ddaSValentin Clement builder, loc, func.getFunctionType(), pointer, target, bounds, sourceFile, 23042b21ddaSValentin Clement sourceLine); 231*12ba74e1SValentin Clement (バレンタイン クレメン) builder.create<fir::CallOp>(loc, func, args); 23242b21ddaSValentin Clement } 233dda01632SValentin Clement 234dda01632SValentin Clement void Fortran::lower::genPointerAssociateLowerBounds(fir::FirOpBuilder &builder, 235dda01632SValentin Clement mlir::Location loc, 236dda01632SValentin Clement mlir::Value pointer, 237dda01632SValentin Clement mlir::Value target, 238dda01632SValentin Clement mlir::Value lbounds) { 239dda01632SValentin Clement mlir::func::FuncOp func = 240dda01632SValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(PointerAssociateLowerBounds)>( 241dda01632SValentin Clement loc, builder); 242dda01632SValentin Clement llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments( 243dda01632SValentin Clement builder, loc, func.getFunctionType(), pointer, target, lbounds); 244*12ba74e1SValentin Clement (バレンタイン クレメン) builder.create<fir::CallOp>(loc, func, args); 245dda01632SValentin Clement } 246