1 //===- ExternalNameConversion.cpp -- convert name with external convention ===//
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 #include "flang/Optimizer/Dialect/FIRDialect.h"
10 #include "flang/Optimizer/Dialect/FIROps.h"
11 #include "flang/Optimizer/Support/InternalNames.h"
12 #include "flang/Optimizer/Transforms/Passes.h"
13 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
14 #include "mlir/Dialect/OpenACC/OpenACC.h"
15 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
16 #include "mlir/IR/SymbolTable.h"
17 #include "mlir/Pass/Pass.h"
18 #include "mlir/Transforms/DialectConversion.h"
21 #define GEN_PASS_DEF_EXTERNALNAMECONVERSION
22 #include "flang/Optimizer/Transforms/Passes.h.inc"
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
31 /// Mangle the name with gfortran convention.
33 mangleExternalName(const std::pair
<fir::NameUniquer::NameKind
,
34 fir::NameUniquer::DeconstructedName
>
36 bool appendUnderscore
) {
37 if (result
.first
== fir::NameUniquer::NameKind::COMMON
&&
38 result
.second
.name
.empty())
42 return result
.second
.name
+ "_";
44 return result
.second
.name
;
47 //===----------------------------------------------------------------------===//
49 //===----------------------------------------------------------------------===//
53 struct MangleNameOnFuncOp
: public mlir::OpRewritePattern
<mlir::func::FuncOp
> {
55 using OpRewritePattern::OpRewritePattern
;
57 MangleNameOnFuncOp(mlir::MLIRContext
*ctx
, bool appendUnderscore
)
58 : mlir::OpRewritePattern
<mlir::func::FuncOp
>(ctx
),
59 appendUnderscore(appendUnderscore
) {}
62 matchAndRewrite(mlir::func::FuncOp op
,
63 mlir::PatternRewriter
&rewriter
) const override
{
64 mlir::LogicalResult ret
= success();
65 rewriter
.startRootUpdate(op
);
66 auto result
= fir::NameUniquer::deconstruct(op
.getSymName());
67 if (fir::NameUniquer::isExternalFacingUniquedName(result
)) {
69 rewriter
.getStringAttr(mangleExternalName(result
, appendUnderscore
));
71 // Try to update all SymbolRef's in the module that match the current op
72 if (mlir::ModuleOp mod
= op
->getParentOfType
<mlir::ModuleOp
>())
73 ret
= op
.replaceAllSymbolUses(newSymbol
, mod
);
75 op
.setSymNameAttr(newSymbol
);
76 mlir::SymbolTable::setSymbolName(op
, newSymbol
);
79 rewriter
.finalizeRootUpdate(op
);
84 bool appendUnderscore
;
87 struct MangleNameForCommonBlock
: public mlir::OpRewritePattern
<fir::GlobalOp
> {
89 using OpRewritePattern::OpRewritePattern
;
91 MangleNameForCommonBlock(mlir::MLIRContext
*ctx
, bool appendUnderscore
)
92 : mlir::OpRewritePattern
<fir::GlobalOp
>(ctx
),
93 appendUnderscore(appendUnderscore
) {}
96 matchAndRewrite(fir::GlobalOp op
,
97 mlir::PatternRewriter
&rewriter
) const override
{
98 rewriter
.startRootUpdate(op
);
99 auto result
= fir::NameUniquer::deconstruct(
100 op
.getSymref().getRootReference().getValue());
101 if (fir::NameUniquer::isExternalFacingUniquedName(result
)) {
102 auto newName
= mangleExternalName(result
, appendUnderscore
);
103 op
.setSymrefAttr(mlir::SymbolRefAttr::get(op
.getContext(), newName
));
104 SymbolTable::setSymbolName(op
, newName
);
106 rewriter
.finalizeRootUpdate(op
);
111 bool appendUnderscore
;
114 struct MangleNameOnAddrOfOp
: public mlir::OpRewritePattern
<fir::AddrOfOp
> {
116 using OpRewritePattern::OpRewritePattern
;
118 MangleNameOnAddrOfOp(mlir::MLIRContext
*ctx
, bool appendUnderscore
)
119 : mlir::OpRewritePattern
<fir::AddrOfOp
>(ctx
),
120 appendUnderscore(appendUnderscore
) {}
123 matchAndRewrite(fir::AddrOfOp op
,
124 mlir::PatternRewriter
&rewriter
) const override
{
125 auto result
= fir::NameUniquer::deconstruct(
126 op
.getSymbol().getRootReference().getValue());
127 if (fir::NameUniquer::isExternalFacingUniquedName(result
)) {
128 auto newName
= SymbolRefAttr::get(
129 op
.getContext(), mangleExternalName(result
, appendUnderscore
));
130 rewriter
.replaceOpWithNewOp
<fir::AddrOfOp
>(op
, op
.getResTy().getType(),
137 bool appendUnderscore
;
140 class ExternalNameConversionPass
141 : public fir::impl::ExternalNameConversionBase
<ExternalNameConversionPass
> {
143 ExternalNameConversionPass(bool appendUnderscoring
)
144 : appendUnderscores(appendUnderscoring
) {}
146 ExternalNameConversionPass() { appendUnderscores
= appendUnderscore
; }
148 mlir::ModuleOp
getModule() { return getOperation(); }
149 void runOnOperation() override
;
152 bool appendUnderscores
;
156 void ExternalNameConversionPass::runOnOperation() {
157 auto op
= getOperation();
158 auto *context
= &getContext();
160 mlir::RewritePatternSet
patterns(context
);
161 patterns
.insert
<MangleNameOnFuncOp
, MangleNameForCommonBlock
,
162 MangleNameOnAddrOfOp
>(context
, appendUnderscore
);
164 ConversionTarget
target(*context
);
165 target
.addLegalDialect
<fir::FIROpsDialect
, LLVM::LLVMDialect
,
166 acc::OpenACCDialect
, omp::OpenMPDialect
>();
168 target
.addDynamicallyLegalOp
<mlir::func::FuncOp
>([](mlir::func::FuncOp op
) {
169 return !fir::NameUniquer::needExternalNameMangling(op
.getSymName());
172 target
.addDynamicallyLegalOp
<fir::GlobalOp
>([](fir::GlobalOp op
) {
173 return !fir::NameUniquer::needExternalNameMangling(
174 op
.getSymref().getRootReference().getValue());
177 target
.addDynamicallyLegalOp
<fir::AddrOfOp
>([](fir::AddrOfOp op
) {
178 return !fir::NameUniquer::needExternalNameMangling(
179 op
.getSymbol().getRootReference().getValue());
182 if (failed(applyPartialConversion(op
, target
, std::move(patterns
))))
186 std::unique_ptr
<mlir::Pass
> fir::createExternalNameConversionPass() {
187 return std::make_unique
<ExternalNameConversionPass
>();
190 std::unique_ptr
<mlir::Pass
>
191 fir::createExternalNameConversionPass(bool appendUnderscoring
) {
192 return std::make_unique
<ExternalNameConversionPass
>(appendUnderscoring
);