1 //===- FuncToEmitC.cpp - Func to EmitC Patterns -----------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements patterns to convert the Func dialect to the EmitC
12 //===----------------------------------------------------------------------===//
14 #include "mlir/Conversion/FuncToEmitC/FuncToEmitC.h"
16 #include "mlir/Dialect/EmitC/IR/EmitC.h"
17 #include "mlir/Dialect/Func/IR/FuncOps.h"
18 #include "mlir/Transforms/DialectConversion.h"
22 //===----------------------------------------------------------------------===//
23 // Conversion Patterns
24 //===----------------------------------------------------------------------===//
27 class CallOpConversion final
: public OpConversionPattern
<func::CallOp
> {
29 using OpConversionPattern
<func::CallOp
>::OpConversionPattern
;
32 matchAndRewrite(func::CallOp callOp
, OpAdaptor adaptor
,
33 ConversionPatternRewriter
&rewriter
) const override
{
34 // Multiple results func cannot be 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");
39 rewriter
.replaceOpWithNewOp
<emitc::CallOp
>(callOp
, callOp
.getResultTypes(),
40 adaptor
.getOperands(),
47 class FuncOpConversion final
: public OpConversionPattern
<func::FuncOp
> {
49 using OpConversionPattern
<func::FuncOp
>::OpConversionPattern
;
52 matchAndRewrite(func::FuncOp funcOp
, OpAdaptor adaptor
,
53 ConversionPatternRewriter
&rewriter
) const override
{
55 if (funcOp
.getFunctionType().getNumResults() > 1)
56 return rewriter
.notifyMatchFailure(
57 funcOp
, "only functions with zero or one result can be converted");
59 // Create the converted `emitc.func` op.
60 emitc::FuncOp newFuncOp
= rewriter
.create
<emitc::FuncOp
>(
61 funcOp
.getLoc(), funcOp
.getName(), funcOp
.getFunctionType());
63 // Copy over all attributes other than the function name and type.
64 for (const auto &namedAttr
: funcOp
->getAttrs()) {
65 if (namedAttr
.getName() != funcOp
.getFunctionTypeAttrName() &&
66 namedAttr
.getName() != SymbolTable::getSymbolAttrName())
67 newFuncOp
->setAttr(namedAttr
.getName(), namedAttr
.getValue());
70 // Add `extern` to specifiers if `func.func` is declaration only.
71 if (funcOp
.isDeclaration()) {
72 ArrayAttr specifiers
= rewriter
.getStrArrayAttr({"extern"});
73 newFuncOp
.setSpecifiersAttr(specifiers
);
76 // Add `static` to specifiers if `func.func` is private but not a
78 if (funcOp
.isPrivate() && !funcOp
.isDeclaration()) {
79 ArrayAttr specifiers
= rewriter
.getStrArrayAttr({"static"});
80 newFuncOp
.setSpecifiersAttr(specifiers
);
83 if (!funcOp
.isDeclaration())
84 rewriter
.inlineRegionBefore(funcOp
.getBody(), newFuncOp
.getBody(),
86 rewriter
.eraseOp(funcOp
);
92 class ReturnOpConversion final
: public OpConversionPattern
<func::ReturnOp
> {
94 using OpConversionPattern
<func::ReturnOp
>::OpConversionPattern
;
97 matchAndRewrite(func::ReturnOp returnOp
, OpAdaptor adaptor
,
98 ConversionPatternRewriter
&rewriter
) const override
{
99 if (returnOp
.getNumOperands() > 1)
100 return rewriter
.notifyMatchFailure(
101 returnOp
, "only zero or one operand is supported");
103 rewriter
.replaceOpWithNewOp
<emitc::ReturnOp
>(
105 returnOp
.getNumOperands() ? adaptor
.getOperands()[0] : nullptr);
111 //===----------------------------------------------------------------------===//
112 // Pattern population
113 //===----------------------------------------------------------------------===//
115 void mlir::populateFuncToEmitCPatterns(RewritePatternSet
&patterns
) {
116 MLIRContext
*ctx
= patterns
.getContext();
118 patterns
.add
<CallOpConversion
, FuncOpConversion
, ReturnOpConversion
>(ctx
);