Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions flang/lib/Optimizer/Transforms/DebugTypeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,31 @@ 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 (mlir::isa<mlir::FunctionType>(Ty)) {
// Handle function types - these represent procedure pointers after the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think dummy procedures will also fall here now when converting function types with dummy procedure arguments (flang only gives them the () -> () type because they are usually implicitly typed, but with your fix they should at least appear as function address in the debug info now).

All that to say I would just add a mention to dummy procedures to this comment (and maybe a test).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a comment. I was trying to add a test but noticed that somehow DeclareOp is not being generated for the dummy procedure. I will investigate that separately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is not because as far as lowering is concerned, it is not a variable/entity. But I imagine debug info needs to map the name. I agree this is out of the scope of your PR.

With your change, at least the debug type for the procedure with debug argument should be correct now.

subroutine foo(bar)
  external :: bar
end subroutine

was:

!4 = distinct !DISubprogram(name: "foo", linkageName: "foo_", scope: !1, file: !1, line: 1, type: !5, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0)
!5 = !DISubroutineType(cc: DW_CC_normal, types: !6)
!6 = !{null, !7}
!7 = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)

and I think your patch is fixing !7

// BoxedProcedure pass has run and unwrapped the fir.boxproc type, as well
// as dummy procedures (which are represented as function types in FIR)
llvm::SmallVector<mlir::LLVM::DITypeAttr> types;

auto funcTy = mlir::cast<mlir::FunctionType>(Ty);
// Add return type (or void if no return type)
if (funcTy.getNumResults() == 0)
types.push_back(mlir::LLVM::DINullTypeAttr::get(context));
else
types.push_back(
convertType(funcTy.getResult(0), fileAttr, scope, declOp));

for (mlir::Type paramTy : funcTy.getInputs())
types.push_back(convertType(paramTy, fileAttr, scope, declOp));

auto subroutineTy = mlir::LLVM::DISubroutineTypeAttr::get(
context, /*callingConvention=*/0, types);

return mlir::LLVM::DIDerivedTypeAttr::get(
context, llvm::dwarf::DW_TAG_pointer_type,
mlir::StringAttr::get(context, ""), subroutineTy,
/*sizeInBits=*/ptrSize * 8, /*alignInBits=*/0, /*offset=*/0,
/*optional<address space>=*/std::nullopt, /*extra data=*/nullptr);
} else if (auto refTy = mlir::dyn_cast_if_present<fir::ReferenceType>(Ty)) {
auto elTy = refTy.getEleTy();
return convertPointerLikeType(elTy, fileAttr, scope, declOp,
Expand Down
26 changes: 26 additions & 0 deletions flang/test/Integration/debug-proc-ptr-e2e.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this test in the test/Integration folder next to the other debug test using -emit-llvm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I somehow failed to see this. Fixed now.


program test_proc_ptr
implicit none
procedure(fun1), pointer :: fun_ptr

fun_ptr => fun1
print *, fun_ptr(3)

contains
integer function fun1(x)
integer :: x
fun1 = x + 1
end function fun1
end program test_proc_ptr

! Check that fun_ptr is declared with correct type
! CHECK-DAG: ![[INT:.*]] = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)
! CHECK-DAG: ![[PTR_INT:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[INT]], size: 64)

! Check that fun_ptr variable is a pointer to a subroutine type
! The order is: DILocalVariable -> pointer type -> subroutine type -> {return, params}
! CHECK-DAG: ![[FUN_PTR_VAR:.*]] = !DILocalVariable(name: "fun_ptr", {{.*}}type: ![[PROC_PTR:[0-9]+]]
! CHECK-DAG: ![[PROC_PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[SUBR_TYPE:[0-9]+]], size: 64)
! CHECK-DAG: ![[SUBR_TYPE]] = !DISubroutineType(types: ![[SUBR_TYPES:[0-9]+]])
! CHECK-DAG: ![[SUBR_TYPES]] = !{![[INT]], ![[PTR_INT]]}
41 changes: 41 additions & 0 deletions flang/test/Transforms/debug-proc-ptr.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s

module {
func.func @_QQmain() attributes {fir.bindc_name = "test"} {
%0 = fir.alloca (!fir.ref<i32>) -> i32 {bindc_name = "fun_ptr", uniq_name = "_QFEfun_ptr"}
%1 = fircg.ext_declare %0 {uniq_name = "_QFEfun_ptr"} : (!fir.ref<(!fir.ref<i32>) -> i32>) -> !fir.ref<(!fir.ref<i32>) -> i32> loc(#loc1)

// Procedure pointer with no return: procedure(sub1), pointer :: sub_ptr
%2 = fir.alloca () -> () {bindc_name = "sub_ptr", uniq_name = "_QFEsub_ptr"}
%3 = fircg.ext_declare %2 {uniq_name = "_QFEsub_ptr"} : (!fir.ref<() -> ()>) -> !fir.ref<() -> ()> loc(#loc2)

// Procedure pointer with multiple args: procedure(func2), pointer :: func_ptr
%4 = fir.alloca (!fir.ref<i32>, !fir.ref<f64>) -> f32 {bindc_name = "func_ptr", uniq_name = "_QFEfunc_ptr"}
%5 = fircg.ext_declare %4 {uniq_name = "_QFEfunc_ptr"} : (!fir.ref<(!fir.ref<i32>, !fir.ref<f64>) -> f32>) -> !fir.ref<(!fir.ref<i32>, !fir.ref<f64>) -> f32> loc(#loc3)

return
} loc(#loc)
}
#loc = loc("test.f90":1:1)
#loc1 = loc("test.f90":2:30)
#loc2 = loc("test.f90":3:30)
#loc3 = loc("test.f90":4:30)

// CHECK-DAG: #[[INT:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "integer", sizeInBits = 32, encoding = DW_ATE_signed>
// CHECK-DAG: #[[REAL32:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real", sizeInBits = 32, encoding = DW_ATE_float>
// CHECK-DAG: #[[REAL:.*]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "real(kind=8)", sizeInBits = 64, encoding = DW_ATE_float>

// CHECK-DAG: #[[PTR_INT:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[INT]]{{.*}}>
// CHECK-DAG: #[[PTR_REAL:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[REAL]]{{.*}}>

// CHECK-DAG: #[[SUB1:.*]] = #llvm.di_subroutine_type<types = #[[INT]], #[[PTR_INT]]>
// CHECK-DAG: #[[PTR_SUB1:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[SUB1]]{{.*}}>
// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "fun_ptr"{{.*}}type = #[[PTR_SUB1]]{{.*}}>

// CHECK-DAG: #di_subroutine_type{{.*}} = #llvm.di_subroutine_type<types = #di_null_type>
// CHECK-DAG: #di_local_variable{{.*}} = #llvm.di_local_variable<{{.*}}name = "sub_ptr"{{.*}}type = #di_derived_type{{.*}}>
// CHECK-DAG: #di_derived_type{{.*}} = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #di_subroutine_type{{.*}}{{.*}}>

// CHECK-DAG: #[[SUB3:.*]] = #llvm.di_subroutine_type<types = #[[REAL32]], #[[PTR_INT]], #[[PTR_REAL]]>
// CHECK-DAG: #[[PTR_SUB3:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type{{.*}}baseType = #[[SUB3]]{{.*}}>
// CHECK-DAG: #llvm.di_local_variable<{{.*}}name = "func_ptr"{{.*}}type = #[[PTR_SUB3]]{{.*}}>
Loading