1 //===-- Runtime.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "flang/Lower/Runtime.h" 10 #include "flang/Lower/Bridge.h" 11 #include "flang/Lower/Todo.h" 12 #include "flang/Optimizer/Builder/FIRBuilder.h" 13 #include "flang/Optimizer/Builder/Runtime/RTBuilder.h" 14 #include "flang/Parser/parse-tree.h" 15 #include "flang/Runtime/stop.h" 16 #include "flang/Semantics/tools.h" 17 #include "llvm/Support/Debug.h" 18 19 #define DEBUG_TYPE "flang-lower-runtime" 20 21 using namespace Fortran::runtime; 22 23 /// Runtime calls that do not return to the caller indicate this condition by 24 /// terminating the current basic block with an unreachable op. 25 static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { 26 builder.create<fir::UnreachableOp>(loc); 27 mlir::Block *newBlock = 28 builder.getBlock()->splitBlock(builder.getInsertionPoint()); 29 builder.setInsertionPointToStart(newBlock); 30 } 31 32 //===----------------------------------------------------------------------===// 33 // Misc. Fortran statements that lower to runtime calls 34 //===----------------------------------------------------------------------===// 35 36 void Fortran::lower::genStopStatement( 37 Fortran::lower::AbstractConverter &converter, 38 const Fortran::parser::StopStmt &stmt) { 39 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 40 mlir::Location loc = converter.getCurrentLocation(); 41 llvm::SmallVector<mlir::Value> operands; 42 mlir::FuncOp callee; 43 mlir::FunctionType calleeType; 44 // First operand is stop code (zero if absent) 45 if (std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) { 46 TODO(loc, "STOP first operand not lowered yet"); 47 } else { 48 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); 49 calleeType = callee.getType(); 50 operands.push_back( 51 builder.createIntegerConstant(loc, calleeType.getInput(0), 0)); 52 } 53 54 // Second operand indicates ERROR STOP 55 bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) == 56 Fortran::parser::StopStmt::Kind::ErrorStop; 57 operands.push_back(builder.createIntegerConstant( 58 loc, calleeType.getInput(operands.size()), isError)); 59 60 // Third operand indicates QUIET (default to false). 61 if (std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) { 62 TODO(loc, "STOP third operand not lowered yet"); 63 } else { 64 operands.push_back(builder.createIntegerConstant( 65 loc, calleeType.getInput(operands.size()), 0)); 66 } 67 68 builder.create<fir::CallOp>(loc, callee, operands); 69 genUnreachable(builder, loc); 70 } 71 72 void Fortran::lower::genPauseStatement( 73 Fortran::lower::AbstractConverter &converter, 74 const Fortran::parser::PauseStmt &) { 75 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 76 mlir::Location loc = converter.getCurrentLocation(); 77 mlir::FuncOp callee = 78 fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); 79 builder.create<fir::CallOp>(loc, callee, llvm::None); 80 } 81