Skip to content

Commit

Permalink
[musttail] Don't forward AL on Win64
Browse files Browse the repository at this point in the history
AL is only used for varargs on SysV platforms. Don't forward it on
Windows. This allows control flow guard to set up an extra hidden
parameter in RAX, as described in PR44049.

This also has the effect of freeing up RAX for use in virtual member
pointer thunks, which may also be a nice little code size improvement on
Win64.

Fixes PR44049

Reviewers: ajpaverd, efriedma, hans

Differential Revision: https://reviews.llvm.org/D70413
  • Loading branch information
rnk committed Nov 20, 2019
1 parent bffdee8 commit 606a2bd
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 20 deletions.
4 changes: 2 additions & 2 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -3467,8 +3467,8 @@ SDValue X86TargetLowering::LowerFormalArguments(
FuncInfo->getForwardedMustTailRegParms();
CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_X86);

// Conservatively forward AL on x86_64, since it might be used for varargs.
if (Is64Bit && !CCInfo.isAllocated(X86::AL)) {
// Forward AL for SysV x86_64 targets, since it is used for varargs.
if (Is64Bit && !IsWin64 && !CCInfo.isAllocated(X86::AL)) {
unsigned ALVReg = MF.addLiveIn(X86::AL, &X86::GR8RegClass);
Forwards.push_back(ForwardedRegister(ALVReg, X86::AL, MVT::i8));
}
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/CodeGen/X86/cfguard-checks.ll
Expand Up @@ -176,6 +176,39 @@ entry:
; X64-NOT: callq
}

%struct.Foo = type { i32 (%struct.Foo*)** }

; Test that Control Flow Guard checks are correctly added for variadic musttail
; calls. These are used for MS C++ ABI virtual member pointer thunks.
; PR44049
define i32 @vmptr_thunk(%struct.Foo* inreg %p) {
entry:
%vptr.addr = getelementptr inbounds %struct.Foo, %struct.Foo* %p, i32 0, i32 0
%vptr = load i32 (%struct.Foo*)**, i32 (%struct.Foo*)*** %vptr.addr
%slot = getelementptr inbounds i32 (%struct.Foo*)*, i32 (%struct.Foo*)** %vptr, i32 1
%vmethod = load i32 (%struct.Foo*)*, i32 (%struct.Foo*)** %slot
%rv = musttail call i32 %vmethod(%struct.Foo* inreg %p)
ret i32 %rv

; On i686, the call to __guard_check_icall_fptr should come immediately before the call to the target function.
; X32-LABEL: _vmptr_thunk:
; X32: movl %eax, %esi
; X32: movl (%eax), %eax
; X32: movl 4(%eax), %ecx
; X32: calll *___guard_check_icall_fptr
; X32: movl %esi, %eax
; X32: jmpl *%ecx # TAILCALL
; X32-NOT: calll

; Use NEXT here because we previously had an extra instruction in this sequence.
; X64-LABEL: vmptr_thunk:
; X64: movq (%rcx), %rax
; X64-NEXT: movq 8(%rax), %rax
; X64-NEXT: movq __guard_dispatch_icall_fptr(%rip), %rdx
; X64-NEXT: addq $40, %rsp
; X64-NEXT: rex64 jmpq *%rdx # TAILCALL
; X64-NOT: callq
}

; Test that longjmp targets have public labels and are included in the .gljmp section.
%struct._SETJMP_FLOAT128 = type { [2 x i64] }
Expand Down
30 changes: 12 additions & 18 deletions llvm/test/CodeGen/X86/musttail-varargs.ll
Expand Up @@ -211,37 +211,31 @@ define void @f_thunk(i8* %this, ...) {
; WINDOWS-NEXT: .seh_pushreg %rsi
; WINDOWS-NEXT: pushq %rdi
; WINDOWS-NEXT: .seh_pushreg %rdi
; WINDOWS-NEXT: pushq %rbp
; WINDOWS-NEXT: .seh_pushreg %rbp
; WINDOWS-NEXT: pushq %rbx
; WINDOWS-NEXT: .seh_pushreg %rbx
; WINDOWS-NEXT: subq $64, %rsp
; WINDOWS-NEXT: .seh_stackalloc 64
; WINDOWS-NEXT: subq $72, %rsp
; WINDOWS-NEXT: .seh_stackalloc 72
; WINDOWS-NEXT: .seh_endprologue
; WINDOWS-NEXT: movl %eax, %r14d
; WINDOWS-NEXT: movq %r9, %rsi
; WINDOWS-NEXT: movq %r9, %r14
; WINDOWS-NEXT: movq %r8, %rdi
; WINDOWS-NEXT: movq %rdx, %rbx
; WINDOWS-NEXT: movq %rcx, %rbp
; WINDOWS-NEXT: movq %rcx, %rsi
; WINDOWS-NEXT: movq %rdx, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: movq %r8, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: movq %r9, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: leaq {{[0-9]+}}(%rsp), %rax
; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: callq get_f
; WINDOWS-NEXT: movq %rax, %r10
; WINDOWS-NEXT: movq %rbp, %rcx
; WINDOWS-NEXT: movq %rsi, %rcx
; WINDOWS-NEXT: movq %rbx, %rdx
; WINDOWS-NEXT: movq %rdi, %r8
; WINDOWS-NEXT: movq %rsi, %r9
; WINDOWS-NEXT: movl %r14d, %eax
; WINDOWS-NEXT: addq $64, %rsp
; WINDOWS-NEXT: movq %r14, %r9
; WINDOWS-NEXT: addq $72, %rsp
; WINDOWS-NEXT: popq %rbx
; WINDOWS-NEXT: popq %rbp
; WINDOWS-NEXT: popq %rdi
; WINDOWS-NEXT: popq %rsi
; WINDOWS-NEXT: popq %r14
; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .seh_handlerdata
; WINDOWS-NEXT: .text
; WINDOWS-NEXT: .seh_endproc
Expand Down Expand Up @@ -397,14 +391,14 @@ define void @h_thunk(%struct.Foo* %this, ...) {
; WINDOWS-NEXT: cmpb $1, (%rcx)
; WINDOWS-NEXT: jne .LBB2_2
; WINDOWS-NEXT: # %bb.1: # %then
; WINDOWS-NEXT: movq 8(%rcx), %r10
; WINDOWS-NEXT: movq 8(%rcx), %rax
; WINDOWS-NEXT: addq $40, %rsp
; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .LBB2_2: # %else
; WINDOWS-NEXT: movq 16(%rcx), %r10
; WINDOWS-NEXT: movq 16(%rcx), %rax
; WINDOWS-NEXT: movl $42, {{.*}}(%rip)
; WINDOWS-NEXT: addq $40, %rsp
; WINDOWS-NEXT: rex64 jmpq *%r10 # TAILCALL
; WINDOWS-NEXT: rex64 jmpq *%rax # TAILCALL
; WINDOWS-NEXT: .seh_handlerdata
; WINDOWS-NEXT: .text
; WINDOWS-NEXT: .seh_endproc
Expand Down

0 comments on commit 606a2bd

Please sign in to comment.