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.getCallee(); 50 if (callee.hasValue()) { 51 auto result = fir::NameUniquer::deconstruct( 52 callee.getValue().getRootReference().getValue()); 53 if (fir::NameUniquer::isExternalFacingUniquedName(result)) 54 op.setCalleeAttr( 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.getSymName()); 71 if (fir::NameUniquer::isExternalFacingUniquedName(result)) 72 op.setSymNameAttr(rewriter.getStringAttr(mangleExternalName(result))); 73 rewriter.finalizeRootUpdate(op); 74 return success(); 75 } 76 }; 77 78 struct MangleNameForCommonBlock : public mlir::OpRewritePattern<fir::GlobalOp> { 79 public: 80 using OpRewritePattern::OpRewritePattern; 81 82 mlir::LogicalResult 83 matchAndRewrite(fir::GlobalOp op, 84 mlir::PatternRewriter &rewriter) const override { 85 rewriter.startRootUpdate(op); 86 auto result = fir::NameUniquer::deconstruct( 87 op.getSymref().getRootReference().getValue()); 88 if (fir::NameUniquer::isExternalFacingUniquedName(result)) { 89 auto newName = mangleExternalName(result); 90 op.setSymrefAttr(mlir::SymbolRefAttr::get(op.getContext(), newName)); 91 SymbolTable::setSymbolName(op, newName); 92 } 93 rewriter.finalizeRootUpdate(op); 94 return success(); 95 } 96 }; 97 98 struct MangleNameOnAddrOfOp : public mlir::OpRewritePattern<fir::AddrOfOp> { 99 public: 100 using OpRewritePattern::OpRewritePattern; 101 102 mlir::LogicalResult 103 matchAndRewrite(fir::AddrOfOp op, 104 mlir::PatternRewriter &rewriter) const override { 105 auto result = fir::NameUniquer::deconstruct( 106 op.getSymbol().getRootReference().getValue()); 107 if (fir::NameUniquer::isExternalFacingUniquedName(result)) { 108 auto newName = 109 SymbolRefAttr::get(op.getContext(), mangleExternalName(result)); 110 rewriter.replaceOpWithNewOp<fir::AddrOfOp>(op, op.getResTy().getType(), 111 newName); 112 } 113 return success(); 114 } 115 }; 116 117 struct MangleNameOnEmboxProcOp 118 : public mlir::OpRewritePattern<fir::EmboxProcOp> { 119 public: 120 using OpRewritePattern::OpRewritePattern; 121 122 mlir::LogicalResult 123 matchAndRewrite(fir::EmboxProcOp op, 124 mlir::PatternRewriter &rewriter) const override { 125 rewriter.startRootUpdate(op); 126 auto result = fir::NameUniquer::deconstruct( 127 op.getFuncname().getRootReference().getValue()); 128 if (fir::NameUniquer::isExternalFacingUniquedName(result)) 129 op.setFuncnameAttr( 130 SymbolRefAttr::get(op.getContext(), mangleExternalName(result))); 131 rewriter.finalizeRootUpdate(op); 132 return success(); 133 } 134 }; 135 136 class ExternalNameConversionPass 137 : public fir::ExternalNameConversionBase<ExternalNameConversionPass> { 138 public: 139 mlir::ModuleOp getModule() { return getOperation(); } 140 void runOnOperation() override; 141 }; 142 } // namespace 143 144 void ExternalNameConversionPass::runOnOperation() { 145 auto op = getOperation(); 146 auto *context = &getContext(); 147 148 mlir::RewritePatternSet patterns(context); 149 patterns.insert<MangleNameOnCallOp, MangleNameOnCallOp, MangleNameOnFuncOp, 150 MangleNameForCommonBlock, MangleNameOnAddrOfOp, 151 MangleNameOnEmboxProcOp>(context); 152 153 ConversionTarget target(*context); 154 target.addLegalDialect<fir::FIROpsDialect, LLVM::LLVMDialect, 155 acc::OpenACCDialect, omp::OpenMPDialect>(); 156 157 target.addDynamicallyLegalOp<fir::CallOp>([](fir::CallOp op) { 158 if (op.getCallee().hasValue()) 159 return !fir::NameUniquer::needExternalNameMangling( 160 op.getCallee().getValue().getRootReference().getValue()); 161 return true; 162 }); 163 164 target.addDynamicallyLegalOp<mlir::FuncOp>([](mlir::FuncOp op) { 165 return !fir::NameUniquer::needExternalNameMangling(op.getSymName()); 166 }); 167 168 target.addDynamicallyLegalOp<fir::GlobalOp>([](fir::GlobalOp op) { 169 return !fir::NameUniquer::needExternalNameMangling( 170 op.getSymref().getRootReference().getValue()); 171 }); 172 173 target.addDynamicallyLegalOp<fir::AddrOfOp>([](fir::AddrOfOp op) { 174 return !fir::NameUniquer::needExternalNameMangling( 175 op.getSymbol().getRootReference().getValue()); 176 }); 177 178 target.addDynamicallyLegalOp<fir::EmboxProcOp>([](fir::EmboxProcOp op) { 179 return !fir::NameUniquer::needExternalNameMangling( 180 op.getFuncname().getRootReference().getValue()); 181 }); 182 183 if (failed(applyPartialConversion(op, target, std::move(patterns)))) 184 signalPassFailure(); 185 } 186 187 std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() { 188 return std::make_unique<ExternalNameConversionPass>(); 189 } 190