diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp index 68584bef055b61..c98f18f8b25196 100644 --- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp +++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp @@ -11,6 +11,7 @@ /// This pass populates some debug information for the module and functions. //===----------------------------------------------------------------------===// +#include "DebugTypeGenerator.h" #include "flang/Common/Version.h" #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" @@ -106,14 +107,27 @@ void AddDebugInfoPass::runOnOperation() { filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue()); } - mlir::StringAttr funcName = + mlir::StringAttr fullName = 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); - // FIXME: Provide proper type for subroutine + auto result = fir::NameUniquer::deconstruct(funcOp.getName()); + mlir::StringAttr funcName = + mlir::StringAttr::get(context, result.second.name); + + llvm::SmallVector types; + fir::DebugTypeGenerator typeGen(module); + for (auto resTy : funcOp.getResultTypes()) { + auto tyAttr = + typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc()); + types.push_back(tyAttr); + } + for (auto inTy : funcOp.getArgumentTypes()) { + auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr, + cuAttr, funcOp.getLoc()); + types.push_back(tyAttr); + } + mlir::LLVM::DISubroutineTypeAttr subTypeAttr = - mlir::LLVM::DISubroutineTypeAttr::get(context, CC, {bT, bT}); + mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types); mlir::LLVM::DIFileAttr funcFileAttr = mlir::LLVM::DIFileAttr::get(context, fileName, filePath); @@ -130,11 +144,13 @@ void AddDebugInfoPass::runOnOperation() { subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition; } - // FIXME: Provide proper line and scopeline. + unsigned line = 1; + if (auto funcLoc = l.dyn_cast()) + line = funcLoc.getLine(); + auto spAttr = mlir::LLVM::DISubprogramAttr::get( - context, id, compilationUnit, fileAttr, funcName, funcName, - funcFileAttr, /*line=*/1, /*scopeline=*/1, subprogramFlags, - subTypeAttr); + context, id, compilationUnit, fileAttr, funcName, fullName, + funcFileAttr, line, line, subprogramFlags, subTypeAttr); funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr)); }); } diff --git a/flang/lib/Optimizer/Transforms/CMakeLists.txt b/flang/lib/Optimizer/Transforms/CMakeLists.txt index fc08d67540ceb0..5a542f237f8f98 100644 --- a/flang/lib/Optimizer/Transforms/CMakeLists.txt +++ b/flang/lib/Optimizer/Transforms/CMakeLists.txt @@ -22,6 +22,7 @@ add_flang_library(FIRTransforms OMPMarkDeclareTarget.cpp VScaleAttr.cpp FunctionAttr.cpp + DebugTypeGenerator.cpp DEPENDS FIRDialect diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp new file mode 100644 index 00000000000000..0f4ebf9507b124 --- /dev/null +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp @@ -0,0 +1,63 @@ +//===-- DebugTypeGenerator.cpp -- type conversion ---------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "flang-debug-type-generator" + +#include "DebugTypeGenerator.h" +#include "llvm/ADT/ScopeExit.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/Support/Debug.h" + +namespace fir { + +DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m) + : module(m), kindMapping(getKindMapping(m)) { + LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n"); +} + +static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) { + return mlir::LLVM::DIBasicTypeAttr::get( + context, llvm::dwarf::DW_TAG_base_type, "void", 32, 1); +} + +static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context, + mlir::StringAttr name, + unsigned bitSize, + unsigned decoding) { + return mlir::LLVM::DIBasicTypeAttr::get( + context, llvm::dwarf::DW_TAG_base_type, name, bitSize, decoding); +} + +mlir::LLVM::DITypeAttr +DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, + mlir::Location loc) { + mlir::MLIRContext *context = module.getContext(); + if (Ty.isInteger()) { + return genBasicType(context, mlir::StringAttr::get(context, "integer"), + Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_signed); + } else if (Ty.isa() || Ty.isa()) { + return genBasicType(context, mlir::StringAttr::get(context, "real"), + Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_float); + } else if (auto logTy = Ty.dyn_cast_or_null()) { + return genBasicType(context, + mlir::StringAttr::get(context, logTy.getMnemonic()), + kindMapping.getLogicalBitsize(logTy.getFKind()), + llvm::dwarf::DW_ATE_boolean); + } else { + // FIXME: These types are currently unhandled. We are generating a + // placeholder type to allow us to test supported bits. + return genPlaceholderType(context); + } +} + +} // namespace fir diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h new file mode 100644 index 00000000000000..5a2bb201db47a3 --- /dev/null +++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.h @@ -0,0 +1,40 @@ +//===-- DebugTypeGenerator.h -- type conversion ------------------- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H +#define FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H + +#include "flang/Optimizer/Dialect/FIRType.h" +#include "flang/Optimizer/Dialect/Support/FIRContext.h" +#include "flang/Optimizer/Dialect/Support/KindMapping.h" +#include "llvm/Support/Debug.h" + +namespace fir { + +/// This converts FIR/mlir type to DITypeAttr. +class DebugTypeGenerator { +public: + DebugTypeGenerator(mlir::ModuleOp module); + + mlir::LLVM::DITypeAttr convertType(mlir::Type Ty, + mlir::LLVM::DIFileAttr fileAttr, + mlir::LLVM::DIScopeAttr scope, + mlir::Location loc); + +private: + mlir::ModuleOp module; + KindMapping kindMapping; +}; + +} // namespace fir + +#endif // FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H diff --git a/flang/test/Transforms/debug-fn-info.f90 b/flang/test/Transforms/debug-fn-info.f90 new file mode 100644 index 00000000000000..c1a817312c959c --- /dev/null +++ b/flang/test/Transforms/debug-fn-info.f90 @@ -0,0 +1,43 @@ +! RUN: %flang_fc1 -emit-fir -debug-info-kind=standalone -mmlir --mlir-print-debuginfo %s -o - | fir-opt --add-debug-info --mlir-print-debuginfo | FileCheck %s + + +! CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type +! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type +! CHECK: #[[TY1:.*]] = #llvm.di_subroutine_type +! CHECK: #[[TY2:.*]] = #llvm.di_subroutine_type + +program mn + integer(kind=4) :: i4 + integer(kind=8) :: i8 + real(kind=4) :: r4 + real(kind=8) :: r8 + logical(kind=1) :: l1 + logical(kind=4) :: l4 + i8 = fn1(i4, r8, l1) + i4 = fn2(i8, r4, l4) +contains + ! CHECK: #di_subprogram1 = #llvm.di_subprogram + function fn1(a, b, c) result (res) + implicit none + integer(kind=4), intent(in) :: a + real(kind=8), intent(in) :: b + logical(kind=1), intent(in) :: c + integer(kind=8) :: res + res = a + b + end function + +! CHECK: #di_subprogram2 = #llvm.di_subprogram + function fn2(a, b, c) result (res) + implicit none + integer(kind=8), intent(in) :: a + real(kind=4), intent(in) :: b + logical(kind=4), intent(in) :: c + integer(kind=4) :: res + res = a + b + end function +end program + diff --git a/flang/test/Transforms/debug-line-table-inc-file.fir b/flang/test/Transforms/debug-line-table-inc-file.fir index dc75482d4f8a7f..d7f60a1a86dbf0 100644 --- a/flang/test/Transforms/debug-line-table-inc-file.fir +++ b/flang/test/Transforms/debug-line-table-inc-file.fir @@ -31,7 +31,7 @@ module attributes {} { // CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}inc.f90":1:1) // CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}simple.f90":3:1) // CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly> -// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QPsinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}> +// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "sinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}> // CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}> // CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]]) // CHECK: #[[FUSED_LOC_FILE]] = loc(fused<#[[DI_SP]]>[#[[LOC_FILE]]])