Files
clang-p2996/flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp
Christian Ulmann fa5255eee2 [MLIR][LLVM] Enable export of DISubprograms on function declarations (#78026)
This commit changes the MLIR to LLVMIR export to also attach subprogram
debug attachements to function declarations.
This commit additonally fixes the two passes that produce subprograms to
not attach the "Definition" flag to function declarations. This
otherwise results in invalid LLVM IR.
2024-01-15 07:34:13 +01:00

119 lines
4.6 KiB
C++

//===- 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<AddDebugFoundationPass> {
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<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(
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<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::createAddDebugFoundationPass() {
return std::make_unique<AddDebugFoundationPass>();
}