LLVMと例外
TechLLVMはC++のコンパイルのために例外をサポートするいくつかの機構を持っています。これはCrystalなど例外を持つ言語で利用されているほか、Rustのように例外を持たない言語でも、関数脱出時の確実な後処理(RustでいうDrop)を実現するために利用されているケースがあります。
https://llvm.org/docs/ExceptionHandling.html
各言語での実装
関連するLLVM命令
- invoke命令
invoke 関数 to label %A unwind label %B
の形をとる- 関数を実行し、例外が発生したらラベルBに飛ぶ。そうでなければラベルAに飛ぶ
- invokeを呼ぶ関数はpersonality functionの指定が必要
- 関数定義時のpersonality functionの指定
- 例:
define void @foo() personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
- rust_eh_personalityは
declare i32 @rust_eh_personality(i32, i32 noundef, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)
のように宣言されている
- 例:
- landingpad命令
invoke ~ unwind %B
のラベルBの冒頭で使われる命令。発生した例外の情報を取り出すために使われる?landingpad ~ catch
: 例外をキャッチした際の処理を指定。landingpad ~ cleanup
: cleanup処理を指定。resume命令で終わること。
- resume命令
- unwind処理を再開する。
- catchswitch命令
- ある関数が複数のcatchをもつ場合に使う?
用語解説
- libunwind
- スタックの巻き戻しをいろんなプラットフォームで実現するライブラリ
- LLVMは独自の実装を持っている
- personality function
- unwind中に、発生した例外をこのフレームがキャッチするかどうか知るためにunwinderが呼び出す関数
- また、cleanup時にも呼ばれる
personality functionの仕様
- personality functionの仕様はLLVMが規定したものではないので、LLVMのドキュメントには書いていない
- Rustでの実装
- ↑を見ると、いくつかの参考資料がリンクされている
例外の発生方法
libunwindの_Unwind_RaiseException()を呼ぶ。