mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-29 10:32:47 +00:00
1ec250a32f
Otherwise we'll attempt to forward ECX, EDX, and EAX for cdecl and stdcall thunks, leaving us with no scratch registers for indirect call targets. Fixes PR22052. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225729 91177308-0d34-0410-b5e6-96231b3b80d8
141 lines
4.2 KiB
LLVM
141 lines
4.2 KiB
LLVM
; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-linux | FileCheck %s --check-prefix=LINUX
|
|
; RUN: llc < %s -enable-tail-merge=0 -mtriple=x86_64-windows | FileCheck %s --check-prefix=WINDOWS
|
|
; RUN: llc < %s -enable-tail-merge=0 -mtriple=i686-windows | FileCheck %s --check-prefix=X86
|
|
|
|
; Test that we actually spill and reload all arguments in the variadic argument
|
|
; pack. Doing a normal call will clobber all argument registers, and we will
|
|
; spill around it. A simple adjustment should not require any XMM spills.
|
|
|
|
declare void @llvm.va_start(i8*) nounwind
|
|
|
|
declare void(i8*, ...)* @get_f(i8* %this)
|
|
|
|
define void @f_thunk(i8* %this, ...) {
|
|
; Use va_start so that we exercise the combination.
|
|
%ap = alloca [4 x i8*], align 16
|
|
%ap_i8 = bitcast [4 x i8*]* %ap to i8*
|
|
call void @llvm.va_start(i8* %ap_i8)
|
|
|
|
%fptr = call void(i8*, ...)*(i8*)* @get_f(i8* %this)
|
|
musttail call void (i8*, ...)* %fptr(i8* %this, ...)
|
|
ret void
|
|
}
|
|
|
|
; Save and restore 6 GPRs, 8 XMMs, and AL around the call.
|
|
|
|
; LINUX-LABEL: f_thunk:
|
|
; LINUX-DAG: movq %rdi, {{.*}}
|
|
; LINUX-DAG: movq %rsi, {{.*}}
|
|
; LINUX-DAG: movq %rdx, {{.*}}
|
|
; LINUX-DAG: movq %rcx, {{.*}}
|
|
; LINUX-DAG: movq %r8, {{.*}}
|
|
; LINUX-DAG: movq %r9, {{.*}}
|
|
; LINUX-DAG: movb %al, {{.*}}
|
|
; LINUX-DAG: movaps %xmm0, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm1, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm2, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm3, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm4, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm5, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm6, {{[0-9]*}}(%rsp)
|
|
; LINUX-DAG: movaps %xmm7, {{[0-9]*}}(%rsp)
|
|
; LINUX: callq get_f
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm0
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm1
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm2
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm3
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm4
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm5
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm6
|
|
; LINUX-DAG: movaps {{[0-9]*}}(%rsp), %xmm7
|
|
; LINUX-DAG: movq {{.*}}, %rdi
|
|
; LINUX-DAG: movq {{.*}}, %rsi
|
|
; LINUX-DAG: movq {{.*}}, %rdx
|
|
; LINUX-DAG: movq {{.*}}, %rcx
|
|
; LINUX-DAG: movq {{.*}}, %r8
|
|
; LINUX-DAG: movq {{.*}}, %r9
|
|
; LINUX-DAG: movb {{.*}}, %al
|
|
; LINUX: jmpq *{{.*}} # TAILCALL
|
|
|
|
; WINDOWS-LABEL: f_thunk:
|
|
; WINDOWS-NOT: mov{{.}}ps
|
|
; WINDOWS-DAG: movq %rdx, {{.*}}
|
|
; WINDOWS-DAG: movq %rcx, {{.*}}
|
|
; WINDOWS-DAG: movq %r8, {{.*}}
|
|
; WINDOWS-DAG: movq %r9, {{.*}}
|
|
; WINDOWS-NOT: mov{{.}}ps
|
|
; WINDOWS: callq get_f
|
|
; WINDOWS-NOT: mov{{.}}ps
|
|
; WINDOWS-DAG: movq {{.*}}, %rdx
|
|
; WINDOWS-DAG: movq {{.*}}, %rcx
|
|
; WINDOWS-DAG: movq {{.*}}, %r8
|
|
; WINDOWS-DAG: movq {{.*}}, %r9
|
|
; WINDOWS-NOT: mov{{.}}ps
|
|
; WINDOWS: jmpq *{{.*}} # TAILCALL
|
|
|
|
; No regparms on normal x86 conventions.
|
|
|
|
; X86-LABEL: _f_thunk:
|
|
; X86: calll _get_f
|
|
; X86: jmpl *{{.*}} # TAILCALL
|
|
|
|
; This thunk shouldn't require any spills and reloads, assuming the register
|
|
; allocator knows what it's doing.
|
|
|
|
define void @g_thunk(i8* %fptr_i8, ...) {
|
|
%fptr = bitcast i8* %fptr_i8 to void (i8*, ...)*
|
|
musttail call void (i8*, ...)* %fptr(i8* %fptr_i8, ...)
|
|
ret void
|
|
}
|
|
|
|
; LINUX-LABEL: g_thunk:
|
|
; LINUX-NOT: movq
|
|
; LINUX: jmpq *%rdi # TAILCALL
|
|
|
|
; WINDOWS-LABEL: g_thunk:
|
|
; WINDOWS-NOT: movq
|
|
; WINDOWS: jmpq *%rcx # TAILCALL
|
|
|
|
; X86-LABEL: _g_thunk:
|
|
; X86: jmpl *%eax # TAILCALL
|
|
|
|
; Do a simple multi-exit multi-bb test.
|
|
|
|
%struct.Foo = type { i1, i8*, i8* }
|
|
|
|
@g = external global i32
|
|
|
|
define void @h_thunk(%struct.Foo* %this, ...) {
|
|
%cond_p = getelementptr %struct.Foo* %this, i32 0, i32 0
|
|
%cond = load i1* %cond_p
|
|
br i1 %cond, label %then, label %else
|
|
|
|
then:
|
|
%a_p = getelementptr %struct.Foo* %this, i32 0, i32 1
|
|
%a_i8 = load i8** %a_p
|
|
%a = bitcast i8* %a_i8 to void (%struct.Foo*, ...)*
|
|
musttail call void (%struct.Foo*, ...)* %a(%struct.Foo* %this, ...)
|
|
ret void
|
|
|
|
else:
|
|
%b_p = getelementptr %struct.Foo* %this, i32 0, i32 2
|
|
%b_i8 = load i8** %b_p
|
|
%b = bitcast i8* %b_i8 to void (%struct.Foo*, ...)*
|
|
store i32 42, i32* @g
|
|
musttail call void (%struct.Foo*, ...)* %b(%struct.Foo* %this, ...)
|
|
ret void
|
|
}
|
|
|
|
; LINUX-LABEL: h_thunk:
|
|
; LINUX: jne
|
|
; LINUX: jmpq *{{.*}} # TAILCALL
|
|
; LINUX: jmpq *{{.*}} # TAILCALL
|
|
; WINDOWS-LABEL: h_thunk:
|
|
; WINDOWS: jne
|
|
; WINDOWS: jmpq *{{.*}} # TAILCALL
|
|
; WINDOWS: jmpq *{{.*}} # TAILCALL
|
|
; X86-LABEL: _h_thunk:
|
|
; X86: jne
|
|
; X86: jmpl *{{.*}} # TAILCALL
|
|
; X86: jmpl *{{.*}} # TAILCALL
|