[flang] Lower basic STOP statement

This patch lowers STOP statement without arguments
and ERROR STOP. STOP statement with arguments lowering will
come in later patches ince it requires some expression lowering
to be added.
STOP statement is lowered to a runtime call.

Also makes sure we are creating a constant in the MLIR arith constant.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: kiranchandramohan, schweitz

Differential Revision: https://reviews.llvm.org/D118697

Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
This commit is contained in:
Valentin Clement 2022-02-01 20:53:00 +01:00
parent 82cf35bc89
commit aab4263ad6
No known key found for this signature in database
GPG Key ID: 086D54783C928776
7 changed files with 100 additions and 6 deletions

View File

@ -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 @@ private:
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) {

View File

@ -9,6 +9,7 @@ add_flang_library(FortranLower
OpenACC.cpp
OpenMP.cpp
PFTBuilder.cpp
Runtime.cpp
SymbolMap.cpp
DEPENDS

View File

@ -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<fir::UnreachableOp>(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<mlir::Value> operands;
mlir::FuncOp callee;
mlir::FunctionType calleeType;
// First operand is stop code (zero if absent)
if (std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) {
TODO(loc, "STOP first operand not lowered yet");
} else {
callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder);
calleeType = callee.getType();
operands.push_back(
builder.createIntegerConstant(loc, calleeType.getInput(0), 0));
}
// Second operand indicates ERROR STOP
bool isError = std::get<Fortran::parser::StopStmt::Kind>(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<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) {
TODO(loc, "STOP third operand not lowered yet");
} else {
operands.push_back(builder.createIntegerConstant(
loc, calleeType.getInput(operands.size()), 0));
}
builder.create<fir::CallOp>(loc, callee, operands);
genUnreachable(builder, loc);
}

View File

@ -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<mlir::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
return create<mlir::arith::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
}
mlir::Value

View File

@ -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

View File

@ -30,8 +30,8 @@ public:
};
void checkConstantValue(const mlir::Value &value, int64_t v) {
EXPECT_TRUE(mlir::isa<ConstantOp>(value.getDefiningOp()));
auto cstOp = dyn_cast<ConstantOp>(value.getDefiningOp());
EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
EXPECT_EQ(v, valueAttr.getInt());
}

View File

@ -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<ConstantOp>(value.getDefiningOp()));
auto cstOp = dyn_cast<ConstantOp>(value.getDefiningOp());
EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
EXPECT_EQ(ty, cstOp.getType());
auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
EXPECT_EQ(v, valueAttr.getInt());