2

コンパイル中のアプリケーションを計測する GCC プラグインを開発しています。アプリケーションは C で記述されており、x86 Linux システム上で GCC 4.7 (4.8 および 4.9 もオプション) でビルドされています。

私のプラグインは、「ssa」標準パスの後に配置され、GIMPLE 表現で動作するコンパイル パスを実装しています。とりわけ、私は以下を実装する必要がありますが、現在それを正しく行う方法を理解できません。

C 関数を処理するとき、将来の処理のために、作成したローカル変数に引数をコピーするコードを先頭に挿入する必要があります。

私の最初の単純な実装は次のようになりました。

tree p;
gimple_seq seq = NULL;
gimple_stmt_iterator gsi = gsi_start_bb(single_succ(ENTRY_BLOCK_PTR));

for (p = DECL_ARGUMENTS(current_function_decl); p; p = DECL_CHAIN(param)) {
    tree copy_par;
    copy_par = create_tmp_var(TREE_TYPE(p), NULL);
    add_referenced_var(copy_par);
    copy_par = make_ssa_name(copy_par, NULL);
    g = gimple_build_assign(copy_par, p);
    SSA_NAME_DEF_STMT(copy_par) = g;
    gimple_seq_add_stmt_without_update (&seq, g);
    ... // more processing here
}
...
gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);

ただし、この方法では、変数へのパラメーター宣言の無効な割り当てがダンプに従って作成されます。

gimple_assign <parm_decl, D.2206_11, par, NULL>

D.2206_11私が作成したローカル変数に対応しますpar- コピーしたい関数の引数。

その結果、GCC は後のパスでクラッシュし、この追加されたステートメントを処理しようとします。これは、それぞれの引数の値を保持する変数pではなく、その変数の宣言であるためだと思います。この通りですか?そして、その変数を取得する方法は?

gimple_build_assign_with_ops(NOP_EXPR, copy_par, p, NULL_TREE)代わりに使ってみgimple_build_assign()ましたが、どちらもしませんでした。GCC は依然として同じ場所でクラッシュします。バックトレースを提供することはできますが、基本的なものが欠けているように感じます。

また、ツリーのトラバーサルから始まりTYPE_ARG_TYPES (TREE_TYPE (current_function_decl))、さらに経由することも調べましTREE_CHAIN(...)たが、それぞれの変数ではなく、引数の型を示しているようです。

したがって、問題は、関数の引数のコピーを適切に追加する方法です。

おそらく、これは MELT または GCC Python プラグインの助けを借りて行うことができますが、このプロジェクトでは、GCC 自体が提供するもののみを使用してコードのすべての変換を実行する必要があります。

4

1 に答える 1

2

引数のコピーは GCC 4.8 および 4.9 では機能しますが、4.7 では機能しないことがわかりました。これが今私のために働くコードinstrument_fentry()です(コピーを実行します)。

後のコンパイル パスでコピーが削除されないようにするために、対応する変数を揮発性にしました。

さらに、特定のパラメーターに指定されたデフォルトの定義ステートメントを持つ SSA_NAME がない場合 ( を参照SSA_NAME_IS_DEFAULT_DEF())、定義ステートメントとして GIMPLE_NOP を持つそのような SSA_NAME を追加しました。

これは今のところ GCC 4.8 と 4.9 で問題なく動作しているため、GCC 4.7 のバグか、GCC 4.7 と 4.8 の間でルールが変更されたようです。ただし、正確なコミットを特定できませんでした。

于 2014-09-22T19:54:35.657 に答える