LLVMの弱点?

yarv2llvmのスレッドランタイム、まだ苦戦しています。色々追ってみて、Cで定義されたグローバル変数がうまく扱えていないことが分かりました.具体的には、ruby_current_threadという変数に現在Activeになっているスレッド構造体を入れておく必要があるのですが、これができないのです。これがちゃんと設定されていないと、RubyのどんなAPIも正常に動かないとおもいます.
このうまく行っていないものというのが、Cならば

  extern rb_thread_t *ruby_current_thread;

と言う感じで1行で済む所なのですが、LLVMではこれがうまくいきません。
もともと、llvmrubyにはCで定義された変数を扱う機能はないのですが、llvmrubyを拡張するのもありで色々やってみました.

llvmrubyにはCで定義された関数は扱うことができるので、変数を無理やり関数として宣言しておいて、使うときにキャストする。こうすると、一応コンパイルできるのですが、うまく動かないです。その理由は関数として定義したシンボルは、

   jmp ruby_current_thread

みたいなスタブを作ってそのアドレスが割り当てられるからです。そのため、キャストしてデータを書き込んでもjmp命令のところに書かれてしまいます. 多分、実行時最適化とかでコードを書き換えるときにCで書かれたライブラリやOSを壊さないようにする配慮じゃないかなと思います.

llvmrubyを拡張してリンケージがexternalな大域変数を生成するメソッドを作ってみました。こうすると、オプティマイザーで落ちてしまいます.多分、このメソッドが生成する大域変数は実体を作ってしまいそれがCの実体とぶつかってしまうからじゃないかなと思います.つまり、Cでexternをつけないで変数宣言したような感じになっているんじゃないかなと思っています。

LLVMにはGlobalAliasというものがあって*1、説明をみるとこれがexternをつけて変数宣言したものに該当するような気がします。そこで、GlobalAliasを使ったメソッドをつくってみました.ところが、このメソッドがセグフォを起こしてしまいます.色々追ってみたのですが理由が分からず、使い方のお手本を求めてGlobalAliasでググってみたのですが、ほとんど使われていないみたいです。

そんなこんなで、LLVMでCのexternを実現するのはなかなか面倒だという話でした。

*1:大域変数はGlobalVariableでGlobalAliasもGlobalVariableもGlobalValueというクラスのサブクラスになっている