Index: llvm/trunk/include/llvm/Target/TargetLowering.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetLowering.h +++ llvm/trunk/include/llvm/Target/TargetLowering.h @@ -960,6 +960,10 @@ 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 { Index: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -88,6 +88,7 @@ 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 Outs; @@ -96,6 +97,31 @@ 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 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 @@ 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 @@ 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 @@ 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()]; } Index: llvm/trunk/lib/CodeGen/StackColoring.cpp =================================================================== --- llvm/trunk/lib/CodeGen/StackColoring.cpp +++ llvm/trunk/lib/CodeGen/StackColoring.cpp @@ -249,11 +249,13 @@ 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 @@ 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); Index: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp @@ -2839,14 +2839,30 @@ // 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. Index: llvm/trunk/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h @@ -927,6 +927,8 @@ 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, Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -18236,6 +18236,10 @@ 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); Index: llvm/trunk/test/CodeGen/X86/catchpad-dynamic-alloca.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/catchpad-dynamic-alloca.ll +++ llvm/trunk/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 Index: llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll +++ llvm/trunk/test/CodeGen/X86/catchpad-lifetime.ll @@ -16,7 +16,7 @@ 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 @@ 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 @@ } ; CHECK-LABEL: $cppxdata$test1: -; CHECK: .long 32 # CatchObjOffset +; CHECK: .long 56 # CatchObjOffset define void @test2() personality i32 (...)* @__CxxFrameHandler3 { entry: Index: llvm/trunk/test/CodeGen/X86/win-catchpad.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/win-catchpad.ll +++ llvm/trunk/test/CodeGen/X86/win-catchpad.ll @@ -122,19 +122,19 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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