summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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