続いてるよ。
さて、では、__mf_registerを調べるために、libmudflap/mf-runtime.cを開いて…と、いうような展開でもいいんだけど、まあ、なんか普通に終わりそうな気がしたので、趣向を変えて、gcc/tree-mudflap.cを見てみる。
https://www.codeblog.org/blog/ssato/
と、ちょっとやってることがかぶるかもしれない。
まあ、車輪は恐くないよ。
さて、中間形式が、GIMPLEやら、SSAにまとめられたおかげで、ここらへんのソースは、それなりに読みやすいような気がする。
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c
勝手にお借りして。
まず、前回の話として、どうやらmudflap1とmudflap2のふたつのパスがあるんじゃないか、ということ。
それっぽいのは一番下にある。
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l1296
struct tree_opt_pass pass_mudflap_1 = { "mudflap1", /* name */ gate_mudflap, /* gate */ execute_mudflap_function_decls, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ 0, /* tv_id */ PROP_gimple_any, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; struct tree_opt_pass pass_mudflap_2 = { "mudflap2", /* name */ gate_mudflap, /* gate */ execute_mudflap_function_ops, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ 0, /* tv_id */ PROP_gimple_leh, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_verify_flow | TODO_verify_stmts | TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ };
この、tree_opt_passっていうのが、パスの定義。
tree-pass.hっていうのがあって、
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-pass.h#l90
passes.cっていうのがあって、
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/passes.c
p = &all_lowering_passes; NEXT_PASS (pass_remove_useless_stmts); NEXT_PASS (pass_mudflap_1); NEXT_PASS (pass_lower_cf); NEXT_PASS (pass_lower_eh); NEXT_PASS (pass_build_cfg); NEXT_PASS (pass_lower_complex_O0);
つまり、tree_opt_passがチェインしてて、全体になってるわけ
全部は見てないので知らんけど、パスの最初は、executeのところ。
つまり、mudflap1のパスは、関数execute_mudflap_function_declsで始まる、というわけ。
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l943
さて、前回見たところ、mudflap1は、変数宣言のあるところに__mf_registerを埋めているような感じだった。
と、いうことは、このexecute_mudflap_function_declsは、そういう処理をやってるに違いない。
まず、mf_marked_p。マークしてたらmarked_tree(ハッシュテーブル)につっこんであるのでほげほげ。
DECL_ARTIFICIAL→謎、push_gimplify_context→謎。
重要そうなのが、mf_xform_decls。DECL_SAVED_TREEというのは、関数の本体の文のリストのこと、DECL_ARGUMENTSは、関数の引数。(GCC内部では、変数、型、関数等は、まとめてDECLと呼ぶ。わかりにくいけど。http://gcc.gnu.org/wiki/New%20DECL%20hierarchy ←ちょっと参考になる)
walk_treeは、構文木の各節に引数でわたしたコールバックを呼び出すような感じ。without_duplicatesだと、同じノードには二回以上コールバックを呼ばないといった感じ。多分。
で、ここまではどうでもいい。要約すると、構文木の各節に対して、mx_xfn_xform_declsが呼ばれる、という感じ。
んで、mx_xfn_xform_decls
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l1065
static tree mx_xfn_xform_decls (tree *t, int *continue_p, void *data) { struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data; if (*t == NULL_TREE || *t == error_mark_node) { *continue_p = 0; return NULL_TREE; } *continue_p = 1; /* continue_pを0にするとwalk_subtreeが止まる…だったはず… */ switch (TREE_CODE (*t)) { case BIND_EXPR: { /* Process function parameters now (but only once). */ mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t)); d->param_decls = NULL_TREE; mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t)); } break; default: break; } return NULL_TREE; }
BIND_EXPRだったら、なんか処理。BIND_EXPRっていうのは、
void func() { int a; { // ←こういうスコープ int b; b = 0; } }
だったと思う(うろおぼえ)
BIND_EXPR_BODYがスコープの中の処理(この場合、b=0;)、BIND_EXPR_VARSが、そのスコープの中の変数のリスト(この場合、int b)
と、ここまで書いて疲れてきたので今日はいいや。なんか微妙なので続かないかも。