<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>