[llvm] r248959 - [WinEH] Emit int3 after noreturn calls on Win64

NAKAMURA Takumi via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 10:18:27 PDT 2015


Reverted in r249032. It broke the builder,
http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/5516

On Thu, Oct 1, 2015 at 8:11 AM Reid Kleckner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: rnk
> Date: Wed Sep 30 18:09:23 2015
> New Revision: 248959
>
> URL: http://llvm.org/viewvc/llvm-project?rev=248959&view=rev
> Log:
> [WinEH] Emit int3 after noreturn calls on Win64
>
> The Win64 unwinder disassembles forwards from each PC to try to
> determine if this PC is in an epilogue. If so, it skips calling the EH
> personality function for that frame. Typically, this means you cannot
> catch an exception in the same frame that you threw it, because 'throw'
> calls a noreturn runtime function.
>
> Previously we avoided this problem with the TrapUnreachable
> TargetOption, but that's a much bigger hammer than we need. All we need
> is a 1 byte non-epilogue instruction right after the call.  Instead,
> what we got was an unconditional branch to a shared block containing the
> ud2, potentially 7 bytes instead of 1. So, this reverts r206684, which
> added TrapUnreachable, and replaces it with something better.
>
> The new code pattern matches for invoke/call followed by unreachable and
> inserts an int3 into the DAG. To be 100% watertight, we would need to
> insert SEH_Epilogue instructions into all basic blocks ending in a call
> with no terminators or successors, but in practice this is unlikely to
> come up.
>
> Added:
>     llvm/trunk/test/CodeGen/X86/win-catchpad-rethrow.ll
> Modified:
>     llvm/trunk/include/llvm/Target/TargetOptions.h
>     llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>     llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>     llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
>     llvm/trunk/test/CodeGen/X86/br-fold.ll
>     llvm/trunk/test/CodeGen/X86/win64_call_epi.ll
>
> Modified: llvm/trunk/include/llvm/Target/TargetOptions.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOptions.h?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetOptions.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetOptions.h Wed Sep 30 18:09:23 2015
> @@ -71,7 +71,7 @@ namespace llvm {
>            EnableFastISel(false), PositionIndependentExecutable(false),
>            UseInitArray(false), DisableIntegratedAS(false),
>            CompressDebugSections(false), FunctionSections(false),
> -          DataSections(false), UniqueSectionNames(true),
> TrapUnreachable(false),
> +          DataSections(false), UniqueSectionNames(true),
>            EmulatedTLS(false), FloatABIType(FloatABI::Default),
>            AllowFPOpFusion(FPOpFusion::Standard),
> Reciprocals(TargetRecip()),
>            JTType(JumpTable::Single),
> @@ -169,9 +169,6 @@ namespace llvm {
>
>      unsigned UniqueSectionNames : 1;
>
> -    /// Emit target-specific trap instruction for 'unreachable' IR
> instructions.
> -    unsigned TrapUnreachable : 1;
> -
>      /// EmulatedTLS - This flag enables emulated TLS model, using emutls
>      /// function in the runtime library..
>      unsigned EmulatedTLS : 1;
> @@ -234,7 +231,6 @@ inline bool operator==(const TargetOptio
>      ARE_EQUAL(EnableFastISel) &&
>      ARE_EQUAL(PositionIndependentExecutable) &&
>      ARE_EQUAL(UseInitArray) &&
> -    ARE_EQUAL(TrapUnreachable) &&
>      ARE_EQUAL(EmulatedTLS) &&
>      ARE_EQUAL(FloatABIType) &&
>      ARE_EQUAL(AllowFPOpFusion) &&
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Wed Sep 30 18:09:23
> 2015
> @@ -1569,10 +1569,8 @@ bool FastISel::selectOperator(const User
>    }
>
>    case Instruction::Unreachable:
> -    if (TM.Options.TrapUnreachable)
> -      return fastEmit_(MVT::Other, MVT::Other, ISD::TRAP) != 0;
> -    else
> -      return true;
> +    // Nothing to emit.
> +    return true;
>
>    case Instruction::Alloca:
>      // FunctionLowering has the static-sized case covered.
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Sep 30
> 18:09:23 2015
> @@ -2205,10 +2205,7 @@ void SelectionDAGBuilder::visitIndirectB
>                            getValue(I.getAddress())));
>  }
>
> -void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {
> -  if (DAG.getTarget().Options.TrapUnreachable)
> -    DAG.setRoot(DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other,
> DAG.getRoot()));
> -}
> +void SelectionDAGBuilder::visitUnreachable(const UnreachableInst &I) {}
>
>  void SelectionDAGBuilder::visitFSub(const User &I) {
>    // -0.0 - X --> fneg
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Sep 30 18:09:23 2015
> @@ -2945,6 +2945,20 @@ static SDValue getMOVL(SelectionDAG &DAG
>    return DAG.getVectorShuffle(VT, dl, V1, V2, &Mask[0]);
>  }
>
> +/// Check if the fall through instruction after a call site is
> unreachable.
> +/// FIXME: This will fail if there are interesting non-code generating IR
> +/// instructions between the call and the unreachable (lifetime.end). In
> +/// practice, this should be rare because optimizations like to delete
> non-call
> +/// code before unreachable.
> +static bool isCallFollowedByUnreachable(ImmutableCallSite CS) {
> +  const Instruction *NextInst;
> +  if (auto *II = dyn_cast<InvokeInst>(CS.getInstruction()))
> +    NextInst = II->getNormalDest()->getFirstNonPHIOrDbg();
> +  else
> +    NextInst = CS.getInstruction()->getNextNode();
> +  return isa<UnreachableInst>(NextInst);
> +}
> +
>  SDValue
>  X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
>                               SmallVectorImpl<SDValue> &InVals) const {
> @@ -3450,6 +3464,15 @@ X86TargetLowering::LowerCall(TargetLower
>      InFlag = Chain.getValue(1);
>    }
>
> +  if (Subtarget->isTargetWin64() && CLI.CS) {
> +    // Look for a call followed by unreachable. On Win64, we need to
> ensure that
> +    // the call does not accidentally fall through to something that
> looks like
> +    // an epilogue. We do this by inserting a DEBUGTRAP, which lowers to
> int3,
> +    // which is what MSVC emits after noreturn calls.
> +    if (isCallFollowedByUnreachable(*CLI.CS))
> +      Chain = DAG.getNode(ISD::DEBUGTRAP, dl, MVT::Other, Chain);
> +  }
> +
>    // Handle result values, copying them out of physregs into vregs that we
>    // return.
>    return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
>
> Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Wed Sep 30 18:09:23 2015
> @@ -110,13 +110,6 @@ X86TargetMachine::X86TargetMachine(const
>                          OL),
>        TLOF(createTLOF(getTargetTriple())),
>        Subtarget(TT, CPU, FS, *this, Options.StackAlignmentOverride) {
> -  // Windows stack unwinder gets confused when execution flow "falls
> through"
> -  // after a call to 'noreturn' function.
> -  // To prevent that, we emit a trap for 'unreachable' IR instructions.
> -  // (which on X86, happens to be the 'ud2' instruction)
> -  if (Subtarget.isTargetWin64())
> -    this->Options.TrapUnreachable = true;
> -
>    // By default (and when -ffast-math is on), enable estimate codegen for
>    // everything except scalar division. By default, use 1 refinement step
> for
>    // all operations. Defaults may be overridden by using command-line
> options.
>
> Modified: llvm/trunk/test/CodeGen/X86/br-fold.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/br-fold.ll?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/br-fold.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/br-fold.ll Wed Sep 30 18:09:23 2015
> @@ -10,10 +10,10 @@
>  ; X64_LINUX-NEXT: %bb8.i329
>
>  ; X64_WINDOWS: orq %rax, %rcx
> -; X64_WINDOWS-NEXT: ud2
> +; X64_WINDOWS-NEXT: %bb8.i329
>
>  ; X64_WINDOWS_GNU: orq %rax, %rcx
> -; X64_WINDOWS_GNU-NEXT: ud2
> +; X64_WINDOWS_GNU-NEXT: %bb8.i329
>
>  @_ZN11xercesc_2_513SchemaSymbols21fgURI_SCHEMAFORSCHEMAE = external
> constant [33 x i16], align 32 ; <[33 x i16]*> [#uses=1]
>  @_ZN11xercesc_2_56XMLUni16fgNotationStringE = external constant [9 x
> i16], align 16 ; <[9 x i16]*> [#uses=1]
>
> Added: llvm/trunk/test/CodeGen/X86/win-catchpad-rethrow.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win-catchpad-rethrow.ll?rev=248959&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/win-catchpad-rethrow.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/win-catchpad-rethrow.ll Wed Sep 30
> 18:09:23 2015
> @@ -0,0 +1,103 @@
> +; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s
> +
> +; C++ EH rethrows are interesting, because they are calls to noreturn
> +; functions. There *must* be some code after the call instruction that
> doesn't
> +; look like an epilogue. We use int3 to be consistent with MSVC.
> +
> +; Based on this C++ source:
> +; int main() {
> +;   try {
> +;     throw 42;
> +;   } catch (int) {
> +;     try {
> +;       throw;
> +;     } catch (int) {
> +;     }
> +;   }
> +;   return 0;
> +; }
> +
> +; ModuleID = 't.cpp'
> +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-pc-windows-msvc"
> +
> +%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
> +%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 }
> +%eh.CatchableTypeArray.1 = type { i32, [1 x i32] }
> +%eh.ThrowInfo = type { i32, i32, i32, i32 }
> +
> +$"\01??_R0H at 8" = comdat any
> +
> +$"_CT??_R0H at 84" = comdat any
> +
> +$_CTA1H = comdat any
> +
> +$_TI1H = comdat any
> +
> +@"\01??_7type_info@@6B@" = external constant i8*
> +@"\01??_R0H at 8" = linkonce_odr global %rtti.TypeDescriptor2 { i8**
> @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
> + at __ImageBase = external constant i8
> +@"_CT??_R0H at 84" = linkonce_odr unnamed_addr constant %eh.CatchableType {
> i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2*
> @"\01??_R0H at 8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32),
> i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat
> + at _CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 {
> i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint
> (%eh.CatchableType* @"_CT??_R0H at 84" to i64), i64 ptrtoint (i8*
> @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
> + at _TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0,
> i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1*
> @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section
> ".xdata", comdat
> +
> +define i32 @main() #0 personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*) {
> +entry:
> +  %tmp = alloca i32, align 4
> +  store i32 42, i32* %tmp, align 4
> +  %0 = bitcast i32* %tmp to i8*
> +  invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* nonnull @_TI1H)
> #1
> +          to label %unreachable unwind label %catch.dispatch
> +
> +catch.dispatch:                                   ; preds = %entry
> +  %1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
> +          to label %catch unwind label %catchendblock
> +
> +catch:                                            ; preds =
> %catch.dispatch
> +  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
> +          to label %unreachable unwind label %catch.dispatch.1
> +
> +catch.dispatch.1:                                 ; preds = %catch
> +  %2 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H at 8", i32 0, i8* null]
> +          to label %catch.3 unwind label %catchendblock.2
> +
> +catch.3:                                          ; preds =
> %catch.dispatch.1
> +  catchret %2 to label %try.cont
> +
> +try.cont:                                         ; preds = %catch.3
> +  catchret %1 to label %try.cont.5
> +
> +try.cont.5:                                       ; preds = %try.cont
> +  ret i32 0
> +
> +catchendblock.2:                                  ; preds =
> %catch.dispatch.1
> +  catchendpad unwind label %catchendblock
> +
> +catchendblock:                                    ; preds =
> %catchendblock.2, %catch.dispatch
> +  catchendpad unwind to caller
> +
> +unreachable:                                      ; preds = %catch, %entry
> +  unreachable
> +}
> +
> +declare void @_CxxThrowException(i8*, %eh.ThrowInfo*)
> +
> +declare i32 @__CxxFrameHandler3(...)
> +
> +attributes #0 = { "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="false"
> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
> "stack-protector-buffer-size"="8" "target-features"="+sse,+sse2"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { noreturn }
> +
> +; CHECK: main:
> +; CHECK: .seh_proc main
> +; CHECK: movl $42,
> +; CHECK-DAG: leaq {{.*}}, %rcx
> +; CHECK-DAG: leaq _TI1H(%rip), %rdx
> +; CHECK: callq _CxxThrowException
> +; CHECK-NEXT: int3
> +
> +; CHECK: "?catch$1@?0?main at 4HA":
> +; CHECK: .seh_proc "?catch$1@?0?main at 4HA"
> +; CHECK-DAG: xorl %ecx, %ecx
> +; CHECK-DAG: xorl %edx, %edx
> +; CHECK: callq _CxxThrowException
> +; CHECK-NEXT: int3
>
> Modified: llvm/trunk/test/CodeGen/X86/win64_call_epi.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win64_call_epi.ll?rev=248959&r1=248958&r2=248959&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/win64_call_epi.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/win64_call_epi.ll Wed Sep 30 18:09:23 2015
> @@ -24,9 +24,9 @@ catch:
>  ; WIN64: nop
>  ; WIN64: addq ${{[0-9]+}}, %rsp
>  ; WIN64: retq
> -; Check for 'ud2' after noreturn call
> +; Check for 'int3' after noreturn call
>  ; WIN64: callq _Unwind_Resume
> -; WIN64-NEXT: ud2
> +; WIN64-NEXT: int3
>  ; WIN64: .seh_endproc
>
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151001/b84a1954/attachment-0001.html>


More information about the llvm-commits mailing list