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.
119 lines
4.6 KiB
C++
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>();
|
|
}
|