xref: /llvm-project/mlir/test/lib/Conversion/FuncToLLVM/TestConvertFuncOp.cpp (revision 2ac2e9a5b6c97cbf267db1ef322ed21ebceb2aba)
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 &registry) 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