//===- AddDebugFoundation.cpp -- add basic debug linetable 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_ADDDEBUGFOUNDATION #define GEN_PASS_DECL_ADDDEBUGFOUNDATION #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir #define DEBUG_TYPE "flang-add-debug-foundation" namespace { class AddDebugFoundationPass : public fir::impl::AddDebugFoundationBase { public: void runOnOperation() override; }; } // namespace void AddDebugFoundationPass::runOnOperation() { mlir::ModuleOp module = getOperation(); mlir::MLIRContext *context = &getContext(); mlir::OpBuilder builder(context); std::string inputFilePath("-"); if (auto fileLoc = module.getLoc().dyn_cast()) 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( context, 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()) return; llvm::StringRef funcFilePath; if (l.dyn_cast()) funcFilePath = l.dyn_cast().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 fir::createAddDebugFoundationPass() { return std::make_unique(); }