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
19namespace fir {
20#define GEN_PASS_DEF_EXTERNALNAMECONVERSION
21#include "flang/Optimizer/Transforms/Passes.h.inc"
22} // namespace fir
23
24using namespace mlir;
25
26//===----------------------------------------------------------------------===//
27// Helper functions
28//===----------------------------------------------------------------------===//
29
30/// Mangle the name with gfortran convention.
31std::string
32mangleExternalName(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
43namespace {
44
45class ExternalNameConversionPass
46 : public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> {
47public:
48 ExternalNameConversionPass(bool appendUnderscoring)
49 : appendUnderscores(appendUnderscoring) {}
50
51 ExternalNameConversionPass() { usePassOpt = true; }
52
53 mlir::ModuleOp getModule() { return getOperation(); }
54 void runOnOperation() override;
55
56private:
57 bool appendUnderscores;
58 bool usePassOpt = false;
59};
60} // namespace
61
62void 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
105std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() {
106 return std::make_unique<ExternalNameConversionPass>();
107}
108
109std::unique_ptr<mlir::Pass>
110fir::createExternalNameConversionPass(bool appendUnderscoring) {
111 return std::make_unique<ExternalNameConversionPass>(appendUnderscoring);
112}
113

source code of flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp