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 : 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** 関数の型 unit size align 64 symtab 0 alias set -1 precision 64 pointer_to_this > QI size constant invariant 8> unit size constant invariant 1> align 8 symtab 0 alias set -1 arg-types > 関数の引数 unit size align 32 .... chain > 配列 BLK size constant invariant 320> unit size constant invariant 40> align 32 symtab 0 alias set -1 domain unit size align 32 symtab 0 alias set -1 precision 32 min max > SI size unit size align 32 symtab 0 alias set -1 precision 32 min max >> 関数呼び出し side-effects arg 0 unsigned SI size unit size align 32 symtab 0 alias set -1> constant invariant arg 0 addressable used public external decl_5 QI defer-output file test_tree.c line 2>> arg 1 chain chain chain 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] ) [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 :