diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Stop.h b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h new file mode 100644 --- /dev/null +++ b/flang/include/flang/Optimizer/Builder/Runtime/Stop.h @@ -0,0 +1,27 @@ +//===-- Stop.h - generate stop runtime API calls ----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_STOP_H +#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_STOP_H + +namespace mlir { +class Value; +class Location; +} // namespace mlir + +namespace fir { +class FirOpBuilder; +} + +namespace fir::runtime { + +/// Generate call to EXIT intrinsic runtime routine. +void genExit(fir::FirOpBuilder &, mlir::Location, mlir::Value status); + +} // namespace fir::runtime +#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_STOP_H diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt --- a/flang/lib/Optimizer/Builder/CMakeLists.txt +++ b/flang/lib/Optimizer/Builder/CMakeLists.txt @@ -14,6 +14,7 @@ Runtime/Numeric.cpp Runtime/Ragged.cpp Runtime/Reduction.cpp + Runtime/Stop.cpp Runtime/Transformational.cpp DEPENDS diff --git a/flang/lib/Optimizer/Builder/Runtime/Stop.cpp b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp new file mode 100644 --- /dev/null +++ b/flang/lib/Optimizer/Builder/Runtime/Stop.cpp @@ -0,0 +1,22 @@ +//===-- Stop.h - generate stop runtime API calls ----------------*- C++ -*-===// +// +// 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/Optimizer/Builder/Runtime/Stop.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Runtime/stop.h" + +using namespace Fortran::runtime; + +void fir::runtime::genExit(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value status) { + auto exitFunc = fir::runtime::getRuntimeFunc(loc, builder); + llvm::SmallVector args = + fir::runtime::createArguments(builder, loc, exitFunc.getType(), status); + builder.create(loc, exitFunc, args); +} diff --git a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h --- a/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h +++ b/flang/unittests/Optimizer/Builder/Runtime/RuntimeCallTestBase.h @@ -120,4 +120,24 @@ checkCallOpFromResultBox(convOp.getResult(), fctName, nbArgs, addLocArgs); } +/// Check the operations in \p block for a `fir::CallOp` operation where the +/// function being called shares its function name with \p fctName and the +/// number of arguments is equal to \p nbArgs. Note that this check only cares +/// if the operation exists, and not the order in when the operation is called. +/// This results in exiting the test as soon as the first correct instance of +/// `fir::CallOp` is found). +static inline void checkBlockForCallOp( + mlir::Block *block, llvm::StringRef fctName, unsigned nbArgs) { + assert(block && "mlir::Block given is a nullptr"); + for (auto &op : block->getOperations()) { + if (auto callOp = mlir::dyn_cast(op)) { + if (fctName == callOp.callee()->getRootReference().getValue()) { + EXPECT_EQ(nbArgs, callOp.args().size()); + return; + } + } + } + FAIL() << "No calls to " << fctName << " were found!"; +} + #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H diff --git a/flang/unittests/Optimizer/Builder/Runtime/StopTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/StopTest.cpp new file mode 100644 --- /dev/null +++ b/flang/unittests/Optimizer/Builder/Runtime/StopTest.cpp @@ -0,0 +1,20 @@ +//===- StopTest.cpp -- Stop runtime builder unit tests ---------===// +// +// 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/Optimizer/Builder/Runtime/Stop.h" +#include "RuntimeCallTestBase.h" +#include "gtest/gtest.h" + +TEST_F(RuntimeCallTest, genExitTest) { + mlir::Location loc = firBuilder->getUnknownLoc(); + mlir::Value status = firBuilder->createIntegerConstant(loc, i32Ty, 0); + fir::runtime::genExit(*firBuilder, loc, status); + mlir::Block *block = firBuilder->getBlock(); + EXPECT_TRUE(block) << "Failed to retrieve the block!"; + checkBlockForCallOp(block, "_FortranAExit", 1); +} diff --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt --- a/flang/unittests/Optimizer/CMakeLists.txt +++ b/flang/unittests/Optimizer/CMakeLists.txt @@ -20,6 +20,7 @@ Builder/Runtime/NumericTest.cpp Builder/Runtime/RaggedTest.cpp Builder/Runtime/ReductionTest.cpp + Builder/Runtime/StopTest.cpp Builder/Runtime/TransformationalTest.cpp FIRContextTest.cpp InternalNamesTest.cpp