[flang-commits] [flang] [flang][debug] Support ClassType. (PR #114809)

Abid Qadeer via flang-commits flang-commits at lists.llvm.org
Wed Nov 13 12:53:13 PST 2024


https://github.com/abidh updated https://github.com/llvm/llvm-project/pull/114809

>From 548bcf4bb4e7a2a4331ea5bf7962150f3cff43a4 Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Mon, 28 Oct 2024 17:52:56 +0000
Subject: [PATCH 1/3] [flang][debug] Support ClassType.

This PR adds the handling of ClassType. It is treated as pointer to
the underlying type. Note that ClassType when passed to the function
have double indirection so it is represented as pointer to type
(and not type as a RecordType will be for example).

If ClassType wraps a pointer or allocatable then we take care to
avoid double indirection.

This is how it looks like in the debugger.

subroutine test_proc (this)
    class(test_type), intent (inout) :: this
    allocate (this%b (3, 2))
    call fill_array_2d (this%b)
    print *, this%a
end

(gdb) p this
$6 = (PTR TO -> ( Type test_type )) 0x2052a0
(gdb) p this%a
$7 = 0
(gdb) p this%b
$8 = ((1, 2, 3) (4, 5, 6))
(gdb)
---
 .../Transforms/DebugTypeGenerator.cpp         | 14 ++++++++++
 flang/test/Transforms/debug-class-type.fir    | 27 +++++++++++++++++++
 2 files changed, 41 insertions(+)
 create mode 100644 flang/test/Transforms/debug-class-type.fir

diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index 0187524d76cdd5c..093c7c897376cbe 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -668,6 +668,20 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
     return convertRecordType(recTy, fileAttr, scope, declOp);
   } else if (auto tupleTy = mlir::dyn_cast_if_present<mlir::TupleType>(Ty)) {
     return convertTupleType(tupleTy, fileAttr, scope, declOp);
+  } else if (auto classTy = mlir::dyn_cast_if_present<fir::ClassType>(Ty)) {
+    // ClassType when passed to the function have double indirection so it
+    // is represented as pointer to type (and not type as a RecordType will be
+    // for example). If ClassType wraps a pointer or allocatable then we get
+    // the real underlying type to avoid translating the Ty to
+    // Ptr -> Ptr -> type.
+    mlir::Type elTy = classTy.getEleTy();
+    if (auto ptrTy = mlir::dyn_cast_if_present<fir::PointerType>(elTy))
+      elTy = ptrTy.getElementType();
+    else if (auto heapTy = mlir::dyn_cast_if_present<fir::HeapType>(elTy))
+      elTy = heapTy.getElementType();
+    return convertPointerLikeType(elTy, fileAttr, scope, declOp,
+                                  /*genAllocated=*/false,
+                                  /*genAssociated=*/false);
   } else if (auto refTy = mlir::dyn_cast_if_present<fir::ReferenceType>(Ty)) {
     auto elTy = refTy.getEleTy();
     return convertPointerLikeType(elTy, fileAttr, scope, declOp,
diff --git a/flang/test/Transforms/debug-class-type.fir b/flang/test/Transforms/debug-class-type.fir
new file mode 100644
index 000000000000000..e11dc7b2a2086ae
--- /dev/null
+++ b/flang/test/Transforms/debug-class-type.fir
@@ -0,0 +1,27 @@
+// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
+
+module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
+  fir.type_info @_QTtest_type nofinal : !fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}> dispatch_table {
+    fir.dt_entry "test_proc", @_QPtest_proc
+  } loc(#loc1)
+  func.func private @_QPtest_proc(%arg0: !fir.class<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>)
+
+    func.func @test()  {
+    %0 = fir.address_of(@_QFEx) : !fir.ref<!fir.class<!fir.heap<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>
+    %1 = fircg.ext_declare %0 {uniq_name = "_QFEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>) -> !fir.ref<!fir.class<!fir.heap<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>> loc(#loc3)
+    %2 = fir.address_of(@_QFEy) : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>
+    %3 = fircg.ext_declare %2 {uniq_name = "_QFEy"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>) -> !fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>> loc(#loc4)
+    return
+  } loc(#loc2)
+}
+
+#loc1 = loc("./simple.f90":2:1)
+#loc2 = loc("./simple.f90":10:1)
+#loc3 = loc("./simple.f90":15:1)
+#loc4 = loc("./simple.f90":22:1)
+
+// CHECK-DAG: #[[TY1:.*]] = #llvm.di_composite_type<{{.*}}name = "test_type"{{.*}}>
+// CHECK-DAG: #[[TY2:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "", baseType = #[[TY1]]{{.*}}>
+// CHECK-DAG: #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #di_null_type, #[[TY2]]>
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "x"{{.*}}type = #[[TY2]]>
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "y"{{.*}}type = #[[TY2]]>

>From b8c1012a596e7ceed3d8136ce4e3f5d8ffe5c44d Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Tue, 5 Nov 2024 19:46:24 +0000
Subject: [PATCH 2/3] Handle review comments.

Merged handling of ClassType with BoxType. Used boxTy.unwrapInnerType()
to avoid special casing for pointer or allocatable. Also improved
convertPointerLikeType to better handle if underlying type in null or
none.
---
 .../Transforms/DebugTypeGenerator.cpp         | 30 ++++++++-----------
 flang/test/Transforms/debug-class-type.fir    |  7 +++++
 2 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index 093c7c897376cbe..a9f2782a8e9a5aa 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -629,7 +629,12 @@ mlir::LLVM::DITypeAttr DebugTypeGenerator::convertPointerLikeType(
     return convertCharacterType(charTy, fileAttr, scope, declOp,
                                 /*hasDescriptor=*/true);
 
-  mlir::LLVM::DITypeAttr elTyAttr = convertType(elTy, fileAttr, scope, declOp);
+  // If elTy is null or none then generate a void*
+  mlir::LLVM::DITypeAttr elTyAttr;
+  if (!elTy || mlir::isa<mlir::NoneType>(elTy))
+    elTyAttr = mlir::LLVM::DINullTypeAttr::get(context);
+  else
+    elTyAttr = convertType(elTy, fileAttr, scope, declOp);
 
   return mlir::LLVM::DIDerivedTypeAttr::get(
       context, llvm::dwarf::DW_TAG_pointer_type,
@@ -668,20 +673,6 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
     return convertRecordType(recTy, fileAttr, scope, declOp);
   } else if (auto tupleTy = mlir::dyn_cast_if_present<mlir::TupleType>(Ty)) {
     return convertTupleType(tupleTy, fileAttr, scope, declOp);
-  } else if (auto classTy = mlir::dyn_cast_if_present<fir::ClassType>(Ty)) {
-    // ClassType when passed to the function have double indirection so it
-    // is represented as pointer to type (and not type as a RecordType will be
-    // for example). If ClassType wraps a pointer or allocatable then we get
-    // the real underlying type to avoid translating the Ty to
-    // Ptr -> Ptr -> type.
-    mlir::Type elTy = classTy.getEleTy();
-    if (auto ptrTy = mlir::dyn_cast_if_present<fir::PointerType>(elTy))
-      elTy = ptrTy.getElementType();
-    else if (auto heapTy = mlir::dyn_cast_if_present<fir::HeapType>(elTy))
-      elTy = heapTy.getElementType();
-    return convertPointerLikeType(elTy, fileAttr, scope, declOp,
-                                  /*genAllocated=*/false,
-                                  /*genAssociated=*/false);
   } else if (auto refTy = mlir::dyn_cast_if_present<fir::ReferenceType>(Ty)) {
     auto elTy = refTy.getEleTy();
     return convertPointerLikeType(elTy, fileAttr, scope, declOp,
@@ -693,8 +684,13 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
     return genBasicType(context, mlir::StringAttr::get(context, "integer"),
                         llvmTypeConverter.getIndexTypeBitwidth(),
                         llvm::dwarf::DW_ATE_signed);
-  } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BoxType>(Ty)) {
-    auto elTy = boxTy.getElementType();
+  } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(Ty)) {
+    if (mlir::isa<fir::ClassType>(Ty))
+      return convertPointerLikeType(boxTy.unwrapInnerType(), fileAttr, scope,
+                                    declOp, /*genAllocated=*/false,
+                                    /*genAssociated=*/true);
+
+    auto elTy = boxTy.getEleTy();
     if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
       return convertBoxedSequenceType(seqTy, fileAttr, scope, declOp, false,
                                       false);
diff --git a/flang/test/Transforms/debug-class-type.fir b/flang/test/Transforms/debug-class-type.fir
index e11dc7b2a2086ae..aad15a831fd2fa9 100644
--- a/flang/test/Transforms/debug-class-type.fir
+++ b/flang/test/Transforms/debug-class-type.fir
@@ -11,6 +11,10 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
     %1 = fircg.ext_declare %0 {uniq_name = "_QFEx"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>) -> !fir.ref<!fir.class<!fir.heap<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>> loc(#loc3)
     %2 = fir.address_of(@_QFEy) : !fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>
     %3 = fircg.ext_declare %2 {uniq_name = "_QFEy"} : (!fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>>) -> !fir.ref<!fir.class<!fir.ptr<!fir.type<_QTtest_type{a:i32,b:!fir.box<!fir.heap<!fir.array<?x?xf32>>>}>>>> loc(#loc4)
+    %4 = fir.address_of(@_QFEz) : !fir.ref<!fir.class<none>>
+    %5 = fircg.ext_declare %4 {uniq_name = "_QFEz"} : (!fir.ref<!fir.class<none>>) -> !fir.ref<!fir.class<none>> loc(#loc4)
+    %6 = fir.address_of(@_QFEt) : !fir.ref<!fir.class<!fir.ptr<none>>>
+    %7 = fircg.ext_declare %6 {uniq_name = "_QFEt"} : (!fir.ref<!fir.class<!fir.ptr<none>>>) -> !fir.ref<!fir.class<!fir.ptr<none>>> loc(#loc4)
     return
   } loc(#loc2)
 }
@@ -22,6 +26,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
 
 // CHECK-DAG: #[[TY1:.*]] = #llvm.di_composite_type<{{.*}}name = "test_type"{{.*}}>
 // CHECK-DAG: #[[TY2:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "", baseType = #[[TY1]]{{.*}}>
+// CHECK-DAG: #[[TY3:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "", baseType = #di_null_type{{.*}}>
 // CHECK-DAG: #llvm.di_subroutine_type<callingConvention = DW_CC_normal, types = #di_null_type, #[[TY2]]>
 // CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "x"{{.*}}type = #[[TY2]]>
 // CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "y"{{.*}}type = #[[TY2]]>
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "z"{{.*}}type = #[[TY3]]>
+// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "t"{{.*}}type = #[[TY3]]>

>From fe75d2c7e568f8f8f080097fd281f09e0f2f58ab Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Wed, 13 Nov 2024 20:21:59 +0000
Subject: [PATCH 3/3] Handle review comments.

Dont special case ClassTyp but handle it like a BoxType. Also in default case, generate a pointer to underlying type instead of a PlaceHolder type.
---
 flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
index a9f2782a8e9a5aa..cc99698ead33f7d 100644
--- a/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
+++ b/flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
@@ -685,11 +685,6 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
                         llvmTypeConverter.getIndexTypeBitwidth(),
                         llvm::dwarf::DW_ATE_signed);
   } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(Ty)) {
-    if (mlir::isa<fir::ClassType>(Ty))
-      return convertPointerLikeType(boxTy.unwrapInnerType(), fileAttr, scope,
-                                    declOp, /*genAllocated=*/false,
-                                    /*genAssociated=*/true);
-
     auto elTy = boxTy.getEleTy();
     if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(elTy))
       return convertBoxedSequenceType(seqTy, fileAttr, scope, declOp, false,
@@ -702,7 +697,9 @@ DebugTypeGenerator::convertType(mlir::Type Ty, mlir::LLVM::DIFileAttr fileAttr,
       return convertPointerLikeType(ptrTy.getElementType(), fileAttr, scope,
                                     declOp, /*genAllocated=*/false,
                                     /*genAssociated=*/true);
-    return genPlaceholderType(context);
+    return convertPointerLikeType(elTy, fileAttr, scope, declOp,
+                                  /*genAllocated=*/false,
+                                  /*genAssociated=*/false);
   } else {
     // FIXME: These types are currently unhandled. We are generating a
     // placeholder type to allow us to test supported bits.



More information about the flang-commits mailing list