From: David Majnemer Date: Tue, 1 Mar 2016 04:30:16 +0000 (+0000) Subject: [WinEH] Allocate the registration node before the catch objects X-Git-Tag: llvmorg-3.9.0-rc1~12861 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb305dea1cdd343510813ac813ecbfdac3906a80;p=platform%2Fupstream%2Fllvm.git [WinEH] Allocate the registration node before the catch objects The CatchObjOffset is relative to the end of the EH registration node for 32-bit x86 WinEH targets. A special sentinel value, 0, is used to indicate that no catch object should be initialized. This means that a catch object allocated immediately before the registration node would be assigned a CatchObjOffset of 0, leading the runtime to believe that a catch object should not be initialized. To handle this, allocate the registration node prior to any other frame object. This will ensure that catch objects will not be allocated before the registration node. This fixes PR26757. Differential Revision: http://reviews.llvm.org/D17689 llvm-svn: 262294 --- diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 4da5b58..c3120e6 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -793,6 +793,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { const MCExpr *FrameAllocOffsetRef = nullptr; if (HT.CatchObj.FrameIndex != INT_MAX) { int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo); + assert(Offset != 0 && "Illegal offset for catch object!"); FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext); } else { FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext); diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 14a2d08..96034ec 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -709,6 +709,10 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { SmallVector ObjectsToAllocate; + int EHRegNodeFrameIndex = INT_MAX; + if (const WinEHFuncInfo *FuncInfo = Fn.getWinEHFuncInfo()) + EHRegNodeFrameIndex = FuncInfo->EHRegNodeFrameIndex; + // Then prepare to assign frame offsets to stack objects that are not used to // spill callee saved registers. for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { @@ -723,12 +727,20 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { continue; if (MFI->getStackProtectorIndex() == (int)i) continue; + if (EHRegNodeFrameIndex == (int)i) + continue; if (ProtectedObjs.count(i)) continue; // Add the objects that we need to allocate to our working set. ObjectsToAllocate.push_back(i); } + + // Allocate the EH registration node first if one is present. + if (EHRegNodeFrameIndex != INT_MAX) + AdjustStackOffset(MFI, EHRegNodeFrameIndex, StackGrowsDown, Offset, + MaxAlign, Skew); + // Give the targets a chance to order the objects the way they like it. if (Fn.getTarget().getOptLevel() != CodeGenOpt::None && Fn.getTarget().Options.StackSymbolOrdering) diff --git a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll index 924dcf7..2e34ada 100644 --- a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll +++ b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll @@ -51,7 +51,7 @@ ehcleanup: ; preds = %entry ; CHECK: "?dtor$2@?0?passes_two@4HA": ; CHECK: pushl %ebp ; CHECK: subl $8, %esp -; CHECK: addl $16, %ebp +; CHECK: addl $12, %ebp ; CHECK: {{movl|leal}} -{{[0-9]+}}(%ebp), %ecx ; CHECK: calll "??1A@@QAE@XZ" ; CHECK: addl $8, %esp diff --git a/llvm/test/CodeGen/X86/pr26757.ll b/llvm/test/CodeGen/X86/pr26757.ll new file mode 100644 index 0000000..96cbb78 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr26757.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc" + +declare void @throw() + +define void @test1() personality i32 (...)* @__CxxFrameHandler3 { + %e = alloca i8, align 4 + invoke void @throw() + to label %.noexc unwind label %catch.dispatch + +.noexc: + unreachable + +catch.object.Exception: + %cp = catchpad within %cs [i8* null, i32 0, i8* %e] + catchret from %cp to label %catchhandler + +catch.dispatch: + %cs = catchswitch within none [label %catch.object.Exception] unwind to caller + +catchhandler: + call void @use(i8* %e) + ret void +} + +; CHECK-LABEL: $handlerMap$0$test1: +; CHECK: .long 0 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long -20 + +declare void @use(i8*) + +declare i32 @__CxxFrameHandler3(...)