[llvm] [Dwarf][Transforms] Add dwarf support when func signature changed (PR #127855)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 20 12:56:17 PST 2025


https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/127855

>From 6924697fbba479b01c2a946bd7369a0c6f634278 Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Tue, 18 Feb 2025 09:54:08 -0800
Subject: [PATCH] [Dwarf][Transforms] Add dwarf support when func signature
 changed

The goal is to add additional tag/attribute to dwarf so users will know
that function signatures get changed. See [1] for motivation. Otherwise,
users may assume function signature remaining the same as its source,
and bpf tracing may get wrong results. With explicit tag/attribute in
dwarf to indicate a func signature change, for bpf tracing, users will
either go into the asm code to find the exact signature or go to find
another non-signature-change function for tracing, instead of debugging
the otherwise rong results.

Earlier I have a pull request [2] attempts to add suffix to indicate
signature change as gcc did this already. But later upstream suggested
to use dwarf to encode such suffix change info ([1]).

This patch introduced a new tag LLVM_func_args_changed and a new
attr LLVM_func_retval_removed. In DeadArgumentElimination pass, if
a function return value is removed, LLVM_func_retval_removed attr will
be added to that func in the dwarf. In DeadArgumentElimination and
ArgumentPromotion passes, if the function signature is changed,
LLVM_func_args_changed tag is added to dwarf. Here, LLVM_func_args_changed
tag is used so later on, we could add more debug info about what changes.

Regarding to potential more info under LLVM_func_args_changed, we might need
the following info.
  1. Trying to have a new set of formal argument types. The existing types
     should be available in related Transforms passes, but will need DIBuilder
     to build DIType's and looks like there is not easy DIBuilder API to do this.
  2. Trying to relate old func signature (from source) to new func signature.
     For example, original arg index 2 becomes new arg index 1, etc.
     More complexity will come from argument promotion and struct arguments
     where struct argument has size greater than an arch register size.

  [1] https://discourse.llvm.org/t/rfc-identify-func-signature-change-in-llvm-compiled-kernel-image/82609
  [2] https://github.com/llvm/llvm-project/pull/109899
---
 llvm/include/llvm/BinaryFormat/Dwarf.def      |  2 +
 llvm/include/llvm/IR/DebugInfoFlags.def       |  4 +-
 llvm/include/llvm/IR/DebugInfoMetadata.h      |  5 +
 .../CodeGen/AsmPrinter/DwarfCompileUnit.cpp   |  2 +
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp     | 12 +++
 llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h       |  3 +
 llvm/lib/Transforms/IPO/ArgumentPromotion.cpp |  8 ++
 .../IPO/DeadArgumentElimination.cpp           | 10 ++
 llvm/test/DebugInfo/X86/arg-prom.ll           | 95 +++++++++++++++++++
 llvm/test/DebugInfo/X86/arg-retval-elim.ll    | 76 +++++++++++++++
 10 files changed, 216 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/DebugInfo/X86/arg-prom.ll
 create mode 100644 llvm/test/DebugInfo/X86/arg-retval-elim.ll

diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 724a14ccc7aea..de4215e088dd5 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -268,6 +268,7 @@ HANDLE_DW_TAG(0x5111, ALTIUM_rom, 0, ALTIUM, DW_KIND_NONE)
 
 // LLVM
 HANDLE_DW_TAG(0x6000, LLVM_annotation, 0, LLVM, DW_KIND_NONE)
+HANDLE_DW_TAG(0x6001, LLVM_func_args_changed, 0, LLVM, DW_KIND_NONE)
 
 // Green Hills.
 HANDLE_DW_TAG(0x8004, GHS_namespace, 0, GHS, DW_KIND_NONE)
@@ -624,6 +625,7 @@ HANDLE_DW_AT(0x3e09, LLVM_ptrauth_authenticates_null_values, 0, LLVM)
 HANDLE_DW_AT(0x3e0a, LLVM_ptrauth_authentication_mode, 0, LLVM)
 HANDLE_DW_AT(0x3e0b, LLVM_num_extra_inhabitants, 0, LLVM)
 HANDLE_DW_AT(0x3e0c, LLVM_stmt_sequence, 0, LLVM)
+HANDLE_DW_AT(0x3e0d, LLVM_func_retval_removed, 0, LLVM)
 
 // Apple extensions.
 
diff --git a/llvm/include/llvm/IR/DebugInfoFlags.def b/llvm/include/llvm/IR/DebugInfoFlags.def
index df375b6c68e81..e693addab7879 100644
--- a/llvm/include/llvm/IR/DebugInfoFlags.def
+++ b/llvm/include/llvm/IR/DebugInfoFlags.def
@@ -91,11 +91,13 @@ 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), ArgChanged)
+HANDLE_DISP_FLAG((1u << 13), RetvalRemoved)
 
 #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 << 13), Largest)
 #undef DISP_FLAG_LARGEST_NEEDED
 #endif
 
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 8515d8eda8568..73d568b5576b4 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -1907,6 +1907,11 @@ class DISubprogram : public DILocalScope {
 
   DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
 
+  void setArgChanged() { SPFlags |= SPFlagArgChanged; }
+  bool getArgChanged() const { return SPFlags & SPFlagArgChanged; }
+  void setRetvalRemoved() { SPFlags |= SPFlagRetvalRemoved; }
+  bool getRetvalRemoved() const { return SPFlags & SPFlagRetvalRemoved; }
+
   StringRef getName() const { return getStringOperand(2); }
   StringRef getLinkageName() const { return getStringOperand(3); }
   /// Only used by clients of CloneFunction, and only right after the cloning.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index ddf0275ddfe6a..a80d764683db7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1123,6 +1123,8 @@ DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
                                                    MCSymbol *LineTableSym) {
   DIE &ScopeDIE = updateSubprogramScopeDIE(Sub, LineTableSym);
 
+  DwarfUnit::addLLVMChangedArgs(ScopeDIE, Sub);
+
   if (Scope) {
     assert(!Scope->getInlinedAt());
     assert(!Scope->isAbstractScope());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 5347c8a049ba6..7dcc10eccab20 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -654,6 +654,15 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
       ->createTypeDIE(Context, *ContextDIE, Ty);
 }
 
+void DwarfUnit::addLLVMChangedArgs(DIE &ScopeDIE, const DISubprogram *SP) {
+  if (!SP->getArgChanged())
+    return;
+
+  auto *LocalDie =
+      DIE::get(DIEValueAllocator, dwarf::DW_TAG_LLVM_func_args_changed);
+  ScopeDIE.addChild(LocalDie);
+}
+
 void DwarfUnit::updateAcceleratorTables(const DIScope *Context,
                                         const DIType *Ty, const DIE &TyDIE) {
   if (Ty->getName().empty())
@@ -1328,6 +1337,9 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
   if (!SkipSPSourceLocation)
     addSourceLine(SPDie, SP);
 
+  if (SP->getRetvalRemoved())
+    addFlag(SPDie, dwarf::DW_AT_LLVM_func_retval_removed);
+
   // Skip the rest of the attributes under -gmlt to save space.
   if (SkipSPAttributes)
     return;
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 9ddd6f8c14175..49724bcfc87ff 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -324,6 +324,9 @@ class DwarfUnit : public DIEUnit {
   void updateAcceleratorTables(const DIScope *Context, const DIType *Ty,
                                const DIE &TyDIE);
 
+  /// Add DW_TAG_LLVM_func_args_changed.
+  void addLLVMChangedArgs(DIE &ScopeDIE, const DISubprogram *SP);
+
 protected:
   ~DwarfUnit();
 
diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
index c440638884322..e81adb830a86b 100644
--- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
@@ -132,6 +133,7 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
 
   // First, determine the new argument list
   unsigned ArgNo = 0, NewArgNo = 0;
+  bool CurrFuncArgChanged = false;
   for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
        ++I, ++ArgNo) {
     if (!ArgsToPromote.count(&*I)) {
@@ -142,6 +144,7 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
     } else if (I->use_empty()) {
       // Dead argument (which are always marked as promotable)
       ++NumArgumentsDead;
+      CurrFuncArgChanged = true;
       ORE.emit([&]() {
         return OptimizationRemark(DEBUG_TYPE, "ArgumentRemoved", F)
                << "eliminating argument " << ore::NV("ArgName", I->getName())
@@ -156,6 +159,7 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
         ArgAttrVec.push_back(AttributeSet());
       }
       ++NumArgumentsPromoted;
+      CurrFuncArgChanged = true;
       ORE.emit([&]() {
         return OptimizationRemark(DEBUG_TYPE, "ArgumentPromoted", F)
                << "promoting argument " << ore::NV("ArgName", I->getName())
@@ -433,6 +437,10 @@ doPromotion(Function *F, FunctionAnalysisManager &FAM,
     PromoteMemToReg(Allocas, DT, &AC);
   }
 
+  DISubprogram *SP = NF->getSubprogram();
+  if (SP && CurrFuncArgChanged)
+    SP->setArgChanged();
+
   return NF;
 }
 
diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
index ed93b4491c50e..5df3d47daa8dd 100644
--- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -757,6 +757,8 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
   // a new set of parameter attributes to correspond. Skip the first parameter
   // attribute, since that belongs to the return value.
   unsigned ArgI = 0;
+  bool CurrFuncArgEliminated = false;
+  bool CurrFuncRetEliminated = false;
   for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
        ++I, ++ArgI) {
     RetOrArg Arg = createArg(F, ArgI);
@@ -767,6 +769,7 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
       HasLiveReturnedArg |= PAL.hasParamAttr(ArgI, Attribute::Returned);
     } else {
       ++NumArgumentsEliminated;
+      CurrFuncArgEliminated = true;
 
       ORE.emit([&]() {
         return OptimizationRemark(DEBUG_TYPE, "ArgumentRemoved", F)
@@ -818,6 +821,7 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
         NewRetIdxs[Ri] = RetTypes.size() - 1;
       } else {
         ++NumRetValsEliminated;
+        CurrFuncRetEliminated = true;
 
         ORE.emit([&]() {
           return OptimizationRemark(DEBUG_TYPE, "ReturnValueRemoved", F)
@@ -1099,6 +1103,12 @@ bool DeadArgumentEliminationPass::removeDeadStuffFromFunction(Function *F) {
   // to call this function or try to interpret the return value.
   if (NFTy != FTy && NF->getSubprogram()) {
     DISubprogram *SP = NF->getSubprogram();
+
+    if (CurrFuncArgEliminated)
+      SP->setArgChanged();
+    if (CurrFuncRetEliminated)
+      SP->setRetvalRemoved();
+
     auto Temp = SP->getType()->cloneWithCC(llvm::dwarf::DW_CC_nocall);
     SP->replaceType(MDNode::replaceWithPermanent(std::move(Temp)));
   }
diff --git a/llvm/test/DebugInfo/X86/arg-prom.ll b/llvm/test/DebugInfo/X86/arg-prom.ll
new file mode 100644
index 0000000000000..3f2fd543cb6fb
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/arg-prom.ll
@@ -0,0 +1,95 @@
+; RUN: opt -S -passes='default<O3>,argpromotion' < %s | FileCheck %s
+;
+; Source code:
+;   __attribute__((noinline)) static int is_absolute_path(const char *path)
+;   {
+;     return path[0] == '/';
+;   }
+;
+;   void quit(char *buf);
+;   const char *make_nonrelative_path(char *buf, const char *path)
+;   {
+;     if (is_absolute_path(path))
+;       quit(buf);
+;     return buf;
+;   }
+
+define dso_local ptr @make_nonrelative_path(ptr noundef %buf, ptr noundef %path) local_unnamed_addr #0 !dbg !10 {
+    #dbg_value(ptr %buf, !18, !DIExpression(), !20)
+    #dbg_value(ptr %path, !19, !DIExpression(), !20)
+  %3 = call fastcc i32 @is_absolute_path(ptr noundef %path), !dbg !21
+  %4 = icmp eq i32 %3, 0, !dbg !21
+  br i1 %4, label %6, label %5, !dbg !21
+
+5:                                                ; preds = %2
+  call void @quit(ptr noundef %buf), !dbg !23
+  br label %6, !dbg !23
+
+6:                                                ; preds = %5, %2
+  ret ptr %buf, !dbg !24
+}
+
+; Function Attrs: noinline nounwind uwtable
+define internal fastcc range(i32 0, 2) i32 @is_absolute_path(ptr noundef %path) unnamed_addr #1 !dbg !25 {
+    #dbg_value(ptr %path, !30, !DIExpression(), !31)
+  %2 = load i8, ptr %path, align 1, !dbg !32, !tbaa !33
+  %3 = icmp eq i8 %2, 47, !dbg !36
+  %4 = zext i1 %3 to i32, !dbg !36
+  ret i32 %4, !dbg !37
+}
+
+; CHECK: define internal fastcc range(i32 0, 2) i32 @is_absolute_path(i8 {{.*}})
+
+declare !dbg !38 void @quit(ptr noundef) local_unnamed_addr
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git (git at github.com:yonghong-song/llvm-project.git 25cfee009e78194d1f7ca70779d63ef1936cc7b9)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/tests/sig-change/prom", checksumkind: CSK_MD5, checksum: "bcc8cf18726713f5d2ab6d82e8ff459d")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!9 = !{!"clang version 21.0.0git (git at github.com:yonghong-song/llvm-project.git 25cfee009e78194d1f7ca70779d63ef1936cc7b9)"}
+!10 = distinct !DISubprogram(name: "make_nonrelative_path", scope: !1, file: !1, line: 7, type: !11, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13, !16, !13}
+!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64)
+!14 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !15)
+!15 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64)
+!17 = !{!18, !19}
+!18 = !DILocalVariable(name: "buf", arg: 1, scope: !10, file: !1, line: 7, type: !16)
+!19 = !DILocalVariable(name: "path", arg: 2, scope: !10, file: !1, line: 7, type: !13)
+!20 = !DILocation(line: 0, scope: !10)
+!21 = !DILocation(line: 9, column: 7, scope: !22)
+!22 = distinct !DILexicalBlock(scope: !10, file: !1, line: 9, column: 7)
+!23 = !DILocation(line: 10, column: 5, scope: !22)
+!24 = !DILocation(line: 11, column: 3, scope: !10)
+!25 = distinct !DISubprogram(name: "is_absolute_path", scope: !1, file: !1, line: 1, type: !26, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !29)
+
+; CHECK: distinct !DISubprogram(name: "is_absolute_path", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized | DISPFlagArgChanged, unit: ![[#]], retainedNodes: ![[#]])
+
+!26 = !DISubroutineType(types: !27)
+!27 = !{!28, !13}
+!28 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!29 = !{!30}
+!30 = !DILocalVariable(name: "path", arg: 1, scope: !25, file: !1, line: 1, type: !13)
+!31 = !DILocation(line: 0, scope: !25)
+!32 = !DILocation(line: 3, column: 10, scope: !25)
+!33 = !{!34, !34, i64 0}
+!34 = !{!"omnipotent char", !35, i64 0}
+!35 = !{!"Simple C/C++ TBAA"}
+!36 = !DILocation(line: 3, column: 18, scope: !25)
+!37 = !DILocation(line: 3, column: 3, scope: !25)
+!38 = !DISubprogram(name: "quit", scope: !1, file: !1, line: 6, type: !39, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)
+!39 = !DISubroutineType(types: !40)
+!40 = !{null, !16}
diff --git a/llvm/test/DebugInfo/X86/arg-retval-elim.ll b/llvm/test/DebugInfo/X86/arg-retval-elim.ll
new file mode 100644
index 0000000000000..205a51ebe17e3
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/arg-retval-elim.ll
@@ -0,0 +1,76 @@
+; RUN: opt -S -passes='default<O2>,deadargelim' < %s | FileCheck %s
+;
+; Source code:
+;   int tar(int a);
+;   __attribute__((noinline)) static int foo(int a, int b)
+;   {
+;     return tar(a) + tar(a + 1);
+;   }
+;   int bar(int a)
+;   {
+;     foo(a, 1);
+;     return 0;
+;   }
+
+define dso_local noundef i32 @bar(i32 noundef %a) local_unnamed_addr #0 !dbg !10 {
+    #dbg_value(i32 %a, !15, !DIExpression(), !16)
+  %2 = tail call fastcc i32 @foo(i32 noundef %a, i32 noundef 1), !dbg !17
+  ret i32 0, !dbg !18
+}
+
+define internal fastcc i32 @foo(i32 noundef %a, i32 noundef %b) unnamed_addr #1 !dbg !19 {
+    #dbg_value(i32 %a, !23, !DIExpression(), !25)
+    #dbg_value(i32 %b, !24, !DIExpression(), !25)
+  %3 = tail call i32 @tar(i32 noundef %a), !dbg !26
+  %4 = add nsw i32 %a, 1, !dbg !27
+  %5 = tail call i32 @tar(i32 noundef %4), !dbg !28
+  %6 = add nsw i32 %5, %3, !dbg !29
+  ret i32 %6, !dbg !30
+}
+
+; CHECK: define internal fastcc void @foo(i32 noundef %a)
+
+declare !dbg !31 i32 @tar(i32 noundef) local_unnamed_addr
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git (git at github.com:yonghong-song/llvm-project.git 25cfee009e78194d1f7ca70779d63ef1936cc7b9)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/tests/sig-change/deadret", checksumkind: CSK_MD5, checksum: "728d225e6425c104712ae21cee1db99b")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!9 = !{!"clang version 21.0.0git (git at github.com:yonghong-song/llvm-project.git 25cfee009e78194d1f7ca70779d63ef1936cc7b9)"}
+!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 6, type: !11, scopeLine: 7, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13, !13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{!15}
+!15 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 6, type: !13)
+!16 = !DILocation(line: 0, scope: !10)
+!17 = !DILocation(line: 8, column: 3, scope: !10)
+!18 = !DILocation(line: 9, column: 3, scope: !10)
+!19 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !20, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !22)
+
+; CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized | DISPFlagArgChanged | DISPFlagRetvalRemoved, unit: !0, retainedNodes: ![[#]])
+
+!20 = !DISubroutineType(types: !21)
+!21 = !{!13, !13, !13}
+!22 = !{!23, !24}
+!23 = !DILocalVariable(name: "a", arg: 1, scope: !19, file: !1, line: 2, type: !13)
+!24 = !DILocalVariable(name: "b", arg: 2, scope: !19, file: !1, line: 2, type: !13)
+!25 = !DILocation(line: 0, scope: !19)
+!26 = !DILocation(line: 4, column: 10, scope: !19)
+!27 = !DILocation(line: 4, column: 25, scope: !19)
+!28 = !DILocation(line: 4, column: 19, scope: !19)
+!29 = !DILocation(line: 4, column: 17, scope: !19)
+!30 = !DILocation(line: 4, column: 3, scope: !19)
+!31 = !DISubprogram(name: "tar", scope: !1, file: !1, line: 1, type: !11, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized)



More information about the llvm-commits mailing list