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" 11aab4263aSValentin Clement #include "flang/Lower/Todo.h" 12aab4263aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 13aab4263aSValentin Clement #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" 14aab4263aSValentin Clement #include "flang/Parser/parse-tree.h" 15aab4263aSValentin Clement #include "flang/Runtime/stop.h" 16aab4263aSValentin Clement #include "flang/Semantics/tools.h" 17aab4263aSValentin Clement #include "llvm/Support/Debug.h" 18aab4263aSValentin Clement 19aab4263aSValentin Clement #define DEBUG_TYPE "flang-lower-runtime" 20aab4263aSValentin Clement 21aab4263aSValentin Clement using namespace Fortran::runtime; 22aab4263aSValentin Clement 23aab4263aSValentin Clement /// Runtime calls that do not return to the caller indicate this condition by 24aab4263aSValentin Clement /// terminating the current basic block with an unreachable op. 25aab4263aSValentin Clement static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { 26aab4263aSValentin Clement builder.create<fir::UnreachableOp>(loc); 27aab4263aSValentin Clement mlir::Block *newBlock = 28aab4263aSValentin Clement builder.getBlock()->splitBlock(builder.getInsertionPoint()); 29aab4263aSValentin Clement builder.setInsertionPointToStart(newBlock); 30aab4263aSValentin Clement } 31aab4263aSValentin Clement 32aab4263aSValentin Clement //===----------------------------------------------------------------------===// 33aab4263aSValentin Clement // Misc. Fortran statements that lower to runtime calls 34aab4263aSValentin Clement //===----------------------------------------------------------------------===// 35aab4263aSValentin Clement 36aab4263aSValentin Clement void Fortran::lower::genStopStatement( 37aab4263aSValentin Clement Fortran::lower::AbstractConverter &converter, 38aab4263aSValentin Clement const Fortran::parser::StopStmt &stmt) { 39aab4263aSValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 40aab4263aSValentin Clement mlir::Location loc = converter.getCurrentLocation(); 41aab4263aSValentin Clement llvm::SmallVector<mlir::Value> operands; 42aab4263aSValentin Clement mlir::FuncOp callee; 43aab4263aSValentin Clement mlir::FunctionType calleeType; 44aab4263aSValentin Clement // First operand is stop code (zero if absent) 45ca53e049SValentin Clement if (const auto &code = 46ca53e049SValentin Clement std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) { 47ca53e049SValentin Clement auto expr = converter.genExprValue(*Fortran::semantics::GetExpr(*code)); 48ca53e049SValentin Clement LLVM_DEBUG(llvm::dbgs() << "stop expression: "; expr.dump(); 49ca53e049SValentin Clement llvm::dbgs() << '\n'); 50ca53e049SValentin Clement expr.match( 51ca53e049SValentin Clement [&](const fir::CharBoxValue &x) { 52*a8d48fe0SValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatementText)>( 53*a8d48fe0SValentin Clement loc, builder); 54*a8d48fe0SValentin Clement calleeType = callee.getType(); 55*a8d48fe0SValentin Clement // Creates a pair of operands for the CHARACTER and its LEN. 56*a8d48fe0SValentin Clement operands.push_back( 57*a8d48fe0SValentin Clement builder.createConvert(loc, calleeType.getInput(0), x.getAddr())); 58*a8d48fe0SValentin Clement operands.push_back( 59*a8d48fe0SValentin Clement builder.createConvert(loc, calleeType.getInput(1), x.getLen())); 60ca53e049SValentin Clement }, 61ca53e049SValentin Clement [&](fir::UnboxedValue x) { 62ca53e049SValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>( 63ca53e049SValentin Clement loc, builder); 64ca53e049SValentin Clement calleeType = callee.getType(); 65ca53e049SValentin Clement mlir::Value cast = 66ca53e049SValentin Clement builder.createConvert(loc, calleeType.getInput(0), x); 67ca53e049SValentin Clement operands.push_back(cast); 68ca53e049SValentin Clement }, 69ca53e049SValentin Clement [&](auto) { 70ca53e049SValentin Clement mlir::emitError(loc, "unhandled expression in STOP"); 71ca53e049SValentin Clement std::exit(1); 72ca53e049SValentin Clement }); 73aab4263aSValentin Clement } else { 74aab4263aSValentin Clement callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); 75aab4263aSValentin Clement calleeType = callee.getType(); 76aab4263aSValentin Clement operands.push_back( 77aab4263aSValentin Clement builder.createIntegerConstant(loc, calleeType.getInput(0), 0)); 78aab4263aSValentin Clement } 79aab4263aSValentin Clement 80aab4263aSValentin Clement // Second operand indicates ERROR STOP 81aab4263aSValentin Clement bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) == 82aab4263aSValentin Clement Fortran::parser::StopStmt::Kind::ErrorStop; 83aab4263aSValentin Clement operands.push_back(builder.createIntegerConstant( 84aab4263aSValentin Clement loc, calleeType.getInput(operands.size()), isError)); 85aab4263aSValentin Clement 86aab4263aSValentin Clement // Third operand indicates QUIET (default to false). 87cc306740SValentin Clement if (const auto &quiet = 88cc306740SValentin Clement std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) { 89cc306740SValentin Clement const SomeExpr *expr = Fortran::semantics::GetExpr(*quiet); 90cc306740SValentin Clement assert(expr && "failed getting typed expression"); 91cc306740SValentin Clement mlir::Value q = fir::getBase(converter.genExprValue(*expr)); 92cc306740SValentin Clement operands.push_back( 93cc306740SValentin Clement builder.createConvert(loc, calleeType.getInput(operands.size()), q)); 94aab4263aSValentin Clement } else { 95aab4263aSValentin Clement operands.push_back(builder.createIntegerConstant( 96aab4263aSValentin Clement loc, calleeType.getInput(operands.size()), 0)); 97aab4263aSValentin Clement } 98aab4263aSValentin Clement 99aab4263aSValentin Clement builder.create<fir::CallOp>(loc, callee, operands); 100aab4263aSValentin Clement genUnreachable(builder, loc); 101aab4263aSValentin Clement } 102db01b123SValentin Clement 103db01b123SValentin Clement void Fortran::lower::genPauseStatement( 104db01b123SValentin Clement Fortran::lower::AbstractConverter &converter, 105db01b123SValentin Clement const Fortran::parser::PauseStmt &) { 106db01b123SValentin Clement fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 107db01b123SValentin Clement mlir::Location loc = converter.getCurrentLocation(); 108db01b123SValentin Clement mlir::FuncOp callee = 109db01b123SValentin Clement fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); 110db01b123SValentin Clement builder.create<fir::CallOp>(loc, callee, llvm::None); 111db01b123SValentin Clement } 112