mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 16:50:51 +08:00
Implements lowering for the Fortran `PAUSE` statement. - Handles PAUSE with no operand. - Handles PAUSE with integer argument. - Handles PAUSE with character literal argument. - Adds a new lowering test: flang/test/Lower/pause-statement.f90. Unlike STOP, PAUSE does not unconditionally terminate control flow. The lowering preserves labels and GOTOs, consistent with legacy Fortran behavior. Fixes: #166821 --------- Co-authored-by: aditya nath <adityanath5002@gmail.com> Co-authored-by: Eugene Epshteyn <eepshteyn@nvidia.com>
This commit is contained in:
@@ -169,12 +169,55 @@ void Fortran::lower::genUnlockStatement(
|
||||
|
||||
void Fortran::lower::genPauseStatement(
|
||||
Fortran::lower::AbstractConverter &converter,
|
||||
const Fortran::parser::PauseStmt &) {
|
||||
const Fortran::parser::PauseStmt &stmt) {
|
||||
|
||||
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
|
||||
mlir::Location loc = converter.getCurrentLocation();
|
||||
mlir::func::FuncOp callee =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
|
||||
fir::CallOp::create(builder, loc, callee, mlir::ValueRange{});
|
||||
Fortran::lower::StatementContext stmtCtx;
|
||||
|
||||
llvm::SmallVector<mlir::Value> operands;
|
||||
mlir::func::FuncOp callee;
|
||||
mlir::FunctionType calleeType;
|
||||
|
||||
if (stmt.v.has_value()) {
|
||||
const auto &code = stmt.v.value();
|
||||
auto expr =
|
||||
converter.genExprValue(*Fortran::semantics::GetExpr(code), stmtCtx);
|
||||
expr.match(
|
||||
// Character-valued expression -> call PauseStatementText (CHAR, LEN)
|
||||
[&](const fir::CharBoxValue &x) {
|
||||
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementText)>(
|
||||
loc, builder);
|
||||
calleeType = callee.getFunctionType();
|
||||
|
||||
operands.push_back(
|
||||
builder.createConvert(loc, calleeType.getInput(0), x.getAddr()));
|
||||
operands.push_back(
|
||||
builder.createConvert(loc, calleeType.getInput(1), x.getLen()));
|
||||
},
|
||||
// Unboxed value -> call PauseStatementInt which accepts an integer.
|
||||
[&](fir::UnboxedValue x) {
|
||||
callee = fir::runtime::getRuntimeFunc<mkRTKey(PauseStatementInt)>(
|
||||
loc, builder);
|
||||
calleeType = callee.getFunctionType();
|
||||
assert(calleeType.getNumInputs() >= 1);
|
||||
mlir::Value cast =
|
||||
builder.createConvert(loc, calleeType.getInput(0), x);
|
||||
operands.push_back(cast);
|
||||
},
|
||||
[&](auto) {
|
||||
fir::emitFatalError(loc, "unhandled expression in PAUSE");
|
||||
});
|
||||
} else {
|
||||
callee =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(PauseStatement)>(loc, builder);
|
||||
calleeType = callee.getFunctionType();
|
||||
}
|
||||
|
||||
fir::CallOp::create(builder, loc, callee, operands);
|
||||
|
||||
// NOTE: PAUSE does not terminate the current block. The program may resume
|
||||
// and continue normal execution, so we do not emit control-flow terminators.
|
||||
}
|
||||
|
||||
void Fortran::lower::genPointerAssociate(fir::FirOpBuilder &builder,
|
||||
|
||||
@@ -2,7 +2,31 @@
|
||||
|
||||
! CHECK-LABEL: pause_test
|
||||
subroutine pause_test()
|
||||
! CHECK: fir.call @_Fortran{{.*}}PauseStatement()
|
||||
! CHECK-NEXT: return
|
||||
pause
|
||||
! CHECK: fir.call @_FortranA{{.*}}PauseStatement()
|
||||
! CHECK-NEXT: return
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: pause_code
|
||||
subroutine pause_code()
|
||||
pause 42
|
||||
! CHECK: %[[c42:.*]] = arith.constant 42 : i32
|
||||
! CHECK: fir.call @_FortranA{{.*}}PauseStatementInt(%[[c42]])
|
||||
! CHECK-NEXT: return
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: pause_msg
|
||||
subroutine pause_msg()
|
||||
pause "hello"
|
||||
! CHECK-DAG: %[[five:.*]] = arith.constant 5 : index
|
||||
! CHECK-DAG: %[[addr:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,5>>
|
||||
! CHECK-DAG: %[[str:.*]]:2 = hlfir.declare %[[addr]] typeparams %[[five]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQ{{.*}}"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
|
||||
! CHECK-DAG: %[[buff:.*]] = fir.convert %[[str]]#0 : (!fir.ref<!fir.char<1,5>>) -> !fir.ref<i8>
|
||||
! CHECK-DAG: %[[len:.*]] = fir.convert %[[five]] : (index) -> i64
|
||||
! CHECK: fir.call @_FortranA{{.*}}PauseStatementText(%[[buff]], %[[len]])
|
||||
! CHECK-NEXT: return
|
||||
end subroutine
|
||||
|
||||
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatement
|
||||
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementInt
|
||||
! CHECK-DAG: func private @_FortranA{{.*}}PauseStatementText
|
||||
|
||||
Reference in New Issue
Block a user