1a4490217Sdrazi //===- TestConvertFuncOp.cpp - Test LLVM Conversion of Func FuncOp --------===// 2a4490217Sdrazi // 3a4490217Sdrazi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a4490217Sdrazi // See https://llvm.org/LICENSE.txt for license information. 5a4490217Sdrazi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a4490217Sdrazi // 7a4490217Sdrazi //===----------------------------------------------------------------------===// 8a4490217Sdrazi 9a4490217Sdrazi #include "TestDialect.h" 10a4490217Sdrazi 11a4490217Sdrazi #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" 12a4490217Sdrazi #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" 13a4490217Sdrazi #include "mlir/Conversion/LLVMCommon/Pattern.h" 14a4490217Sdrazi #include "mlir/Dialect/Func/IR/FuncOps.h" 15a4490217Sdrazi #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 16a4490217Sdrazi #include "mlir/IR/PatternMatch.h" 17a4490217Sdrazi #include "mlir/Pass/Pass.h" 18a4490217Sdrazi 19a4490217Sdrazi using namespace mlir; 20a4490217Sdrazi 21a4490217Sdrazi namespace { 22a4490217Sdrazi 23a4490217Sdrazi /// Test helper Conversion Pattern to directly call `convertFuncOpToLLVMFuncOp` 24a4490217Sdrazi /// to verify this utility function includes all functionalities of conversion 25a4490217Sdrazi struct FuncOpConversion : public ConvertOpToLLVMPattern<func::FuncOp> { 26a4490217Sdrazi FuncOpConversion(const LLVMTypeConverter &converter) 27a4490217Sdrazi : ConvertOpToLLVMPattern(converter) {} 28a4490217Sdrazi 29a4490217Sdrazi LogicalResult 30a4490217Sdrazi matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor, 31a4490217Sdrazi ConversionPatternRewriter &rewriter) const override { 32a4490217Sdrazi FailureOr<LLVM::LLVMFuncOp> newFuncOp = mlir::convertFuncOpToLLVMFuncOp( 33a4490217Sdrazi cast<FunctionOpInterface>(funcOp.getOperation()), rewriter, 34a4490217Sdrazi *getTypeConverter()); 35a4490217Sdrazi if (failed(newFuncOp)) 36a4490217Sdrazi return rewriter.notifyMatchFailure(funcOp, "Could not convert funcop"); 37a4490217Sdrazi 38a4490217Sdrazi rewriter.eraseOp(funcOp); 39a4490217Sdrazi return success(); 40a4490217Sdrazi } 41a4490217Sdrazi }; 42a4490217Sdrazi 43a4490217Sdrazi struct ReturnOpConversion : public ConvertOpToLLVMPattern<func::ReturnOp> { 44a4490217Sdrazi ReturnOpConversion(const LLVMTypeConverter &converter) 45a4490217Sdrazi : ConvertOpToLLVMPattern(converter) {} 46a4490217Sdrazi 47a4490217Sdrazi LogicalResult 48a4490217Sdrazi matchAndRewrite(func::ReturnOp returnOp, OpAdaptor adaptor, 49a4490217Sdrazi ConversionPatternRewriter &rewriter) const override { 50*2ac2e9a5SDiego Caballero SmallVector<Type> resTys; 51*2ac2e9a5SDiego Caballero if (failed(typeConverter->convertTypes(returnOp->getResultTypes(), resTys))) 52*2ac2e9a5SDiego Caballero return failure(); 53*2ac2e9a5SDiego Caballero 54*2ac2e9a5SDiego Caballero rewriter.replaceOpWithNewOp<LLVM::ReturnOp>(returnOp, resTys, 55*2ac2e9a5SDiego Caballero adaptor.getOperands()); 56a4490217Sdrazi return success(); 57a4490217Sdrazi } 58a4490217Sdrazi }; 59a4490217Sdrazi 60*2ac2e9a5SDiego Caballero static std::optional<Type> 61*2ac2e9a5SDiego Caballero convertSimpleATypeToStruct(test::SimpleAType simpleTy) { 62*2ac2e9a5SDiego Caballero MLIRContext *ctx = simpleTy.getContext(); 63*2ac2e9a5SDiego Caballero SmallVector<Type> memberTys(2, IntegerType::get(ctx, /*width=*/8)); 64*2ac2e9a5SDiego Caballero return LLVM::LLVMStructType::getLiteral(ctx, memberTys); 65*2ac2e9a5SDiego Caballero } 66*2ac2e9a5SDiego Caballero 67a4490217Sdrazi struct TestConvertFuncOp 68a4490217Sdrazi : public PassWrapper<TestConvertFuncOp, OperationPass<ModuleOp>> { 69a4490217Sdrazi MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestConvertFuncOp) 70a4490217Sdrazi 71a4490217Sdrazi void getDependentDialects(DialectRegistry ®istry) const final { 72a4490217Sdrazi registry.insert<LLVM::LLVMDialect>(); 73a4490217Sdrazi } 74a4490217Sdrazi 75a4490217Sdrazi StringRef getArgument() const final { return "test-convert-func-op"; } 76a4490217Sdrazi 77a4490217Sdrazi StringRef getDescription() const final { 78a4490217Sdrazi return "Tests conversion of `func.func` to `llvm.func` for different " 79a4490217Sdrazi "attributes"; 80a4490217Sdrazi } 81a4490217Sdrazi 82a4490217Sdrazi void runOnOperation() override { 83a4490217Sdrazi MLIRContext *ctx = &getContext(); 84a4490217Sdrazi 85a4490217Sdrazi LowerToLLVMOptions options(ctx); 86a4490217Sdrazi // Populate type conversions. 87a4490217Sdrazi LLVMTypeConverter typeConverter(ctx, options); 88*2ac2e9a5SDiego Caballero typeConverter.addConversion(convertSimpleATypeToStruct); 89a4490217Sdrazi 90a4490217Sdrazi RewritePatternSet patterns(ctx); 91a4490217Sdrazi patterns.add<FuncOpConversion>(typeConverter); 92a4490217Sdrazi patterns.add<ReturnOpConversion>(typeConverter); 93a4490217Sdrazi 94a4490217Sdrazi LLVMConversionTarget target(getContext()); 95a4490217Sdrazi if (failed(applyPartialConversion(getOperation(), target, 96a4490217Sdrazi std::move(patterns)))) 97a4490217Sdrazi signalPassFailure(); 98a4490217Sdrazi } 99a4490217Sdrazi }; 100a4490217Sdrazi 101a4490217Sdrazi } // namespace 102a4490217Sdrazi 103a4490217Sdrazi namespace mlir::test { 104a4490217Sdrazi void registerConvertFuncOpPass() { PassRegistration<TestConvertFuncOp>(); } 105a4490217Sdrazi } // namespace mlir::test 106