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 (const auto &code = 46 std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) { 47 auto expr = converter.genExprValue(*Fortran::semantics::GetExpr(*code)); 48 LLVM_DEBUG(llvm::dbgs() << "stop expression: "; expr.dump(); 49 llvm::dbgs() << '\n'); 50 expr.match( 51 [&](const fir::CharBoxValue &x) { 52 TODO(loc, "STOP CharBoxValue first operand not lowered yet"); 53 }, 54 [&](fir::UnboxedValue x) { 55 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>( 56 loc, builder); 57 calleeType = callee.getType(); 58 mlir::Value cast = 59 builder.createConvert(loc, calleeType.getInput(0), x); 60 operands.push_back(cast); 61 }, 62 [&](auto) { 63 mlir::emitError(loc, "unhandled expression in STOP"); 64 std::exit(1); 65 }); 66 } else { 67 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); 68 calleeType = callee.getType(); 69 operands.push_back( 70 builder.createIntegerConstant(loc, calleeType.getInput(0), 0)); 71 } 72 73 // Second operand indicates ERROR STOP 74 bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) == 75 Fortran::parser::StopStmt::Kind::ErrorStop; 76 operands.push_back(builder.createIntegerConstant( 77 loc, calleeType.getInput(operands.size()), isError)); 78 79 // Third operand indicates QUIET (default to false). 80 if (const auto &quiet = 81 std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) { 82 const SomeExpr *expr = Fortran::semantics::GetExpr(*quiet); 83 assert(expr && "failed getting typed expression"); 84 mlir::Value q = fir::getBase(converter.genExprValue(*expr)); 85 operands.push_back( 86 builder.createConvert(loc, calleeType.getInput(operands.size()), q)); 87 } else { 88 operands.push_back(builder.createIntegerConstant( 89 loc, calleeType.getInput(operands.size()), 0)); 90 } 91 92 builder.create<fir::CallOp>(loc, callee, operands); 93 genUnreachable(builder, loc); 94 } 95 96 void Fortran::lower::genPauseStatement( 97 Fortran::lower::AbstractConverter &converter, 98 const Fortran::parser::PauseStmt &) { 99 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 100 mlir::Location loc = converter.getCurrentLocation(); 101 mlir::FuncOp callee = 102 fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); 103 builder.create<fir::CallOp>(loc, callee, llvm::None); 104 } 105