how to resolve llvm exception IR?

here are the cpp file:
$ cat -n eh1.catch.cpp
     1 #include <iostream>
     2
     3 int main()
     4 {
     5 try {
     6 throw 78;
     7 }
     8 catch (int){
     9
    10 std::cout << "at catch\n";
    11
    12 }
    13 }

LLVM-IR:

$ llvm-g++ -S -emit-llvm eh1.catch.cpp -o eh1.catch.ll

...
    46 define i32 @main() {
    47 entry:
    48 %0 = tail call i8* @__cxa_allocate_exception(i32 4)
nounwind ; <i8*> [#uses=2]
    49 %1 = bitcast i8* %0 to i32* ; <i32*> [#uses=1]
    50 store i32 78, i32* %1, align 4
    51 invoke void @__cxa_throw(i8* %0, i8* bitcast
(%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*), void (i8*)*
null) noreturn
    52 to label %invcont unwind label %lpad
    53
    54 invcont: ; preds = %entry
    55 unreachable
    56
    57 bb: ; preds = %lpad
    58 %2 = tail call i8* @__cxa_begin_catch(i8* %eh_ptr)
nounwind ; <i8*> [#uses=0]
    59 %3 = invoke
%"struct.std::basic_ostream<char,std::char_traits<char> >"*
@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char>

"* @_ZSt4cout, i8* getelementptr ([10 x i8]* @.str, i32 0, i32 0))

    60 to label %bb6 unwind label %lpad10
         ; <%"struct.std::basic_ostream<char,std::char_traits<char>

"*> [#uses=0]

    61
    62 bb6: ; preds = %bb
    63 tail call void @__cxa_end_catch()
    64 ret i32 0
    65
    66 lpad: ; preds = %entry
    67 %eh_ptr = tail call i8* @llvm.eh.exception()
; <i8*> [#uses=3]
    68 %eh_select9 = tail call i32 (i8*, i8*, ...)*
@llvm.eh.selector.i32(i8* %eh_ptr, i8* bitcast (i32 (...)*
@__gxx_personality_v0 to i8*), i8* bitcast
(%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*), i8* null)
     ; <i32> [#uses=1]
    69 %eh_typeid = tail call i32 @llvm.eh.typeid.for.i32(i8*
bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
  ; <i32> [#uses=1]
    70 %4 = icmp eq i32 %eh_select9, %eh_typeid
; <i1> [#uses=1]
    71 br i1 %4, label %bb, label %Unwind
    72
    73 lpad10: ; preds = %bb
    74 %eh_ptr11 = tail call i8* @llvm.eh.exception()
; <i8*> [#uses=2]
    75 %eh_select13 = tail call i32 (i8*, i8*, ...)*
@llvm.eh.selector.i32(i8* %eh_ptr11, i8* bitcast (i32 (...)*
@__gxx_personality_v0 to i8*), i8* null) ; <i32> [#uses=0]
    76 invoke void @__cxa_end_catch()
    77 to label %Unwind unwind label %lpad14
    78
    79 lpad14: ; preds = %lpad10
    80 %eh_ptr15 = tail call i8* @llvm.eh.exception()
; <i8*> [#uses=1]
    81 %eh_select17 = tail call i32 (i8*, i8*, ...)*
@llvm.eh.selector.i32(i8* %eh_ptr15, i8* bitcast (i32 (...)*
@__gxx_personality_v0 to i8*)) ; <i32> [#uses=0]
    82 tail call void @_ZSt9terminatev() noreturn nounwind
    83 unreachable
    84
    85 Unwind: ; preds = %lpad10, %lpad
    86 %eh_exception.0 = phi i8* [ %eh_ptr, %lpad ], [
%eh_ptr11, %lpad10 ] ; <i8*> [#uses=1]
    87 tail call void @_Unwind_Resume(i8* %eh_exception.0)
    88 unreachable
    89 }

my question is at line 59 can throw an exception?

here is another cpp file:
$ cat -n eh1.try.cpp
     1 #include <iostream>
     2
     3
     4
     5 int main()
     6 {
     7 try {
     8 std::cout << "before throw\n";
     9 throw 78;
    10
    11 }
    12 catch (int){
    13
    14 }
    15 }

the generated LLVM-IR :

46 define i32 @main() {
    47 entry:
    48 %0 = invoke
%"struct.std::basic_ostream<char,std::char_traits<char> >"*
@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char>

"* @_ZSt4cout, i8* getelementptr ([14 x i8]* @.str, i32 0, i32 0))

    49 to label %invcont unwind label %lpad
         ; <%"struct.std::basic_ostream<char,std::char_traits<char>

"*> [#uses=0]

    50
    51 invcont: ; preds = %entry
    52 %1 = tail call i8* @__cxa_allocate_exception(i32 4)
nounwind ; <i8*> [#uses=2]
    53 %2 = bitcast i8* %1 to i32* ; <i32*> [#uses=1]
    54 store i32 78, i32* %2, align 4
    55 invoke void @__cxa_throw(i8* %1, i8* bitcast
(%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*), void (i8*)*
null) noreturn
    56 to label %invcont1 unwind label %lpad
    57
    58 invcont1: ; preds = %invcont
    59 unreachable
    60
    61 bb: ; preds = %lpad
    62 %3 = tail call i8* @__cxa_begin_catch(i8* %eh_ptr)
nounwind ; <i8*> [#uses=0]
    63 tail call void @__cxa_end_catch()
    64 ret i32 0
    65
    66 lpad: ; preds = %invcont, %entry
    67 %eh_ptr = tail call i8* @llvm.eh.exception()
; <i8*> [#uses=3]
    68 %eh_select = tail call i32 (i8*, i8*, ...)*
@llvm.eh.selector.i32(i8* %eh_ptr, i8* bitcast (i32 (...)*
@__gxx_personality_v0 to i8*), i8* bitcast
(%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*), i8* null)
      ; <i32> [#uses=1]
    69 %eh_typeid = tail call i32 @llvm.eh.typeid.for.i32(i8*
bitcast (%struct.__fundamental_type_info_pseudo* @_ZTIi to i8*))
  ; <i32> [#uses=1]
    70 %4 = icmp eq i32 %eh_select, %eh_typeid ; <i1> [#uses=1]
    71 br i1 %4, label %bb, label %Unwind
    72
    73 Unwind: ; preds = %lpad
    74 tail call void @_Unwind_Resume(i8* %eh_ptr)
    75 unreachable
    76 }

here at line 48 can throw an exception?

my another problem : are there any different of above two llmv-ir
on handle c++ exception ?

best regards
zhangzw
2009-4-28

   59 %3 = invoke
%"struct.std::basic_ostream<char,std::char_traits<char> >"*
@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
(%"struct.std::basic_ostream<char,std::char_traits<char>

"* @_ZSt4cout, i8* getelementptr ([10 x i8]* @.str, i32 0, i32 0))

my question is at line 59 can throw an exception?

Yes. The 'invoke' instruction indicates a call which can return either via the normal return sequence or by throwing an exception.

my another problem : are there any different of above two llmv-ir
on handle c++ exception ?

Different in what way? I'm not sure I understand your question. In neither case will an exception thrown from the << operator be caught. In the first case, the << operator is not in a try block, and in both cases, only an exception of integer type is caught, while the << operator throws exceptions (when enabled) of type ios::exception.

Regards,
  Jim

Hi zhangzw,

...

    59 %3 = invoke
%"struct.std::basic_ostream<char,std::char_traits<char> >"*
@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char>
>"* @_ZSt4cout, i8* getelementptr ([10 x i8]* @.str, i32 0, i32 0))
    60 to label %bb6 unwind label %lpad10

...

my question is at line 59 can throw an exception?

I don't know if it can really throw an exception or not. Presumably it
could run out of memory? But it's not marked as not throwing any exceptions
("nounwind") so LLVM has to assume that it might. If LLVM had access to
the definition of @_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
then it might be able to prove that it doesn't throw any exceptions, at which
point the invoke would be turned into an ordinary call. If you know that
this routine cannot throw exceptions, then it can be marked as nothrow in
some the C++ header somewhere (and you should send a patch to the libstdc++
people). By the way, the reason an invoke is needed here is to ensure that
@__cxa_end_catch() will be called on the original exception before the new
exception is propagated out.

...

    48 %0 = invoke
%"struct.std::basic_ostream<char,std::char_traits<char> >"*
@_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc(%"struct.std::basic_ostream<char,std::char_traits<char>
>"* @_ZSt4cout, i8* getelementptr ([14 x i8]* @.str, i32 0, i32 0))

...

here at line 48 can throw an exception?

Same basic answer.

my another problem : are there any different of above two llmv-ir
on handle c++ exception ?

They should result in the same output when the program is run, assuming
that the exception throwing routine doesn't run out of memory and abort,
in which case you might see a message for the second version but not for
the first.

Ciao,

Duncan.

hi,

     I'm doing to make llvm backend support sjlj-eh! I have try to
use the llvm-IR to generate the sjlj-eh code,
but I'm totally despair !
    my major problem is that llvm-ir , I mean exception instrinstics
are enough for codegen the sjlj-eh code? May I need to modify the
llvm-gcc ?
or someone can give some advice about llvm-backend 's support sjlj-eh ?

best regards
zhangzw

Hi,

I'm working on getting SJLJ exception handling working for ARM. What sort of sjlj exception handling are you looking to do? There's a bit of subtlety to getting things working. For example, do you want to use the standard library setjmp/longjmp functions for flow control, or do you want to replicate the GCC approach of builtins to do that? To be compatible with GCC code, the latter approach is necessary, and is what I'm working on.

There's definitely more to it than the current intrinsics, which are there to support dwarf. SJLJ exceptions rely on runtime library functions to register and unregister call frames which require unwinding, so we need to modify LLVM to handle generating those calls. Most of the landing pad organization should transfer over with only a bit of tweaking. The type checking and catch selection needs to be compatible with what's passed from GCC generated code, so there's a bit of work to do there as well.

-Jim