Muf-

続き。
なんか適当に。


mudflap1で実際に処理やってるのが、
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l978
このループ。
declはリストになってて(ていうか、構文木の型であるtreeはchainメンバを持ってるので、全部リストになれる)、その要素ごとにループの処理を実行。


で、それが、こんな感じ。

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
          unregister_fncall_params =
            tree_cons (NULL_TREE,
                       convert (ptr_type_node,
                                mf_mark (build1 (ADDR_EXPR,
                                                 build_pointer_type (TREE_TYPE (decl)),
                                                 decl))),
                       tree_cons (NULL_TREE, 
                                  size,
                                  tree_cons (NULL_TREE,
					     /* __MF_TYPE_STACK */
                                             build_int_cst (NULL_TREE, 3),
                                             NULL_TREE)));
          /* __mf_unregister (...) */
          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
                                                        unregister_fncall_params);

こういうのが読めるようになれば、GCCのソースは1/5ぐらい読めたのと同然だ!!


http://alohakun.blog7.fc2.com/blog-entry-316.html

C コンパイラのソースを読んでいるのか, Lisp 処理系読んでいるか,だんだんわかんなくなってくる w

まさにそんな感じ。


この部分は、引数を作って、その引数で関数 __mf_unregister を呼ぶ式を作ってる、という処理。

          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
          /* __mf_unregister (...) */

このコメントが重要。__MF_TYPE_STACKは定数3なのを思い出して。__mf_unregister( &VARIABLE, sizeof(VARIABLE), 3 )←こういう式を作ってるわけ。VARIABLEはdeclのことね。

  • tree_cons - コンスを作る。一個めの引数は、そのコンスの型になるんだけど、tree_consではあんまり使わないような。
  • convert - 二番目の引数の値を一番目の引数で渡した型に変換する式を返す。
  • build_pointer_type - 引数で渡した型を指すポインタ型を返す
  • build1 - 式を作る。ADDR_EXPR は、アドレス取得する式。Cでいう &var みたいな。
  • build_int_cst - 整数定数を作る。引数いっこめは型。指定しなかったら、integer_type_nodeになる…かも
  • build_function_call_expr - 一個目の引数が関数のDECL。二個目の引数が引数。引数は式のコンスリスト。


register_fncall_paramsのほうも同じ要領で。
ちなみに、関数は、mf_unregister_fndeclと、mf_register_fndecl。これは、mudflap_initで初期化されてる。
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l341


ここらへんの関数呼び出しを作る手順はGCC内で大体一緒なので、覚えておくと、色々便利かもしれぬい。


んで、最後。
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree-mudflap.c#l1054

TRY_FINALLY_EXPRは
https://www.codeblog.org/gonzui/markup/gcc-4.1.0/gcc/tree.def#l792
まあ、そんな感じ。


これで、

extern void f( char *a, char *b );

int func()
{
	char buf[30];
	char arei[30];
	{
		f( buf, arei );
	}
}

これが、

;; Function func (func)

func ()
{
  char buf[30];
  char arei[30];

  try
    {
      __mf_register (&buf, 30, 3, "main.c:5 (func) buf");
      __mf_register (&arei, 30, 3, "main.c:6 (func) arei");
      f (&buf, &arei);
    }
  finally
    {
      __mf_unregister (&buf, 30, 3);
      __mf_unregister (&arei, 30, 3);
    }
}

こうなるところまでは、大体わかるかと思う。

;; Function _GLOBAL__I_0_func (_GLOBAL__I_0_func)

_GLOBAL__I_0_func ()
{
  __mf_init ();
}

この部分についてはファイルごとの処理になるようで、別のようだ…またそのうち考える。


というわけで、mudflap1は、大体、そんなあんな。
mudflap2に続くかもしれない。