1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
//===- GenRuntimeCallsForTest.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
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// \file
/// This pass is only for developers to generate declarations/calls
/// of Fortran runtime function recognized in
/// flang/Optimizer/Transforms/RuntimeFunctions.inc table.
/// Sample of the generated FIR:
/// func.func private
/// @_FortranAioSetStatus(!fir.ref<i8>, !fir.ref<i8>, i64) ->
/// i1 attributes {fir.io, fir.runtime}
///
/// func.func @test__FortranAioSetStatus(
/// %arg0: !fir.ref<i8>, %arg1: !fir.ref<i8>, %arg2: i64) -> i1 {
/// %0 = fir.call @_FortranAioSetStatus(%arg0, %arg1, %arg2) :
/// (!fir.ref<i8>, !fir.ref<i8>, i64) -> i1
/// return %0 : i1
/// }
//===----------------------------------------------------------------------===//
#include "flang/Common/static-multimap-view.h"
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Optimizer/Transforms/Passes.h"
#include "flang/Runtime/io-api.h"
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
namespace fir {
#define GEN_PASS_DEF_GENRUNTIMECALLSFORTEST
#include "flang/Optimizer/Transforms/Passes.h.inc"
} // namespace fir
#define DEBUG_TYPE "gen-runtime-calls-for-test"
using namespace Fortran::runtime;
using namespace Fortran::runtime::io;
#define mkIOKey(X) FirmkKey(IONAME(X))
#define mkRTKey(X) FirmkKey(RTNAME(X))
namespace {
class GenRuntimeCallsForTestPass
: public fir::impl::GenRuntimeCallsForTestBase<GenRuntimeCallsForTestPass> {
using GenRuntimeCallsForTestBase<
GenRuntimeCallsForTestPass>::GenRuntimeCallsForTestBase;
public:
void runOnOperation() override;
};
} // end anonymous namespace
static constexpr llvm::StringRef testPrefix = "test_";
void GenRuntimeCallsForTestPass::runOnOperation() {
mlir::ModuleOp moduleOp = getOperation();
mlir::OpBuilder mlirBuilder(moduleOp.getRegion());
fir::FirOpBuilder builder(mlirBuilder, moduleOp);
mlir::Location loc = mlir::UnknownLoc::get(builder.getContext());
#define KNOWN_IO_FUNC(X) \
fir::runtime::getIORuntimeFunc<mkIOKey(X)>(loc, builder)
#define KNOWN_RUNTIME_FUNC(X) \
fir::runtime::getRuntimeFunc<mkRTKey(X)>(loc, builder)
mlir::func::FuncOp runtimeFuncsTable[] = {
#include "flang/Optimizer/Transforms/RuntimeFunctions.inc"
};
if (!doGenerateCalls)
return;
// Generate thin wrapper functions calling the known Fortran
// runtime functions.
llvm::SmallVector<mlir::Operation *> newFuncs;
for (unsigned i = 0;
i < sizeof(runtimeFuncsTable) / sizeof(runtimeFuncsTable[0]); ++i) {
mlir::func::FuncOp funcOp = runtimeFuncsTable[i];
mlir::FunctionType funcTy = funcOp.getFunctionType();
std::string name = (llvm::Twine(testPrefix) + funcOp.getName()).str();
mlir::func::FuncOp callerFunc = builder.createFunction(loc, name, funcTy);
callerFunc.setVisibility(mlir::SymbolTable::Visibility::Public);
mlir::OpBuilder::InsertPoint insertPt = builder.saveInsertionPoint();
// Generate the wrapper function body that consists of a call and return.
builder.setInsertionPointToStart(callerFunc.addEntryBlock());
mlir::Block::BlockArgListType args = callerFunc.front().getArguments();
auto callOp = fir::CallOp::create(builder, loc, funcOp, args);
mlir::func::ReturnOp::create(builder, loc, callOp.getResults());
newFuncs.push_back(callerFunc.getOperation());
builder.restoreInsertionPoint(insertPt);
}
// Make sure all wrapper functions are at the beginning
// of the module.
auto moduleBegin = moduleOp.getBody()->begin();
for (auto func : newFuncs)
func->moveBefore(moduleOp.getBody(), moduleBegin);
}
|