summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-03-03 00:01:25 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-03-03 00:01:25 +0000
commit1ef654024f490b403494265c968570ca6bd800f3 (patch)
tree8915b153475cd3e51343662f1764be4d0b78a497
parentfe5a7109c5f800310dc7b0bb7626a835423c7dd5 (diff)
downloadbcm5719-llvm-1ef654024f490b403494265c968570ca6bd800f3.tar.gz
bcm5719-llvm-1ef654024f490b403494265c968570ca6bd800f3.zip
[X86] Don't give catch objects a displacement of zero
Catch objects with a displacement of zero do not initialize a catch object. The displacement is relative to %rsp at the end of the function's prologue for x86_64 targets. If we place an object at the top-of-stack, we will end up wit a displacement of zero resulting in our catch object remaining uninitialized. Address this by creating our catch objects as fixed objects. We will ensure that the UnwindHelp object is created after the catch objects so that no catch object will have a displacement of zero. Differential Revision: http://reviews.llvm.org/D17823 llvm-svn: 262546
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h4
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp60
-rw-r--r--llvm/lib/CodeGen/StackColoring.cpp11
-rw-r--r--llvm/lib/Target/X86/X86FrameLowering.cpp18
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp4
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.h2
-rw-r--r--llvm/test/CodeGen/X86/catchpad-dynamic-alloca.ll65
-rw-r--r--llvm/test/CodeGen/X86/catchpad-lifetime.ll8
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad.ll22
9 files changed, 154 insertions, 40 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index 6abeb44a368..ad3e26c7207 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/include/llvm/Target/TargetLowering.h
@@ -960,6 +960,10 @@ public:
return 0;
}
+ virtual bool needsFixedCatchObjects() const {
+ report_fatal_error("Funclet EH is not implemented for this target");
+ }
+
/// Returns the target's jmp_buf size in bytes (if never set, the default is
/// 200)
unsigned getJumpBufSize() const {
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 08815ed787d..e5c7ade8859 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -88,6 +88,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
RegInfo = &MF->getRegInfo();
MachineModuleInfo &MMI = MF->getMMI();
const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
+ unsigned StackAlign = TFI->getStackAlignment();
// Check whether the function can return without sret-demotion.
SmallVector<ISD::OutputArg, 4> Outs;
@@ -96,6 +97,31 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
CanLowerReturn = TLI->CanLowerReturn(Fn->getCallingConv(), *MF,
Fn->isVarArg(), Outs, Fn->getContext());
+ // If this personality uses funclets, we need to do a bit more work.
+ DenseMap<const AllocaInst *, int *> CatchObjects;
+ EHPersonality Personality = classifyEHPersonality(
+ Fn->hasPersonalityFn() ? Fn->getPersonalityFn() : nullptr);
+ if (isFuncletEHPersonality(Personality)) {
+ // Calculate state numbers if we haven't already.
+ WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
+ if (Personality == EHPersonality::MSVC_CXX)
+ calculateWinCXXEHStateNumbers(&fn, EHInfo);
+ else if (isAsynchronousEHPersonality(Personality))
+ calculateSEHStateNumbers(&fn, EHInfo);
+ else if (Personality == EHPersonality::CoreCLR)
+ calculateClrEHStateNumbers(&fn, EHInfo);
+
+ // Map all BB references in the WinEH data to MBBs.
+ for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
+ for (WinEHHandlerType &H : TBME.HandlerArray) {
+ if (const AllocaInst *AI = H.CatchObj.Alloca)
+ CatchObjects.insert({AI, &H.CatchObj.FrameIndex});
+ else
+ H.CatchObj.FrameIndex = INT_MAX;
+ }
+ }
+ }
+
// Initialize the mapping of values to registers. This is only set up for
// instruction values that are used outside of the block that defines
// them.
@@ -108,7 +134,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
unsigned Align =
std::max((unsigned)MF->getDataLayout().getPrefTypeAlignment(Ty),
AI->getAlignment());
- unsigned StackAlign = TFI->getStackAlignment();
// Static allocas can be folded into the initial stack frame
// adjustment. For targets that don't realign the stack, don't
@@ -120,9 +145,21 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
TySize *= CUI->getZExtValue(); // Get total allocated size.
if (TySize == 0) TySize = 1; // Don't create zero-sized stack objects.
+ int FrameIndex = INT_MAX;
+ auto Iter = CatchObjects.find(AI);
+ if (Iter != CatchObjects.end() && TLI->needsFixedCatchObjects()) {
+ FrameIndex = MF->getFrameInfo()->CreateFixedObject(
+ TySize, 0, /*Immutable=*/false, /*isAliased=*/true);
+ MF->getFrameInfo()->setObjectAlignment(FrameIndex, Align);
+ } else {
+ FrameIndex =
+ MF->getFrameInfo()->CreateStackObject(TySize, Align, false, AI);
+ }
- StaticAllocaMap[AI] =
- MF->getFrameInfo()->CreateStackObject(TySize, Align, false, AI);
+ StaticAllocaMap[AI] = FrameIndex;
+ // Update the catch handler information.
+ if (Iter != CatchObjects.end())
+ *Iter->second = FrameIndex;
} else {
// FIXME: Overaligned static allocas should be grouped into
// a single dynamic allocation instead of using a separate
@@ -281,31 +318,14 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
LPads.push_back(LPI);
}
- // If this personality uses funclets, we need to do a bit more work.
- if (!Fn->hasPersonalityFn())
- return;
- EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn());
if (!isFuncletEHPersonality(Personality))
return;
- // Calculate state numbers if we haven't already.
WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo();
- if (Personality == EHPersonality::MSVC_CXX)
- calculateWinCXXEHStateNumbers(&fn, EHInfo);
- else if (isAsynchronousEHPersonality(Personality))
- calculateSEHStateNumbers(&fn, EHInfo);
- else if (Personality == EHPersonality::CoreCLR)
- calculateClrEHStateNumbers(&fn, EHInfo);
// Map all BB references in the WinEH data to MBBs.
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
for (WinEHHandlerType &H : TBME.HandlerArray) {
- if (H.CatchObj.Alloca) {
- assert(StaticAllocaMap.count(H.CatchObj.Alloca));
- H.CatchObj.FrameIndex = StaticAllocaMap[H.CatchObj.Alloca];
- } else {
- H.CatchObj.FrameIndex = INT_MAX;
- }
if (H.Handler)
H.Handler = MBBMap[H.Handler.get<const BasicBlock *>()];
}
diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp
index 984ce470c6f..852db5d2a01 100644
--- a/llvm/lib/CodeGen/StackColoring.cpp
+++ b/llvm/lib/CodeGen/StackColoring.cpp
@@ -249,11 +249,13 @@ unsigned StackColoring::collectMarkers(unsigned NumSlot) {
MI.getOpcode() != TargetOpcode::LIFETIME_END)
continue;
- Markers.push_back(&MI);
-
bool IsStart = MI.getOpcode() == TargetOpcode::LIFETIME_START;
const MachineOperand &MO = MI.getOperand(0);
- unsigned Slot = MO.getIndex();
+ int Slot = MO.getIndex();
+ if (Slot < 0)
+ continue;
+
+ Markers.push_back(&MI);
MarkersFound++;
@@ -393,7 +395,8 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
bool IsStart = MI->getOpcode() == TargetOpcode::LIFETIME_START;
const MachineOperand &Mo = MI->getOperand(0);
int Slot = Mo.getIndex();
- assert(Slot >= 0 && "Invalid slot");
+ if (Slot < 0)
+ continue;
SlotIndex ThisIndex = Indexes->getInstructionIndex(*MI);
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index 378204f6c0c..de56259f744 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -2839,14 +2839,30 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized(
// were no fixed objects, use offset -SlotSize, which is immediately after the
// return address. Fixed objects have negative frame indices.
MachineFrameInfo *MFI = MF.getFrameInfo();
+ WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo();
int64_t MinFixedObjOffset = -SlotSize;
for (int I = MFI->getObjectIndexBegin(); I < 0; ++I)
MinFixedObjOffset = std::min(MinFixedObjOffset, MFI->getObjectOffset(I));
+ for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
+ for (WinEHHandlerType &H : TBME.HandlerArray) {
+ int FrameIndex = H.CatchObj.FrameIndex;
+ if (FrameIndex != INT_MAX) {
+ // Ensure alignment.
+ unsigned Align = MFI->getObjectAlignment(FrameIndex);
+ MinFixedObjOffset -= std::abs(MinFixedObjOffset) % Align;
+ MinFixedObjOffset -= MFI->getObjectSize(FrameIndex);
+ MFI->setObjectOffset(FrameIndex, MinFixedObjOffset);
+ }
+ }
+ }
+
+ // Ensure alignment.
+ MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8;
int64_t UnwindHelpOffset = MinFixedObjOffset - SlotSize;
int UnwindHelpFI =
MFI->CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false);
- MF.getWinEHFuncInfo()->UnwindHelpFrameIdx = UnwindHelpFI;
+ EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
// Store -2 into UnwindHelp on function entry. We have to scan forwards past
// other frame setup instructions.
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 596f487681c..b2e20110421 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -18236,6 +18236,10 @@ unsigned X86TargetLowering::getExceptionSelectorRegister(
return Subtarget.isTarget64BitLP64() ? X86::RDX : X86::EDX;
}
+bool X86TargetLowering::needsFixedCatchObjects() const {
+ return Subtarget.isTargetWin64();
+}
+
SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
SDValue Offset = Op.getOperand(1);
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 4ee5e613909..a6dd76253c3 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -927,6 +927,8 @@ namespace llvm {
unsigned
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
+ virtual bool needsFixedCatchObjects() const override;
+
/// This method returns a target specific FastISel object,
/// or null if the target does not support "fast" ISel.
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
diff --git a/llvm/test/CodeGen/X86/catchpad-dynamic-alloca.ll b/llvm/test/CodeGen/X86/catchpad-dynamic-alloca.ll
new file mode 100644
index 00000000000..4e8a8d8868b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/catchpad-dynamic-alloca.ll
@@ -0,0 +1,65 @@
+; RUN: llc < %s | FileCheck %s
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+declare void @rt_init()
+
+declare i32 @__CxxFrameHandler3(...)
+
+define void @test1(void ()* %fp, i64 %n) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ %t.i = alloca i8*
+ %t.ii = alloca i8
+ %.alloca8 = alloca i8, i64 %n
+ store volatile i8 0, i8* %t.ii
+ store volatile i8 0, i8* %.alloca8
+ invoke void @rt_init()
+ to label %try.cont unwind label %catch.switch
+
+try.cont:
+ invoke void %fp()
+ to label %exit unwind label %catch.switch
+
+exit:
+ ret void
+
+catch.pad:
+ %cp = catchpad within %cs [i8* null, i32 0, i8** %t.i]
+ catchret from %cp to label %exit
+
+catch.switch:
+ %cs = catchswitch within none [label %catch.pad] unwind to caller
+}
+
+; CHECK-LABEL: $handlerMap$0$test1:
+; CHECK: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 16
+
+define void @test2(void ()* %fp, i64 %n) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+ %t.i = alloca i128
+ %.alloca8 = alloca i8, i64 %n
+ store volatile i8 0, i8* %.alloca8
+ invoke void @rt_init()
+ to label %try.cont unwind label %catch.switch
+
+try.cont:
+ invoke void %fp()
+ to label %exit unwind label %catch.switch
+
+exit:
+ ret void
+
+catch.pad:
+ %cp = catchpad within %cs [i8* null, i32 0, i128* %t.i]
+ catchret from %cp to label %exit
+
+catch.switch:
+ %cs = catchswitch within none [label %catch.pad] unwind to caller
+}
+
+; CHECK-LABEL: $handlerMap$0$test2:
+; CHECK: .long 0
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long 8
diff --git a/llvm/test/CodeGen/X86/catchpad-lifetime.ll b/llvm/test/CodeGen/X86/catchpad-lifetime.ll
index dfd75334561..77d3f25057c 100644
--- a/llvm/test/CodeGen/X86/catchpad-lifetime.ll
+++ b/llvm/test/CodeGen/X86/catchpad-lifetime.ll
@@ -16,7 +16,7 @@ entry:
to label %unreachable unwind label %catch.dispatch
; CHECK-LABEL: test1:
-; CHECK: movq $0, -16(%rbp)
+; CHECK: movq $0, -8(%rbp)
; CHECK: callq throw
catch.dispatch: ; preds = %entry
@@ -33,8 +33,8 @@ catch.pad: ; preds = %catch.dispatch
unreachable
; CHECK-LABEL: "?catch$2@?0?test1@4HA"
-; CHECK: movq $0, -16(%rbp)
-; CHECK: movq $0, -16(%rbp)
+; CHECK: movq $0, -8(%rbp)
+; CHECK: movq $0, -8(%rbp)
; CHECK: ud2
unreachable: ; preds = %entry
@@ -42,7 +42,7 @@ unreachable: ; preds = %entry
}
; CHECK-LABEL: $cppxdata$test1:
-; CHECK: .long 32 # CatchObjOffset
+; CHECK: .long 56 # CatchObjOffset
define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
entry:
diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll
index f6db515cbad..22e206a9b90 100644
--- a/llvm/test/CodeGen/X86/win-catchpad.ll
+++ b/llvm/test/CodeGen/X86/win-catchpad.ll
@@ -122,19 +122,19 @@ try.cont:
; X64: Lfunc_begin0:
; X64: pushq %rbp
; X64: .seh_pushreg 5
-; X64: subq $48, %rsp
-; X64: .seh_stackalloc 48
-; X64: leaq 48(%rsp), %rbp
-; X64: .seh_setframe 5, 48
+; X64: subq $[[STCK_ALLOC:.*]], %rsp
+; X64: .seh_stackalloc [[STCK_ALLOC]]
+; X64: leaq [[STCK_ALLOC]](%rsp), %rbp
+; X64: .seh_setframe 5, [[STCK_ALLOC]]
; X64: .seh_endprologue
-; X64: movq $-2, -8(%rbp)
+; X64: movq $-2, -16(%rbp)
; X64: .Ltmp0
; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx
; X64-DAG: movl $1, %ecx
; X64: callq f
; X64: [[contbb:\.LBB0_[0-9]+]]: # Block address taken
; X64-NEXT: # %try.cont
-; X64: addq $48, %rsp
+; X64: addq $[[STCK_ALLOC]], %rsp
; X64: popq %rbp
; X64: retq
@@ -145,10 +145,10 @@ try.cont:
; X64: .seh_pushreg 5
; X64: subq $32, %rsp
; X64: .seh_stackalloc 32
-; X64: leaq 48(%rdx), %rbp
+; X64: leaq [[STCK_ALLOC]](%rdx), %rbp
; X64: .seh_endprologue
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
-; X64-DAG: movl -12(%rbp), %ecx
+; X64-DAG: movl -4(%rbp), %ecx
; X64: callq f
; X64: leaq [[contbb]](%rip), %rax
; X64-NEXT: addq $32, %rsp
@@ -162,7 +162,7 @@ try.cont:
; X64: .seh_pushreg 5
; X64: subq $32, %rsp
; X64: .seh_stackalloc 32
-; X64: leaq 48(%rdx), %rbp
+; X64: leaq [[STCK_ALLOC]](%rdx), %rbp
; X64: .seh_endprologue
; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
; X64-DAG: movl $3, %ecx
@@ -180,7 +180,7 @@ try.cont:
; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL
; X64-NEXT: .long 5
; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL
-; X64-NEXT: .long 40
+; X64-NEXT: .long 48
; X64-NEXT: .long 0
; X64-NEXT: .long 1
@@ -194,7 +194,7 @@ try.cont:
; X64: $handlerMap$0$try_catch_catch:
; X64-NEXT: .long 0
; X64-NEXT: .long "??_R0H@8"@IMGREL
-; X64-NEXT: .long 36
+; X64-NEXT: .long 60
; X64-NEXT: .long "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
; X64-NEXT: .long 56
; X64-NEXT: .long 64
OpenPOWER on IntegriCloud