1fc66dbbaSValentin Clement //===- ExternalNameConversion.cpp -- convert name with external convention ===//
2fc66dbbaSValentin Clement //
3fc66dbbaSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fc66dbbaSValentin Clement // See https://llvm.org/LICENSE.txt for license information.
5fc66dbbaSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fc66dbbaSValentin Clement //
7fc66dbbaSValentin Clement //===----------------------------------------------------------------------===//
8fc66dbbaSValentin Clement 
9fc66dbbaSValentin Clement #include "PassDetail.h"
10fc66dbbaSValentin Clement #include "flang/Optimizer/Dialect/FIROps.h"
11fc66dbbaSValentin Clement #include "flang/Optimizer/Support/InternalNames.h"
12fc66dbbaSValentin Clement #include "flang/Optimizer/Transforms/Passes.h"
13fc66dbbaSValentin Clement #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
14fc66dbbaSValentin Clement #include "mlir/Dialect/OpenACC/OpenACC.h"
15fc66dbbaSValentin Clement #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
16fc66dbbaSValentin Clement #include "mlir/IR/SymbolTable.h"
17fc66dbbaSValentin Clement #include "mlir/Pass/Pass.h"
18fc66dbbaSValentin Clement #include "mlir/Transforms/DialectConversion.h"
19fc66dbbaSValentin Clement 
20092601d4SAndrzej Warzynski using namespace mlir;
21092601d4SAndrzej Warzynski 
22fc66dbbaSValentin Clement //===----------------------------------------------------------------------===//
23fc66dbbaSValentin Clement // Helper functions
24fc66dbbaSValentin Clement //===----------------------------------------------------------------------===//
25fc66dbbaSValentin Clement 
26fc66dbbaSValentin Clement /// Mangle the name with gfortran convention.
27fc66dbbaSValentin Clement std::string
mangleExternalName(const std::pair<fir::NameUniquer::NameKind,fir::NameUniquer::DeconstructedName> result)28fc66dbbaSValentin Clement mangleExternalName(const std::pair<fir::NameUniquer::NameKind,
29fc66dbbaSValentin Clement                                    fir::NameUniquer::DeconstructedName>
30fc66dbbaSValentin Clement                        result) {
31fc66dbbaSValentin Clement   if (result.first == fir::NameUniquer::NameKind::COMMON &&
32fc66dbbaSValentin Clement       result.second.name.empty())
33fc66dbbaSValentin Clement     return "__BLNK__";
34fc66dbbaSValentin Clement   return result.second.name + "_";
35fc66dbbaSValentin Clement }
36fc66dbbaSValentin Clement 
37fc66dbbaSValentin Clement //===----------------------------------------------------------------------===//
38fc66dbbaSValentin Clement // Rewrite patterns
39fc66dbbaSValentin Clement //===----------------------------------------------------------------------===//
40fc66dbbaSValentin Clement 
41fc66dbbaSValentin Clement namespace {
42fc66dbbaSValentin Clement 
43fc66dbbaSValentin Clement class MangleNameOnCallOp : public mlir::OpRewritePattern<fir::CallOp> {
44fc66dbbaSValentin Clement public:
45fc66dbbaSValentin Clement   using OpRewritePattern::OpRewritePattern;
46fc66dbbaSValentin Clement 
47fc66dbbaSValentin Clement   mlir::LogicalResult
matchAndRewrite(fir::CallOp op,mlir::PatternRewriter & rewriter) const48fc66dbbaSValentin Clement   matchAndRewrite(fir::CallOp op,
49fc66dbbaSValentin Clement                   mlir::PatternRewriter &rewriter) const override {
50fc66dbbaSValentin Clement     rewriter.startRootUpdate(op);
51149ad3d5SShraiysh Vaishay     auto callee = op.getCallee();
5286b8c1d9SKazu Hirata     if (callee) {
53*fac0fb4dSKazu Hirata       auto result =
54*fac0fb4dSKazu Hirata           fir::NameUniquer::deconstruct(callee->getRootReference().getValue());
55fc66dbbaSValentin Clement       if (fir::NameUniquer::isExternalFacingUniquedName(result))
56149ad3d5SShraiysh Vaishay         op.setCalleeAttr(
57fc66dbbaSValentin Clement             SymbolRefAttr::get(op.getContext(), mangleExternalName(result)));
58fc66dbbaSValentin Clement     }
59fc66dbbaSValentin Clement     rewriter.finalizeRootUpdate(op);
60fc66dbbaSValentin Clement     return success();
61fc66dbbaSValentin Clement   }
62fc66dbbaSValentin Clement };
63fc66dbbaSValentin Clement 
6458ceae95SRiver Riddle struct MangleNameOnFuncOp : public mlir::OpRewritePattern<mlir::func::FuncOp> {
65fc66dbbaSValentin Clement public:
66fc66dbbaSValentin Clement   using OpRewritePattern::OpRewritePattern;
67fc66dbbaSValentin Clement 
68fc66dbbaSValentin Clement   mlir::LogicalResult
matchAndRewrite__anon849139e70111::MangleNameOnFuncOp6958ceae95SRiver Riddle   matchAndRewrite(mlir::func::FuncOp op,
70fc66dbbaSValentin Clement                   mlir::PatternRewriter &rewriter) const override {
71fc66dbbaSValentin Clement     rewriter.startRootUpdate(op);
72f8d5c73cSRiver Riddle     auto result = fir::NameUniquer::deconstruct(op.getSymName());
73f8d5c73cSRiver Riddle     if (fir::NameUniquer::isExternalFacingUniquedName(result))
74f8d5c73cSRiver Riddle       op.setSymNameAttr(rewriter.getStringAttr(mangleExternalName(result)));
75fc66dbbaSValentin Clement     rewriter.finalizeRootUpdate(op);
76fc66dbbaSValentin Clement     return success();
77fc66dbbaSValentin Clement   }
78fc66dbbaSValentin Clement };
79fc66dbbaSValentin Clement 
80fc66dbbaSValentin Clement struct MangleNameForCommonBlock : public mlir::OpRewritePattern<fir::GlobalOp> {
81fc66dbbaSValentin Clement public:
82fc66dbbaSValentin Clement   using OpRewritePattern::OpRewritePattern;
83fc66dbbaSValentin Clement 
84fc66dbbaSValentin Clement   mlir::LogicalResult
matchAndRewrite__anon849139e70111::MangleNameForCommonBlock85fc66dbbaSValentin Clement   matchAndRewrite(fir::GlobalOp op,
86fc66dbbaSValentin Clement                   mlir::PatternRewriter &rewriter) const override {
87fc66dbbaSValentin Clement     rewriter.startRootUpdate(op);
88fc66dbbaSValentin Clement     auto result = fir::NameUniquer::deconstruct(
89149ad3d5SShraiysh Vaishay         op.getSymref().getRootReference().getValue());
90fc66dbbaSValentin Clement     if (fir::NameUniquer::isExternalFacingUniquedName(result)) {
91fc66dbbaSValentin Clement       auto newName = mangleExternalName(result);
92149ad3d5SShraiysh Vaishay       op.setSymrefAttr(mlir::SymbolRefAttr::get(op.getContext(), newName));
93fc66dbbaSValentin Clement       SymbolTable::setSymbolName(op, newName);
94fc66dbbaSValentin Clement     }
95fc66dbbaSValentin Clement     rewriter.finalizeRootUpdate(op);
96fc66dbbaSValentin Clement     return success();
97fc66dbbaSValentin Clement   }
98fc66dbbaSValentin Clement };
99fc66dbbaSValentin Clement 
100fc66dbbaSValentin Clement struct MangleNameOnAddrOfOp : public mlir::OpRewritePattern<fir::AddrOfOp> {
101fc66dbbaSValentin Clement public:
102fc66dbbaSValentin Clement   using OpRewritePattern::OpRewritePattern;
103fc66dbbaSValentin Clement 
104fc66dbbaSValentin Clement   mlir::LogicalResult
matchAndRewrite__anon849139e70111::MangleNameOnAddrOfOp105fc66dbbaSValentin Clement   matchAndRewrite(fir::AddrOfOp op,
106fc66dbbaSValentin Clement                   mlir::PatternRewriter &rewriter) const override {
107fc66dbbaSValentin Clement     auto result = fir::NameUniquer::deconstruct(
108149ad3d5SShraiysh Vaishay         op.getSymbol().getRootReference().getValue());
109fc66dbbaSValentin Clement     if (fir::NameUniquer::isExternalFacingUniquedName(result)) {
110fc66dbbaSValentin Clement       auto newName =
111fc66dbbaSValentin Clement           SymbolRefAttr::get(op.getContext(), mangleExternalName(result));
112149ad3d5SShraiysh Vaishay       rewriter.replaceOpWithNewOp<fir::AddrOfOp>(op, op.getResTy().getType(),
113fc66dbbaSValentin Clement                                                  newName);
114fc66dbbaSValentin Clement     }
115fc66dbbaSValentin Clement     return success();
116fc66dbbaSValentin Clement   }
117fc66dbbaSValentin Clement };
118fc66dbbaSValentin Clement 
119fc66dbbaSValentin Clement class ExternalNameConversionPass
120fc66dbbaSValentin Clement     : public fir::ExternalNameConversionBase<ExternalNameConversionPass> {
121fc66dbbaSValentin Clement public:
getModule()122fc66dbbaSValentin Clement   mlir::ModuleOp getModule() { return getOperation(); }
123fc66dbbaSValentin Clement   void runOnOperation() override;
124fc66dbbaSValentin Clement };
125fc66dbbaSValentin Clement } // namespace
126fc66dbbaSValentin Clement 
runOnOperation()127fc66dbbaSValentin Clement void ExternalNameConversionPass::runOnOperation() {
128fc66dbbaSValentin Clement   auto op = getOperation();
129fc66dbbaSValentin Clement   auto *context = &getContext();
130fc66dbbaSValentin Clement 
1319f85c198SRiver Riddle   mlir::RewritePatternSet patterns(context);
132fc66dbbaSValentin Clement   patterns.insert<MangleNameOnCallOp, MangleNameOnCallOp, MangleNameOnFuncOp,
133fe252f8eSValentin Clement                   MangleNameForCommonBlock, MangleNameOnAddrOfOp>(context);
134fc66dbbaSValentin Clement 
135fc66dbbaSValentin Clement   ConversionTarget target(*context);
136fc66dbbaSValentin Clement   target.addLegalDialect<fir::FIROpsDialect, LLVM::LLVMDialect,
137fc66dbbaSValentin Clement                          acc::OpenACCDialect, omp::OpenMPDialect>();
138fc66dbbaSValentin Clement 
139fc66dbbaSValentin Clement   target.addDynamicallyLegalOp<fir::CallOp>([](fir::CallOp op) {
14086b8c1d9SKazu Hirata     if (op.getCallee())
141fc66dbbaSValentin Clement       return !fir::NameUniquer::needExternalNameMangling(
142*fac0fb4dSKazu Hirata           op.getCallee()->getRootReference().getValue());
143fc66dbbaSValentin Clement     return true;
144fc66dbbaSValentin Clement   });
145fc66dbbaSValentin Clement 
14658ceae95SRiver Riddle   target.addDynamicallyLegalOp<mlir::func::FuncOp>([](mlir::func::FuncOp op) {
147f8d5c73cSRiver Riddle     return !fir::NameUniquer::needExternalNameMangling(op.getSymName());
148fc66dbbaSValentin Clement   });
149fc66dbbaSValentin Clement 
150fc66dbbaSValentin Clement   target.addDynamicallyLegalOp<fir::GlobalOp>([](fir::GlobalOp op) {
151fc66dbbaSValentin Clement     return !fir::NameUniquer::needExternalNameMangling(
152149ad3d5SShraiysh Vaishay         op.getSymref().getRootReference().getValue());
153fc66dbbaSValentin Clement   });
154fc66dbbaSValentin Clement 
155fc66dbbaSValentin Clement   target.addDynamicallyLegalOp<fir::AddrOfOp>([](fir::AddrOfOp op) {
156fc66dbbaSValentin Clement     return !fir::NameUniquer::needExternalNameMangling(
157149ad3d5SShraiysh Vaishay         op.getSymbol().getRootReference().getValue());
158fc66dbbaSValentin Clement   });
159fc66dbbaSValentin Clement 
160fc66dbbaSValentin Clement   if (failed(applyPartialConversion(op, target, std::move(patterns))))
161fc66dbbaSValentin Clement     signalPassFailure();
162fc66dbbaSValentin Clement }
163fc66dbbaSValentin Clement 
createExternalNameConversionPass()164fc66dbbaSValentin Clement std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() {
165fc66dbbaSValentin Clement   return std::make_unique<ExternalNameConversionPass>();
166fc66dbbaSValentin Clement }
167