Skip to content

Commit f029da5

Browse files
authored
[flang] Improve debug info for functions. (#90083)
This PR improves the debug information for functions in the following ways: 1. Get line number information from FuncOp and remove hard-coded line numbers. 2. Use proper type for function signature. I have a added a type converter. Currently, it is very limited but will be enhanced with time. 3. Use de-constructed function name.
1 parent a19a411 commit f029da5

File tree

6 files changed

+174
-11
lines changed

6 files changed

+174
-11
lines changed

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/// This pass populates some debug information for the module and functions.
1212
//===----------------------------------------------------------------------===//
1313

14+
#include "DebugTypeGenerator.h"
1415
#include "flang/Common/Version.h"
1516
#include "flang/Optimizer/Builder/FIRBuilder.h"
1617
#include "flang/Optimizer/Builder/Todo.h"
@@ -106,14 +107,27 @@ void AddDebugInfoPass::runOnOperation() {
106107
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
107108
}
108109

109-
mlir::StringAttr funcName =
110+
mlir::StringAttr fullName =
110111
mlir::StringAttr::get(context, funcOp.getName());
111-
mlir::LLVM::DIBasicTypeAttr bT = mlir::LLVM::DIBasicTypeAttr::get(
112-
context, llvm::dwarf::DW_TAG_base_type, "void", /*sizeInBits=*/0,
113-
/*encoding=*/1);
114-
// FIXME: Provide proper type for subroutine
112+
auto result = fir::NameUniquer::deconstruct(funcOp.getName());
113+
mlir::StringAttr funcName =
114+
mlir::StringAttr::get(context, result.second.name);
115+
116+
llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
117+
fir::DebugTypeGenerator typeGen(module);
118+
for (auto resTy : funcOp.getResultTypes()) {
119+
auto tyAttr =
120+
typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
121+
types.push_back(tyAttr);
122+
}
123+
for (auto inTy : funcOp.getArgumentTypes()) {
124+
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
125+
cuAttr, funcOp.getLoc());
126+
types.push_back(tyAttr);
127+
}
128+
115129
mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
116-
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, {bT, bT});
130+
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
117131
mlir::LLVM::DIFileAttr funcFileAttr =
118132
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);
119133

@@ -130,11 +144,13 @@ void AddDebugInfoPass::runOnOperation() {
130144
subprogramFlags =
131145
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
132146
}
133-
// FIXME: Provide proper line and scopeline.
147+
unsigned line = 1;
148+
if (auto funcLoc = l.dyn_cast<mlir::FileLineColLoc>())
149+
line = funcLoc.getLine();
150+
134151
auto spAttr = mlir::LLVM::DISubprogramAttr::get(
135-
context, id, compilationUnit, fileAttr, funcName, funcName,
136-
funcFileAttr, /*line=*/1, /*scopeline=*/1, subprogramFlags,
137-
subTypeAttr);
152+
context, id, compilationUnit, fileAttr, funcName, fullName,
153+
funcFileAttr, line, line, subprogramFlags, subTypeAttr);
138154
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));
139155
});
140156
}

flang/lib/Optimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_flang_library(FIRTransforms
2222
OMPMarkDeclareTarget.cpp
2323
VScaleAttr.cpp
2424
FunctionAttr.cpp
25+
DebugTypeGenerator.cpp
2526

2627
DEPENDS
2728
FIRDialect
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===-- DebugTypeGenerator.cpp -- type conversion ---------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEBUG_TYPE "flang-debug-type-generator"
14+
15+
#include "DebugTypeGenerator.h"
16+
#include "llvm/ADT/ScopeExit.h"
17+
#include "llvm/BinaryFormat/Dwarf.h"
18+
#include "llvm/Support/Debug.h"
19+
20+
namespace fir {
21+
22+
DebugTypeGenerator::DebugTypeGenerator(mlir::ModuleOp m)
23+
: module(m), kindMapping(getKindMapping(m)) {
24+
LLVM_DEBUG(llvm::dbgs() << "DITypeAttr generator\n");
25+
}
26+
27+
static mlir::LLVM::DITypeAttr genPlaceholderType(mlir::MLIRContext *context) {
28+
return mlir::LLVM::DIBasicTypeAttr::get(
29+
context, llvm::dwarf::DW_TAG_base_type, "void", 32, 1);
30+
}
31+
32+
static mlir::LLVM::DITypeAttr genBasicType(mlir::MLIRContext *context,
33+
mlir::StringAttr name,
34+
unsigned bitSize,
35+
unsigned decoding) {
36+
return mlir::LLVM::DIBasicTypeAttr::get(
37+
context, llvm::dwarf::DW_TAG_base_type, name, bitSize, decoding);
38+
}
39+
40+
mlir::LLVM::DITypeAttr
41+
DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
42+
mlir::LLVM::DIScopeAttr scope,
43+
mlir::Location loc) {
44+
mlir::MLIRContext *context = module.getContext();
45+
if (Ty.isIntOrIndex()) {
46+
return genBasicType(context, mlir::StringAttr::get(context, "integer"),
47+
Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_signed);
48+
} else if (Ty.isa<mlir::FloatType>() || Ty.isa<fir::RealType>()) {
49+
return genBasicType(context, mlir::StringAttr::get(context, "real"),
50+
Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_float);
51+
} else if (auto logTy = Ty.dyn_cast_or_null<fir::LogicalType>()) {
52+
return genBasicType(context,
53+
mlir::StringAttr::get(context, logTy.getMnemonic()),
54+
kindMapping.getLogicalBitsize(logTy.getFKind()),
55+
llvm::dwarf::DW_ATE_boolean);
56+
} else {
57+
// FIXME: These types are currently unhandled. We are generating a
58+
// placeholder type to allow us to test supported bits.
59+
return genPlaceholderType(context);
60+
}
61+
}
62+
63+
} // namespace fir
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===-- DebugTypeGenerator.h -- type conversion ------------------- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
14+
#define FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
15+
16+
#include "flang/Optimizer/Dialect/FIRType.h"
17+
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
18+
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
19+
#include "llvm/Support/Debug.h"
20+
21+
namespace fir {
22+
23+
/// This converts FIR/mlir type to DITypeAttr.
24+
class DebugTypeGenerator {
25+
public:
26+
DebugTypeGenerator(mlir::ModuleOp module);
27+
28+
mlir::LLVM::DITypeAttr convertType(mlir::Type Ty,
29+
mlir::LLVM::DIFileAttr fileAttr,
30+
mlir::LLVM::DIScopeAttr scope,
31+
mlir::Location loc);
32+
33+
private:
34+
mlir::ModuleOp module;
35+
KindMapping kindMapping;
36+
};
37+
38+
} // namespace fir
39+
40+
#endif // FORTRAN_OPTIMIZER_TRANSFORMS_DEBUGTYPEGENERATOR_H
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
! 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
2+
3+
4+
! CHECK-DAG: #[[INT8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 64, encoding = DW_ATE_signed>
5+
! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed>
6+
! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 64, encoding = DW_ATE_float>
7+
! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 8, encoding = DW_ATE_boolean>
8+
! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float>
9+
! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 32, encoding = DW_ATE_boolean>
10+
! CHECK: #[[TY1:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT8]], #[[INT4]], #[[REAL8]], #[[LOG1]]>
11+
! CHECK: #[[TY2:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT4]], #[[INT8]], #[[REAL4]], #[[LOG4]]>
12+
13+
program mn
14+
integer(kind=4) :: i4
15+
integer(kind=8) :: i8
16+
real(kind=4) :: r4
17+
real(kind=8) :: r8
18+
logical(kind=1) :: l1
19+
logical(kind=4) :: l4
20+
i8 = fn1(i4, r8, l1)
21+
i4 = fn2(i8, r4, l4)
22+
contains
23+
! CHECK: #di_subprogram1 = #llvm.di_subprogram<id = {{.*}}, compileUnit = {{.*}}, scope = {{.*}}, name = "fn1", linkageName = "_QFPfn1", file = {{.*}}, line = [[@LINE+1]], scopeLine = [[@LINE+1]], subprogramFlags = Definition, type = #[[TY1]]>
24+
function fn1(a, b, c) result (res)
25+
implicit none
26+
integer(kind=4), intent(in) :: a
27+
real(kind=8), intent(in) :: b
28+
logical(kind=1), intent(in) :: c
29+
integer(kind=8) :: res
30+
res = a + b
31+
end function
32+
33+
! CHECK: #di_subprogram2 = #llvm.di_subprogram<id = {{.*}}, compileUnit = {{.*}}, scope = {{.*}}, name = "fn2", linkageName = "_QFPfn2", file = {{.*}}, line = [[@LINE+1]], scopeLine = [[@LINE+1]], subprogramFlags = Definition, type = #[[TY2]]>
34+
function fn2(a, b, c) result (res)
35+
implicit none
36+
integer(kind=8), intent(in) :: a
37+
real(kind=4), intent(in) :: b
38+
logical(kind=4), intent(in) :: c
39+
integer(kind=4) :: res
40+
res = a + b
41+
end function
42+
end program
43+

flang/test/Transforms/debug-line-table-inc-file.fir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ module attributes {} {
3131
// CHECK: #[[LOC_INC_FILE:.*]] = loc("{{.*}}inc.f90":1:1)
3232
// CHECK: #[[LOC_FILE:.*]] = loc("{{.*}}simple.f90":3:1)
3333
// CHECK: #[[DI_CU:.*]] = #llvm.di_compile_unit<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly>
34-
// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QPsinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
34+
// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "sinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
3535
// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QQmain", linkageName = "_QQmain", file = #[[DI_FILE]], {{.*}}>
3636
// CHECK: #[[FUSED_LOC_INC_FILE]] = loc(fused<#[[DI_SP_INC]]>[#[[LOC_INC_FILE]]])
3737
// CHECK: #[[FUSED_LOC_FILE]] = loc(fused<#[[DI_SP]]>[#[[LOC_FILE]]])

0 commit comments

Comments
 (0)