1 | //===- FuncToEmitC.cpp - Func to EmitC Patterns -----------------*- C++ -*-===// |
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 | // This file implements patterns to convert the Func dialect to the EmitC |
10 | // dialect. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "mlir/Conversion/FuncToEmitC/FuncToEmitC.h" |
15 | |
16 | #include "mlir/Dialect/EmitC/IR/EmitC.h" |
17 | #include "mlir/Dialect/Func/IR/FuncOps.h" |
18 | #include "mlir/Transforms/DialectConversion.h" |
19 | |
20 | using namespace mlir; |
21 | |
22 | //===----------------------------------------------------------------------===// |
23 | // Conversion Patterns |
24 | //===----------------------------------------------------------------------===// |
25 | |
26 | namespace { |
27 | class CallOpConversion final : public OpConversionPattern<func::CallOp> { |
28 | public: |
29 | using OpConversionPattern<func::CallOp>::OpConversionPattern; |
30 | |
31 | LogicalResult |
32 | matchAndRewrite(func::CallOp callOp, OpAdaptor adaptor, |
33 | ConversionPatternRewriter &rewriter) const override { |
34 | // Multiple results func was not converted to `emitc.func`. |
35 | if (callOp.getNumResults() > 1) |
36 | return rewriter.notifyMatchFailure( |
37 | callOp, "only functions with zero or one result can be converted" ); |
38 | |
39 | rewriter.replaceOpWithNewOp<emitc::CallOp>( |
40 | callOp, |
41 | callOp.getNumResults() ? callOp.getResult(0).getType() : nullptr, |
42 | adaptor.getOperands(), callOp->getAttrs()); |
43 | |
44 | return success(); |
45 | } |
46 | }; |
47 | |
48 | class FuncOpConversion final : public OpConversionPattern<func::FuncOp> { |
49 | public: |
50 | using OpConversionPattern<func::FuncOp>::OpConversionPattern; |
51 | |
52 | LogicalResult |
53 | matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor, |
54 | ConversionPatternRewriter &rewriter) const override { |
55 | |
56 | if (funcOp.getFunctionType().getNumResults() > 1) |
57 | return rewriter.notifyMatchFailure( |
58 | funcOp, "only functions with zero or one result can be converted" ); |
59 | |
60 | // Create the converted `emitc.func` op. |
61 | emitc::FuncOp newFuncOp = rewriter.create<emitc::FuncOp>( |
62 | funcOp.getLoc(), funcOp.getName(), funcOp.getFunctionType()); |
63 | |
64 | // Copy over all attributes other than the function name and type. |
65 | for (const auto &namedAttr : funcOp->getAttrs()) { |
66 | if (namedAttr.getName() != funcOp.getFunctionTypeAttrName() && |
67 | namedAttr.getName() != SymbolTable::getSymbolAttrName()) |
68 | newFuncOp->setAttr(namedAttr.getName(), namedAttr.getValue()); |
69 | } |
70 | |
71 | // Add `extern` to specifiers if `func.func` is declaration only. |
72 | if (funcOp.isDeclaration()) { |
73 | ArrayAttr specifiers = rewriter.getStrArrayAttr({"extern" }); |
74 | newFuncOp.setSpecifiersAttr(specifiers); |
75 | } |
76 | |
77 | // Add `static` to specifiers if `func.func` is private but not a |
78 | // declaration. |
79 | if (funcOp.isPrivate() && !funcOp.isDeclaration()) { |
80 | ArrayAttr specifiers = rewriter.getStrArrayAttr({"static" }); |
81 | newFuncOp.setSpecifiersAttr(specifiers); |
82 | } |
83 | |
84 | if (!funcOp.isDeclaration()) |
85 | rewriter.inlineRegionBefore(funcOp.getBody(), newFuncOp.getBody(), |
86 | newFuncOp.end()); |
87 | rewriter.eraseOp(op: funcOp); |
88 | |
89 | return success(); |
90 | } |
91 | }; |
92 | |
93 | class ReturnOpConversion final : public OpConversionPattern<func::ReturnOp> { |
94 | public: |
95 | using OpConversionPattern<func::ReturnOp>::OpConversionPattern; |
96 | |
97 | LogicalResult |
98 | matchAndRewrite(func::ReturnOp returnOp, OpAdaptor adaptor, |
99 | ConversionPatternRewriter &rewriter) const override { |
100 | if (returnOp.getNumOperands() > 1) |
101 | return rewriter.notifyMatchFailure( |
102 | returnOp, "only zero or one operand is supported" ); |
103 | |
104 | rewriter.replaceOpWithNewOp<emitc::ReturnOp>( |
105 | returnOp, |
106 | returnOp.getNumOperands() ? adaptor.getOperands()[0] : nullptr); |
107 | return success(); |
108 | } |
109 | }; |
110 | } // namespace |
111 | |
112 | //===----------------------------------------------------------------------===// |
113 | // Pattern population |
114 | //===----------------------------------------------------------------------===// |
115 | |
116 | void mlir::populateFuncToEmitCPatterns(RewritePatternSet &patterns) { |
117 | MLIRContext *ctx = patterns.getContext(); |
118 | |
119 | patterns.add<CallOpConversion, FuncOpConversion, ReturnOpConversion>(arg&: ctx); |
120 | } |
121 | |