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
まさにそんな感じ。
この部分は、引数を作って、その引数で関数 __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に続くかもしれない。