Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -959,6 +959,15 @@ .getValueAsString() .getAsInteger(0, StackProbeSize); + // Re-align the stack on 64-bit if the x86-interrupt calling convention is used + // and an error code was pushed, since the x86-64 ABI requires a 16-byte stack + // alignment. + if (Fn->getCallingConv() == CallingConv::X86_INTR && Is64Bit && Fn->arg_size() == 2) { + StackSize += 8; + MFI.setStackSize(StackSize); + emitSPUpdate(MBB, MBBI, -8, /*InEpilogue=*/false); + } + // If this is x86-64 and the Red Zone is not disabled, if we are a leaf // function, and use up to 128 bytes of stack space, don't have a frame // pointer, calls, or dynamic alloca then we do not need to adjust the Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -2697,6 +2697,11 @@ // Offset of last argument need to be set to -4/-8 bytes. // Where offset of the first argument out of two, should be set to 0 bytes. Offset = (Subtarget.is64Bit() ? 8 : 4) * ((i + 1) % Ins.size() - 1); + if (Subtarget.is64Bit() && Ins.size() == 2) { + // The stack pointer needs to be realigned for 64 bit handlers with error + // code, so the argument offset changes by 8 bytes. + Offset += 8; + } } // FIXME: For now, all byval parameter objects are marked mutable. This can be @@ -3113,8 +3118,9 @@ MF.getTarget().Options.GuaranteedTailCallOpt)) { FuncInfo->setBytesToPopOnReturn(StackSize); // Callee pops everything. } else if (CallConv == CallingConv::X86_INTR && Ins.size() == 2) { - // X86 interrupts must pop the error code if present - FuncInfo->setBytesToPopOnReturn(Is64Bit ? 8 : 4); + // X86 interrupts must pop the error code (and the alignment padding) + // if present. + FuncInfo->setBytesToPopOnReturn(Is64Bit ? 16 : 4); } else { FuncInfo->setBytesToPopOnReturn(0); // Callee pops nothing. // If this is an sret function, the return should pop the hidden pointer. Index: test/CodeGen/X86/x86-64-intrcc-nosse.ll =================================================================== --- test/CodeGen/X86/x86-64-intrcc-nosse.ll +++ test/CodeGen/X86/x86-64-intrcc-nosse.ll @@ -9,10 +9,11 @@ define x86_intrcc void @test_isr_sse_clobbers(%struct.interrupt_frame* %frame, i64 %ecode) { ; CHECK-LABEL: test_isr_sse_clobbers: ; CHECK: # BB#0: + ; CHECK-NEXT: pushq %rax ; CHECK-NEXT: cld ; CHECK-NEXT: #APP ; CHECK-NEXT: #NO_APP - ; CHECK-NEXT: addq $8, %rsp + ; CHECK-NEXT: addq $16, %rsp ; CHECK-NEXT: iretq call void asm sideeffect "", "~{xmm0},~{xmm6}"() ret void Index: test/CodeGen/X86/x86-64-intrcc.ll =================================================================== --- test/CodeGen/X86/x86-64-intrcc.ll +++ test/CodeGen/X86/x86-64-intrcc.ll @@ -30,22 +30,24 @@ 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 16(%rsp), %rax - ; CHECK: movq 40(%rsp), %rcx + ; CHECK: movq 24(%rsp), %rax + ; CHECK: movq 48(%rsp), %rcx ; CHECK: popq %rcx ; CHECK: popq %rax - ; CHECK: addq $8, %rsp + ; CHECK: addq $16, %rsp ; CHECK: iretq ; CHECK0-LABEL: test_isr_ecode ; CHECK0: pushq %rax + ; CHECK0: pushq %rax ; CHECK0: pushq %rcx - ; CHECK0: movq 16(%rsp), %rax - ; CHECK0: leaq 24(%rsp), %rcx + ; CHECK0: movq 24(%rsp), %rax + ; CHECK0: leaq 32(%rsp), %rcx ; CHECK0: movq 16(%rcx), %rcx ; CHECK0: popq %rcx ; CHECK0: popq %rax - ; CHECK0: addq $8, %rsp + ; 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 @@ -58,6 +60,7 @@ 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 @@ -67,10 +70,11 @@ ; CHECK-SSE-NEXT: popq %rbp ; CHECK-SSE-NEXT: popq %r11 ; CHECK-SSE-NEXT: popq %rax - ; CHECK-SSE-NEXT: addq $8, %rsp + ; CHECK-SSE-NEXT: addq $16, %rsp ; CHECK-SSE-NEXT: iretq ; CHECK0-LABEL: test_isr_clobbers ; CHECK0-SSE-NEXT: pushq %rax + ; CHECK0-SSE-NEXT: pushq %rax ; CHECK0-SSE-NEXT; pushq %r11 ; CHECK0-SSE-NEXT: pushq %rbp ; CHECK0-SSE-NEXT: pushq %rbx @@ -80,7 +84,7 @@ ; CHECK0-SSE-NEXT: popq %rbp ; CHECK0-SSE-NEXT: popq %r11 ; CHECK0-SSE-NEXT: popq %rax - ; CHECK0-SSE-NEXT: addq $8, %rsp + ; CHECK0-SSE-NEXT: addq $16, %rsp ; CHECK0-SSE-NEXT: iretq ret void }