[clang] [llvm] [clang] Add "debug_transparent" attribute (PR #110188)
Augusto Noronha via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 1 12:58:56 PDT 2024
https://github.com/augusto2112 updated https://github.com/llvm/llvm-project/pull/110188
>From 807fc9a690555930ef0c047f0c4253c6204376a9 Mon Sep 17 00:00:00 2001
From: Augusto Noronha <augusto2112 at me.com>
Date: Thu, 30 Mar 2023 14:01:36 -0700
Subject: [PATCH] [clang] Add "debug_transparent" attribute
The `debug_transparent` attribute is intended as a hint for
debuggers that this function itself is not interesting, but it calls a
function that might be. So, when stepping in arrives at a function
with this attribute, debuggers should transparently step-in through it
into the functions called by the annotated function (but not by
subsequent calls made by those functions), stopping at the first one its
normal rules for whether to stop says to stop at - or stepping out again
if none qualify. Also, when stepping out arrives at a function with this
attribute, the debugger should continue stepping out to its caller.
---
clang/docs/ReleaseNotes.rst | 4 ++
clang/include/clang/Basic/Attr.td | 7 +++
clang/include/clang/Basic/AttrDocs.td | 60 +++++++++++++++++++
.../clang/Basic/DiagnosticCommonKinds.td | 2 +
clang/lib/CodeGen/CGDebugInfo.cpp | 17 ++++++
.../CodeGen/attr-debug-transparent-cxx.cpp | 37 ++++++++++++
.../attr-debug-transparent-method-warning.cpp | 14 +++++
.../attr-debug-transparent-no-warning.c | 10 ++++
.../attr-debug-transparent-objc-warning.m | 12 ++++
.../CodeGen/attr-debug-transparent-objc.m | 13 ++++
.../CodeGen/attr-debug-transparent-warning.c | 9 +++
clang/test/CodeGen/attr-debug-transparent.c | 10 ++++
...a-attribute-supported-attributes-list.test | 1 +
clang/test/Sema/attr-debug-transparent.c | 7 +++
.../SemaCXX/attr-debug-transparent-method.cpp | 11 ++++
.../SemaObjC/attr-debug-transparent-objc.m | 9 +++
llvm/include/llvm/IR/DebugInfoFlags.def | 3 +-
llvm/include/llvm/IR/DebugInfoMetadata.h | 3 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 5 ++
.../disubprogram-debug-transparent.ll | 39 ++++++++++++
.../AArch64/disubprogram-debug-transparent.ll | 42 +++++++++++++
llvm/unittests/IR/MetadataTest.cpp | 7 +++
22 files changed, 321 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGen/attr-debug-transparent-cxx.cpp
create mode 100644 clang/test/CodeGen/attr-debug-transparent-method-warning.cpp
create mode 100644 clang/test/CodeGen/attr-debug-transparent-no-warning.c
create mode 100644 clang/test/CodeGen/attr-debug-transparent-objc-warning.m
create mode 100644 clang/test/CodeGen/attr-debug-transparent-objc.m
create mode 100644 clang/test/CodeGen/attr-debug-transparent-warning.c
create mode 100644 clang/test/CodeGen/attr-debug-transparent.c
create mode 100644 clang/test/Sema/attr-debug-transparent.c
create mode 100644 clang/test/SemaCXX/attr-debug-transparent-method.cpp
create mode 100644 clang/test/SemaObjC/attr-debug-transparent-objc.m
create mode 100644 llvm/test/Assembler/disubprogram-debug-transparent.ll
create mode 100644 llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 34d2b584274a5f..63a65bec74b1aa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -299,6 +299,10 @@ Attribute Changes in Clang
- Fix a bug where clang doesn't automatically apply the ``[[gsl::Owner]]`` or
``[[gsl::Pointer]]`` to STL explicit template specialization decls. (#GH109442)
+- Introduced a new function attribute ``__attribute__((debug_transparent))``
+ which is intended as a hint to debuggers that they should not stop at the annotated
+ function, but instead step through it when stepping in, and continuing directly to
+ its caller when stepping out.
Improvements to Clang's diagnostics
-----------------------------------
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index fbcbf0ed416416..3b6c8cb409e8a0 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -876,6 +876,13 @@ def Artificial : InheritableAttr {
let SimpleHandler = 1;
}
+def DebugTransparent: InheritableAttr {
+ let Spellings = [Clang<"debug_transparent">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
+ let Documentation = [DebugTransparentDocs];
+ let SimpleHandler = 1;
+}
+
def XRayInstrument : InheritableAttr {
let Spellings = [Clang<"xray_always_instrument">,
Clang<"xray_never_instrument">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 53d88482698f00..81a062a5d72a56 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7866,6 +7866,66 @@ As such, this function attribute is currently only supported on X86 targets.
}];
}
+def DebugTransparentDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``debug_transparent`` attribute is intended as a hint for debuggers that this
+function itself is not interesting, but it calls a function that might be. So, when
+stepping in arrives at a function with this attribute, debuggers should transparently
+step-in through it into the functions called by the annotated function (but not by
+subsequent calls made by those functions), stopping at the first one its normal rules
+for whether to stop says to stop at - or stepping out again if none qualify. Also, when
+stepping out arrives at a function with this attribute, the debugger should continue
+stepping out to its caller. This attribute is currently only supported by DWARF.
+
+For example:
+
+.. code-block:: c
+
+ int bar(void) {
+ return 42;
+ }
+
+ __attribute__((debug_transparent))
+ int foo(void) {
+ return bar();
+ }
+
+ int caller(void) {
+ return foo();
+ }
+
+Stepping into ``foo`` should step directly into ``bar`` instead, and stepping out of ``bar``
+should stop in ``caller``.
+
+Functions with the ``debug_transparent`` attribute can be chained together:
+
+.. code-block:: c
+
+ int baz(void) {
+ return 42;
+ }
+
+ __attribute__((debug_transparent))
+ int bar(void) {
+ return baz();
+ }
+
+ __attribute__((debug_transparent))
+ int foo(void) {
+ return bar();
+ }
+
+ int caller(void) {
+ return foo();
+ }
+
+In this example, stepping into ``foo`` should step directly into ``baz``, and stepping out of
+``baz`` should stop in ``caller``.
+ }];
+}
+
+
def ReadOnlyPlacementDocs : Documentation {
let Category = DocCatType;
let Content = [{This attribute is attached to a structure, class or union declaration.
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index ae709e45a700a1..e9cb8a9aaadfe2 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -467,4 +467,6 @@ def warn_try_not_valid_on_target : Warning<
"target '%0' does not support exception handling;"
" 'catch' block is ignored">,
InGroup<OpenMPTargetException>;
+def warn_debug_transparent_ignored : Warning<
+ "'debug_transparent' attribute is ignored since it is only supported by DWARF">;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 8887c4de7c4c81..396a7b141fa497 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -21,6 +21,7 @@
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/Attrs.inc"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
@@ -109,6 +110,20 @@ static bool IsArtificial(VarDecl const *VD) {
cast<Decl>(VD->getDeclContext())->isImplicit());
}
+static bool usesDebugTransparent(const Decl *D, const CodeGenModule &CGM) {
+ if (!D)
+ return false;
+
+ if (auto *attr = D->getAttr<DebugTransparentAttr>()) {
+ if (CGM.getCodeGenOpts().DwarfVersion == 0)
+ CGM.getDiags().Report(attr->getLocation(),
+ diag::warn_debug_transparent_ignored);
+ return true;
+ }
+
+ return false;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
@@ -4480,6 +4495,8 @@ void CGDebugInfo::emitFunctionStart(GlobalDecl GD, SourceLocation Loc,
SPFlags |= llvm::DISubprogram::SPFlagLocalToUnit;
if (CGM.getLangOpts().Optimize)
SPFlags |= llvm::DISubprogram::SPFlagOptimized;
+ if (usesDebugTransparent(D, CGM))
+ SPFlags |= llvm::DISubprogram::SPFlagIsDebugTransparent;
llvm::DINode::DIFlags FlagsForDef = Flags | getCallSiteRelatedAttrs();
llvm::DISubprogram::DISPFlags SPFlagsForDef =
diff --git a/clang/test/CodeGen/attr-debug-transparent-cxx.cpp b/clang/test/CodeGen/attr-debug-transparent-cxx.cpp
new file mode 100644
index 00000000000000..e8cc7a35312ad3
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-cxx.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s
+
+void foo(void) {}
+
+struct A {
+ [[clang::debug_transparent()]]
+ A() {
+ foo();
+ }
+
+ [[clang::debug_transparent()]]
+ ~A() {
+ foo();
+ }
+[[clang::debug_transparent()]]
+void method(void) {
+ foo();
+}
+
+[[clang::always_inline()]]
+[[clang::debug_transparent()]]
+void inline_method(void) {
+ foo();
+}
+
+};
+
+int main() {
+ auto a = A();
+ a.method();
+ a.inline_method();
+}
+
+// CHECK: DISubprogram(name: "inline_method"{{.*}} DISPFlagIsDebugTransparent
+// CHECK: DISubprogram(name: "method"{{.*}} DISPFlagIsDebugTransparent
+// CHECK: DISubprogram(name: "A"{{.*}} DISPFlagIsDebugTransparent
+// CHECK: DISubprogram(name: "~A"{{.*}} DISPFlagIsDebugTransparent
diff --git a/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp b/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp
new file mode 100644
index 00000000000000..71b8617d46bd2c
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-method-warning.cpp
@@ -0,0 +1,14 @@
+// Pipe stderr to FileCheck since we're checking for a warning
+// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s
+
+
+struct S {
+[[clang::debug_transparent]]
+void foo(void) {}
+};
+
+int main() {
+ S s;
+ s.foo();
+}
+// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF
diff --git a/clang/test/CodeGen/attr-debug-transparent-no-warning.c b/clang/test/CodeGen/attr-debug-transparent-no-warning.c
new file mode 100644
index 00000000000000..d49f1ce0bb4a82
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-no-warning.c
@@ -0,0 +1,10 @@
+// Pipe stderr to FileCheck since we're checking for a warning
+// RUN: %clang -gcodeview -emit-llvm -S %s -o - 2>&1 | FileCheck %s
+
+
+__attribute__((debug_transparent))
+void foo(void) {}
+
+// Check that the warning is NOT printed when compiling without debug information.
+// CHECK-NOT: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF
+
diff --git a/clang/test/CodeGen/attr-debug-transparent-objc-warning.m b/clang/test/CodeGen/attr-debug-transparent-objc-warning.m
new file mode 100644
index 00000000000000..ff43bd46c5975c
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-objc-warning.m
@@ -0,0 +1,12 @@
+// Pipe stderr to FileCheck since we're checking for a warning
+// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s
+
+ at interface ObjCClass
+- (void)foo __attribute__((debug_transparent));
+ at end
+
+ at implementation ObjCClass
+- (void)foo {}
+ at end
+
+// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF
diff --git a/clang/test/CodeGen/attr-debug-transparent-objc.m b/clang/test/CodeGen/attr-debug-transparent-objc.m
new file mode 100644
index 00000000000000..4b1450ff4311c7
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-objc.m
@@ -0,0 +1,13 @@
+// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s
+
+
+ at interface ObjCClass
+- (void)foo __attribute__((debug_transparent));
+ at end
+
+ at implementation ObjCClass
+- (void)foo {}
+ at end
+
+
+// CHECK: DISubprogram(name: "-[ObjCClass foo]"{{.*}} DISPFlagIsDebugTransparent
diff --git a/clang/test/CodeGen/attr-debug-transparent-warning.c b/clang/test/CodeGen/attr-debug-transparent-warning.c
new file mode 100644
index 00000000000000..ef3e931e3bab82
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent-warning.c
@@ -0,0 +1,9 @@
+// Pipe stderr to FileCheck since we're checking for a warning
+// RUN: %clang -gcodeview -g -emit-llvm -S %s -o - 2>&1 | FileCheck %s
+
+
+__attribute__((debug_transparent))
+void foo(void) {}
+
+// CHECK: warning: 'debug_transparent' attribute is ignored since it is only supported by DWARF
+
diff --git a/clang/test/CodeGen/attr-debug-transparent.c b/clang/test/CodeGen/attr-debug-transparent.c
new file mode 100644
index 00000000000000..03af1366723af7
--- /dev/null
+++ b/clang/test/CodeGen/attr-debug-transparent.c
@@ -0,0 +1,10 @@
+// RUN: %clang -gdwarf -emit-llvm -S %s -o - | FileCheck %s
+
+void bar(void) {}
+
+__attribute__((debug_transparent))
+void foo(void) {
+ bar();
+}
+
+// CHECK: DISubprogram(name: "foo"{{.*}} DISPFlagIsDebugTransparent
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 914f94c08a9fd9..d5e8094ec6fe32 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -68,6 +68,7 @@
// CHECK-NEXT: CoroWrapper (SubjectMatchRule_function)
// CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface)
// CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface)
+// CHECK-NEXT: DebugTransparent (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: Destructor (SubjectMatchRule_function)
// CHECK-NEXT: DiagnoseAsBuiltin (SubjectMatchRule_function)
// CHECK-NEXT: DisableSanitizerInstrumentation (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global)
diff --git a/clang/test/Sema/attr-debug-transparent.c b/clang/test/Sema/attr-debug-transparent.c
new file mode 100644
index 00000000000000..98b2d4357a99ee
--- /dev/null
+++ b/clang/test/Sema/attr-debug-transparent.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+__attribute__((debug_transparent))
+void correct(void) {}
+
+__attribute__((debug_transparent(1))) // expected-error {{'debug_transparent' attribute takes no arguments}}
+void wrong_arg(void) {}
diff --git a/clang/test/SemaCXX/attr-debug-transparent-method.cpp b/clang/test/SemaCXX/attr-debug-transparent-method.cpp
new file mode 100644
index 00000000000000..b19da619742f4e
--- /dev/null
+++ b/clang/test/SemaCXX/attr-debug-transparent-method.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+
+struct S {
+[[clang::debug_transparent]]
+void correct(void) {}
+
+[[clang::debug_transparent(1)]] // expected-error {{'debug_transparent' attribute takes no arguments}}
+void one_arg(void) {}
+};
+
diff --git a/clang/test/SemaObjC/attr-debug-transparent-objc.m b/clang/test/SemaObjC/attr-debug-transparent-objc.m
new file mode 100644
index 00000000000000..1fbde59ecb9350
--- /dev/null
+++ b/clang/test/SemaObjC/attr-debug-transparent-objc.m
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+
+
+
+ at interface ObjCClass
+- (void)correct __attribute__((debug_transparent));
+- (void)one_arg __attribute__((debug_transparent(1))); // expected-error {{'debug_transparent' attribute takes no arguments}}
+ at end
+
diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def
index df375b6c68e810..9903580fb95502 100644
--- a/llvm/include/llvm/IR/DebugInfoFlags.def
+++ b/llvm/include/llvm/IR/DebugInfoFlags.def
@@ -91,11 +91,12 @@ HANDLE_DISP_FLAG((1u << 8), MainSubprogram)
// for defaulted functions
HANDLE_DISP_FLAG((1u << 9), Deleted)
HANDLE_DISP_FLAG((1u << 11), ObjCDirect)
+HANDLE_DISP_FLAG((1u << 12), IsDebugTransparent)
#ifdef DISP_FLAG_LARGEST_NEEDED
// Intended to be used with ADT/BitmaskEnum.h.
// NOTE: Always must be equal to largest flag, check this when adding new flags.
-HANDLE_DISP_FLAG((1 << 11), Largest)
+HANDLE_DISP_FLAG((1 << 12), Largest)
#undef DISP_FLAG_LARGEST_NEEDED
#endif
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index d2b4e900438d37..80d0c9e57b23de 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -1830,6 +1830,9 @@ class DISubprogram : public DILocalScope {
bool isElemental() const { return getSPFlags() & SPFlagElemental; }
bool isRecursive() const { return getSPFlags() & SPFlagRecursive; }
bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; }
+ bool isDebugTransparent() const {
+ return getSPFlags() & SPFlagIsDebugTransparent;
+ }
/// Check if this is deleted member function.
///
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index e76b0fe2081c07..bde716c862036c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1260,6 +1260,9 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,
(DD->useAllLinkageNames() || DU->getAbstractScopeDIEs().lookup(SP)))
addLinkageName(SPDie, LinkageName);
+ if (SP->isDebugTransparent())
+ addFlag(SPDie, dwarf::DW_AT_trampoline);
+
if (!DeclDie)
return false;
@@ -1378,6 +1381,8 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
if (!SP->getTargetFuncName().empty())
addString(SPDie, dwarf::DW_AT_trampoline, SP->getTargetFuncName());
+ else if (SP->isDebugTransparent())
+ addFlag(SPDie, dwarf::DW_AT_trampoline);
if (DD->getDwarfVersion() >= 5 && SP->isDeleted())
addFlag(SPDie, dwarf::DW_AT_deleted);
diff --git a/llvm/test/Assembler/disubprogram-debug-transparent.ll b/llvm/test/Assembler/disubprogram-debug-transparent.ll
new file mode 100644
index 00000000000000..316d6d367809cf
--- /dev/null
+++ b/llvm/test/Assembler/disubprogram-debug-transparent.ll
@@ -0,0 +1,39 @@
+; This test verifies that the DISPFlagIsDebugTransparent attribute in a DISubprogram
+; is assembled/disassembled correctly.
+;
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+;
+; CHECK: !DISubprogram(name: "baz",{{.*}} DISPFlagIsDebugTransparent
+;
+; ModuleID = 't.c'
+source_filename = "t.c"
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-apple-macosx13.0.0"
+
+; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
+define void @baz() #0 !dbg !10 {
+entry:
+ ret void, !dbg !14
+}
+
+attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
+!llvm.dbg.cu = !{!7}
+!llvm.ident = !{!9}
+
+!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 2]}
+!1 = !{i32 7, !"Dwarf Version", i32 4}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !{i32 1, !"wchar_size", i32 4}
+!4 = !{i32 8, !"PIC Level", i32 2}
+!5 = !{i32 7, !"uwtable", i32 1}
+!6 = !{i32 7, !"frame-pointer", i32 1}
+!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 17.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!8 = !DIFile(filename: "t.c", directory: "/")
+!9 = !{!"clang version 17.0.0"}
+!10 = distinct !DISubprogram(name: "baz", scope: !8, file: !8, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagIsDebugTransparent, unit: !7, retainedNodes: !13)
+!11 = !DISubroutineType(types: !12)
+!12 = !{null}
+!13 = !{}
+!14 = !DILocation(line: 4, column: 1, scope: !10)
diff --git a/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll b/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll
new file mode 100644
index 00000000000000..65facbb4a36955
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/disubprogram-debug-transparent.ll
@@ -0,0 +1,42 @@
+; This test verifies that the proper DWARF debug info is emitted
+; for a trampoline function with no target.
+;
+; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
+;
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_AT_name ("baz")
+; CHECK: DW_AT_trampoline (true)
+;
+; ModuleID = 't.c'
+source_filename = "t.c"
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-apple-macosx13.0.0"
+
+; Function Attrs: noinline nounwind optnone ssp uwtable(sync)
+define void @baz() #0 !dbg !10 {
+entry:
+ ret void, !dbg !14
+}
+
+attributes #0 = { noinline nounwind optnone ssp uwtable(sync) "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-m1" "target-features"="+aes,+crc,+dotprod,+fp-armv8,+fp16fml,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+sha2,+sha3,+v8.1a,+v8.2a,+v8.3a,+v8.4a,+v8.5a,+v8a,+zcm,+zcz" }
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6}
+!llvm.dbg.cu = !{!7}
+!llvm.ident = !{!9}
+
+!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 13, i32 2]}
+!1 = !{i32 7, !"Dwarf Version", i32 4}
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = !{i32 1, !"wchar_size", i32 4}
+!4 = !{i32 8, !"PIC Level", i32 2}
+!5 = !{i32 7, !"uwtable", i32 1}
+!6 = !{i32 7, !"frame-pointer", i32 1}
+!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 17.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!8 = !DIFile(filename: "t.c", directory: "/")
+!9 = !{!"clang version 17.0.0"}
+!10 = distinct !DISubprogram(name: "baz", scope: !8, file: !8, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagIsDebugTransparent, unit: !7, retainedNodes: !13)
+!11 = !DISubroutineType(types: !12)
+!12 = !{null}
+!13 = !{}
+!14 = !DILocation(line: 4, column: 1, scope: !10)
+
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 778fd4d4994f44..dbe38aa323b38b 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -2553,6 +2553,7 @@ TEST_F(DISubprogramTest, get) {
assert(!IsLocalToUnit && IsDefinition && !IsOptimized &&
"bools and SPFlags have to match");
SPFlags |= DISubprogram::SPFlagDefinition;
+ SPFlags |= DISubprogram::SPFlagIsDebugTransparent;
auto *N = DISubprogram::get(
Context, Scope, Name, LinkageName, File, Line, Type, ScopeLine,
@@ -2636,6 +2637,12 @@ TEST_F(DISubprogramTest, get) {
Flags, SPFlags ^ DISubprogram::SPFlagDefinition, Unit,
TemplateParams, Declaration, RetainedNodes, ThrownTypes,
Annotations, TargetFuncName));
+ EXPECT_NE(N, DISubprogram::get(
+ Context, Scope, Name, LinkageName, File, Line, Type,
+ ScopeLine, ContainingType, VirtualIndex, ThisAdjustment,
+ Flags, SPFlags ^ DISubprogram::SPFlagIsDebugTransparent,
+ Unit, TemplateParams, Declaration, RetainedNodes,
+ ThrownTypes, Annotations, TargetFuncName));
EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
Type, ScopeLine + 1, ContainingType,
VirtualIndex, ThisAdjustment, Flags, SPFlags,
More information about the cfe-commits
mailing list