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

source code of flang/lib/Optimizer/Transforms/GenRuntimeCallsForTest.cpp