<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, May 13, 2014 at 12:36 PM, Stephan Tolksdorf <span dir="ltr"><<a href="mailto:st@quanttec.com" target="_blank">st@quanttec.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">On 2014-05-11 Richard Smith wrote:<br>
</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">
On Sun, May 11, 2014 at 8:19 AM, Stephan Tolksdorf <<a href="mailto:st@quanttec.com" target="_blank">st@quanttec.com</a><br></div><div class="">
<mailto:<a href="mailto:st@quanttec.com" target="_blank">st@quanttec.com</a>>> wrote:<br>
<br>
    Hi,<br>
<br>
    When clang/LLVM can't prove that a noexcept function only contains<br>
    non-throwing code, it seems to insert an explicit exception handler<br>
    that calls std::terminate. Why doesn't clang leave it to the eh<br>
    personality function to call std::terminate when an exception is<br>
    thrown inside a noexcept function, as GCC does?<br>
<br>
<br>
As far as I can see, this is impossible to represent in LLVM IR. (If<br>
there is a way, I'm sure we'd be happy to make clang emit that IR.)<br>
</div></blockquote>
<br>
Thanks for the reply! Do you or maybe somebody else have an opinion on what the best way would be to efficiently support this case in LLVM IR?<br></blockquote><div><br></div><div>Here's a reduced testcase:</div><div>
<br></div><div>void f();</div><div>void g() noexcept { f(); }</div><div><br></div><div>One obvious approach would be to emit the call to 'f' as a 'call', not an 'invoke', with some attribute indicating that the program is terminated if it unwinds. (We can't use 'nounwind' for this, because that gives us UB on unwind, not a call to terminate.)</div>
<div><br></div><div>Not-very-well-thought-through strawman: add a function attribute to indicate that that the function does not return if a call unwinds (and pass it the personality function so that we can generate the right CFI stuff).</div>
<div><br></div><div>call void @_Z1fv() terminateonunwind(i32 (...)* @__gxx_personality_v0)</div><div><br></div><div>This would result in a call that is not covered by any range in the call site table in the calling function's LSDA.</div>
<div><br></div><div><br></div><div>Another case:</div><div><br></div><div>void h() noexcept { try { f(); } catch (int) {} }</div><div><br></div><div>Here, I don't think there's a better representation than the one we're currently using (though we should at least omit the pointless __cxa_begin_catch immediately before our synthesized call to std::terminate).</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div><div class="h5">    For example, GCC generates more efficient code for this test case:<br>
<br>
       using FP = void(*)();<br>
<br>
       inline void test(FP fp) noexcept {<br>
         fp();<br>
       }<br>
<br>
       void test2(FP fp) {<br>
         test(fp);<br>
         test(fp);<br>
       }<br>
<br>
    The code generated by GCC (ToT, -O3, Linux x64) is:<br>
<br>
    .LHOTB0:<br>
             .p2align 4,,15<br>
             .globl  _Z5test2PFvvE<br>
             .type   _Z5test2PFvvE, @function<br>
    _Z5test2PFvvE:<br>
    .LFB1:<br>
             .cfi_startproc<br>
             .cfi_personality 0x3,__gxx_personality_v0<br>
             .cfi_lsda 0x3,.LLSDA1<br>
             pushq   %rbx<br>
             .cfi_def_cfa_offset 16<br>
             .cfi_offset 3, -16<br>
             movq    %rdi, %rbx<br>
             call    *%rdi<br>
             movq    %rbx, %rax<br>
             popq    %rbx<br>
             .cfi_def_cfa_offset 8<br>
             jmp     *%rax<br>
             .cfi_endproc<br>
    .LFE1:<br>
             .globl  __gxx_personality_v0<br></div></div>
             .section        .gcc_except_table,"a",@__<u></u>progbits<div><div class="h5"><br>
    .LLSDA1:<br>
             .byte   0xff<br>
             .byte   0xff<br>
             .byte   0x1<br>
             .uleb128 .LLSDACSE1-.LLSDACSB1<br>
    .LLSDACSB1:<br>
    .LLSDACSE1:<br>
             .text<br>
             .size   _Z5test2PFvvE, .-_Z5test2PFvvE<br>
             .section        .text.unlikely<br>
<br>
<br>
    The code generated by clang (ToT, -O3, Linux x64) is:<br>
<br>
    .globl  _Z5test2PFvvE<br>
             .align  16, 0x90<br>
             .type   _Z5test2PFvvE,@function<br>
    _Z5test2PFvvE:                          # @_Z5test2PFvvE<br>
             .cfi_startproc<br>
             .cfi_personality 3, __gxx_personality_v0<br>
    .Leh_func_begin0:<br>
             .cfi_lsda 3, .Lexception0<br>
    # BB#0:                                 # %entry<br>
             pushq   %rbx<br>
    .Ltmp6:<br>
             .cfi_def_cfa_offset 16<br>
    .Ltmp7:<br>
             .cfi_offset %rbx, -16<br>
             movq    %rdi, %rbx<br>
    .Ltmp0:<br>
             callq   *%rbx<br>
    .Ltmp1:<br>
    # BB#1:                                 # %_Z4testPFvvE.exit<br>
    .Ltmp3:<br>
             callq   *%rbx<br>
    .Ltmp4:<br>
    # BB#2:                                 # %_Z4testPFvvE.exit3<br>
             popq    %rbx<br>
             retq<br>
    .LBB0_3:                                # %terminate.lpad.i<br>
    .Ltmp2:<br>
             movq    %rax, %rdi<br>
             callq   __clang_call_terminate<br>
    .LBB0_4:                                # %terminate.lpad.i2<br>
    .Ltmp5:<br>
             movq    %rax, %rdi<br>
             callq   __clang_call_terminate<br>
    .Ltmp8:<br>
             .size   _Z5test2PFvvE, .Ltmp8-_Z5test2PFvvE<br>
             .cfi_endproc<br>
    .Leh_func_end0:<br></div></div>
             .section        .gcc_except_table,"a",@__<u></u>progbits<div><div class="h5"><br>
             .align  4<br>
    GCC_except_table0:<br>
    .Lexception0:<br>
             .byte   255                     # @LPStart Encoding = omit<br>
             .byte   3                       # @TType Encoding = udata4<br>
             .asciz  "\242\200\200"          # @TType base offset<br>
             .byte   3                       # Call site Encoding = udata4<br>
             .byte   26                      # Call site table length<br>
    .Lset0 = .Ltmp0-.Leh_func_begin0        # >> Call Site 1 <<<br>
             .long   .Lset0<br>
    .Lset1 = .Ltmp1-.Ltmp0                  #   Call between .Ltmp0 and<br>
    .Ltmp1<br>
             .long   .Lset1<br>
    .Lset2 = .Ltmp2-.Leh_func_begin0        #     jumps to .Ltmp2<br>
             .long   .Lset2<br>
             .byte   1                       #   On action: 1<br>
    .Lset3 = .Ltmp3-.Leh_func_begin0        # >> Call Site 2 <<<br>
             .long   .Lset3<br>
    .Lset4 = .Ltmp4-.Ltmp3                  #   Call between .Ltmp3 and<br>
    .Ltmp4<br>
             .long   .Lset4<br>
    .Lset5 = .Ltmp5-.Leh_func_begin0        #     jumps to .Ltmp5<br>
             .long   .Lset5<br>
             .byte   1                       #   On action: 1<br>
             .byte   1                       # >> Action Record 1 <<<br>
                                             #   Catch TypeInfo 1<br>
             .byte   0                       #   No further actions<br>
                                             # >> Catch TypeInfos <<<br>
             .long   0                       # TypeInfo 1<br>
             .align  4<br>
<br>
             .section<br></div></div>
    .text.__clang_call_terminate,"<u></u>__axG",@progbits,__clang_call_<u></u>__terminate,comdat<div class=""><br>
             .hidden __clang_call_terminate<br>
             .weak   __clang_call_terminate<br>
             .align  16, 0x90<br></div>
             .type   __clang_call_terminate,@__<u></u>function<div class=""><br>
    __clang_call_terminate:                 # @__clang_call_terminate<br>
    # BB#0:<br>
             pushq   %rax<br>
             callq   __cxa_begin_catch<br>
             callq   _ZSt9terminatev<br>
    .Ltmp9:<br>
             .size   __clang_call_terminate, .Ltmp9-__clang_call_terminate<br>
<br>
    - Stephan<br></div>
    ______________________________<u></u>___________________<br>
    cfe-dev mailing list<br>
    <a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a> <mailto:<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a>><br>
    <a href="http://lists.cs.uiuc.edu/__mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/__<u></u>mailman/listinfo/cfe-dev</a><br>
    <<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-dev</a>><br>
<br>
<br>
</blockquote>
</blockquote></div><br></div></div>