[MemProf] Templatize CallStackRadixTreeBuilder (NFC) (#117014)
[llvm-project.git] / flang / lib / Optimizer / Transforms / ExternalNameConversion.cpp
blob648628fd1c9af05a32ef320839f7619a2384c740
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 //===----------------------------------------------------------------------===//
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"
19 namespace fir {
20 #define GEN_PASS_DEF_EXTERNALNAMECONVERSION
21 #include "flang/Optimizer/Transforms/Passes.h.inc"
22 } // namespace fir
24 using namespace mlir;
26 //===----------------------------------------------------------------------===//
27 // Helper functions
28 //===----------------------------------------------------------------------===//
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);
43 namespace {
45 class ExternalNameConversionPass
46 : public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> {
47 public:
48 using ExternalNameConversionBase<
49 ExternalNameConversionPass>::ExternalNameConversionBase;
51 mlir::ModuleOp getModule() { return getOperation(); }
52 void runOnOperation() override;
54 } // namespace
56 void ExternalNameConversionPass::runOnOperation() {
57 auto op = getOperation();
58 auto *context = &getContext();
60 llvm::DenseMap<mlir::StringAttr, mlir::FlatSymbolRefAttr> remappings;
61 // Update names of external Fortran functions and names of Common Block
62 // globals.
63 for (auto &funcOrGlobal : op->getRegion(0).front()) {
64 if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal) ||
65 llvm::isa<fir::GlobalOp>(funcOrGlobal)) {
66 auto symName = funcOrGlobal.getAttrOfType<mlir::StringAttr>(
67 mlir::SymbolTable::getSymbolAttrName());
68 auto deconstructedName = fir::NameUniquer::deconstruct(symName);
69 if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) {
70 auto newName =
71 mangleExternalName(deconstructedName, appendUnderscoreOpt);
72 auto newAttr = mlir::StringAttr::get(context, newName);
73 mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr);
74 auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr);
75 remappings.try_emplace(symName, newSymRef);
76 if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal))
77 funcOrGlobal.setAttr(fir::getInternalFuncNameAttrName(), symName);
82 if (remappings.empty())
83 return;
85 // Update all uses of the functions and globals that have been renamed.
86 op.walk([&remappings](mlir::Operation *nestedOp) {
87 llvm::SmallVector<std::pair<mlir::StringAttr, mlir::SymbolRefAttr>> updates;
88 for (const mlir::NamedAttribute &attr : nestedOp->getAttrDictionary())
89 if (auto symRef = llvm::dyn_cast<mlir::SymbolRefAttr>(attr.getValue()))
90 if (auto remap = remappings.find(symRef.getRootReference());
91 remap != remappings.end())
92 updates.emplace_back(std::pair<mlir::StringAttr, mlir::SymbolRefAttr>{
93 attr.getName(), mlir::SymbolRefAttr(remap->second)});
94 for (auto update : updates)
95 nestedOp->setAttr(update.first, update.second);
96 });