[llvm] dd1bc59 - [CSInfo][MIPS][DwarfDebug] Add support for delay slots

Djordje Todorovic via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 02:26:14 PDT 2020


Author: Djordje Todorovic
Date: 2020-06-03T11:25:17+02:00
New Revision: dd1bc59b729a31d6c0fe3aecc8559b9349363bf9

URL: https://github.com/llvm/llvm-project/commit/dd1bc59b729a31d6c0fe3aecc8559b9349363bf9
DIFF: https://github.com/llvm/llvm-project/commit/dd1bc59b729a31d6c0fe3aecc8559b9349363bf9.diff

LOG: [CSInfo][MIPS][DwarfDebug] Add support for delay slots

This adds call site info support for call instructions with delay slot.
Search for instructions inside call delay slot, which load value
into parameter forwarding registers.
Return address of the call points to instruction after call delay slot,
which is not the one, immediately after the call instruction.

Patch by Nikola Tesic

Differential revision: https://reviews.llvm.org/D78107

Added: 
    llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation-64bit.mir
    llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation.mir
    llvm/test/DebugInfo/Mips/dbg-call-site-low-pc.ll

Modified: 
    llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index a1ac00dec719..67504f827d63 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -752,6 +752,10 @@ static bool interpretNextInstr(const MachineInstr *CurMI,
   if (ForwardedRegWorklist.empty())
     return false;
 
+  // Avoid NOP description.
+  if (CurMI->getNumOperands() == 0)
+    return true;
+
   interpretValues(CurMI, ForwardedRegWorklist, Params);
 
   return true;
@@ -798,6 +802,18 @@ static void collectCallSiteParameters(const MachineInstr *CallMI,
   // as the entry value within basic blocks other than the first one.
   bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin();
 
+  // Search for a loading value in forwarding registers inside call delay slot.
+  if (CallMI->hasDelaySlot()) {
+    auto Suc = std::next(CallMI->getIterator());
+    // Only one-instruction delay slot is supported.
+    auto BundleEnd = llvm::getBundleEnd(CallMI->getIterator());
+    assert(std::next(Suc) == BundleEnd &&
+           "More than one instruction in call delay slot");
+    // Try to interpret value loaded by instruction.
+    if (!interpretNextInstr(&*Suc, ForwardedRegWorklist, Params))
+      return;
+  }
+
   // Search for a loading value in forwarding registers.
   for (; I != MBB->rend(); ++I) {
     // Try to interpret values loaded by instruction.
@@ -834,6 +850,23 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
   assert(TII && "TargetInstrInfo not found: cannot label tail calls");
 
+  // Delay slot support check.
+  auto delaySlotSupported = [&](const MachineInstr &MI) {
+    if (!MI.isBundledWithSucc())
+      return false;
+    auto Suc = std::next(MI.getIterator());
+    auto CallInstrBundle = getBundleStart(MI.getIterator());
+    auto DelaySlotBundle = getBundleStart(Suc);
+    // Ensure that label after call is following delay slot instruction.
+    // Ex. CALL_INSTRUCTION {
+    //       DELAY_SLOT_INSTRUCTION }
+    //      LABEL_AFTER_CALL
+    assert(getLabelAfterInsn(&*CallInstrBundle) ==
+               getLabelAfterInsn(&*DelaySlotBundle) &&
+           "Call and its successor instruction don't have same label after.");
+    return true;
+  };
+
   // Emit call site entries for each call or tail call in the function.
   for (const MachineBasicBlock &MBB : MF) {
     for (const MachineInstr &MI : MBB.instrs()) {
@@ -853,8 +886,8 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
       if (MI.getFlag(MachineInstr::FrameSetup))
         continue;
 
-      // TODO: Add support for targets with delay slots (see: beginInstruction).
-      if (MI.hasDelaySlot())
+      // Check if delay slot support is enabled.
+      if (MI.hasDelaySlot() && !delaySlotSupported(*&MI))
         return;
 
       // If this is a direct call, find the callee's subprogram.
@@ -1855,11 +1888,23 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
   bool NoDebug =
       !SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug;
 
+  // Delay slot support check.
+  auto delaySlotSupported = [](const MachineInstr &MI) {
+    if (!MI.isBundledWithSucc())
+      return false;
+    auto Suc = std::next(MI.getIterator());
+    // Ensure that delay slot instruction is successor of the call instruction.
+    // Ex. CALL_INSTRUCTION {
+    //        DELAY_SLOT_INSTRUCTION }
+    assert(Suc->isBundledWithPred() &&
+           "Call bundle instructions are out of order");
+    return true;
+  };
+
   // When describing calls, we need a label for the call instruction.
-  // TODO: Add support for targets with delay slots.
   if (!NoDebug && SP->areAllCallsDescribed() &&
       MI->isCandidateForCallSiteEntry(MachineInstr::AnyInBundle) &&
-      !MI->hasDelaySlot()) {
+      (!MI->hasDelaySlot() || delaySlotSupported(*MI))) {
     const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
     bool IsTail = TII->isTailCall(*MI);
     // For tail calls, we need the address of the branch instruction for

diff  --git a/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation-64bit.mir b/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation-64bit.mir
new file mode 100644
index 000000000000..f36cd43b335b
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation-64bit.mir
@@ -0,0 +1,129 @@
+## Test mips64:
+# RUN: llc -emit-call-site-info -start-after=machineverifier -filetype=obj -mtriple=mips64-linux-gnu %s -o -| llvm-dwarfdump -| FileCheck %s
+## Test mips64el:
+# RUN: llc -emit-call-site-info -start-after=machineverifier -filetype=obj -mtriple=mips64el-linux-gnu %s -o -| llvm-dwarfdump -| FileCheck %s
+
+## Built from source:
+## extern int __attribute__((noinline)) sum(int a, int b);
+## void __attribute__((noinline)) set(int *adr, int val) {
+##   val++;
+##   *adr = val + sum(val, val);
+## }
+## Using command:
+## clang -g -O2 -target mips64-linux-gnu m.c -c -mllvm -stop-before=machineverifier
+## Check that call site interpretation analysis can interpret calls with delay slot and
+## parameters set outside and inside of the call delay slot.
+
+## Test mips64:
+# CHECK:        DW_TAG_GNU_call_site
+# CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "sum"
+# CHECK-NEXT:     DW_AT_low_pc
+# CHECK-EMPTY:
+## Parameter forwarding register A1_64 is set in call delay slot.
+# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:       DW_AT_location      (DW_OP_reg5 A1_64)
+# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg17 S1_64+0)
+# CHECK-EMPTY:
+# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:       DW_AT_location      (DW_OP_reg4 A0_64)
+# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg17 S1_64+0)
+
+--- |
+  ; ModuleID = 'm.ll'
+  source_filename = "m.c"
+  target datalayout = "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"
+  target triple = "mips64-unknown-linux-gnu"
+  ; Function Attrs: noinline nounwind
+  define void @set(i32* nocapture %adr, i32 signext %val) local_unnamed_addr !dbg !13 {
+  entry:
+    call void @llvm.dbg.value(metadata i32* %adr, metadata !18, metadata !DIExpression()), !dbg !20
+    call void @llvm.dbg.value(metadata i32 %val, metadata !19, metadata !DIExpression()), !dbg !20
+    %inc = add nsw i32 %val, 1, !dbg !20
+    call void @llvm.dbg.value(metadata i32 %inc, metadata !19, metadata !DIExpression()), !dbg !20
+    %call = tail call signext i32 @sum(i32 signext %inc, i32 signext %inc), !dbg !20
+    %add = add nsw i32 %call, %inc, !dbg !20
+    store i32 %add, i32* %adr, align 4, !dbg !20
+    ret void
+  }
+
+  declare !dbg !4 signext i32 @sum(i32 signext, i32 signext) local_unnamed_addr
+
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!8, !9, !10, !11}
+  !llvm.ident = !{!12}
+
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "m.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "sum", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{!7, !7, !7}
+  !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !8 = !{i32 7, !"Dwarf Version", i32 4}
+  !9 = !{i32 2, !"Debug Info Version", i32 3}
+  !10 = !{i32 1, !"wchar_size", i32 4}
+  !11 = !{i32 7, !"PIC Level", i32 1}
+  !12 = !{!"clang version 11.0.0"}
+  !13 = distinct !DISubprogram(name: "set", scope: !1, file: !1, line: 2, type: !14, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17)
+  !14 = !DISubroutineType(types: !15)
+  !15 = !{null, !16, !7}
+  !16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+  !17 = !{!18, !19}
+  !18 = !DILocalVariable(name: "adr", arg: 1, scope: !13, file: !1, line: 2, type: !16)
+  !19 = !DILocalVariable(name: "val", arg: 2, scope: !13, file: !1, line: 2, type: !7)
+  !20 = !DILocation(line: 0, scope: !13)
+
+...
+---
+name:            set
+alignment:       8
+stack:
+  - { id: 0, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8,
+      stack-id: default, callee-saved-register: '$ra_64', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8,
+      stack-id: default, callee-saved-register: '$s1_64', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 2, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8,
+      stack-id: default, callee-saved-register: '$s0_64', callee-saved-restored: true,
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+callSites:
+  - { bb: 0, offset: 17, fwdArgRegs:
+      - { arg: 0, reg: '$a0_64' }
+      - { arg: 1, reg: '$a1_64' } }
+body:             |
+  bb.0.entry:
+    DBG_VALUE $a0_64, $noreg, !18, !DIExpression(), debug-location !20
+    DBG_VALUE $a1_64, $noreg, !19, !DIExpression(), debug-location !20
+    DBG_VALUE $a1_64, $noreg, !19, !DIExpression(), debug-location !20
+    $sp_64 = DADDiu $sp_64, -32
+    CFI_INSTRUCTION def_cfa_offset 32
+    SD killed $ra_64, $sp_64, 24 :: (store 8 into %stack.0)
+    SD killed $s1_64, $sp_64, 16 :: (store 8 into %stack.1)
+    SD killed $s0_64, $sp_64, 8 :: (store 8 into %stack.2)
+    CFI_INSTRUCTION offset $ra_64, -8
+    CFI_INSTRUCTION offset $s1_64, -16
+    CFI_INSTRUCTION offset $s0_64, -24
+    $s0_64 = OR64 $a0_64, $zero_64
+    DBG_VALUE $a1, $noreg, !19, !DIExpression(), debug-location !20
+    DBG_VALUE $s0_64, $noreg, !18, !DIExpression(), debug-location !20
+    renamable $s1 = ADDiu renamable $a1, 1, implicit killed $a1_64, implicit-def $s1_64, debug-location !20
+    DBG_VALUE $s1, $noreg, !19, !DIExpression(), debug-location !20
+    $a0_64 = OR64 $s1_64, $zero_64, debug-location !20
+    JAL @sum, csr_n64, implicit-def dead $ra, implicit $a0_64, implicit $a1_64, implicit-def $sp, implicit-def $v0, debug-location !20 {
+      $a1_64 = OR64 $s1_64, $zero_64, debug-location !20
+    }
+    renamable $at = nsw ADDu killed renamable $v0, renamable $s1, implicit killed $s1_64, debug-location !20
+    SW killed renamable $at, killed renamable $s0_64, 0
+    $s0_64 = LD $sp_64, 8
+    $s1_64 = LD $sp_64, 16
+    $ra_64 = LD $sp_64, 24
+    PseudoReturn64 undef $ra_64 {
+      $sp_64 = DADDiu $sp_64, 32
+    }
+
+...

diff  --git a/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation.mir b/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation.mir
new file mode 100644
index 000000000000..cd42f92ca603
--- /dev/null
+++ b/llvm/test/DebugInfo/MIR/Mips/dbg-call-site-delay-slot-interpretation.mir
@@ -0,0 +1,127 @@
+## Test mips32:
+# RUN: llc -emit-call-site-info -start-after=machineverifier -filetype=obj -mtriple=mips-linux-gnu %s -o -| llvm-dwarfdump -| FileCheck %s
+## Test mipsel:
+# RUN: llc -emit-call-site-info -start-after=machineverifier -filetype=obj -mtriple=mipsel-linux-gnu %s -o -| llvm-dwarfdump -| FileCheck %s
+
+## Built from source:
+## extern int __attribute__((noinline)) sum(int a, int b);
+## void __attribute__((noinline)) set(int *adr, int val) {
+##   val++;
+##   *adr = val + sum(val, val);
+## }
+## Using command:
+## clang -g -O2 -target mips-linux-gnu m.c -c -mllvm -stop-before=machineverifier
+## Check that call site interpretation analysis can interpret calls with delay slot and
+## parameters set outside and inside of the call delay slot.
+
+## Test mips32:
+# CHECK:        DW_TAG_GNU_call_site
+# CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "sum"
+# CHECK-NEXT:     DW_AT_low_pc
+# CHECK-EMPTY:
+## Parameter forwarding register A1_64 is set in call delay slot.
+# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:       DW_AT_location      (DW_OP_reg5 A1_64)
+# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg17 S1_64+0)
+# CHECK-EMPTY:
+# CHECK-NEXT:     DW_TAG_GNU_call_site_parameter
+# CHECK-NEXT:       DW_AT_location      (DW_OP_reg4 A0_64)
+# CHECK-NEXT:       DW_AT_GNU_call_site_value   (DW_OP_breg17 S1_64+0)
+
+--- |
+  ; ModuleID = 'm.ll'
+  source_filename = "m.c"
+  target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
+  target triple = "mips-unknown-linux-gnu"
+  ; Function Attrs: noinline nounwind
+  define dso_local void @set(i32* nocapture %adr, i32 signext %val) local_unnamed_addr !dbg !12 {
+  entry:
+    call void @llvm.dbg.value(metadata i32* %adr, metadata !17, metadata !DIExpression()), !dbg !19
+    call void @llvm.dbg.value(metadata i32 %val, metadata !18, metadata !DIExpression()), !dbg !19
+    %inc = add nsw i32 %val, 1, !dbg !19
+    call void @llvm.dbg.value(metadata i32 %inc, metadata !18, metadata !DIExpression()), !dbg !19
+    %call = tail call i32 @sum(i32 signext %inc, i32 signext %inc), !dbg !19
+    %add = add nsw i32 %call, %inc, !dbg !19
+    store i32 %add, i32* %adr, align 4, !dbg !19
+    ret void
+  }
+  declare !dbg !4 dso_local i32 @sum(i32 signext, i32 signext) local_unnamed_addr
+  ; Function Attrs: nounwind readnone speculatable willreturn
+  declare void @llvm.dbg.value(metadata, metadata, metadata)
+  
+  !llvm.dbg.cu = !{!0}
+  !llvm.module.flags = !{!8, !9, !10}
+  !llvm.ident = !{!11}
+  
+  !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, splitDebugInlining: false, nameTableKind: None)
+  !1 = !DIFile(filename: "m.c", directory: "/dir")
+  !2 = !{}
+  !3 = !{!4}
+  !4 = !DISubprogram(name: "sum", scope: !1, file: !1, line: 1, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+  !5 = !DISubroutineType(types: !6)
+  !6 = !{!7, !7, !7}
+  !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+  !8 = !{i32 7, !"Dwarf Version", i32 4}
+  !9 = !{i32 2, !"Debug Info Version", i32 3}
+  !10 = !{i32 1, !"wchar_size", i32 4}
+  !11 = !{!"clang version 11.0.0"}
+  !12 = distinct !DISubprogram(name: "set", scope: !1, file: !1, line: 2, type: !13, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
+  !13 = !DISubroutineType(types: !14)
+  !14 = !{null, !15, !7}
+  !15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32)
+  !16 = !{!17, !18}
+  !17 = !DILocalVariable(name: "adr", arg: 1, scope: !12, file: !1, line: 2, type: !15)
+  !18 = !DILocalVariable(name: "val", arg: 2, scope: !12, file: !1, line: 2, type: !7)
+  !19 = !DILocation(line: 0, scope: !12)
+
+...
+---
+name:            set
+alignment:       4
+stack:
+  - { id: 0, name: '', type: spill-slot, offset: -4, size: 4, alignment: 4, 
+      stack-id: default, callee-saved-register: '$ra', callee-saved-restored: true, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 1, name: '', type: spill-slot, offset: -8, size: 4, alignment: 4, 
+      stack-id: default, callee-saved-register: '$s1', callee-saved-restored: true, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+  - { id: 2, name: '', type: spill-slot, offset: -12, size: 4, alignment: 4, 
+      stack-id: default, callee-saved-register: '$s0', callee-saved-restored: true, 
+      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
+callSites:
+  - { bb: 0, offset: 16, fwdArgRegs: 
+      - { arg: 0, reg: '$a0' }
+      - { arg: 1, reg: '$a1' } }
+body:             |
+  bb.0.entry:
+    DBG_VALUE $a0, $noreg, !17, !DIExpression(), debug-location !19
+    DBG_VALUE $a1, $noreg, !18, !DIExpression(), debug-location !19
+    DBG_VALUE $a1, $noreg, !18, !DIExpression(), debug-location !19
+    $sp = ADDiu $sp, -32
+    CFI_INSTRUCTION def_cfa_offset 32
+    SW killed $ra, $sp, 28 :: (store 4 into %stack.0)
+    SW killed $s1, $sp, 24 :: (store 4 into %stack.1)
+    SW killed $s0, $sp, 20 :: (store 4 into %stack.2)
+    CFI_INSTRUCTION offset $ra_64, -4
+    CFI_INSTRUCTION offset $s1_64, -8
+    CFI_INSTRUCTION offset $s0_64, -12
+    $s0 = OR $a0, $zero
+    DBG_VALUE $s0, $noreg, !17, !DIExpression(), debug-location !19
+    renamable $s1 = nsw ADDiu killed renamable $a1, 1, debug-location !19
+    DBG_VALUE $s1, $noreg, !18, !DIExpression(), debug-location !19
+    $a0 = OR $s1, $zero, debug-location !19
+    JAL @sum, csr_o32, implicit-def dead $ra, implicit $a0, implicit $a1, implicit-def $sp, implicit-def $v0, debug-location !19 {
+      $a1 = OR $s1, $zero, debug-location !19
+    }
+    renamable $at = nsw ADDu killed renamable $v0, killed renamable $s1, debug-location !19
+    SW killed renamable $at, killed renamable $s0, 0, debug-location !19 :: (store 4 into %ir.adr)
+    $s0 = LW $sp, 20
+    DBG_VALUE $a0, $noreg, !17, !DIExpression(DW_OP_LLVM_entry_value, 1), debug-location !19
+    $s1 = LW $sp, 24
+    $ra = LW $sp, 28
+    PseudoReturn undef $ra {
+      $sp = ADDiu $sp, 32
+    }
+
+...
+

diff  --git a/llvm/test/DebugInfo/Mips/dbg-call-site-low-pc.ll b/llvm/test/DebugInfo/Mips/dbg-call-site-low-pc.ll
new file mode 100644
index 000000000000..46b1bc6b54ad
--- /dev/null
+++ b/llvm/test/DebugInfo/Mips/dbg-call-site-low-pc.ll
@@ -0,0 +1,67 @@
+;; Test mips32:
+; RUN: llc -emit-call-site-info %s -mtriple=mips -filetype=obj -o -| llvm-dwarfdump -| FileCheck %s
+;; Test mipsel:
+; RUN: llc -emit-call-site-info %s -mtriple=mipsel -filetype=obj -o -| llvm-dwarfdump -| FileCheck %s
+;; Test mips64:
+; RUN: llc -emit-call-site-info %s -mtriple=mips64 -filetype=obj -o -| llvm-dwarfdump -| FileCheck %s
+;; Test mips64el:
+; RUN: llc -emit-call-site-info %s -mtriple=mips64el -filetype=obj -o -| llvm-dwarfdump -| FileCheck %s
+
+;; Source:
+;; __attribute__((noinline))
+;; extern void f1(int a);
+;; __attribute__((noinline))
+;; int main(){
+;;   int x = 10;
+;;   f1(x);
+;;   return ++x;
+;; }
+;; Command: clang -g -O2 -target mips-linux-gnu -S -emit-llvm m.c -c
+;; Confirm that DW_AT_low_pc (call return address) points to instruction after call delay slot.
+
+;; Test mips, mipsel, mips64, mips64el:
+; CHECK:        DW_TAG_GNU_call_site
+; CHECK-NEXT:     DW_AT_abstract_origin {{.*}} "f1"
+; CHECK-NEXT:     DW_AT_low_pc (0x0000000000000010)
+
+; ModuleID = 'm.c'
+source_filename = "m.c"
+target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
+target triple = "mips-unknown-linux-gnu"
+
+; Function Attrs: noinline nounwind
+define dso_local i32 @main() local_unnamed_addr !dbg !12 {
+entry:
+  call void @llvm.dbg.value(metadata i32 10, metadata !16, metadata !DIExpression()), !dbg !17
+  tail call void @f1(i32 signext 10), !dbg !17
+  call void @llvm.dbg.value(metadata i32 11, metadata !16, metadata !DIExpression()), !dbg !17
+  ret i32 11, !dbg !17
+}
+
+declare !dbg !4 dso_local void @f1(i32 signext) local_unnamed_addr
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!8, !9, !10}
+!llvm.ident = !{!11}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "m.c", directory: "/dir")
+!2 = !{}
+!3 = !{!4}
+!4 = !DISubprogram(name: "f1", scope: !1, file: !1, line: 2, type: !5, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null, !7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = !{i32 7, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"wchar_size", i32 4}
+!11 = !{!"clang version 11.0.0"}
+!12 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !15)
+!13 = !DISubroutineType(types: !14)
+!14 = !{!7}
+!15 = !{!16}
+!16 = !DILocalVariable(name: "x", scope: !12, file: !1, line: 6, type: !7)
+!17 = !DILocation(line: 0, scope: !12)


        


More information about the llvm-commits mailing list