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