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