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