| //===-------------- AddDebugInfo.cpp -- add debug info -------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// This pass populates some debug information for the module and functions. |
| //===----------------------------------------------------------------------===// |
| |
| #include "flang/Optimizer/Builder/FIRBuilder.h" |
| #include "flang/Optimizer/Builder/Todo.h" |
| #include "flang/Optimizer/Dialect/FIRDialect.h" |
| #include "flang/Optimizer/Dialect/FIROps.h" |
| #include "flang/Optimizer/Dialect/FIRType.h" |
| #include "flang/Optimizer/Dialect/Support/FIRContext.h" |
| #include "flang/Optimizer/Transforms/Passes.h" |
| #include "mlir/Dialect/Func/IR/FuncOps.h" |
| #include "mlir/Dialect/LLVMIR/LLVMDialect.h" |
| #include "mlir/IR/Matchers.h" |
| #include "mlir/IR/TypeUtilities.h" |
| #include "mlir/Pass/Pass.h" |
| #include "mlir/Transforms/DialectConversion.h" |
| #include "mlir/Transforms/GreedyPatternRewriteDriver.h" |
| #include "mlir/Transforms/RegionUtils.h" |
| #include "llvm/BinaryFormat/Dwarf.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| namespace fir { |
| #define GEN_PASS_DEF_ADDDEBUGINFO |
| #define GEN_PASS_DECL_ADDDEBUGINFO |
| #include "flang/Optimizer/Transforms/Passes.h.inc" |
| } // namespace fir |
| |
| #define DEBUG_TYPE "flang-add-debug-foundation" |
| |
| namespace { |
| |
| class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> { |
| public: |
| void runOnOperation() override; |
| }; |
| |
| } // namespace |
| |
| void AddDebugInfoPass::runOnOperation() { |
| mlir::ModuleOp module = getOperation(); |
| mlir::MLIRContext *context = &getContext(); |
| mlir::OpBuilder builder(context); |
| std::string inputFilePath("-"); |
| if (auto fileLoc = module.getLoc().dyn_cast<mlir::FileLineColLoc>()) |
| inputFilePath = fileLoc.getFilename().getValue(); |
| |
| auto getFileAttr = [context](llvm::StringRef path) -> mlir::LLVM::DIFileAttr { |
| return mlir::LLVM::DIFileAttr::get(context, llvm::sys::path::filename(path), |
| llvm::sys::path::parent_path(path)); |
| }; |
| |
| mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath); |
| mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang"); |
| mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get( |
| mlir::DistinctAttr::create(mlir::UnitAttr::get(context)), |
| llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer, |
| /*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly); |
| |
| module.walk([&](mlir::func::FuncOp funcOp) { |
| mlir::Location l = funcOp->getLoc(); |
| // If fused location has already been created then nothing to do |
| // Otherwise, create a fused location. |
| if (l.dyn_cast<mlir::FusedLoc>()) |
| return; |
| |
| llvm::StringRef funcFilePath; |
| if (l.dyn_cast<mlir::FileLineColLoc>()) |
| funcFilePath = |
| l.dyn_cast<mlir::FileLineColLoc>().getFilename().getValue(); |
| else |
| funcFilePath = inputFilePath; |
| |
| mlir::StringAttr funcName = |
| mlir::StringAttr::get(context, funcOp.getName()); |
| mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get( |
| context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0, |
| /*encoding=*/1); |
| mlir::LLVM::DISubroutineTypeAttr subTypeAttr = |
| mlir::LLVM::DISubroutineTypeAttr::get( |
| context, llvm::dwarf::getCallingConvention("DW_CC_normal"), |
| {bT, bT}); |
| mlir::LLVM::DIFileAttr funcFileAttr = getFileAttr(funcFilePath); |
| |
| // Only definitions need a distinct identifier and a compilation unit. |
| mlir::DistinctAttr id; |
| mlir::LLVM::DICompileUnitAttr compilationUnit; |
| auto subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized; |
| if (!funcOp.isExternal()) { |
| id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context)); |
| compilationUnit = cuAttr; |
| subprogramFlags = |
| subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; |
| } |
| auto spAttr = mlir::LLVM::DISubprogramAttr::get( |
| context, id, compilationUnit, fileAttr, funcName, funcName, |
| funcFileAttr, |
| /*line=*/1, |
| /*scopeline=*/1, subprogramFlags, subTypeAttr); |
| funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); |
| }); |
| } |
| |
| std::unique_ptr<mlir::Pass> fir::createAddDebugInfoPass() { |
| return std::make_unique<AddDebugInfoPass>(); |
| } |