[cfe-dev] Code generation for noexcept functions

Stephan Tolksdorf st at quanttec.com
Sun May 11 08:19:46 PDT 2014


Hi,

When clang/LLVM can't prove that a noexcept function only contains 
non-throwing code, it seems to insert an explicit exception handler that 
calls std::terminate. Why doesn't clang leave it to the eh personality 
function to call std::terminate when an exception is thrown inside a 
noexcept function, as GCC does?

For example, GCC generates more efficient code for this test case:

   using FP = void(*)();

   inline void test(FP fp) noexcept {
     fp();
   }

   void test2(FP fp) {
     test(fp);
     test(fp);
   }

The code generated by GCC (ToT, -O3, Linux x64) is:

.LHOTB0:
	.p2align 4,,15
	.globl	_Z5test2PFvvE
	.type	_Z5test2PFvvE, @function
_Z5test2PFvvE:
.LFB1:
	.cfi_startproc
	.cfi_personality 0x3,__gxx_personality_v0
	.cfi_lsda 0x3,.LLSDA1
	pushq	%rbx
	.cfi_def_cfa_offset 16
	.cfi_offset 3, -16
	movq	%rdi, %rbx
	call	*%rdi
	movq	%rbx, %rax
	popq	%rbx
	.cfi_def_cfa_offset 8
	jmp	*%rax
	.cfi_endproc
.LFE1:
	.globl	__gxx_personality_v0
	.section	.gcc_except_table,"a", at progbits
.LLSDA1:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSE1-.LLSDACSB1
.LLSDACSB1:
.LLSDACSE1:
	.text
	.size	_Z5test2PFvvE, .-_Z5test2PFvvE
	.section	.text.unlikely


The code generated by clang (ToT, -O3, Linux x64) is:

.globl	_Z5test2PFvvE
	.align	16, 0x90
	.type	_Z5test2PFvvE, at function
_Z5test2PFvvE:                          # @_Z5test2PFvvE
	.cfi_startproc
	.cfi_personality 3, __gxx_personality_v0
.Leh_func_begin0:
	.cfi_lsda 3, .Lexception0
# BB#0:                                 # %entry
	pushq	%rbx
.Ltmp6:
	.cfi_def_cfa_offset 16
.Ltmp7:
	.cfi_offset %rbx, -16
	movq	%rdi, %rbx
.Ltmp0:
	callq	*%rbx
.Ltmp1:
# BB#1:                                 # %_Z4testPFvvE.exit
.Ltmp3:
	callq	*%rbx
.Ltmp4:
# BB#2:                                 # %_Z4testPFvvE.exit3
	popq	%rbx
	retq
.LBB0_3:                                # %terminate.lpad.i
.Ltmp2:
	movq	%rax, %rdi
	callq	__clang_call_terminate
.LBB0_4:                                # %terminate.lpad.i2
.Ltmp5:
	movq	%rax, %rdi
	callq	__clang_call_terminate
.Ltmp8:
	.size	_Z5test2PFvvE, .Ltmp8-_Z5test2PFvvE
	.cfi_endproc
.Leh_func_end0:
	.section	.gcc_except_table,"a", at progbits
	.align	4
GCC_except_table0:
.Lexception0:
	.byte	255                     # @LPStart Encoding = omit
	.byte	3                       # @TType Encoding = udata4
	.asciz	"\242\200\200"          # @TType base offset
	.byte	3                       # Call site Encoding = udata4
	.byte	26                      # Call site table length
.Lset0 = .Ltmp0-.Leh_func_begin0        # >> Call Site 1 <<
	.long	.Lset0
.Lset1 = .Ltmp1-.Ltmp0                  #   Call between .Ltmp0 and .Ltmp1
	.long	.Lset1
.Lset2 = .Ltmp2-.Leh_func_begin0        #     jumps to .Ltmp2
	.long	.Lset2
	.byte	1                       #   On action: 1
.Lset3 = .Ltmp3-.Leh_func_begin0        # >> Call Site 2 <<
	.long	.Lset3
.Lset4 = .Ltmp4-.Ltmp3                  #   Call between .Ltmp3 and .Ltmp4
	.long	.Lset4
.Lset5 = .Ltmp5-.Leh_func_begin0        #     jumps to .Ltmp5
	.long	.Lset5
	.byte	1                       #   On action: 1
	.byte	1                       # >> Action Record 1 <<
                                         #   Catch TypeInfo 1
	.byte	0                       #   No further actions
                                         # >> Catch TypeInfos <<
	.long	0                       # TypeInfo 1
	.align	4

	.section 
.text.__clang_call_terminate,"axG", at progbits,__clang_call_terminate,comdat
	.hidden	__clang_call_terminate
	.weak	__clang_call_terminate
	.align	16, 0x90
	.type	__clang_call_terminate, at function
__clang_call_terminate:                 # @__clang_call_terminate
# BB#0:
	pushq	%rax
	callq	__cxa_begin_catch
	callq	_ZSt9terminatev
.Ltmp9:
	.size	__clang_call_terminate, .Ltmp9-__clang_call_terminate

- Stephan



More information about the cfe-dev mailing list