Mudflap

続いてるよ。


さて、では、__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)


と、ここまで書いて疲れてきたので今日はいいや。なんか微妙なので続かないかも。