-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Improve debug info for functions. #90083
Conversation
This PR improves the debug information for functions in the following way: 1. Remove hardcoded line numbers. 2. Use proper type for function signature. I have a added a type convertor. It currently is very limited but will be enhanced with time. 3. Use de-constructed function name so that user see the same name as was in the source.
@llvm/pr-subscribers-flang-fir-hlfir Author: Abid Qadeer (abidh) ChangesThis PR improves the debug information for functions in the following ways:
Full diff: https://github.com/llvm/llvm-project/pull/90083.diff 6 Files Affected:
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 68584bef055b61..5a023db7dd59af 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<mlir::LLVM::DITypeAttr> types;
+ fir::DebugTypeGenerator typeGen(module);
+ for (auto resTy : funcOp.getResultTypes()) {
+ auto tyAttr = typeGen.convertType(fir::unwrapRefType(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<mlir::FileLineColLoc>())
+ 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..0057e08f8a763b
--- /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.isIntOrIndex()) {
+ return genBasicType(context, mlir::StringAttr::get(context, "integer"),
+ Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_signed);
+ } else if (Ty.isa<mlir::FloatType>() || Ty.isa<fir::RealType>()) {
+ return genBasicType(context, mlir::StringAttr::get(context, "real"),
+ Ty.getIntOrFloatBitWidth(), llvm::dwarf::DW_ATE_float);
+ } else if (auto logTy = Ty.dyn_cast_or_null<fir::LogicalType>()) {
+ 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<tag = DW_TAG_base_type, name = "integer", sizeInBits = 64, encoding = DW_ATE_signed>
+! CHECK-DAG: #[[INT4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed>
+! CHECK-DAG: #[[REAL8:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 64, encoding = DW_ATE_float>
+! CHECK-DAG: #[[LOG1:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 8, encoding = DW_ATE_boolean>
+! CHECK-DAG: #[[REAL4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float>
+! CHECK-DAG: #[[LOG4:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "logical", sizeInBits = 32, encoding = DW_ATE_boolean>
+! CHECK: #[[TY1:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT8]], #[[INT4]], #[[REAL8]], #[[LOG1]]>
+! CHECK: #[[TY2:.*]] = #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #[[INT4]], #[[INT8]], #[[REAL4]], #[[LOG4]]>
+
+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<id = {{.*}}, compileUnit = {{.*}}, scope = {{.*}}, name = "fn1", linkageName = "_QFPfn1", file = {{.*}}, line = [[@LINE+1]], scopeLine = [[@LINE+1]], subprogramFlags = Definition, type = #[[TY1]]>
+ 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<id = {{.*}}, compileUnit = {{.*}}, scope = {{.*}}, name = "fn2", linkageName = "_QFPfn2", file = {{.*}}, line = [[@LINE+1]], scopeLine = [[@LINE+1]], subprogramFlags = Definition, type = #[[TY2]]>
+ 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<id = distinct[{{.*}}]<>, sourceLanguage = DW_LANG_Fortran95, file = #[[DI_FILE]], producer = "flang{{.*}}", isOptimized = false, emissionKind = LineTablesOnly>
-// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "_QPsinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
+// CHECK: #[[DI_SP_INC:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #[[DI_CU]], scope = #[[DI_FILE]], name = "sinc", linkageName = "_QPsinc", file = #[[DI_INC_FILE]], {{.*}}>
// CHECK: #[[DI_SP:.*]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, 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]]])
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Would it be possible to reconstruct the type for Complex, Derived and various array types without passing additional info from the frontend?
llvm::SmallVector<mlir::LLVM::DITypeAttr> types; | ||
fir::DebugTypeGenerator typeGen(module); | ||
for (auto resTy : funcOp.getResultTypes()) { | ||
auto tyAttr = typeGen.convertType(fir::unwrapRefType(resTy), fileAttr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to remove the reference type of returned values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right that it is not required. I will remove it. On this topic, can you kindly explain why the arguments are wrapped in the reference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without the VALUE keyword, fortran defaults to passing all arguments by reference
I think complex and array type should be ok. Some work may need to be done for calculation of offsets for derived types but @jeanPerier commented on the design document that it should be do-able using FIR RecordType type directly + mlir datalayout. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
This has caused a test suite failure. This particular bot is red already but this specific failure is new:
The test file is https://github.com/llvm/llvm-test-suite/blob/main/Fortran/gfortran/regression/lto/20091016-1_0.f90. |
This reverts commit f029da5.
Reverts #90083 due to a test suite failure: https://lab.llvm.org/buildbot/#/builders/184/builds/11961 ``` flang-new: ../llvm/mlir/lib/IR/Types.cpp:126: unsigned int mlir::Type::getIntOrFloatBitWidth() const: Assertion `isIntOrFloat() && "only integers and floats have a bitwidth"' failed. ```
Thanks @DavidSpickett for reverting it. I will investigate the regression. |
The initial PR llvm#90083 was reverted as it caused the regression in one of the gfortran tests. This commit fixes this issue by replacing isIntOrIndex with isInteger which is the right function to check for integer type.
…ixed. (#90484) The original PR #90083 had to be reverted in PR #90444 as it caused one of the gfortran tests to fail. The issue was using `isIntOrIndex` for checking for integer type. It allowed index type which later caused assertion when calling `getIntOrFloatBitWidth`. I have now replaced it with `isInteger` which should fix this regression.
The initial PR llvm#90083 was reverted as it caused the regression in one of the gfortran tests. This commit fixes this issue by replacing isIntOrIndex with isInteger which is the right function to check for integer type.
This PR improves the debug information for functions in the following ways: