brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.1 KiB · 803ea37 Raw
164 lines · c
1//===- RuntimeCallTestBase.cpp -- Base for runtime call generation tests --===//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#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H10#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H11 12#include "gtest/gtest.h"13#include "flang/Optimizer/Builder/FIRBuilder.h"14#include "flang/Optimizer/Dialect/Support/KindMapping.h"15#include "flang/Optimizer/Support/InitFIR.h"16 17struct RuntimeCallTest : public testing::Test {18public:19  void SetUp() override {20    fir::support::loadDialects(context);21 22    mlir::OpBuilder builder(&context);23    auto loc = builder.getUnknownLoc();24 25    // Set up a Module with a dummy function operation inside.26    // Set the insertion point in the function entry block.27    moduleOp = mlir::ModuleOp::create(builder, loc);28    builder.setInsertionPointToStart(moduleOp->getBody());29    mlir::func::FuncOp func = mlir::func::FuncOp::create(builder, loc,30        "runtime_unit_tests_func", builder.getFunctionType({}, {}));31    auto *entryBlock = func.addEntryBlock();32    builder.setInsertionPointToStart(entryBlock);33 34    kindMap = std::make_unique<fir::KindMapping>(&context);35    firBuilder = std::make_unique<fir::FirOpBuilder>(builder, *kindMap);36 37    i1Ty = firBuilder->getI1Type();38    i8Ty = firBuilder->getI8Type();39    i16Ty = firBuilder->getIntegerType(16);40    i32Ty = firBuilder->getI32Type();41    i64Ty = firBuilder->getI64Type();42    i128Ty = firBuilder->getIntegerType(128);43 44    f32Ty = firBuilder->getF32Type();45    f64Ty = firBuilder->getF64Type();46    f80Ty = firBuilder->getF80Type();47    f128Ty = firBuilder->getF128Type();48 49    c4Ty = mlir::ComplexType::get(f32Ty);50    c8Ty = mlir::ComplexType::get(f64Ty);51    c10Ty = mlir::ComplexType::get(f80Ty);52    c16Ty = mlir::ComplexType::get(f128Ty);53 54    seqTy10 = fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);55    boxTy = fir::BoxType::get(mlir::NoneType::get(firBuilder->getContext()));56 57    char1Ty = fir::CharacterType::getSingleton(builder.getContext(), 1);58    char2Ty = fir::CharacterType::getSingleton(builder.getContext(), 2);59    char4Ty = fir::CharacterType::getSingleton(builder.getContext(), 4);60 61    logical1Ty = fir::LogicalType::get(builder.getContext(), 1);62    logical2Ty = fir::LogicalType::get(builder.getContext(), 2);63    logical4Ty = fir::LogicalType::get(builder.getContext(), 4);64    logical8Ty = fir::LogicalType::get(builder.getContext(), 8);65  }66 67  mlir::MLIRContext context;68  mlir::OwningOpRef<mlir::ModuleOp> moduleOp;69  std::unique_ptr<fir::KindMapping> kindMap;70  std::unique_ptr<fir::FirOpBuilder> firBuilder;71 72  // Commonly used types73  mlir::Type i1Ty;74  mlir::Type i8Ty;75  mlir::Type i16Ty;76  mlir::Type i32Ty;77  mlir::Type i64Ty;78  mlir::Type i128Ty;79  mlir::Type f32Ty;80  mlir::Type f64Ty;81  mlir::Type f80Ty;82  mlir::Type f128Ty;83  mlir::Type c4Ty;84  mlir::Type c8Ty;85  mlir::Type c10Ty;86  mlir::Type c16Ty;87  mlir::Type seqTy10;88  mlir::Type boxTy;89  mlir::Type char1Ty;90  mlir::Type char2Ty;91  mlir::Type char4Ty;92  mlir::Type logical1Ty;93  mlir::Type logical2Ty;94  mlir::Type logical4Ty;95  mlir::Type logical8Ty;96};97 98/// Check that the \p op is a `fir::CallOp` operation and its name matches99/// \p fctName and the number of arguments is equal to \p nbArgs.100/// Most runtime calls have two additional location arguments added. These are101/// added in this check when \p addLocArgs is true.102static inline void checkCallOp(mlir::Operation *op, llvm::StringRef fctName,103    unsigned nbArgs, bool addLocArgs = true) {104  EXPECT_TRUE(mlir::isa<fir::CallOp>(*op));105  auto callOp = mlir::dyn_cast<fir::CallOp>(*op);106  EXPECT_TRUE(callOp.getCallee().has_value());107  mlir::SymbolRefAttr callee = *callOp.getCallee();108  EXPECT_EQ(fctName, callee.getRootReference().getValue());109  // sourceFile and sourceLine are added arguments.110  if (addLocArgs)111    nbArgs += 2;112  EXPECT_EQ(nbArgs, callOp.getArgs().size());113}114 115/// Check the call operation from the \p result value. In some cases the116/// value is directly used in the call and sometimes there is an indirection117/// through a `fir.convert` operation. Once the `fir.call` operation is118/// retrieved the check is made by `checkCallOp`.119///120/// Directly used in `fir.call`.121/// ```122/// %result = arith.constant 1 : i32123/// %0 = fir.call @foo(%result) : (i32) -> i1124/// ```125///126/// Value used in `fir.call` through `fir.convert` indirection.127/// ```128/// %result = arith.constant 1 : i32129/// %arg = fir.convert %result : (i32) -> i16130/// %0 = fir.call @foo(%arg) : (i16) -> i1131/// ```132static inline void checkCallOpFromResultBox(mlir::Value result,133    llvm::StringRef fctName, unsigned nbArgs, bool addLocArgs = true) {134  EXPECT_TRUE(result.hasOneUse());135  const auto &u = result.user_begin();136  if (mlir::isa<fir::CallOp>(*u))137    return checkCallOp(*u, fctName, nbArgs, addLocArgs);138  auto convOp = mlir::dyn_cast<fir::ConvertOp>(*u);139  EXPECT_NE(nullptr, convOp);140  checkCallOpFromResultBox(convOp.getResult(), fctName, nbArgs, addLocArgs);141}142 143/// Check the operations in \p block for a `fir::CallOp` operation where the144/// function being called shares its function name with \p fctName and the145/// number of arguments is equal to \p nbArgs. Note that this check only cares146/// if the operation exists, and not the order in when the operation is called.147/// This results in exiting the test as soon as the first correct instance of148/// `fir::CallOp` is found).149static inline void checkBlockForCallOp(150    mlir::Block *block, llvm::StringRef fctName, unsigned nbArgs) {151  assert(block && "mlir::Block given is a nullptr");152  for (auto &op : block->getOperations()) {153    if (auto callOp = mlir::dyn_cast<fir::CallOp>(op)) {154      if (fctName == callOp.getCallee()->getRootReference().getValue()) {155        EXPECT_EQ(nbArgs, callOp.getArgs().size());156        return;157      }158    }159  }160  FAIL() << "No calls to " << fctName << " were found!";161}162 163#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H164