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 "flang/Common/Fortran.h" |
10 | #include "flang/Optimizer/Dialect/FIRDialect.h" |
11 | #include "flang/Optimizer/Dialect/FIROps.h" |
12 | #include "flang/Optimizer/Dialect/FIROpsSupport.h" |
13 | #include "flang/Optimizer/Support/InternalNames.h" |
14 | #include "flang/Optimizer/Transforms/Passes.h" |
15 | #include "mlir/IR/Attributes.h" |
16 | #include "mlir/IR/SymbolTable.h" |
17 | #include "mlir/Pass/Pass.h" |
18 | |
19 | namespace fir { |
20 | #define GEN_PASS_DEF_EXTERNALNAMECONVERSION |
21 | #include "flang/Optimizer/Transforms/Passes.h.inc" |
22 | } // namespace fir |
23 | |
24 | using namespace mlir; |
25 | |
26 | //===----------------------------------------------------------------------===// |
27 | // Helper functions |
28 | //===----------------------------------------------------------------------===// |
29 | |
30 | /// Mangle the name with gfortran convention. |
31 | std::string |
32 | mangleExternalName(const std::pair<fir::NameUniquer::NameKind, |
33 | fir::NameUniquer::DeconstructedName> |
34 | result, |
35 | bool appendUnderscore) { |
36 | if (result.first == fir::NameUniquer::NameKind::COMMON && |
37 | result.second.name.empty()) |
38 | return Fortran::common::blankCommonObjectName; |
39 | return Fortran::common::GetExternalAssemblyName(result.second.name, |
40 | appendUnderscore); |
41 | } |
42 | |
43 | namespace { |
44 | |
45 | class ExternalNameConversionPass |
46 | : public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> { |
47 | public: |
48 | ExternalNameConversionPass(bool appendUnderscoring) |
49 | : appendUnderscores(appendUnderscoring) {} |
50 | |
51 | ExternalNameConversionPass() { usePassOpt = true; } |
52 | |
53 | mlir::ModuleOp getModule() { return getOperation(); } |
54 | void runOnOperation() override; |
55 | |
56 | private: |
57 | bool appendUnderscores; |
58 | bool usePassOpt = false; |
59 | }; |
60 | } // namespace |
61 | |
62 | void ExternalNameConversionPass::runOnOperation() { |
63 | auto op = getOperation(); |
64 | auto *context = &getContext(); |
65 | |
66 | appendUnderscores = (usePassOpt) ? appendUnderscoreOpt : appendUnderscores; |
67 | llvm::DenseMap<mlir::StringAttr, mlir::FlatSymbolRefAttr> remappings; |
68 | // Update names of external Fortran functions and names of Common Block |
69 | // globals. |
70 | for (auto &funcOrGlobal : op->getRegion(0).front()) { |
71 | if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal) || |
72 | llvm::isa<fir::GlobalOp>(funcOrGlobal)) { |
73 | auto symName = funcOrGlobal.getAttrOfType<mlir::StringAttr>( |
74 | mlir::SymbolTable::getSymbolAttrName()); |
75 | auto deconstructedName = fir::NameUniquer::deconstruct(symName); |
76 | if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) { |
77 | auto newName = mangleExternalName(deconstructedName, appendUnderscores); |
78 | auto newAttr = mlir::StringAttr::get(context, newName); |
79 | mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr); |
80 | auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr); |
81 | remappings.try_emplace(symName, newSymRef); |
82 | if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal)) |
83 | funcOrGlobal.setAttr(fir::getInternalFuncNameAttrName(), symName); |
84 | } |
85 | } |
86 | } |
87 | |
88 | if (remappings.empty()) |
89 | return; |
90 | |
91 | // Update all uses of the functions and globals that have been renamed. |
92 | op.walk([&remappings](mlir::Operation *nestedOp) { |
93 | llvm::SmallVector<std::pair<mlir::StringAttr, mlir::SymbolRefAttr>> updates; |
94 | for (const mlir::NamedAttribute &attr : nestedOp->getAttrDictionary()) |
95 | if (auto symRef = llvm::dyn_cast<mlir::SymbolRefAttr>(attr.getValue())) |
96 | if (auto remap = remappings.find(symRef.getRootReference()); |
97 | remap != remappings.end()) |
98 | updates.emplace_back(std::pair<mlir::StringAttr, mlir::SymbolRefAttr>{ |
99 | attr.getName(), mlir::SymbolRefAttr(remap->second)}); |
100 | for (auto update : updates) |
101 | nestedOp->setAttr(update.first, update.second); |
102 | }); |
103 | } |
104 | |
105 | std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() { |
106 | return std::make_unique<ExternalNameConversionPass>(); |
107 | } |
108 | |
109 | std::unique_ptr<mlir::Pass> |
110 | fir::createExternalNameConversionPass(bool appendUnderscoring) { |
111 | return std::make_unique<ExternalNameConversionPass>(appendUnderscoring); |
112 | } |
113 | |