1 //===-------------- AddDebugInfo.cpp -- add debug info -------------------===// 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 //===----------------------------------------------------------------------===// 10 /// \file 11 /// This pass populates some debug information for the module and functions. 12 //===----------------------------------------------------------------------===// 13 14 #include "flang/Optimizer/Builder/FIRBuilder.h" 15 #include "flang/Optimizer/Builder/Todo.h" 16 #include "flang/Optimizer/Dialect/FIRDialect.h" 17 #include "flang/Optimizer/Dialect/FIROps.h" 18 #include "flang/Optimizer/Dialect/FIRType.h" 19 #include "flang/Optimizer/Dialect/Support/FIRContext.h" 20 #include "flang/Optimizer/Transforms/Passes.h" 21 #include "mlir/Dialect/Func/IR/FuncOps.h" 22 #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 23 #include "mlir/IR/Matchers.h" 24 #include "mlir/IR/TypeUtilities.h" 25 #include "mlir/Pass/Pass.h" 26 #include "mlir/Transforms/DialectConversion.h" 27 #include "mlir/Transforms/GreedyPatternRewriteDriver.h" 28 #include "mlir/Transforms/RegionUtils.h" 29 #include "llvm/BinaryFormat/Dwarf.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/Path.h" 32 #include "llvm/Support/raw_ostream.h" 33 34 namespace fir { 35 #define GEN_PASS_DEF_ADDDEBUGINFO 36 #define GEN_PASS_DECL_ADDDEBUGINFO 37 #include "flang/Optimizer/Transforms/Passes.h.inc" 38 } // namespace fir 39 40 #define DEBUG_TYPE "flang-add-debug-foundation" 41 42 namespace { 43 44 class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> { 45 public: 46 void runOnOperation() override; 47 }; 48 49 } // namespace 50 51 void AddDebugInfoPass::runOnOperation() { 52 mlir::ModuleOp module = getOperation(); 53 mlir::MLIRContext *context = &getContext(); 54 mlir::OpBuilder builder(context); 55 std::string inputFilePath("-"); 56 if (auto fileLoc = module.getLoc().dyn_cast<mlir::FileLineColLoc>()) 57 inputFilePath = fileLoc.getFilename().getValue(); 58 59 auto getFileAttr = [context](llvm::StringRef path) -> mlir::LLVM::DIFileAttr { 60 return mlir::LLVM::DIFileAttr::get(context, llvm::sys::path::filename(path), 61 llvm::sys::path::parent_path(path)); 62 }; 63 64 mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath); 65 mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang"); 66 mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get( 67 mlir::DistinctAttr::create(mlir::UnitAttr::get(context)), 68 llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, 69 /*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly); 70 71 module.walk([&](mlir::func::FuncOp funcOp) { 72 mlir::Location l = funcOp->getLoc(); 73 // If fused location has already been created then nothing to do 74 // Otherwise, create a fused location. 75 if (l.dyn_cast<mlir::FusedLoc>()) 76 return; 77 78 llvm::StringRef funcFilePath; 79 if (l.dyn_cast<mlir::FileLineColLoc>()) 80 funcFilePath = 81 l.dyn_cast<mlir::FileLineColLoc>().getFilename().getValue(); 82 else 83 funcFilePath = inputFilePath; 84 85 mlir::StringAttr funcName = 86 mlir::StringAttr::get(context, funcOp.getName()); 87 mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get( 88 context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0, 89 /*encoding=*/1); 90 mlir::LLVM::DISubroutineTypeAttr subTypeAttr = 91 mlir::LLVM::DISubroutineTypeAttr::get( 92 context, llvm::dwarf::getCallingConvention("DW_CC_normal"), 93 {bT, bT}); 94 mlir::LLVM::DIFileAttr funcFileAttr = getFileAttr(funcFilePath); 95 96 // Only definitions need a distinct identifier and a compilation unit. 97 mlir::DistinctAttr id; 98 mlir::LLVM::DICompileUnitAttr compilationUnit; 99 auto subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; 100 if (!funcOp.isExternal()) { 101 id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); 102 compilationUnit = cuAttr; 103 subprogramFlags = 104 subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; 105 } 106 auto spAttr = mlir::LLVM::DISubprogramAttr::get( 107 context, id, compilationUnit, fileAttr, funcName, funcName, 108 funcFileAttr, 109 /*line=*/1, 110 /*scopeline=*/1, subprogramFlags, subTypeAttr); 111 funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); 112 }); 113 } 114 115 std::unique_ptr<mlir::Pass> fir::createAddDebugInfoPass() { 116 return std::make_unique<AddDebugInfoPass>(); 117 } 118