[flang-commits] [flang] 603e5c8 - [flang][debug] Supply missing subprogram attributes (#181425)
via flang-commits
flang-commits at lists.llvm.org
Fri Feb 20 13:23:06 PST 2026
Author: Tim
Date: 2026-02-20T21:23:01Z
New Revision: 603e5c832a5508e789316475cc0b8228de876f7c
URL: https://github.com/llvm/llvm-project/commit/603e5c832a5508e789316475cc0b8228de876f7c
DIFF: https://github.com/llvm/llvm-project/commit/603e5c832a5508e789316475cc0b8228de876f7c.diff
LOG: [flang][debug] Supply missing subprogram attributes (#181425)
Add DW_AT_elemental, DW_AT_pure, and DW_AT_recursive attributes to
subprograms and functions when they are specified in the source.
Added:
flang/test/Lower/HLFIR/recursive-user-procedure.f90
flang/test/Transforms/debug-fn-attr.fir
Modified:
flang/include/flang/Optimizer/Dialect/FIRAttr.td
flang/lib/Lower/CallInterface.cpp
flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
index 2fbe195ee9f33..b23d28fdde55c 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
@@ -77,12 +77,14 @@ def FIRfuncPure : I32BitEnumAttrCaseBit<"pure", 1>;
def FIRfuncNonRecursive : I32BitEnumAttrCaseBit<"non_recursive", 2>;
def FIRfuncSimple : I32BitEnumAttrCaseBit<"simple", 3>;
def FIRfuncBind_c : I32BitEnumAttrCaseBit<"bind_c", 4>;
-
-def fir_FortranProcedureFlagsEnum : I32BitEnumAttr<
- "FortranProcedureFlagsEnum",
- "Fortran procedure attributes",
- [FIRfuncNoAttributes, FIRfuncElemental, FIRfuncPure, FIRfuncNonRecursive,
- FIRfuncSimple, FIRfuncBind_c]> {
+def FIRfuncRecursive : I32BitEnumAttrCaseBit<"recursive", 5>;
+
+def fir_FortranProcedureFlagsEnum
+ : I32BitEnumAttr<"FortranProcedureFlagsEnum",
+ "Fortran procedure attributes",
+ [FIRfuncNoAttributes, FIRfuncElemental, FIRfuncPure,
+ FIRfuncNonRecursive, FIRfuncSimple, FIRfuncBind_c,
+ FIRfuncRecursive]> {
let separator = ", ";
let cppNamespace = "::fir";
let genSpecializedAttr = 0;
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index f5ae2de5cad8b..129f71a027451 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -1579,9 +1579,14 @@ Fortran::lower::CallInterface<T>::getProcedureAttrs(
if (sym->attrs().test(Fortran::semantics::Attr::NON_RECURSIVE) ||
(sym->owner().context().languageFeatures().IsEnabled(
Fortran::common::LanguageFeature::DefaultSave) &&
- !sym->attrs().test(Fortran::semantics::Attr::RECURSIVE))) {
+ !sym->attrs().test(Fortran::semantics::Attr::RECURSIVE)))
flags = flags | fir::FortranProcedureFlagsEnum::non_recursive;
- }
+
+ // Set RECURSIVE if the attribute is explicitly present. This is only
+ // used for debug info generation to maintain consistency with pre-F2018
+ // compilers.
+ if (sym->attrs().test(Fortran::semantics::Attr::RECURSIVE))
+ flags = flags | fir::FortranProcedureFlagsEnum::recursive;
}
}
if (flags != fir::FortranProcedureFlagsEnum::none)
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 42080dacc731a..63698fdb88909 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -565,6 +565,20 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
subprogramFlags =
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
}
+
+ // Check if the function has the pure, elemental, or recursive procedure
+ // attribute
+ if (fir::hasProcedureAttr<fir::FortranProcedureFlagsEnum::pure>(funcOp))
+ subprogramFlags = subprogramFlags | mlir::LLVM::DISubprogramFlags::Pure;
+
+ if (fir::hasProcedureAttr<fir::FortranProcedureFlagsEnum::elemental>(funcOp))
+ subprogramFlags =
+ subprogramFlags | mlir::LLVM::DISubprogramFlags::Elemental;
+
+ if (fir::hasProcedureAttr<fir::FortranProcedureFlagsEnum::recursive>(funcOp))
+ subprogramFlags =
+ subprogramFlags | mlir::LLVM::DISubprogramFlags::Recursive;
+
unsigned line = getLineFromLoc(l);
if (fir::isInternalProcedure(funcOp)) {
// For contained functions, the scope is the parent subroutine.
diff --git a/flang/test/Lower/HLFIR/recursive-user-procedure.f90 b/flang/test/Lower/HLFIR/recursive-user-procedure.f90
new file mode 100644
index 0000000000000..cbbd1a260d429
--- /dev/null
+++ b/flang/test/Lower/HLFIR/recursive-user-procedure.f90
@@ -0,0 +1,8 @@
+! Test lowering of user-defined recursive function attribute
+! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s
+recursive integer function factorial(n)
+ implicit none
+ integer, intent(in) :: n
+end function factorial
+
+! CHECK: func.func @_QPfactorial{{.*}} attributes {fir.proc_attrs = #fir.proc_attrs<recursive>}
diff --git a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
index d6175dd8730c2..46465eece5050 100644
--- a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
+++ b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
@@ -161,7 +161,7 @@ SUBROUTINE SUBR_DEFAULT_EXTENDEDLIST()
!! -----
! DEVICE-LABEL: func.func @_QPrecursive_declare_target
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}
RECURSIVE FUNCTION RECURSIVE_DECLARE_TARGET(INCREMENT) RESULT(K)
!$omp declare target to(RECURSIVE_DECLARE_TARGET) device_type(nohost)
INTEGER :: INCREMENT, K
@@ -173,7 +173,7 @@ RECURSIVE FUNCTION RECURSIVE_DECLARE_TARGET(INCREMENT) RESULT(K)
END FUNCTION RECURSIVE_DECLARE_TARGET
! DEVICE-LABEL: func.func @_QPrecursive_declare_target_enter
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}
RECURSIVE FUNCTION RECURSIVE_DECLARE_TARGET_ENTER(INCREMENT) RESULT(K)
!$omp declare target enter(RECURSIVE_DECLARE_TARGET_ENTER) device_type(nohost)
INTEGER :: INCREMENT, K
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
index e8709f23c5413..2caa6ba0b5b1e 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
@@ -105,7 +105,7 @@ end function target_function_test_host
!! -----
! DEVICE-LABEL: func.func @_QPimplicitly_captured_with_dev_type_recursive
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter), automap = false>{{.*}}}
recursive function implicitly_captured_with_dev_type_recursive(increment) result(k)
!$omp declare target enter(implicitly_captured_with_dev_type_recursive) device_type(host)
integer :: increment, k
@@ -174,7 +174,7 @@ recursive subroutine implicitly_captured_recursive(increment)
end program
! DEVICE-LABEL: func.func @_QPimplicitly_captured_recursive
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (enter), automap = false>{{.*}}}
recursive subroutine implicitly_captured_recursive(increment)
integer :: increment
if (increment == 10) then
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
index be1e5a0d31f4b..32a5058029174 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
@@ -131,7 +131,7 @@ end function target_function_test_host
!! -----
! DEVICE-LABEL: func.func @_QPimplicitly_captured_with_dev_type_recursive
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (to), automap = false>{{.*}}}
recursive function implicitly_captured_with_dev_type_recursive(increment) result(k)
!$omp declare target to(implicitly_captured_with_dev_type_recursive) device_type(host)
integer :: increment, k
@@ -200,7 +200,7 @@ recursive subroutine implicitly_captured_recursive(increment)
end program
! DEVICE-LABEL: func.func @_QPimplicitly_captured_recursive
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
recursive subroutine implicitly_captured_recursive(increment)
integer :: increment
if (increment == 10) then
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90
index c1c1ea37fe471..c31bfd1e61e8e 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-tarop-cap.f90
@@ -67,7 +67,7 @@ end function target_function_test_device
!! -----
! DEVICE-LABEL: func.func @_QPimplicitly_captured_recursive
-! DEVICE-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
+! DEVICE-SAME: {{.*}}attributes {{.*}}omp.declare_target = #omp.declaretarget<device_type = (nohost), capture_clause = (to), automap = false>{{.*}}}
recursive function implicitly_captured_recursive(increment) result(k)
integer :: increment, k
if (increment == 10) then
diff --git a/flang/test/Transforms/debug-fn-attr.fir b/flang/test/Transforms/debug-fn-attr.fir
new file mode 100644
index 0000000000000..d6409e1402cce
--- /dev/null
+++ b/flang/test/Transforms/debug-fn-attr.fir
@@ -0,0 +1,17 @@
+// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s
+
+module {
+ func.func @_QPvector_magnitude() attributes {fir.proc_attrs = #fir.proc_attrs<pure>} {
+ return
+ }
+ func.func @_QPsquare() attributes {fir.proc_attrs = #fir.proc_attrs<elemental, pure>} {
+ return
+ }
+ func.func @_QPfactorial() attributes {fir.proc_attrs = #fir.proc_attrs<recursive>} {
+ return
+ }
+}
+
+// CHECK: #di_subprogram = #llvm.di_subprogram<{{.*}}, name = "vector_magnitude",{{.*}}subprogramFlags = "Definition|Pure"
+// CHECK: #di_subprogram1 = #llvm.di_subprogram<{{.*}}, name = "square",{{.*}}subprogramFlags = "Definition|Pure|Elemental"
+// CHECK: #di_subprogram2 = #llvm.di_subprogram<{{.*}}, name = "factorial",{{.*}}subprogramFlags = "Definition|Recursive"
More information about the flang-commits
mailing list