forked from OSchip/llvm-project
[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:
parent
82cf35bc89
commit
aab4263ad6
flang
lib
test/Lower
unittests/Optimizer/Builder
|
@ -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) {
|
||||
|
|
|
@ -9,6 +9,7 @@ add_flang_library(FortranLower
|
|||
OpenACC.cpp
|
||||
OpenMP.cpp
|
||||
PFTBuilder.cpp
|
||||
Runtime.cpp
|
||||
SymbolMap.cpp
|
||||
|
||||
DEPENDS
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue