1 //===- ExternalNameConversion.cpp -- convert name with external convention ===//
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
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"
20 #define GEN_PASS_DEF_EXTERNALNAMECONVERSION
21 #include "flang/Optimizer/Transforms/Passes.h.inc"
26 //===----------------------------------------------------------------------===//
28 //===----------------------------------------------------------------------===//
30 /// Mangle the name with gfortran convention.
32 mangleExternalName(const std::pair
<fir::NameUniquer::NameKind
,
33 fir::NameUniquer::DeconstructedName
>
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
,
45 class ExternalNameConversionPass
46 : public fir::impl::ExternalNameConversionBase
<ExternalNameConversionPass
> {
48 using ExternalNameConversionBase
<
49 ExternalNameConversionPass
>::ExternalNameConversionBase
;
51 mlir::ModuleOp
getModule() { return getOperation(); }
52 void runOnOperation() override
;
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
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
)) {
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())
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
);