LLVMパスで、llvm::Module::getFunctionList()
によって返されたリストを使用してモジュール関数リストを反復しようとしています。私はこの1つのようなループを使用します。LLVM pass:モジュール関数リストを反復するときのエラー
for (auto curFref = M->getFunctionList().begin(),
endFref = M->getFunctionList().end();
curFref != endFref; ++curFref) {
errs() << "found function: " << curFref->getName() << "\n";
}
予想通り、このループの最初の反復は、機能を取得し、それはリストの終わりを検出していないし、ちょうど後続の反復である他のオブジェクトを取得し続けその関数パラメータのような関数ではありません(getName()
によって報告されています)。いくつかの反復の後、おそらく現在の "関数"参照を参照していくらかのゴミ(またはNULL)に達し、クラッシュします。
int foo(int k) {
int i, s = 0;
for (i = 0; i < k; ++i)
s += i;
return s;
}
:
...
; Function Attrs: nounwind uwtable
define i32 @foo(i32 %k) #0 {
entry:
...
出力は次のようになります。
found function: foo
found function: k
found function: #0 0x00007f481f77c46e llvm::sys::PrintStackTrace(llvm::raw_ostream&) /home/me/work/llvm-3.8.0/lib/Support/Unix/Signals.inc:322:0
...
ですから、後に正常に反復処理することを見ることができる。例えば、このプログラムの foo
を超えると、パラメータk
のようなオブジェクトに続きました。
モジュールパス(runOnModule()
)とFunctionパス(F.getParent()を使用してモジュールをクエリしています)の両方でこれを試してみたところ、同じ結果が得られました。
問題は、LLVM 3.8.0とLLVM 3.5.2の両方にも複製されます。
戻り値の関数リストを正しく反復できないことが何であるか考えてみてください。
=====
EDIT:
注そのようなイテレータためM.begin()/end()
を用いて、またはCを使用した場合であっても場合など、モジュールの機能の上に別の反復を使用する場合と同じ挙動が示されていること++ 11範囲ベースfor
ループ:for (Function &curF: M) ...
。
さらに、M.getFunctionList().size()
は、リスト項目を反復しようとする際にセグメンテーション違反を引き起こします。関数リストが実際に壊れているようです。しかし、それは私がrunOnModule()
エントリポイントのちょうど始めに得たリストです。だから私のコードで壊れてしまったようなものではない。
======
EDIT 2:この問題は、私のLLVMパスが動的にロード可能なライブラリとしてLLVMのソースツリーから外部に構築され、その後にロードされている場合
私は考えていますコマンドラインオプション-load=foo.so
を使用してください。
@Chandler Carruthの答えがこの問題を解決しました。彼の答えの中核をなすのは、LLVMをmake/configureでビルドしたときに、ninja/cmakeを使ってLLVMをビルドすることを勧めました。 ninja/cmakeを使って再構築することでこの問題は解決されました。 LLVM 3.8.0のリリースノートは、make/configureでのビルドがまだサポートされていることを示唆していますが、この問題は何とか壊れていることを示唆しています。 – ElazarR