the new llvm exception handling scheme2011/09/16  · catch (int i) {dosomethingwithint(i);} catch...

35
The new LLVM exception handling scheme Duncan Sands DeepBlueCapital / CNRS

Upload: others

Post on 04-Jun-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

The new LLVM exception handling scheme

Duncan Sands

DeepBlueCapital / CNRS

Page 2: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

Control flow

Page 3: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

Control flow

Page 4: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

Control flow

Throws an exception?

No

Yes

Page 5: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

Control flow

Throws an exception?

No

Yes

Matches type of thrown object?Yes

NoMatches type of thrown object?

Yes

Continue further up the call stack

No

Page 6: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv() ...

Page 7: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

Throws an exception?No

Page 8: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

Throws an exception?

lpad: %info = landingpad { i8*, i32 } ...

No

Yes

Page 9: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

lpad: %info = landingpad { i8*, i32 } ...

Information describing the exception

The type of %info

Page 10: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

lpad: %info = landingpad { i8*, i32 } ...

Information describing the exception

The type of %info

Exception pointer part Selector value part

Page 11: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

lpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A} Simplified version:

real version has types

Page 12: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

lpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A

Language specific personality functionKnows how to compare the exception with a catch condition (C++ type)

Page 13: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructs

invoke void @_Z17MayThrowSomethingv()to label %cont unwind label %lpad

cont: invoke void @_Z19AnotherFunctionCallv() ...

lpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A } Type infos: language

specific global variablesthat represent the catchcondition (C++ types)

Page 14: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) ...

The exception object

Page 15: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) ...

The selector value(which condition matched)

Page 16: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) call void @__cxa_end_catch() br label %finished

The selector value for a matchwith type “int”

Check if the selector has thisvalue

Page 17: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) call void @__cxa_end_catch() br label %finished

try_next: ...

Yes NoNoDid the exception match the“int” catch clause?

Page 18: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) call void @__cxa_end_catch() br label %finished

try_next: ...

{Run the catch code

Language specific library calls

Yes No

Page 19: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

...try_next: %typeid2 = call i32 @llvm.eh.typeid.for(@_ZTI1A) %match2 = icmp eq i32 %selector, %typeid2 br i1 %match2, label %run_catch2, label %end

run_catch2: ...

end:

Did the exception match the“int” catch clause?

No

Did the exception match the“class A” catch clause?

Yes

No

Page 20: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A

...

br i1 %match2, label %run_catch2, label %end

...

end: resume { i8*, i32 } %info

The exception didn't matchany of the catch clauses

Page 21: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A

...

br i1 %match2, label %run_catch2, label %end

...

end: resume { i8*, i32 } %info

The exception didn't matchany of the catch clauses

Continue unwinding the exceptionfurther up the call stack

Page 22: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke Function call inside “try” block

Page 23: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

Function call inside “try” block

Lists catch clausesReturns exception info

Page 24: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

Function call inside “try” block

Lists catch clausesReturns exception info

New!

Page 25: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

llvm.eh.typeid.for

Function call inside “try” block

Lists catch clausesReturns exception info

New!

Map from typeinfo to selector value

Page 26: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

llvm.eh.typeid.for

resume

Function call inside “try” block

Lists catch clausesReturns exception info

New!

Map from typeinfo to selector value

Keep unwinding

Page 27: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

llvm.eh.typeid.for

resume

Function call inside “try” block

Lists catch clausesReturns exception info

New!

Map from typeinfo to selector value

Keep unwinding New!

Page 28: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

Summary

invoke

landingpad

llvm.eh.typeid.for

resume

Function call inside “try” block

Lists catch clausesReturns exception info

New!

Map from typeinfo to selector value

Keep unwinding New!

Page 29: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ... try { ... MayThrowSomething(); ... } catch (int i) { DoSomethingWithInt(i); } catch (class A a) { DoSomethingWithA(a); } ...} catch (class B b) { DoSomethingWithB(b);} catch (...) { DoSomethingElse();}

Nested try

lpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A catch @_ZTI1B catch null

List all catch clauses thatthe exception may meet

}

Page 30: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

int foo() throw () { bar(); return 0;}

Filters

invoke void @_Z3barv() to label %cont unwind label %lpad

cont: ret i32 0

lpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 filter [0 x i8*] zeroinitializer %except = extractvalue { i8*, i32 } %info, 0 tail call void @__cxa_call_unexpected(%except) unreachable

Page 31: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

void oof(void *);

void bar(void) { int x __attribute__((cleanup(oof))); foo(); ...}

Destructors

define void @bar() {entry: %x = alloca i32 invoke void @foo() to label %cont unwind label %lpad

cont: ...

lpad: %info = landingpad { i8*, i32 } personality @__gcc_personality_v0 cleanup %var_ptr = bitcast i32* %x to i8* call void @oof(i8* %var_ptr) resume { i8*, i32 } %info}

{Run the cleanup

Continue unwinding

Page 32: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

try { ...

MayThrowSomething(); AnotherFunctionCall();

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

Control flow

Throws an exception?

No

Yes

Matches type of thrown object?Yes

No

Page 33: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A

Control reaches this point if:

● The exception matched one of catch clauses in the landingpad instruction. The selector indicates which clause matched.

● The exception didn't match any clauses but the unwinder chose to resume execution here anyway. The selector holds a value which does not correspond to any of the catch clauses.

Page 34: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) ...

Page 35: The new LLVM exception handling scheme2011/09/16  · catch (int i) {DoSomethingWithInt(i);} catch (class A a) {DoSomethingWithA(a);} LLVM constructs lpad: %info = landingpad { i8*,

...} catch (int i) { DoSomethingWithInt(i);} catch (class A a) { DoSomethingWithA(a);}

LLVM constructslpad: %info = landingpad { i8*, i32 } personality @__gxx_personality_v0 catch @_ZTIi catch @_ZTI1A %except = extractvalue { i8*, i32 } %info, 0 %selector = extractvalue { i8*, i32 } %info, 1 %typeid = call i32 @llvm.eh.typeid.for(@_ZTIi) %match = icmp eq i32 %selector, %typeid br i1 %match, label %run_catch, label %try_next

run_catch: %thrown = call i8* @__cxa_begin_catch(%except) %tmp = bitcast i8* %thrown to i32* %i = load i32* %tmp call void @_Z18DoSomethingWithInti(i32 %i) call void @__cxa_end_catch() br label %finished

try_next: ...

Yes

Did the exception match the“int” catch clause?

No