LLVMで例外を実装するには
LLVMを使った自作言語に例外を入れることを考えてた。結論からいうとCrystalのソースを真似するのでよさそう。
- Crystal → libunwind →
_Unwind_RaiseException
- C++ →
__cxa_throw
→ libunwind →_Unwind_RaiseException
_Unwind_RaiseException
等の仕様はここ。http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
「Itanium C++ ABI」という名前ではあるけれど、Level I, II, IIIのうちのLevel I部分(_Unwind_RaiseException
等)はC++に限らない言語独立なAPIになっている。__cxa_throw
はLevel IIで、C++用のもの(であるけれど、場合によってはこれが使えることもあるかも)。
1. http://releases.llvm.org/4.0.0/docs/ExceptionHandling.html
LLVMの公式ドキュメントに例外についての文書があるんだけど、これ読んでも何をしたらいいのか良く分からんのだよな。 特に例外を投げる方法が書いてない。
2. http://sile.hatenablog.jp/entry/20100206/1265454978
過去のLLVM(2.6)では「unwind命令」というのがあり、例外を投げることができたっぽい?
3. Crystal
Crystalのソースを見るとlibunwindというライブラリを使っているらしいことがわかる。
4. clang
clangでthrowがどうコンパイルされるか見てみると、@__cxa_throw
という外部関数の呼び出しになった。
declare void @__cxa_throw(i8*, i8*, i8*)
5. g++ http://d.hatena.ne.jp/fixme/20100124/1264301168
__cxa_throw
で検索すると、g++における実装が見つかる。_Unwind_RaiseExceptionという関数を呼び出している。
6. http://stackoverflow.com/a/17695760/1662841
でですね、StackOverflowによると、_Unwind_RaiseExceptionはlibunwindの関数であるらしい。
Short answer is that _Unwind_RaiseException is not a C++-specific function. It comes from the libunwind library, and allows to throw any type of exception.
ということでまとめると以下のような構図になっている。
- Crystal → libunwind → _Unwind_RaiseException
- C++ →
__cxa_throw
→ libunwind → _Unwind_RaiseException
参考文献
真面目にやるならこのへん読むのがよさそう
- http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
- https://monoinfinito.wordpress.com/category/programming/c/exceptions/page/3/
- すごい長いけど、各回で内容がけっこうオーバーラップしている
- 最初の方は読んでおくといいと思う。途中からはC++固有の内容になる(と思う)
おまけ1
libunwindは http://www.nongnu.org/libunwind/ だが、githubに公式ミラーがある。
llvm-mirrorにもlibunwindというリポジトリがあるけど、中を見る限り別のものっぽい(これかな?)
おまけ2
http://www.snsystems.com/ja/technology/tech-blog/2015/06/11/abi-bugs-are-a-nightmare/
ItaniumってインテルのCPUの名前じゃなかったっけ?という疑問に対する解答があった
IA-64 ABI または Itanium ABI として知られる、現在使用されている C++ コンパイラのほとんどに採用されている C++ ABI は、当初 Itanium 64 ビット プロセッサ用に開発されたものでした。しかし、この ABI は、GNU-C++、ARMcc、Clang/LLVM や PS3、PSVita および PS4 などの PlayStation 用コンパイラなど、広く使用されている多くのコンパイラによって利用されてきました。Microsoft Visual C++ コンパイラを除き、C++ ABI は、コンパイラ ベンダーの事実上の業界標準になりました。