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 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatementText)>( 53 loc, builder); 54 calleeType = callee.getType(); 55 // Creates a pair of operands for the CHARACTER and its LEN. 56 operands.push_back( 57 builder.createConvert(loc, calleeType.getInput(0), x.getAddr())); 58 operands.push_back( 59 builder.createConvert(loc, calleeType.getInput(1), x.getLen())); 60 }, 61 [&](fir::UnboxedValue x) { 62 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>( 63 loc, builder); 64 calleeType = callee.getType(); 65 mlir::Value cast = 66 builder.createConvert(loc, calleeType.getInput(0), x); 67 operands.push_back(cast); 68 }, 69 [&](auto) { 70 mlir::emitError(loc, "unhandled expression in STOP"); 71 std::exit(1); 72 }); 73 } else { 74 callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder); 75 calleeType = callee.getType(); 76 operands.push_back( 77 builder.createIntegerConstant(loc, calleeType.getInput(0), 0)); 78 } 79 80 // Second operand indicates ERROR STOP 81 bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) == 82 Fortran::parser::StopStmt::Kind::ErrorStop; 83 operands.push_back(builder.createIntegerConstant( 84 loc, calleeType.getInput(operands.size()), isError)); 85 86 // Third operand indicates QUIET (default to false). 87 if (const auto &quiet = 88 std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) { 89 const SomeExpr *expr = Fortran::semantics::GetExpr(*quiet); 90 assert(expr && "failed getting typed expression"); 91 mlir::Value q = fir::getBase(converter.genExprValue(*expr)); 92 operands.push_back( 93 builder.createConvert(loc, calleeType.getInput(operands.size()), q)); 94 } else { 95 operands.push_back(builder.createIntegerConstant( 96 loc, calleeType.getInput(operands.size()), 0)); 97 } 98 99 builder.create<fir::CallOp>(loc, callee, operands); 100 genUnreachable(builder, loc); 101 } 102 103 void Fortran::lower::genPauseStatement( 104 Fortran::lower::AbstractConverter &converter, 105 const Fortran::parser::PauseStmt &) { 106 fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 107 mlir::Location loc = converter.getCurrentLocation(); 108 mlir::FuncOp callee = 109 fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder); 110 builder.create<fir::CallOp>(loc, callee, llvm::None); 111 } 112