1+ // ===- ExternalNameConversion.cpp -- convert name with external convention ===//
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 " PassDetail.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/Pass/Pass.h"
17+ #include " mlir/Transforms/DialectConversion.h"
18+
19+ // ===----------------------------------------------------------------------===//
20+ // Helper functions
21+ // ===----------------------------------------------------------------------===//
22+
23+ // / Mangle the name with gfortran convention.
24+ std::string
25+ mangleExternalName (const std::pair<fir::NameUniquer::NameKind,
26+ fir::NameUniquer::DeconstructedName>
27+ result) {
28+ if (result.first == fir::NameUniquer::NameKind::COMMON &&
29+ result.second .name .empty ())
30+ return " __BLNK__" ;
31+ return result.second .name + " _" ;
32+ }
33+
34+ // ===----------------------------------------------------------------------===//
35+ // Rewrite patterns
36+ // ===----------------------------------------------------------------------===//
37+
38+ namespace {
39+
40+ class MangleNameOnCallOp : public mlir ::OpRewritePattern<fir::CallOp> {
41+ public:
42+ using OpRewritePattern::OpRewritePattern;
43+
44+ mlir::LogicalResult
45+ matchAndRewrite (fir::CallOp op,
46+ mlir::PatternRewriter &rewriter) const override {
47+ rewriter.startRootUpdate (op);
48+ auto callee = op.callee ();
49+ if (callee.hasValue ()) {
50+ auto result =
51+ fir::NameUniquer::deconstruct (callee.getValue ().getRootReference ());
52+ if (fir::NameUniquer::isExternalFacingUniquedName (result))
53+ op.calleeAttr (
54+ SymbolRefAttr::get (op.getContext (), mangleExternalName (result)));
55+ }
56+ rewriter.finalizeRootUpdate (op);
57+ return success ();
58+ }
59+ };
60+
61+ struct MangleNameOnFuncOp : public mlir ::OpRewritePattern<mlir::FuncOp> {
62+ public:
63+ using OpRewritePattern::OpRewritePattern;
64+
65+ mlir::LogicalResult
66+ matchAndRewrite (mlir::FuncOp op,
67+ mlir::PatternRewriter &rewriter) const override {
68+ rewriter.startRootUpdate (op);
69+ auto result = fir::NameUniquer::deconstruct (op.sym_name ());
70+ if (fir::NameUniquer::isExternalFacingUniquedName (result)) {
71+ op.sym_nameAttr (rewriter.getStringAttr (mangleExternalName (result)));
72+ }
73+ rewriter.finalizeRootUpdate (op);
74+ return success ();
75+ }
76+ };
77+
78+ struct MangleNameForCommonBlock : public mlir ::OpRewritePattern<fir::GlobalOp> {
79+ public:
80+ using OpRewritePattern::OpRewritePattern;
81+
82+ mlir::LogicalResult
83+ matchAndRewrite (fir::GlobalOp op,
84+ mlir::PatternRewriter &rewriter) const override {
85+ rewriter.startRootUpdate (op);
86+ auto result = fir::NameUniquer::deconstruct (op.symref ().getRootReference ());
87+ if (fir::NameUniquer::isExternalFacingUniquedName (result))
88+ op.symrefAttr (mlir::SymbolRefAttr::get (op.getContext (),
89+ mangleExternalName (result)));
90+ rewriter.finalizeRootUpdate (op);
91+ return success ();
92+ }
93+ };
94+
95+ struct MangleNameOnAddrOfOp : public mlir ::OpRewritePattern<fir::AddrOfOp> {
96+ public:
97+ using OpRewritePattern::OpRewritePattern;
98+
99+ mlir::LogicalResult
100+ matchAndRewrite (fir::AddrOfOp op,
101+ mlir::PatternRewriter &rewriter) const override {
102+ auto result = fir::NameUniquer::deconstruct (op.symbol ().getRootReference ());
103+ if (fir::NameUniquer::isExternalFacingUniquedName (result)) {
104+ auto newName = rewriter.getSymbolRefAttr (mangleExternalName (result));
105+ rewriter.replaceOpWithNewOp <fir::AddrOfOp>(op, op.resTy ().getType (),
106+ newName);
107+ }
108+ return success ();
109+ }
110+ };
111+
112+ struct MangleNameOnEmboxProcOp
113+ : public mlir::OpRewritePattern<fir::EmboxProcOp> {
114+ public:
115+ using OpRewritePattern::OpRewritePattern;
116+
117+ mlir::LogicalResult
118+ matchAndRewrite (fir::EmboxProcOp op,
119+ mlir::PatternRewriter &rewriter) const override {
120+ rewriter.startRootUpdate (op);
121+ auto result =
122+ fir::NameUniquer::deconstruct (op.funcname ().getRootReference ());
123+ if (fir::NameUniquer::isExternalFacingUniquedName (result))
124+ op.funcnameAttr (
125+ SymbolRefAttr::get (op.getContext (), mangleExternalName (result)));
126+ rewriter.finalizeRootUpdate (op);
127+ return success ();
128+ }
129+ };
130+
131+ class ExternalNameConversionPass
132+ : public fir::ExternalNameConversionBase<ExternalNameConversionPass> {
133+ public:
134+ mlir::ModuleOp getModule () { return getOperation (); }
135+ void runOnOperation () override ;
136+ };
137+ } // namespace
138+
139+ void ExternalNameConversionPass::runOnOperation () {
140+ auto op = getOperation ();
141+ auto *context = &getContext ();
142+
143+ mlir::OwningRewritePatternList patterns (context);
144+ patterns.insert <MangleNameOnCallOp, MangleNameOnCallOp, MangleNameOnFuncOp,
145+ MangleNameForCommonBlock, MangleNameOnAddrOfOp,
146+ MangleNameOnEmboxProcOp>(context);
147+
148+ ConversionTarget target (*context);
149+ target.addLegalDialect <fir::FIROpsDialect, LLVM::LLVMDialect,
150+ acc::OpenACCDialect, omp::OpenMPDialect>();
151+
152+ target.addDynamicallyLegalOp <fir::CallOp>([](fir::CallOp op) {
153+ if (op.callee ().hasValue ())
154+ return !fir::NameUniquer::needExternalNameMangling (
155+ op.callee ().getValue ().getRootReference ());
156+ return true ;
157+ });
158+
159+ target.addDynamicallyLegalOp <mlir::FuncOp>([](mlir::FuncOp op) {
160+ return !fir::NameUniquer::needExternalNameMangling (op.sym_name ());
161+ });
162+
163+ target.addDynamicallyLegalOp <fir::GlobalOp>([](fir::GlobalOp op) {
164+ return !fir::NameUniquer::needExternalNameMangling (
165+ op.symref ().getRootReference ());
166+ });
167+
168+ target.addDynamicallyLegalOp <fir::AddrOfOp>([](fir::AddrOfOp op) {
169+ return !fir::NameUniquer::needExternalNameMangling (
170+ op.symbol ().getRootReference ());
171+ });
172+
173+ target.addDynamicallyLegalOp <fir::EmboxProcOp>([](fir::EmboxProcOp op) {
174+ return !fir::NameUniquer::needExternalNameMangling (
175+ op.funcname ().getRootReference ());
176+ });
177+
178+ if (failed (applyPartialConversion (op, target, std::move (patterns))))
179+ signalPassFailure ();
180+ }
181+
182+ std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass () {
183+ return std::make_unique<ExternalNameConversionPass>();
184+ }
0 commit comments