view CbC-memo.ja @ 103:edcadcec937d

modify __rectype
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Fri, 23 Mar 2012 17:11:33 +0900
parents cc07adb17855
children ab0bcb71f44d
line wrap: on
line source

GCC




[[configureオプションの追加]]
$ cd gcc
$ vi configure.ac
  ...
$ autoheader-2.59  # versionはconfigure.acの中に書いてある奴に合わせる
$ autoconf-2.59
$ vi Makefile.in
これでconfigureスクリプトが完成するが、このautoconfはtarボールでは成功しない
svnリポジトリからチェックアウトしないと必要な関数が定義されてないのでエラーになる
なのでチェックアウトしたものでconfigureを生成したあと、それだけコピーしてこればOK
TOPディレクトリでは
$ autogen Makefile.def
$ autoconf-2.59
ただしこれを使うことはないと思われる?


[[fastcall i386]]
1: %ecx
2: %edx
3: (%esp)
4: 4(%esp)
5: 8(%esp)

__attribute__((noreturn)): 今のところこれでは問題が出ない
__attribute__((fastcall)): こっちはいろいろ問題あり


fastcallで起こる問題:
せっかく計算したebpが上書きされてしまっている
ecxに退避してそこにjmpすれば動く (これを直にかける?)
expand_cbc_gotoを直す必要がある
08048714 <returner>:
8048714:       53                      push   %ebx
8048715:       83 ec 28                sub    $0x28,%esp
8048718:       89 4c 24 0c             mov    %ecx,0xc(%esp)
804871c:       8b 44 24 0c             mov    0xc(%esp),%eax
8048720:       89 44 24 1c             mov    %eax,0x1c(%esp)
8048724:       8b 44 24 1c             mov    0x1c(%esp),%eax
8048728:       8b 00                   mov    (%eax),%eax
804872a:       01 44 24 0c             add    %eax,0xc(%esp)
804872e:       8b 44 24 1c             mov    0x1c(%esp),%eax
8048732:       8b 58 08                mov    0x8(%eax),%ebx
8048735:       8b 44 24 1c             mov    0x1c(%esp),%eax
8048739:       8b 40 04                mov    0x4(%eax),%eax
804873c:       8b 54 24 0c             mov    0xc(%esp),%edx
8048740:       89 c1                   mov    %eax,%ecx
8048742:       83 c4 28                add    $0x28,%esp
8048745:       5b                      pop    %ebx
8048746:       ff e3                   jmp    *%ebx
これを手動で直すと-O0でも-O2でも動くことが確認できた





**PROJECT CVS**
firefly.cr:~one/CVS_DB/CbC_Project/GCC

-checkout
	cvs co CbC_project/GCC
-commit
	cvs commit
-import from 3rdparty source
	tar xzvf gcc-xxx.tgz
	cd gcc-xxx
	cvs import -ko -m ".." CbC/project/GCC FSF_GCC REL_4_x_y
-merge
	cd /temp
	cvs checkout -jREL_4_2_1 -jREL_xxx CbC_project/GCC
	もしくはすでに本流をcheckoutしているディレクトリで
	cvs update -jREL_4_2_1 -jREL_4_2_2 でもできる? (4_2_2に移行時はこれをしたけど...まだ分かんない  )
	cvs update -jREL_4_2_2 -jREL_4_2_3


コンパイル時に実行されるプログラムは主に3つ
省略すると
cc1, as, collect2
/usr/libexec/gcc/i386/redhat-linux/4.1.1/cc1 test.c -o test.s
as -o test.o test.s
/usr/libexec/gcc/i386/redhat/linux/4.1.1/collect2 ..... test.o

cc1とcollect2は
gcc-core-4.2.0/gcc/内でコンパイルされるもの。
必要なのはcc1だ。



CbCの実装
 tail callを使う。

tail call 
関数の末尾呼び出しを最適化して、callでなくjmpで関数に飛ぶようになる。
gcc -O1 -foptimize-sibling-calls か
gcc -O2 でコンパイルすればこの最適化が行われる。

最適化条件? (構造体未確認)
(推測!!)
 返り値が同じ
 呼ばれる関数の引数サイズが呼び出し側関数の引数サイズより小さい

expand_gimple_basic_blockでstatement毎にRTLに変換されているが、
ほとんどのstmtはexpand_expr_stmtに送られるけど、
tail call の場合は expand_gimple_tailcallに直接送られる


**TEST BUILD**
mkdir build-test
cd build-test
../GCC/configure --disable-nls --disable-bootstrap --enable-languages=c --prefix=$PWD/installed --enable-checking=tree,rtl,assert
デバグのため、下の(a)を実行
make
make install  # これまでしないと処理系によってはerrorがいくつか...

(a). 全てのMakefileの-O2 を -O0 に変更  viで :%s/-O2/-O0/gってとこか?
     どうやら --prefix=...って、ちゃんとしないといけない?
     stdio.hをインクルードしてるとエラーが出る。
     これはオレが失敗したのか?それともconfigureが悪いのか?

$ CFLAGS="-O0 -gdwarf-2 -g3" ../GCC/configure ...


stdio.hをインクルードしたらerrorが出る問題
firefly: --prefix=$PWD/USR-LOCALあり、別ディレクトリ
  preinstall: NG   postinstall: OK   installed: OK
firefly: --prefixなし、別ディレクトリ
  preinstall: NG   postinstall: ??
firefly: --prefixあり、同ディレクトリ
  preinstall: NG   postinstall: OK   installed: OK
firefly(nativePkg): --prefixなし、別ディレクトリ
  preinstall: NG

chani:   --prefix=$PWD/installedあり、同ディレクトリ
  preinstall: OK
chani(nativePkg): --prefixなし、別ディレクトリ
  preinstall: OK
  


$PWD/installed/bin/gcc -O2 ....
$PWD/installed/libexec/gcc/i686-pc-linux-gnu/4.2.1/cc1 -O2 test01.c
browse_tree (tree)
debug_rtx(rtl)



**GCC DEBUG**
gdb $BUILD-TEST/installed/libexec/gcc/i686-pc-linux-gnu/4.2.1/cc1
プログラム内で
p browse_tree (current_function_decl)





cc1
main.c, toplev.c,

main() in main.c

toplev_main() in toplev.c
	general_init(argv[0])
		signal設定
		init_gcc()
	decode_options(argc, argv)
	randomize()
	do_compile() in toplev.c
		timevar_start(TV_TOTAL)
		process_options()
		compile_file()

struct lang_hooks lang_hooks
この構造体にパーサ等の関数ポインタが含まれている。
これはlanghooks-def.hでLANG_HOOKS_INITIALIZERが定義されているが、
言語ごとの定義はcならc-objc-common.hで、各メンバの定義が入れ替えられる。

options
decode_options  -O?などのオプションを処理
	handle_options  その他のオプションを順番に走査
	                コンパイル対象のファイル名を main_input_filenameに入れる
	                -で始まる引数があればhandle_optionを呼ぶ
		handle_option  オプションを処理する


compile_file()
	lang_hooks.parse_file() == c_common_parse_file
		c_parse_file() in c-parser.c  Parse a single source file.
			c_parser_translation_unit() in c-parser.c
				c_parser_external_declaration()


c_parser_external_declaration() in c-parser.c
CPPのtokenはここで処理して通常のはc_parser_declaration_or_fndefに渡す

全体を通して、c_parser *parserという変数が関数の第一引数に渡される。
これがファイルをparseする際の状態を保持しているっぽい

c_parser_declaration_or_fndef()
こいつがglobalな関数、変数の宣言を処理する。
	c_parser_declspecs()  基本type (int, char, strcut...)
		declspecs_add_scspec(specs, tree)  extern,inline,staticなどのstorageをspecsにおさめる(specsのフラグをたてる)
		declspecs_add_type(specs, c_typespec t) int, char, longなど第2引数が型名、第1引数にそれを格納
	finish_declspecs() Complexやunsignedなどの後に来る型名の処理?
	shadow_tag(specs) 名前無しのstructやunionを処理。
	c_parser_declarator() 名前の前の*の処理
		c_parser_direct_declarator() idを取得
			c_parser_direct_declarator_inner() idの後の[]や()をパース
				c_parser_parms_declarator() 引数リストもしくはidリスト(これはoldSTYLEのため)
					c_parser_parms_list_declarator()
						c_parser_parameter_declaration()
	通常の変数なら
	start_decl()
	start_init() c_parser_initializer() finish_init()
	finish_decl()

	関数パラメータ
	start_function()  関数のdeclaration treeを作成する
		treeはcurrent_function_declに保存
	old-styleパラメータ(while c_parser_declaration_or_fndef(parser, f, f, t, f)
	fnbody = c_parser_compound_statement(parser) 関数本体の定義
	add_stmt(fnbody) fnbodyを専用のstatement listに追加する gimplifyに使われる?
	finish_function()
		current_function_declからfndeclを取得
		...(fndecl) = pop_stmt_list(....(fndecl))  statement listからbodyを取得しfndeclにつなげる
		c_genericize(fndecl)  convert LD-tree to LI-tree
		c_gimple_diagnostics_recursively(fndecl)
		cgraph_finalize_function(fndecl,false)  ファイルにアセンブラを出力?
			cgraph_assemble_pending_functions()  in cgraphunit.c

関数とcode segment
code segmentはパース中の型はcts_CbC_codeとしてdeclspecsに保持している
finish_declspecsにおいて、treeを構成する際に型をvoid_type_nodeで格納
このvoid_typeになんらかのフラグをつける?それともfunction_typeにつける?



IDの取得
c_parser_declarator() 名前の前の*の処理
	c_parser_direct_declarator() id or (.id)をパース
		c_parser_direct_declarator_inner() idの後の[]や()をパース fnTreeを生成
			c_parser_parms_declarator() 型なしidリスト(これはoldSTYLEのため)
				c_parser_parms_list_declarator() 型付き引数リストのパース 可変長かもみる
					c_parser_parameter_declaration() 
			build_function_declarator() パースした引数とdelcで関数の宣言をつくる 
			                            c_declarator->u.arg_infoに引数を保持


**expand_*  treeをパースしてRTLを出力する
tree_expand_cfg()
	expand_used_vars()
	expand_function_start(current_function_decl)
	  cfunの値を設定して行く
		assign_parms()
		  ここでcfun->args_sizeが設定されている
	expand_gimple_basic_block() in for-loop
		expand_expr_stmt() in stmt.c
			expand_expr() in expr.h
				expand_expr_real() expr.c
					expand_expr_real_1()

expand_expr_real_1()  expr.c:8210
	expand_mult()  expmed.c
		expand_binop()  optabs.c
			GEN_FCN (icode) (temp, xop0, xop1);
			  下の感じのRTLが返される
			  (set (reg:DF 67)    (mult:DF (reg:DF 66)        (reg/v:DF 64 [ d ])))
			  が、この関数が返すのは (reg:DF 67)だけ
				emit_insn(rtx)
				  RTLをDL-listに追加する. rtxはinsnでなければinsnでラッピングされる


**PASS LIST**
関数ごとに出力する場合、
cgraph_assemble_pending_functions()  flag_unit_at_a_timeが真なら実行
	cgraph_expand_function()
		tree_rest_of_compilation
			execute_pass_list

まとめて出力する場合
compile_file
	lang_hooks.decls.final_write_globals = c_write_global_declarations  flag_unit_at_a_timeが偽なら実行
		cgraph_optimize
			cgraph_expand_all_functions
				cgraph_expand_function

GIMPLE treeから RTL への変換
pass.execute = tree_expand_cfg()

RTLからアセンブラへの変換pass final.cで定義
pass_final.execute == rest_of_handle_final  in final.c


最終的な RTL=>"文字列" 変換する pass
execute_one_pass()
	rest_of_handle_final()
		assemble_start_function()
		final_start_function()
		final()                      # insnリストを出力
			final_scan_insn()        # 与えられたinsnのアセンブラを出力
				recog_memoized()     # insn_data[code]のcode 決定
				get_insn_template()  # 出力するアセンブラのchar*文字列を返す
				output_asm_insn()    # 文字列の%..を修正してファイルに出力
		final_end_function()
		assemble_end_function()

RTLの仮想レジスタを物理レジスタに置き換える pass
execute_one_pass()
	instantiate_virtual_regs()
		instantiate_virtual_regs_in_insn()  for each instruction
			extract_insn()
				recog_memoized()
				insn_extract()
ppcではこのrecog_memoizedで-1しか返ってこないことで落ちる

下のmdのmatch_operand 0がaddressにしか対応してないのが問題だと思う
;; sibling call patterns
(define_expand "sibcall"
	[(parallel [(call (mem:SI (match_operand 0 "address_operand" ""))
					(match_operand 1 "" ""))
				(use (match_operand 2 "" ""))
				(use (reg:SI LR_REGNO))
				(return)])]
	""
	"
	{
		#if TARGET_MACHO
		if (MACHOPIC_INDIRECT)
		operands[0] = machopic_indirect_call_target (operands[0]);
		#endif

		gcc_assert (GET_CODE (operands[0]) == MEM);
		gcc_assert (GET_CODE (operands[1]) == CONST_INT);

		operands[0] = XEXP (operands[0], 0);
	}")


targetm.asm_outから出力
ターゲットマシンによってtargetm構造体の内容が変わる。



/* In all nodes that are expressions, this is the data type of the expression.
   In POINTER_TYPE nodes, this is the type that the pointer points to.
   In ARRAY_TYPE nodes, this is the type of the elements.
   In VECTOR_TYPE nodes, this is the type of the elements.  */
#define TREE_TYPE(NODE) ((NODE)->common.type)  // in tree.h
このnodeの型を表す(functionなら関数の型、pointerならそいつのさしている型..

/* The tree-code says what kind of node it is.
   Codes are defined in tree.def.  */
#define TREE_CODE(NODE) ((enum tree_code) (NODE)->common.code) // in tree.h
このnodeがどんなtreeなのかを表す



c_parser_compound_statement()
	c_begin_compound_stmt()
	c_parser_compund_statement_nostart() __label__, lvarの処理
		c_parser_statement_after_labels()
	c_end_compound_stmt()

c_parser_if_statement()
c_parser_do_statement()

c_parser_paren_condition()  ifやwhileの'()'の中をparseする


parse expressions

c_parser_unary_expression() increment,decrement, &, *ポインタ、アドレスの処理
c_parser_postfix_expression() 数字や変数、文字列などの処理(TCCのunary()か)
c_parser_postfix_expression_after_primary() 変数とかの後ろの'[]'や'()'の処理(関数や配列の添字)


c_parser_*  Cのパーサ
build_*     treeの生成 (Cパーサから呼ばれる)
expand_*    tree(gimple)のパーサ
emit_*      rtlの生成 (treeパーサから呼ばれる)




宣言時の新しい識別子
token->type==CPP_NAME
build_id_declarator
	XOBNEWを使って parser_obstackに作られる => gcc_obstack_init in default.h
変数名等を格納するc_declaratorはparser_obstack上に作られ、


tree.def
tree.[ch]

union tree_node GTY((ptr_alias (union lang_tree_node),
					 desc ("tree_node_structure (&%h)")))
{
	struct tree_common GTY ((tag ("IS_COMMON"))) common;
	struct tree_int_cst GTY ((tag ("IS_INT_CST"))) common;
	struct tree_real_cst GTY ((tag ("IS_REAL_CST"))) common;
	..
	..
};
c-tree.h:
struct c_expr{
	tree value;
	enum tree_code original_code;
}


tokenizer

c_parser_peek_token() int c-parser.c 現在参照すべきtoken を返す
	c_lex_one_token() in c-parser.c
		c_lex_with_flags() in c-lex.c
			cpp_get_token() in libcpp(macro.c)
c_parser_next_token_is( parser, token0) tokenを取得し、それがtoken0ならtrue
c_parser_consume_token( parser)   次のtokenを取ってくる

parser->tokens[0,1]  (c_token)
この[0]に現在のtokenの情報がある。
[1]はnext?
新たなtokenはlibcppのcpp_get_tokenによって取得する。

cppでは'!'や'*'などの一つ一つのtokenとなんらかの文字列を返す
予約語等の処理はgccがやる.
token
struct c_token{
	enum cpp_ttype type: 8;    /* libcppで得られるtokenのtype, '<','==', name, '['などなど */
	enum c_id_kind id_kind: 8; /* type==CPP=NAMEの時のみ */
	enum rid keyword: 8;       /* Cの予約語(int, if, typedef, gotoなど) */
	pragma_kind: 7;
	in_systemheader: 1;
	tree value;
	location_t location;
}
enum cpp_ttype  in libcpp/include/cpplib.h
{
  TTYPE_TABLE ==>> CPP_EQ, CPP_NOT, ... , CPP_NAME, ..., CPP_PADDING,
  N_TTYPES,

  /* Positions in the table.  */
  CPP_LAST_EQ        = CPP_LSHIFT,
  CPP_FIRST_DIGRAPH  = CPP_HASH,
  CPP_LAST_PUNCTUATOR= CPP_ATSIGN,
  CPP_LAST_CPP_OP    = CPP_LESS_EQ
};
本来予約語もCPP_NAMEに含まれるが、無理矢理CPP_KEYWORDを作っている
CPP_KEYWORDはc-parser.cで独自に定義、N_TTYPES+1
typedef enum c_id_kind {
  C_ID_ID,        /* An ordinary identifier.  */
  C_ID_TYPENAME,  /* An identifier declared as a typedef name.  */
  C_ID_CLASSNAME, /* An identifier declared as an Objective-C class name.  */
  C_ID_NONE       /* Not an identifier.  */
} c_id_kind;


enum c_declarator_kind {    /*  in c-tree.h */
  cdk_id,        /* An identifier.  */
  cdk_function,  /* A function.  */
  cdk_array,     /* An array.  */
  cdk_pointer,   /* A pointer.  */
  cdk_attrs      /* Parenthesized declarator with nested attributes.  */
};
struct c_declarator {       /* in c-tree.h  */
  enum c_declarator_kind kind;     /* The kind of declarator.  */
  struct c_declarator *declarator; /* Except for cdk_id, the contained declarator.  For cdk_id, NULL.  */
  location_t id_loc;               /* Currently only set for cdk_id. */
  union {
    tree id;                     /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract declarator.  */
    struct c_arg_info *arg_info; /* For functions.  */
    struct {                          /* For arrays.  */
      tree dimen;                     /* The array dimension, or NULL for [] and [*].  */
      int quals;                      /* The qualifiers inside [].  */
      tree attrs;                     /* The attributes (currently ignored) inside [].  */
      BOOL_BITFIELD static_p : 1;     /* Whether [static] was used.  */
      BOOL_BITFIELD vla_unspec_p : 1; /* Whether [*] was used.  */
    } array;
    int pointer_quals;   /* For pointers, the qualifiers on the pointer type.  */
    tree attrs;          /* For attributes.  */
  } u;
};

/* A type specifier keyword "void", "_Bool", "char", "int", "float",
   "double", or none of these.  */
enum c_typespec_keyword { //でも使われてるのはdeclspec
  cts_none,
  cts_void,
  cts_CbC_code, いる?
  cts_bool,
  cts_char,
  cts_int,
  cts_float,
  cts_double,
  cts_dfloat32,
  cts_dfloat64,
  cts_dfloat128
};
enum c_typespec_kind {
  ctsk_resword,
  ctsk_tagref,
  ctsk_tagfirstref,
  /* A definition of a tag such as "struct foo { int a; }".  */
  ctsk_tagdef,
  ctsk_typedef,
  ctsk_objc,
  ctsk_typeof
};
struct c_typespec {
  enum c_typespec_kind kind;
  tree spec;
};
struct c_declspecs { /* c-tree.c */
  /* The type specified, if a single type specifier such as a struct,
     union or enum specifier, typedef name or typeof specifies the
     whole type, or NULL_TREE if none or a keyword such as "void" or
     "char" is used.  Does not include qualifiers.  */
  tree type;
  /* The attributes from a typedef decl.  */
  tree decl_attr;
  /* When parsing, the attributes.  Outside the parser, this will be
     NULL; attributes (possibly from multiple lists) will be passed
     separately.  */
  tree attrs;
  /* Any type specifier keyword used such as "int", not reflecting
     modifiers such as "short", or cts_none if none.  */
  enum c_typespec_keyword typespec_word;
  /* The storage class specifier, or csc_none if none.  */
  enum c_storage_class storage_class;
  BOOL_BITFIELD declspecs_seen_p : 1;
  BOOL_BITFIELD type_seen_p : 1;
  BOOL_BITFIELD typedef_p : 1;
  BOOL_BITFIELD default_int_p;
  BOOL_BITFIELD long_p : 1;
  BOOL_BITFIELD long_long_p : 1;
  BOOL_BITFIELD short_p : 1;
  BOOL_BITFIELD signed_p : 1;
	:
}




**TAIL CALL OPTIMIZATION**
execute_tail_calls  in tree-tailcall.c
	tree_optimize_tail_calls_1(true)
	たいした調査もせず、簡単にフラグCALL_EXPR_TAILCALLをたててるだけ。

expand_call  1834-3115 in calls.c
	initialize_argument_information();
		引数処理
		引数をレジスタやスタックのどこに保存するかを決める
		tree actparmsで示された引数をargs, args_sizeに格納する
		1011行目 We can't use sibcalls if a callee-copied argument is stored in the current function's frame.
	if statement 2200行目: try_tail_call=0
		targetm.function_ok?for?sibcall(fndecl, exp)
		args_size.constant > (current_function_args_size - current_function_pretend_args_size)
	emit_call_1();
		SIBLING_CALL_P(..)  =  ( (ecf_flag & ECF_SIBLING) != 0);

expand_callでtailcall可能かどうかの判定を詳しく行っているようだ
bool try_tail_call = CALL_EXPR_TAILCALL(exp);
2252あたりのfor文が怪しいが、900行ある。

2252 in calls.c
for(pass = try_tail_call ? 0:1; pass<2; pass++) 2253-3087
2回ループ。
1回目はtailcall用。
2回目は普通のcalling
生成後にどちらかを選ぶ?
2227 args_size.constant > (current_function_args_size - current_function_pretend_args_size)

	hard_function_value
	check_sibcall_argument_overlap
	prepare_call_address
	load_register_parameters



Language Dependent Tree
  v
GENERIC
  v
GIMPLE

GENERIC trees + LD trees
  v
GIMPLE


**RTL**
RTL expression
  クラス: RTX_OBJ, RTX_CONST_OBJ, _COMPARE _COMM_COMPARE _UNARY ...  in rtx.def
  オペランド: e(expression), i(integer), w, s, E, ...

RTLへのアクセス
GET_CODE (RTX)  (enum rtx_code) (RTX)->code
    RTXのコード(種類)を返す
GET_RTX_CLASS (code)
    このrtxコードのクラスを返す
GET_RTX_LENGTH (code)
    このrtxコードのオペランドの数を返す
GET_RTX_FORMAT (code)
    オペランドの種類を文字列で返す
    i.e. "iuuBieieee" on CALL_INSN
XEXP(RTX, N)  X->u.fld[N].rt_rtx
    RTX のN番目のオペランドをexpressionとして取得する
XINT(RTX, N)  X->u.fld[N].rt_int
    RTX のN番目のオペランドをintegerとして取得する
XVEC(RTX, N)  X->u.fld[N].rt_rtvec
    RTX のN番目のオペランドをrtvectorとして取得する
  XVECEXP(RTX, N, M)  XVEC(RTX,N)->elem[M]
    RTX のN番目のオペランドをrtvectorとし、その M番目の要素を返す
  XVECLEN(RTX, N)     XVEC(RTX,N)->num_elem
    RTX のN番目のオペランドをrtvectorとし、そのサイズを返す

struct rtvec_def GTY(()) {
  int num_elem;         /* number of elements */
  rtx GTY ((length ("%h.num_elem"))) elem[1];
};


typedef struct trx_def *rtx; //gcc/coretypes.h
struct rtx_def; //gcc/rtl.h
struct rtx_def GTY((chain_next ("RTX_NEXT (&%h)"),
                    chain_prev ("RTX_PREV (&%h)")))
{
  /* The kind of expression this is.  */
  ENUM_BITFIELD(rtx_code) code: 16;

  /* The kind of value the expression has.  */
  ENUM_BITFIELD(machine_mode) mode : 8;

  /* 1 in a MEM if we should keep the alias set for this mem unchanged
     when we access a component.
     1 in a CALL_INSN if it is a sibling call.
     1 in a SET that is for a return.
     In a CODE_LABEL, part of the two-bit alternate entry field.  */
  unsigned int jump : 1;
  /* In a CODE_LABEL, part of the two-bit alternate entry field.
     1 in a MEM if it cannot trap.  */
  unsigned int call : 1;
  /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
     1 in a SUBREG if it references an unsigned object whose mode has been
     from a promoted to a wider mode.
     1 in a SYMBOL_REF if it addresses something in the per-function
     constants pool.
     1 in a CALL_INSN, NOTE, or EXPR_LIST for a const or pure call.
     1 in a JUMP_INSN, CALL_INSN, or INSN of an annulling branch.  */
  unsigned int unchanging : 1;
  /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
     1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE
     if it has been deleted.
     1 in a REG expression if corresponds to a variable declared by the user,
     0 for an internally generated temporary.
     1 in a SUBREG with a negative value.
     1 in a LABEL_REF or in a REG_LABEL note for a non-local label.
     In a SYMBOL_REF, this flag is used for machine-specific purposes.  */
  unsigned int volatil : 1;
  /* 1 in a MEM referring to a field of an aggregate.
     0 if the MEM was a variable or the result of a * operator in C;
     1 if it was the result of a . or -> operator (on a struct) in C.
     1 in a REG if the register is used only in exit code a loop.
     1 in a SUBREG expression if was generated from a variable with a
     promoted mode.
     1 in a CODE_LABEL if the label is used for nonlocal gotos
     and must not be deleted even if its count is zero.
     1 in an INSN, JUMP_INSN or CALL_INSN if this insn must be scheduled
     together with the preceding insn.  Valid only within sched.
     1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and
     from the target of a branch.  Valid from reorg until end of compilation;
     cleared before used.  */
  unsigned int in_struct : 1;
  /* At the end of RTL generation, 1 if this rtx is used.  This is used for
     copying shared structure.  See `unshare_all_rtl'.
     In a REG, this is not needed for that purpose, and used instead
     in `leaf_renumber_regs_insn'.
     1 in a SYMBOL_REF, means that emit_library_call
     has used it as the function.  */
  unsigned int used : 1;
  /* 1 in an INSN or a SET if this rtx is related to the call frame,
     either changing how we compute the frame address or saving and
     restoring registers in the prologue and epilogue.
     1 in a REG or MEM if it is a pointer.
     1 in a SYMBOL_REF if it addresses something in the per-function
     constant string pool.  */
  unsigned frame_related : 1;
  /* 1 in a REG or PARALLEL that is the current function's return value.
     1 in a MEM if it refers to a scalar.
     1 in a SYMBOL_REF for a weak symbol.  */
  unsigned return_val : 1;

  /* The first element of the operands of this rtx.
     The number of operands and their types are controlled
     by the `code' field, according to rtl.def.  */
  union u {
    rtunion fld[1];
    HOST_WIDE_INT hwint[1];
    struct block_symbol block_sym;
    struct real_value rv;
  } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
};


FUNCTION_TYPEの実態はtree_type
make_node_stat(FUNCTION_TYPE)で作成される
  TREE_TYPE
  TYPE_ARG_TYPES    ->type.values
  TYPE_UID          ->type.uid
  TYPE_ALIGN        ->type.align
  TYPE_USER_ALIGN   ->type.user_align
  TYPE_MAIN_VARIANT ->type.main_variant
  TYPE_ATTRIBUTES   ->type.attributes

こいつの lang_flag_6 ビットフィールドをcode segmentかどうかのフラグとする。
#define TYPE_LANG_FLAG_5(NODE) (TYPE_CHECK (NODE)->type.lang_flag_5) //tree.h
#define CbC_IS_CODE_SEGMENT(TYPE) TYPE_LANG_FLAG_5 (TYPE)  //c-tree.h
code segmentを作ったらCbC_IS_CODE_SEGMENT(type) = 1 でセット できる?






**GENERIC TREE**
関数の型
<function_type 0xb7b7d9b4
    type <real_type 0xb7b72a6c double DF
        size <integer_cst 0xb7b60528 constant invariant 64>
        unit size <integer_cst 0xb7b60540 constant invariant 8>
        align 64 symtab 0 alias set -1 precision 64
        pointer_to_this <pointer_type 0xb7b72b80>>
    QI
    size <integer_cst 0xb7b601f8 type <integer_type 0xb7b7205c bit_size_type> constant invariant 8>
    unit size <integer_cst 0xb7b60210 type <integer_type 0xb7b72000 unsigned int> constant invariant 1>
    align 8 symtab 0 alias set -1
    arg-types <tree_list 0xb7b7c8a0

関数の宣言
<function_decl
    type <function_type ... >>

関数の引数
<tree_list 
    value <integer_type
        size <integer_cst ...>
        unit size <integer_cst ...>
        align 32 .... <integer_cst ...>
    chain <tree_list ...>>

配列
<array_type 0xb7f04170
    type <integer_type 0xb7e7f284 int public SI ... >
    BLK
    size <integer_cst 0xb7f02f18 type <integer_type 0xb7e7f05c bit_size_type> constant invariant 320>
    unit size <integer_cst 0xb7f05030 type <integer_type 0xb7e7f000 unsigned int> constant invariant 40>
    align 32 symtab 0 alias set -1
    domain <integer_type 0xb7f04114
        type <integer_type 0xb7e7f000 unsigned int public unsigned sizetype SI size <integer_cst 0xb7e6d3f0 32> unit size <integer_cst 0xb7e6d180 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0xb7e6d468 0> max <integer_cst 0xb7e6d9f0 -1>>
        SI size <integer_cst 0xb7e6d3f0 32> unit size <integer_cst 0xb7e6d180 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0xb7e6d198 0> max <integer_cst 0xb7f02fc0 9>>>

関数呼び出し
<call_expr 0xb7e52078
    type <real_type 0xb7e55a6c double DF ...>
    side-effects    arg 0 <addr_expr 0xb7ed2080
        type <pointer_type 0xb7eda170 type <function_type 0xb7ecff18>
            unsigned SI
            size <integer_cst 0xb7e433f0 constant invariant 32>
            unit size <integer_cst 0xb7e43180 constant invariant 4>
            align 32 symtab 0 alias set -1>
        constant invariant
        arg 0 <function_decl 0xb7ed15b0 test type <function_type 0xb7ecff18>
            addressable used public external decl_5 QI defer-output file test_tree.c line 2>>
    arg 1 <tree_list 0xb7edb138
        value <integer_cst 0xb7edb030 constant invariant 97>
        chain <tree_list 0xb7edb168
            value <integer_cst 0xb7edb060 constant invariant 98>
            chain <tree_list 0xb7edb180
                value <integer_cst 0xb7edb090 constant invariant 10>
                chain <tree_list 0xb7edb198
                    value <real_cst 0xb7edb0c0 type <real_type 0xb7e55a6c double>
                        constant invariant 2.5e+0>>>>>>


build_function_call(tree fndecl, tree exprlist)
FUNCTION_DECLとEXPRのリストからCALL_EXPRを作って返す

convert_arguments(arglist, params, function, fundecl);
check_function_arguments();


配列の作り方
icst : INTEGER_CST
itype: INTEGER_TYPE

icst  = build_int_cst (NULL_TREE, size-1);
itype = build_index_type (icst);
array = build_array_type

//build_range_type(size_type, integer_zero_node, exp)



**PPC**
http://developer.apple.com/documentation/DeveloperTools/Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/32bitPowerPC.html#//apple_ref/doc/uid/TP40002438-SW17
http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
http://www.freescale.co.jp/pdf/MPCFPE32BJ_R1a.pdf
http://www.nk.rim.or.jp/~jun/ppcasm/ppcasm01.html





**ソースコード読み会 準備**
cd ~/public_html
mkdir gcc; cd gcc
checkout CbC_project/GCC; CbC_project/GCC
./configure --...
make
gtags
htags -Ffx -t 'GCC source tour'
cd ../../
tar -czv CbC_project --exclude **/CVS -f GCC-source-....tar.gz



normal tail call
(call_insn/j 24 23 0 (parallel [
            (call (mem:SI (symbol_ref:SI ("cs0") [flags 0x403] <function_decl 0x42e03980 cs0>) [0 S4 A8])
                (const_int 256 [0x100]))
            (use (const_int 0 [0x0]))
            (use (reg:SI 125))
            (return)
        ]) -1 (nil)
    (expr_list:REG_EH_REGION (const_int 0 [0x0])
        (nil))
    (expr_list:REG_DEP_TRUE (use (reg:SI 6 r6))
        (expr_list:REG_DEP_TRUE (use (reg:SI 5 r5))
            (expr_list:REG_DEP_TRUE (use (reg:SI 4 r4))
                (expr_list:REG_DEP_TRUE (use (reg:SI 3 r3))
                    (nil))))))

indirect tail call
(call_insn/j 25 24 0 (parallel [
            (call (mem:SI (reg/f:SI 129) [0 S4 A8])
                (const_int 256 [0x100]))
            (use (const_int 0 [0x0]))
            (use (reg:SI 130))
            (return)
        ]) -1 (nil)
    (nil)
    (expr_list:REG_DEP_TRUE (use (reg:SI 6 r6))
        (expr_list:REG_DEP_TRUE (use (reg:SI 5 r5))
            (expr_list:REG_DEP_TRUE (use (reg:SI 4 r4))
                (expr_list:REG_DEP_TRUE (use (reg:SI 3 r3))
                    (nil))))))



CFLAGS='-O0 -gdwarf-2 -g3' ../GCC/configure --disable-nls --disable-bootstrap --enable-languages=c --prefix=$PWD/INSTALL-DIR --enable-checking=tree,rtl,assert --disable-shared --disable-threads --with-headers --with-system-zlib --with-newlib --enable-version-specific-runtime-libs --disable-libssp  --target=spu

../toolchain/gcc/configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --disable-shared --disable-threads --disable-checking --with-headers --with-system-zlib --with-newlib --enable-languages=c,c++,fortran --disable-nls --enable-version-specific-runtime-libs --disable-libssp --program-prefix=spu- --target=spu




$ cvs checkout CbC_project/GCC
$ mkdir tmp; cd tmp
$ wget http://www.bsc.es/projects/deepcomputing/linuxoncell/cellsimulator/sdk3.0/SRPMS/spu-gcc-4.1.1-107.src.rpm
$ rpm2cpio spu-gcc--4.1.1-107.src.rpm | cpio -i -v
$ tar xjvf gcc-r886.tar.bz2
$ cat *.diff | patch -d ../CbC_project/GCC -p2
$ cp toolchain/gcc/config.sub ../CbC_project/GCC/
$ cp toolchain/gcc/gcc/config.gcc ../CbC_project/GCC/gcc/
$ cd ../CbC_project/GCC
$


change bit_merge to vec_merge in gcc/config/spu/spu.md
split0_completed;  in recog.c, rtl.h, final.c
SPU_FLOAT_FORMAT
: