Add cfi instr for CFA calculation when movpc is expanded to call and pop
authorPetar Jovanovic <petar.jovanovic@imgtec.com>
Thu, 5 Nov 2015 17:19:59 +0000 (17:19 +0000)
committerPetar Jovanovic <petar.jovanovic@imgtec.com>
Thu, 5 Nov 2015 17:19:59 +0000 (17:19 +0000)
This fixes the issue of wrong CFA calculation in the following case:

0x08048400 <+0>: push   %ebx
0x08048401 <+1>: sub    $0x8,%esp
0x08048404 <+4>: **call   0x8048409 <test+9>**
0x08048409 <+9>: **pop    %eax**
0x0804840a <+10>: add    $0x1bf7,%eax
0x08048410 <+16>: mov    %eax,%ebx
0x08048412 <+18>: call   0x80483f0 <bar>
0x08048417 <+23>: add    $0x8,%esp
0x0804841a <+26>: pop    %ebx
0x0804841b <+27>: ret

The highlighted instructions are a product of movpc instruction. The call
instruction changes the stack pointer, and pop instruction restores its
value. However, the rule for computing CFA is not updated and is wrong on
the pop instruction. So, e.g. backtrace in gdb does not work when on the pop
instruction. This adds cfi instructions for both call and pop instructions.

cfi_adjust_cfa_offset** instruction is used with the appropriate offset for
setting the rules to calculate CFA correctly.

Patch by Violeta Vukobrat.

Differential Revision: http://reviews.llvm.org/D14021

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252176 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86MCInstLower.cpp
test/CodeGen/X86/movpc32-check.ll [new file with mode: 0644]

index a59ddb7e995f83f0a350d8cd49473d3e6bb64329..6887f2e4c04ae0f08b3591fe249dce061c85e5c7 100644 (file)
@@ -1140,12 +1140,27 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
     EmitAndCountInstruction(MCInstBuilder(X86::CALLpcrel32)
       .addExpr(MCSymbolRefExpr::create(PICBase, OutContext)));
 
+    const X86FrameLowering* FrameLowering =
+        MF->getSubtarget<X86Subtarget>().getFrameLowering();
+    bool hasFP = FrameLowering->hasFP(*MF);
+
+    bool NeedsDwarfCFI = MMI->usePreciseUnwindInfo();
+    int stackGrowth = -RI->getSlotSize();
+
+    if (NeedsDwarfCFI && !hasFP) {
+      OutStreamer->EmitCFIAdjustCfaOffset(-stackGrowth);
+    }
+
     // Emit the label.
     OutStreamer->EmitLabel(PICBase);
 
     // popl $reg
     EmitAndCountInstruction(MCInstBuilder(X86::POP32r)
                             .addReg(MI->getOperand(0).getReg()));
+
+    if (NeedsDwarfCFI && !hasFP) {
+      OutStreamer->EmitCFIAdjustCfaOffset(stackGrowth);
+    }
     return;
   }
 
diff --git a/test/CodeGen/X86/movpc32-check.ll b/test/CodeGen/X86/movpc32-check.ll
new file mode 100644 (file)
index 0000000..0835a1b
--- /dev/null
@@ -0,0 +1,42 @@
+; RUN: llc < %s -mtriple=i686-pc-linux -relocation-model=pic | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128"
+target triple = "i686-pc-linux"
+
+; Function Attrs: nounwind
+define void @test() #0 {
+entry:
+  call void bitcast (void (...)* @bar to void ()*)(), !dbg !11
+  ret void, !dbg !12
+}
+
+declare void @bar(...) #1
+
+attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="i686" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="i686" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (http://llvm.org/git/clang.git 3490ab8630d5643f71f1f04e46984f05b27b8d67) (http://llvm.org/git/llvm.git d2643e2ff955ed234944fe3c6b4ffc1250085843)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
+!1 = !DIFile(filename: "test.c", directory: "movpc-test")
+!2 = !{}
+!3 = !{!4}
+!4 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, function: void ()* @test, variables: !2)
+!5 = !DISubroutineType(types: !6)
+!6 = !{null}
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"PIC Level", i32 2}
+!10 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 3490ab8630d5643f71f1f04e46984f05b27b8d67) (http://llvm.org/git/llvm.git d2643e2ff955ed234944fe3c6b4ffc1250085843)"}
+!11 = !DILocation(line: 4, column: 3, scope: !4)
+!12 = !DILocation(line: 5, column: 1, scope: !4)
+
+; CHECK: calll .L0$pb
+; CHECK-NEXT: .Ltmp3:
+; CHECK-NEXT: .cfi_adjust_cfa_offset 4
+; CHECK-NEXT: .L0$pb:
+; CHECK-NEXT: popl
+; CHECK-NEXT: .Ltmp4:
+; CHECK-NEXT: .cfi_adjust_cfa_offset -4