diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index fdd422586690e..fd52a76cf2f65 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -15,6 +15,7 @@ #include "flang/Lower/CallInterface.h" #include "flang/Lower/Mangler.h" #include "flang/Lower/PFTBuilder.h" +#include "flang/Lower/Runtime.h" #include "flang/Lower/SymbolMap.h" #include "flang/Lower/Todo.h" #include "flang/Optimizer/Support/FIRContext.h" @@ -553,8 +554,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { TODO(toLocation(), "FailImageStmt lowering"); } + // call STOP, ERROR STOP in runtime void genFIR(const Fortran::parser::StopStmt &stmt) { - TODO(toLocation(), "StopStmt lowering"); + genStopStatement(*this, stmt); } void genFIR(const Fortran::parser::ReturnStmt &stmt) { diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 9981f5d2b8bca..925ac0acfe2b6 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -9,6 +9,7 @@ add_flang_library(FortranLower OpenACC.cpp OpenMP.cpp PFTBuilder.cpp + Runtime.cpp SymbolMap.cpp DEPENDS diff --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp new file mode 100644 index 0000000000000..7156a8851f1dc --- /dev/null +++ b/flang/lib/Lower/Runtime.cpp @@ -0,0 +1,70 @@ +//===-- Runtime.cpp -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "flang/Lower/Runtime.h" +#include "flang/Lower/Bridge.h" +#include "flang/Lower/Todo.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Runtime/stop.h" +#include "flang/Semantics/tools.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "flang-lower-runtime" + +using namespace Fortran::runtime; + +/// Runtime calls that do not return to the caller indicate this condition by +/// terminating the current basic block with an unreachable op. +static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) { + builder.create(loc); + mlir::Block *newBlock = + builder.getBlock()->splitBlock(builder.getInsertionPoint()); + builder.setInsertionPointToStart(newBlock); +} + +//===----------------------------------------------------------------------===// +// Misc. Fortran statements that lower to runtime calls +//===----------------------------------------------------------------------===// + +void Fortran::lower::genStopStatement( + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::StopStmt &stmt) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mlir::Location loc = converter.getCurrentLocation(); + llvm::SmallVector operands; + mlir::FuncOp callee; + mlir::FunctionType calleeType; + // First operand is stop code (zero if absent) + if (std::get>(stmt.t)) { + TODO(loc, "STOP first operand not lowered yet"); + } else { + callee = fir::runtime::getRuntimeFunc(loc, builder); + calleeType = callee.getType(); + operands.push_back( + builder.createIntegerConstant(loc, calleeType.getInput(0), 0)); + } + + // Second operand indicates ERROR STOP + bool isError = std::get(stmt.t) == + Fortran::parser::StopStmt::Kind::ErrorStop; + operands.push_back(builder.createIntegerConstant( + loc, calleeType.getInput(operands.size()), isError)); + + // Third operand indicates QUIET (default to false). + if (std::get>(stmt.t)) { + TODO(loc, "STOP third operand not lowered yet"); + } else { + operands.push_back(builder.createIntegerConstant( + loc, calleeType.getInput(operands.size()), 0)); + } + + builder.create(loc, callee, operands); + genUnreachable(builder, loc); +} diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index b9a9316325adc..ac56e32c4e00f 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -80,7 +80,7 @@ mlir::Value fir::FirOpBuilder::createNullConstant(mlir::Location loc, mlir::Value fir::FirOpBuilder::createIntegerConstant(mlir::Location loc, mlir::Type ty, std::int64_t cst) { - return create(loc, ty, getIntegerAttr(ty, cst)); + return create(loc, ty, getIntegerAttr(ty, cst)); } mlir::Value diff --git a/flang/test/Lower/stop-statement.f90 b/flang/test/Lower/stop-statement.f90 new file mode 100644 index 0000000000000..497b6db1a9f4b --- /dev/null +++ b/flang/test/Lower/stop-statement.f90 @@ -0,0 +1,21 @@ +! RUN: bbc %s -emit-fir --canonicalize -o - | FileCheck %s + +! CHECK-LABEL stop_test +subroutine stop_test() + ! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : i32 + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK: fir.call @_Fortran{{.*}}StopStatement(%[[c0]], %[[false]], %[[false]]) + ! CHECK-NEXT: fir.unreachable + stop +end subroutine + + +! CHECK-LABEL stop_error +subroutine stop_error() + error stop + ! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : i32 + ! CHECK-DAG: %[[true:.*]] = arith.constant true + ! CHECK-DAG: %[[false:.*]] = arith.constant false + ! CHECK: fir.call @_Fortran{{.*}}StopStatement(%[[c0]], %[[true]], %[[false]]) + ! CHECK-NEXT: fir.unreachable +end subroutine diff --git a/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp b/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp index 348438238a7ae..0808c4eb5d3bd 100644 --- a/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp +++ b/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp @@ -30,8 +30,8 @@ struct DoLoopHelperTest : public testing::Test { }; void checkConstantValue(const mlir::Value &value, int64_t v) { - EXPECT_TRUE(mlir::isa(value.getDefiningOp())); - auto cstOp = dyn_cast(value.getDefiningOp()); + EXPECT_TRUE(mlir::isa(value.getDefiningOp())); + auto cstOp = dyn_cast(value.getDefiningOp()); auto valueAttr = cstOp.getValue().dyn_cast_or_null(); EXPECT_EQ(v, valueAttr.getInt()); } diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp index 6fb5c745bce21..7613d9145944a 100644 --- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp +++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp @@ -48,8 +48,8 @@ static arith::CmpIOp createCondition(fir::FirOpBuilder &builder) { } static void checkIntegerConstant(mlir::Value value, mlir::Type ty, int64_t v) { - EXPECT_TRUE(mlir::isa(value.getDefiningOp())); - auto cstOp = dyn_cast(value.getDefiningOp()); + EXPECT_TRUE(mlir::isa(value.getDefiningOp())); + auto cstOp = dyn_cast(value.getDefiningOp()); EXPECT_EQ(ty, cstOp.getType()); auto valueAttr = cstOp.getValue().dyn_cast_or_null(); EXPECT_EQ(v, valueAttr.getInt());