mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-05 00:59:19 +00:00

The x86_64 ABI requires that the stack is 16 byte aligned on function calls. Thus, the 8-byte error code, which is pushed by the CPU for certain exceptions, leads to a misaligned stack. This results in bugs such as Bug 26413, where misaligned movaps instructions are generated. This commit fixes the misalignment by adjusting the stack pointer in these cases. The adjustment is done at the beginning of the prologue generation by subtracting another 8 bytes from the stack pointer. These additional bytes are popped again in the function epilogue. Fixes Bug 26413 Patch by Philipp Oppermann. Differential Revision: https://reviews.llvm.org/D30049 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299383 91177308-0d34-0410-b5e6-96231b3b80d8
107 lines
3.7 KiB
LLVM
107 lines
3.7 KiB
LLVM
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
|
|
; RUN: llc -mtriple=x86_64-unknown-unknown -O0 < %s | FileCheck %s -check-prefix=CHECK0
|
|
|
|
%struct.interrupt_frame = type { i64, i64, i64, i64, i64 }
|
|
|
|
@llvm.used = appending global [4 x i8*] [i8* bitcast (void (%struct.interrupt_frame*)* @test_isr_no_ecode to i8*), i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_ecode to i8*), i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_clobbers to i8*), i8* bitcast (void (%struct.interrupt_frame*)* @test_isr_x87 to i8*)], section "llvm.metadata"
|
|
|
|
; Spills rax, putting original esp at +8.
|
|
; No stack adjustment if declared with no error code
|
|
define x86_intrcc void @test_isr_no_ecode(%struct.interrupt_frame* %frame) {
|
|
; CHECK-LABEL: test_isr_no_ecode:
|
|
; CHECK: pushq %rax
|
|
; CHECK: movq 24(%rsp), %rax
|
|
; CHECK: popq %rax
|
|
; CHECK: iretq
|
|
; CHECK0-LABEL: test_isr_no_ecode:
|
|
; CHECK0: pushq %rax
|
|
; CHECK0: leaq 8(%rsp), %rax
|
|
; CHECK0: movq 16(%rax), %rax
|
|
; CHECK0: popq %rax
|
|
; CHECK0: iretq
|
|
%pflags = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %frame, i32 0, i32 2
|
|
%flags = load i64, i64* %pflags, align 4
|
|
call void asm sideeffect "", "r"(i64 %flags)
|
|
ret void
|
|
}
|
|
|
|
; Spills rax and rcx, putting original rsp at +16. Stack is adjusted up another 8 bytes
|
|
; before return, popping the error code.
|
|
define x86_intrcc void @test_isr_ecode(%struct.interrupt_frame* %frame, i64 %ecode) {
|
|
; CHECK-LABEL: test_isr_ecode
|
|
; CHECK: pushq %rax
|
|
; CHECK: pushq %rax
|
|
; CHECK: pushq %rcx
|
|
; CHECK: movq 24(%rsp), %rax
|
|
; CHECK: movq 48(%rsp), %rcx
|
|
; CHECK: popq %rcx
|
|
; CHECK: popq %rax
|
|
; CHECK: addq $16, %rsp
|
|
; CHECK: iretq
|
|
; CHECK0-LABEL: test_isr_ecode
|
|
; CHECK0: pushq %rax
|
|
; CHECK0: pushq %rax
|
|
; CHECK0: pushq %rcx
|
|
; CHECK0: movq 24(%rsp), %rax
|
|
; CHECK0: leaq 32(%rsp), %rcx
|
|
; CHECK0: movq 16(%rcx), %rcx
|
|
; CHECK0: popq %rcx
|
|
; CHECK0: popq %rax
|
|
; CHECK0: addq $16, %rsp
|
|
; CHECK0: iretq
|
|
%pflags = getelementptr inbounds %struct.interrupt_frame, %struct.interrupt_frame* %frame, i32 0, i32 2
|
|
%flags = load i64, i64* %pflags, align 4
|
|
call void asm sideeffect "", "r,r"(i64 %flags, i64 %ecode)
|
|
ret void
|
|
}
|
|
|
|
; All clobbered registers must be saved
|
|
define x86_intrcc void @test_isr_clobbers(%struct.interrupt_frame* %frame, i64 %ecode) {
|
|
call void asm sideeffect "", "~{rax},~{rbx},~{rbp},~{r11},~{xmm0}"()
|
|
; CHECK-LABEL: test_isr_clobbers
|
|
; CHECK-SSE-NEXT: pushq %rax
|
|
; CHECK-SSE-NEXT: pushq %rax
|
|
; CHECK-SSE-NEXT; pushq %r11
|
|
; CHECK-SSE-NEXT: pushq %rbp
|
|
; CHECK-SSE-NEXT: pushq %rbx
|
|
; CHECK-SSE-NEXT: movaps %xmm0
|
|
; CHECK-SSE-NEXT: movaps %xmm0
|
|
; CHECK-SSE-NEXT: popq %rbx
|
|
; CHECK-SSE-NEXT: popq %rbp
|
|
; CHECK-SSE-NEXT: popq %r11
|
|
; CHECK-SSE-NEXT: popq %rax
|
|
; CHECK-SSE-NEXT: addq $8, %rsp
|
|
; CHECK-SSE-NEXT: iretq
|
|
; CHECK0-LABEL: test_isr_clobbers
|
|
; CHECK0-SSE-NEXT: pushq %rax
|
|
; CHECK0-SSE-NEXT; pushq %r11
|
|
; CHECK0-SSE-NEXT: pushq %rbp
|
|
; CHECK0-SSE-NEXT: pushq %rbx
|
|
; CHECK0-SSE-NEXT: movaps %xmm0
|
|
; CHECK0-SSE-NEXT: movaps %xmm0
|
|
; CHECK0-SSE-NEXT: popq %rbx
|
|
; CHECK0-SSE-NEXT: popq %rbp
|
|
; CHECK0-SSE-NEXT: popq %r11
|
|
; CHECK0-SSE-NEXT: popq %rax
|
|
; CHECK0-SSE-NEXT: addq $16, %rsp
|
|
; CHECK0-SSE-NEXT: iretq
|
|
ret void
|
|
}
|
|
|
|
@f80 = common global x86_fp80 0xK00000000000000000000, align 4
|
|
|
|
; Test that the presence of x87 does not crash the FP stackifier
|
|
define x86_intrcc void @test_isr_x87(%struct.interrupt_frame* %frame) {
|
|
; CHECK-LABEL: test_isr_x87
|
|
; CHECK-DAG: fldt f80
|
|
; CHECK-DAG: fld1
|
|
; CHECK: faddp
|
|
; CHECK-NEXT: fstpt f80
|
|
; CHECK-NEXT: iretq
|
|
entry:
|
|
%ld = load x86_fp80, x86_fp80* @f80, align 4
|
|
%add = fadd x86_fp80 %ld, 0xK3FFF8000000000000000
|
|
store x86_fp80 %add, x86_fp80* @f80, align 4
|
|
ret void
|
|
}
|