11b3cd35aSValentin Clement //===- RuntimeCallTestBase.cpp -- Base for runtime call generation tests --===// 21b3cd35aSValentin Clement // 31b3cd35aSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41b3cd35aSValentin Clement // See https://llvm.org/LICENSE.txt for license information. 51b3cd35aSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61b3cd35aSValentin Clement // 71b3cd35aSValentin Clement //===----------------------------------------------------------------------===// 81b3cd35aSValentin Clement 91b3cd35aSValentin Clement #ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H 101b3cd35aSValentin Clement #define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H 111b3cd35aSValentin Clement 121b3cd35aSValentin Clement #include "gtest/gtest.h" 131b3cd35aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h" 14b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/KindMapping.h" 151b3cd35aSValentin Clement #include "flang/Optimizer/Support/InitFIR.h" 161b3cd35aSValentin Clement 171b3cd35aSValentin Clement struct RuntimeCallTest : public testing::Test { 181b3cd35aSValentin Clement public: 191b3cd35aSValentin Clement void SetUp() override { 2036550692SRiver Riddle fir::support::loadDialects(context); 2136550692SRiver Riddle 221b3cd35aSValentin Clement mlir::OpBuilder builder(&context); 231b3cd35aSValentin Clement auto loc = builder.getUnknownLoc(); 241b3cd35aSValentin Clement 251b3cd35aSValentin Clement // Set up a Module with a dummy function operation inside. 261b3cd35aSValentin Clement // Set the insertion point in the function entry block. 27*c870632eSMatthias Springer moduleOp = builder.create<mlir::ModuleOp>(loc); 28*c870632eSMatthias Springer builder.setInsertionPointToStart(moduleOp->getBody()); 2958ceae95SRiver Riddle mlir::func::FuncOp func = 30*c870632eSMatthias Springer builder.create<mlir::func::FuncOp>(loc, "runtime_unit_tests_func", 3163b63c3dSKazu Hirata builder.getFunctionType(std::nullopt, std::nullopt)); 321b3cd35aSValentin Clement auto *entryBlock = func.addEntryBlock(); 331b3cd35aSValentin Clement builder.setInsertionPointToStart(entryBlock); 341b3cd35aSValentin Clement 351b3cd35aSValentin Clement kindMap = std::make_unique<fir::KindMapping>(&context); 36*c870632eSMatthias Springer firBuilder = std::make_unique<fir::FirOpBuilder>(builder, *kindMap); 371b3cd35aSValentin Clement 385ebbcfa0SJosh Mottley i1Ty = firBuilder->getI1Type(); 391b3cd35aSValentin Clement i8Ty = firBuilder->getI8Type(); 401b3cd35aSValentin Clement i16Ty = firBuilder->getIntegerType(16); 411b3cd35aSValentin Clement i32Ty = firBuilder->getI32Type(); 421b3cd35aSValentin Clement i64Ty = firBuilder->getI64Type(); 431b3cd35aSValentin Clement i128Ty = firBuilder->getIntegerType(128); 441b3cd35aSValentin Clement 451b3cd35aSValentin Clement f32Ty = firBuilder->getF32Type(); 461b3cd35aSValentin Clement f64Ty = firBuilder->getF64Type(); 471b3cd35aSValentin Clement f80Ty = firBuilder->getF80Type(); 481b3cd35aSValentin Clement f128Ty = firBuilder->getF128Type(); 491b3cd35aSValentin Clement 50c4204c0bSjeanPerier c4Ty = mlir::ComplexType::get(f32Ty); 51c4204c0bSjeanPerier c8Ty = mlir::ComplexType::get(f64Ty); 52c4204c0bSjeanPerier c10Ty = mlir::ComplexType::get(f80Ty); 53c4204c0bSjeanPerier c16Ty = mlir::ComplexType::get(f128Ty); 54f6ae8e8cSValentin Clement 55f6ae8e8cSValentin Clement seqTy10 = fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); 56d59a0f58SValentin Clement boxTy = fir::BoxType::get(mlir::NoneType::get(firBuilder->getContext())); 579f6aae46SSlava Zakharin 589f6aae46SSlava Zakharin char1Ty = fir::CharacterType::getSingleton(builder.getContext(), 1); 599f6aae46SSlava Zakharin char2Ty = fir::CharacterType::getSingleton(builder.getContext(), 2); 609f6aae46SSlava Zakharin char4Ty = fir::CharacterType::getSingleton(builder.getContext(), 4); 618ce1aed5SSlava Zakharin 628ce1aed5SSlava Zakharin logical1Ty = fir::LogicalType::get(builder.getContext(), 1); 638ce1aed5SSlava Zakharin logical2Ty = fir::LogicalType::get(builder.getContext(), 2); 648ce1aed5SSlava Zakharin logical4Ty = fir::LogicalType::get(builder.getContext(), 4); 658ce1aed5SSlava Zakharin logical8Ty = fir::LogicalType::get(builder.getContext(), 8); 661b3cd35aSValentin Clement } 671b3cd35aSValentin Clement 681b3cd35aSValentin Clement mlir::MLIRContext context; 69*c870632eSMatthias Springer mlir::OwningOpRef<mlir::ModuleOp> moduleOp; 701b3cd35aSValentin Clement std::unique_ptr<fir::KindMapping> kindMap; 711b3cd35aSValentin Clement std::unique_ptr<fir::FirOpBuilder> firBuilder; 721b3cd35aSValentin Clement 731b3cd35aSValentin Clement // Commonly used types 745ebbcfa0SJosh Mottley mlir::Type i1Ty; 751b3cd35aSValentin Clement mlir::Type i8Ty; 761b3cd35aSValentin Clement mlir::Type i16Ty; 771b3cd35aSValentin Clement mlir::Type i32Ty; 781b3cd35aSValentin Clement mlir::Type i64Ty; 791b3cd35aSValentin Clement mlir::Type i128Ty; 801b3cd35aSValentin Clement mlir::Type f32Ty; 811b3cd35aSValentin Clement mlir::Type f64Ty; 821b3cd35aSValentin Clement mlir::Type f80Ty; 831b3cd35aSValentin Clement mlir::Type f128Ty; 841b3cd35aSValentin Clement mlir::Type c4Ty; 851b3cd35aSValentin Clement mlir::Type c8Ty; 861b3cd35aSValentin Clement mlir::Type c10Ty; 871b3cd35aSValentin Clement mlir::Type c16Ty; 88f6ae8e8cSValentin Clement mlir::Type seqTy10; 89d59a0f58SValentin Clement mlir::Type boxTy; 909f6aae46SSlava Zakharin mlir::Type char1Ty; 919f6aae46SSlava Zakharin mlir::Type char2Ty; 929f6aae46SSlava Zakharin mlir::Type char4Ty; 938ce1aed5SSlava Zakharin mlir::Type logical1Ty; 948ce1aed5SSlava Zakharin mlir::Type logical2Ty; 958ce1aed5SSlava Zakharin mlir::Type logical4Ty; 968ce1aed5SSlava Zakharin mlir::Type logical8Ty; 971b3cd35aSValentin Clement }; 981b3cd35aSValentin Clement 991b3cd35aSValentin Clement /// Check that the \p op is a `fir::CallOp` operation and its name matches 1001b3cd35aSValentin Clement /// \p fctName and the number of arguments is equal to \p nbArgs. 1011b3cd35aSValentin Clement /// Most runtime calls have two additional location arguments added. These are 1021b3cd35aSValentin Clement /// added in this check when \p addLocArgs is true. 10399961b4fSValentin Clement static inline void checkCallOp(mlir::Operation *op, llvm::StringRef fctName, 1041b3cd35aSValentin Clement unsigned nbArgs, bool addLocArgs = true) { 1051b3cd35aSValentin Clement EXPECT_TRUE(mlir::isa<fir::CallOp>(*op)); 1061b3cd35aSValentin Clement auto callOp = mlir::dyn_cast<fir::CallOp>(*op); 107c82fb16fSKazu Hirata EXPECT_TRUE(callOp.getCallee().has_value()); 108149ad3d5SShraiysh Vaishay mlir::SymbolRefAttr callee = *callOp.getCallee(); 1091b3cd35aSValentin Clement EXPECT_EQ(fctName, callee.getRootReference().getValue()); 1101b3cd35aSValentin Clement // sourceFile and sourceLine are added arguments. 1111b3cd35aSValentin Clement if (addLocArgs) 1121b3cd35aSValentin Clement nbArgs += 2; 113149ad3d5SShraiysh Vaishay EXPECT_EQ(nbArgs, callOp.getArgs().size()); 1141b3cd35aSValentin Clement } 1151b3cd35aSValentin Clement 1161b3cd35aSValentin Clement /// Check the call operation from the \p result value. In some cases the 1171b3cd35aSValentin Clement /// value is directly used in the call and sometimes there is an indirection 1181b3cd35aSValentin Clement /// through a `fir.convert` operation. Once the `fir.call` operation is 1191b3cd35aSValentin Clement /// retrieved the check is made by `checkCallOp`. 1201b3cd35aSValentin Clement /// 1211b3cd35aSValentin Clement /// Directly used in `fir.call`. 1221b3cd35aSValentin Clement /// ``` 1231b3cd35aSValentin Clement /// %result = arith.constant 1 : i32 1241b3cd35aSValentin Clement /// %0 = fir.call @foo(%result) : (i32) -> i1 1251b3cd35aSValentin Clement /// ``` 1261b3cd35aSValentin Clement /// 1271b3cd35aSValentin Clement /// Value used in `fir.call` through `fir.convert` indirection. 1281b3cd35aSValentin Clement /// ``` 1291b3cd35aSValentin Clement /// %result = arith.constant 1 : i32 1301b3cd35aSValentin Clement /// %arg = fir.convert %result : (i32) -> i16 1311b3cd35aSValentin Clement /// %0 = fir.call @foo(%arg) : (i16) -> i1 1321b3cd35aSValentin Clement /// ``` 13399961b4fSValentin Clement static inline void checkCallOpFromResultBox(mlir::Value result, 1341b3cd35aSValentin Clement llvm::StringRef fctName, unsigned nbArgs, bool addLocArgs = true) { 1351b3cd35aSValentin Clement EXPECT_TRUE(result.hasOneUse()); 1361b3cd35aSValentin Clement const auto &u = result.user_begin(); 1371b3cd35aSValentin Clement if (mlir::isa<fir::CallOp>(*u)) 1381b3cd35aSValentin Clement return checkCallOp(*u, fctName, nbArgs, addLocArgs); 1391b3cd35aSValentin Clement auto convOp = mlir::dyn_cast<fir::ConvertOp>(*u); 1401b3cd35aSValentin Clement EXPECT_NE(nullptr, convOp); 1411b3cd35aSValentin Clement checkCallOpFromResultBox(convOp.getResult(), fctName, nbArgs, addLocArgs); 1421b3cd35aSValentin Clement } 1431b3cd35aSValentin Clement 144ce8022faSJosh Mottley /// Check the operations in \p block for a `fir::CallOp` operation where the 145ce8022faSJosh Mottley /// function being called shares its function name with \p fctName and the 146ce8022faSJosh Mottley /// number of arguments is equal to \p nbArgs. Note that this check only cares 147ce8022faSJosh Mottley /// if the operation exists, and not the order in when the operation is called. 148ce8022faSJosh Mottley /// This results in exiting the test as soon as the first correct instance of 149ce8022faSJosh Mottley /// `fir::CallOp` is found). 150ce8022faSJosh Mottley static inline void checkBlockForCallOp( 151ce8022faSJosh Mottley mlir::Block *block, llvm::StringRef fctName, unsigned nbArgs) { 152ce8022faSJosh Mottley assert(block && "mlir::Block given is a nullptr"); 153ce8022faSJosh Mottley for (auto &op : block->getOperations()) { 154ce8022faSJosh Mottley if (auto callOp = mlir::dyn_cast<fir::CallOp>(op)) { 155149ad3d5SShraiysh Vaishay if (fctName == callOp.getCallee()->getRootReference().getValue()) { 156149ad3d5SShraiysh Vaishay EXPECT_EQ(nbArgs, callOp.getArgs().size()); 157ce8022faSJosh Mottley return; 158ce8022faSJosh Mottley } 159ce8022faSJosh Mottley } 160ce8022faSJosh Mottley } 161ce8022faSJosh Mottley FAIL() << "No calls to " << fctName << " were found!"; 162ce8022faSJosh Mottley } 163ce8022faSJosh Mottley 1641b3cd35aSValentin Clement #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_RUNTIMECALLTESTBASE_H 165