From b0d280a58878b855dacbc1848d220fed4484b708 Mon Sep 17 00:00:00 2001 From: Joseph Tremoulet Date: Thu, 5 Nov 2015 02:20:07 +0000 Subject: [PATCH] [WinEH] Fix establisher param reg in CLR funclets Summary: The CLR's personality routine passes the pointer to the establisher frame in RCX, not RDX. Reviewers: pgavlin, majnemer, rnk Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14343 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252135 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86FrameLowering.cpp | 29 ++++++++++++++++++++--------- test/CodeGen/WinEH/wineh-coreclr.ll | 8 ++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index ee866fa45c3..ae4cc77fcc9 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -18,6 +18,7 @@ #include "X86Subtarget.h" #include "X86TargetMachine.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -624,6 +625,9 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment. uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate. bool IsFunclet = MBB.isEHFuncletEntry(); + bool IsClrFunclet = + IsFunclet && + classifyEHPersonality(Fn->getPersonalityFn()) == EHPersonality::CoreCLR; bool HasFP = hasFP(MF); bool IsWin64CC = STI.isCallingConvWin64(Fn->getCallingConv()); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); @@ -701,13 +705,20 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, uint64_t NumBytes = 0; int stackGrowth = -SlotSize; - unsigned RDX = Uses64BitFramePtr ? X86::RDX : X86::EDX; - if (IsWin64Prologue && IsFunclet) { - // Immediately spill RDX into the home slot. The runtime cares about this. + // Find the funclet establisher parameter + unsigned Establisher = X86::NoRegister; + if (IsClrFunclet) + Establisher = Uses64BitFramePtr ? X86::RCX : X86::ECX; + else if (IsFunclet) + Establisher = Uses64BitFramePtr ? X86::RDX : X86::EDX; + + if (IsWin64Prologue && IsFunclet & !IsClrFunclet) { + // Immediately spill establisher into the home slot. + // The runtime cares about this. // MOV64mr %rdx, 16(%rsp) unsigned MOVmr = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr; addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(MOVmr)), StackPtr, true, 16) - .addReg(RDX) + .addReg(Establisher) .setMIFlag(MachineInstr::FrameSetup); } @@ -911,16 +922,16 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, int SEHFrameOffset = 0; if (IsWin64Prologue && HasFP) { // Set RBP to a small fixed offset from RSP. In the funclet case, we base - // this calculation on the incoming RDX, which holds the value of RSP from - // the parent frame at the end of the prologue. - unsigned SPOrRDX = !IsFunclet ? StackPtr : RDX; + // this calculation on the incoming establisher, which holds the value of + // RSP from the parent frame at the end of the prologue. + unsigned SPOrEstablisher = IsFunclet ? Establisher : StackPtr; SEHFrameOffset = calculateSetFPREG(ParentFrameNumBytes); if (SEHFrameOffset) addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA64r), FramePtr), - SPOrRDX, false, SEHFrameOffset); + SPOrEstablisher, false, SEHFrameOffset); else BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64rr), FramePtr) - .addReg(SPOrRDX); + .addReg(SPOrEstablisher); // If this is not a funclet, emit the CFI describing our frame pointer. if (NeedsWinCFI && !IsFunclet) diff --git a/test/CodeGen/WinEH/wineh-coreclr.ll b/test/CodeGen/WinEH/wineh-coreclr.ll index 56675fefae7..f5e046aa01c 100644 --- a/test/CodeGen/WinEH/wineh-coreclr.ll +++ b/test/CodeGen/WinEH/wineh-coreclr.ll @@ -50,6 +50,8 @@ catch1.pad: %catch1 = catchpad [i32 1] to label %catch1.body unwind label %catch2.pad catch1.body: +; CHECK: leaq {{[0-9]+}}(%rcx), %rbp +; ^ establisher frame pointer passed in rcx ; CHECK: .seh_endprologue ; CHECK: [[L_before_f3:.+]]: ; CHECK-NEXT: movl $3, %ecx @@ -64,6 +66,8 @@ catch2.pad: %catch2 = catchpad [i32 2] to label %catch2.body unwind label %catch.end catch2.body: +; CHECK: leaq {{[0-9]+}}(%rcx), %rbp +; ^ establisher frame pointer passed in rcx ; CHECK: .seh_endprologue ; CHECK: [[L_before_f4:.+]]: ; CHECK-NEXT: movl $4, %ecx @@ -82,6 +86,8 @@ try_in_catch: fault.pad: ; CHECK: .seh_proc [[L_fault:[^ ]+]] %fault = cleanuppad [i32 undef] +; CHECK: leaq {{[0-9]+}}(%rcx), %rbp +; ^ establisher frame pointer passed in rcx ; CHECK: .seh_endprologue ; CHECK: [[L_before_f6:.+]]: ; CHECK-NEXT: movl $6, %ecx @@ -103,6 +109,8 @@ finally.clone: finally.pad: ; CHECK: .seh_proc [[L_finally:[^ ]+]] %finally = cleanuppad [] +; CHECK: leaq {{[0-9]+}}(%rcx), %rbp +; ^ establisher frame pointer passed in rcx ; CHECK: .seh_endprologue ; CHECK: [[L_before_f7:.+]]: ; CHECK-NEXT: movl $7, %ecx -- 2.34.1