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

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 14:58:12 PDT 2015


David ended up solving the problem a different way (powering down
BranchFolding), so I guess I won't pursue this.

On Thu, Oct 1, 2015 at 10:18 AM, NAKAMURA Takumi <geek4civic at gmail.com>
wrote:

> 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/b7de1833/attachment.html>


More information about the llvm-commits mailing list