mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-07 19:19:26 +00:00
Don't emit CFI instructions at the end of a function
When functions are terminated by unreachable instructions, the last instruction might trigger a CFI instruction to be generated. However, emitting it would be be illegal since the function (and thus the FDE the CFI is in) has already ended with the previous instruction. Darwin's dwarfdump --verify --eh-frame complains about this and the specification supports this. Relevant bits from the DWARF 5 standard (6.4 Call Frame Information): "[The] address_range [field in an FDE]: The number of bytes of program instructions described by this entry." "Row creation instructions: [...] The new location value is always greater than the current one." The first quotation implies that a CFI cannot describe a target address outside of the enclosing FDE's range. rdar://problem/26244988 Differential Revision: https://reviews.llvm.org/D32246 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301219 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6f76a43cea
commit
83092adef9
@ -938,6 +938,16 @@ void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
|
||||
if (needsCFIMoves() == CFI_M_None)
|
||||
return;
|
||||
|
||||
// If there is no "real" instruction following this CFI instruction, skip
|
||||
// emitting it; it would be beyond the end of the function's FDE range.
|
||||
auto *MBB = MI.getParent();
|
||||
auto I = std::next(MI.getIterator());
|
||||
while (I != MBB->end() && I->isTransient())
|
||||
++I;
|
||||
if (I == MBB->instr_end() &&
|
||||
MBB->getReverseIterator() == MBB->getParent()->rbegin())
|
||||
return;
|
||||
|
||||
const std::vector<MCCFIInstruction> &Instrs = MF->getFrameInstructions();
|
||||
unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
|
||||
const MCCFIInstruction &CFI = Instrs[CFIIndex];
|
||||
|
@ -24,9 +24,7 @@ entry:
|
||||
; LINUX-NO-FP-NEXT: .size func, .L[[END]]-.L[[BEGIN]]
|
||||
; LINUX-NO-FP-NEXT: .cfi_endproc
|
||||
|
||||
; A cfi directive can point to the end of a function. It (and in fact the
|
||||
; entire body) could be optimized out because of the unreachable, but we
|
||||
; don't do it right now.
|
||||
; A cfi directive cannot point to the end of a function.
|
||||
; LINUX-FP: func:
|
||||
; LINUX-FP-NEXT: {{^}}.L[[BEGIN:.*]]:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_startproc
|
||||
@ -38,8 +36,6 @@ entry:
|
||||
; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_offset r31, -4
|
||||
; LINUX-FP-NEXT: mr 31, 1
|
||||
; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_def_cfa_register r31
|
||||
; LINUX-FP-NEXT: {{^}}.L[[END:.*]]:{{$}}
|
||||
; LINUX-FP-NEXT: .size func, .L[[END]]-.L[[BEGIN]]
|
||||
; LINUX-FP-NEXT: .cfi_endproc
|
||||
|
@ -14,19 +14,11 @@ entry:
|
||||
; LINUX-NO-FP-NEXT: .size func, .L{{.*}}-func
|
||||
; LINUX-NO-FP-NEXT: .cfi_endproc
|
||||
|
||||
; A cfi directive can point to the end of a function. It (and in fact the
|
||||
; entire body) could be optimized out because of the unreachable, but we
|
||||
; don't do it right now.
|
||||
; A cfi directive cannot point to the end of a function.
|
||||
; LINUX-FP: func:
|
||||
; LINUX-FP-NEXT: .cfi_startproc
|
||||
; LINUX-FP-NEXT: {{^}}!
|
||||
; LINUX-FP-NEXT: save %sp, -96, %sp
|
||||
; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_def_cfa_register %fp
|
||||
; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_window_save
|
||||
; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_register 15, 31
|
||||
; LINUX-FP-NEXT: {{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .size func, .Lfunc_end0-func
|
||||
; LINUX-FP-NEXT: .cfi_endproc
|
||||
|
11
test/CodeGen/X86/eh-frame-unreachable.ll
Normal file
11
test/CodeGen/X86/eh-frame-unreachable.ll
Normal file
@ -0,0 +1,11 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
|
||||
; Test that we don't emit a row that extends beyond the FDE's range_size.
|
||||
;
|
||||
; CHECK: movq %rsp, %rbp
|
||||
; CHECK-NEXT: .cfi_endproc
|
||||
; CHECK-NOT: .cfi
|
||||
|
||||
define void @f() #0 {
|
||||
unreachable
|
||||
}
|
||||
attributes #0 = { "no-frame-pointer-elim"="true" }
|
@ -23,8 +23,6 @@ entry:
|
||||
; CHECK-FP-NEXT: :
|
||||
; CHECK-FP-NEXT: .cfi_offset %rbp, -16
|
||||
; CHECK-FP-NEXT: movq %rsp, %rbp
|
||||
; CHECK-FP-NEXT: :
|
||||
; CHECK-FP-NEXT: .cfi_def_cfa_register %rbp
|
||||
; CHECK-FP-NEXT: .cfi_endproc
|
||||
|
||||
; An empty function is perfectly fine on ELF.
|
||||
@ -35,9 +33,7 @@ entry:
|
||||
; LINUX-NO-FP-NEXT: .size func, .L{{.*}}-func
|
||||
; LINUX-NO-FP-NEXT: .cfi_endproc
|
||||
|
||||
; A cfi directive can point to the end of a function. It (and in fact the
|
||||
; entire body) could be optimized out because of the unreachable, but we
|
||||
; don't do it right now.
|
||||
; A cfi directive cannot point to the end of a function.
|
||||
; LINUX-FP: func:
|
||||
; LINUX-FP-NEXT: .cfi_startproc
|
||||
; LINUX-FP-NEXT: {{^}}#
|
||||
@ -48,7 +44,5 @@ entry:
|
||||
; LINUX-FP-NEXT: .cfi_offset %rbp, -16
|
||||
; LINUX-FP-NEXT: movq %rsp, %rbp
|
||||
; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .cfi_def_cfa_register %rbp
|
||||
; LINUX-FP-NEXT:{{^}}.L{{.*}}:{{$}}
|
||||
; LINUX-FP-NEXT: .size func, .Lfunc_end0-func
|
||||
; LINUX-FP-NEXT: .cfi_endproc
|
||||
|
Loading…
x
Reference in New Issue
Block a user