107 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9//===----------------------------------------------------------------------===//10/// \file11/// This pass is only for developers to generate declarations/calls12/// of Fortran runtime function recognized in13/// flang/Optimizer/Transforms/RuntimeFunctions.inc table.14/// Sample of the generated FIR:15/// func.func private16/// @_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) -> i123/// return %0 : i124/// }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_GENRUNTIMECALLSFORTEST37#include "flang/Optimizer/Transforms/Passes.h.inc"38} // namespace fir39 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 GenRuntimeCallsForTestPass50 : public fir::impl::GenRuntimeCallsForTestBase<GenRuntimeCallsForTestPass> {51 using GenRuntimeCallsForTestBase<52 GenRuntimeCallsForTestPass>::GenRuntimeCallsForTestBase;53 54public:55 void runOnOperation() override;56};57} // end anonymous namespace58 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 Fortran80 // 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 = fir::CallOp::create(builder, loc, funcOp, args);95 mlir::func::ReturnOp::create(builder, 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 beginning102 // of the module.103 auto moduleBegin = moduleOp.getBody()->begin();104 for (auto func : newFuncs)105 func->moveBefore(moduleOp.getBody(), moduleBegin);106}107