# HG changeset patch # User kent # Date 1259209668 -32400 # Node ID cc07adb178554a0fbab328e4db075cdd768fefee # Parent f2ea7e07d0305be90e07f5c918f2496b6d6f092f deleting old commented out code. diff -r f2ea7e07d030 -r cc07adb17855 .hgignore --- a/.hgignore Mon Nov 16 17:22:19 2009 +0900 +++ b/.hgignore Thu Nov 26 13:27:48 2009 +0900 @@ -1,5 +1,7 @@ syntax: glob +*.o +*.s .*.swp .*.swo GTAGS diff -r f2ea7e07d030 -r cc07adb17855 CbC-INSTALL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CbC-INSTALL Thu Nov 26 13:27:48 2009 +0900 @@ -0,0 +1,125 @@ + + * CbC on GCCのインストール方法 + +まずはMercurialリポジトリから取得 + hg clone ssh://one@firefly.cr/hg/CbC/GCC cbc-gcc +ビルド用ディレクトリへ + mkdir build-gcc; cd build-gcc +コンフィギュア +一般的には以下のconfigureでビルドできる + ../cbc-gcc/configure CFLAGS="-g3 -O0" + --prefix=$PWD/INSTALL_DIR --disable-nls \ + --disable-bootstrap --enable-languages=c \ + --enable-checking=tree,rtl,assert,types + + -g3: + gdbでmacroの展開を可能にする + -O0: + gdbでトレースしやすいように、最適化をカット + --prefix: + インストールするベースディレクトリ + --enbale-checking: + デバグ用の指定、browse_treeやdebug_rtx、assertもこれでonになる + --disable-bootstrap: + 通常、GCCは3回ビルドされる。それを最初の1回だけに限定 + --disable-nls: + gettextのl10nをoffにしよう + --enable-language: + 使用する言語 c|c++|ada ... もちろんCbCはcだけ + これもcbcを使えるようにしたい +ビルド +make && make install + + + + * PowerPC Macでのインストール + +最新のlibgmp, libmpfrをインストール +[gmp] + ./configure --enable-cxx --build=powerpc-apple-darwin9 --host=powerpc-apple-darwin9 + make && make install +[mpfr] + ./configure --build=powerpc-apple-darwin9 --host=powerpc-apple-darwin9 + make && make install +[CbC on GCC] + ../cbc-gcc/configure CFLAGS="-g3 -O0" --with-gmp=/usr/local + --with-mpfr=/usr/local --prefix=$PWD/INSTALL_DIR \ + --disable-nls --disable-bootstrap --enable-languages=c \ + --enable-checking=tree,rtl,assert,types + make && make install +もちろんインストール場所によってprefixは変更しよう + + + + + * PS3でのビルド + SPU +../CbConGCC/configure --prefix=/usr/local/spu-cbc \ + --build=powerpc --target=spu --program-prefix=spu- \ + --disable-bootstrap --enable-checking=tree,rtl,assert \ + --disable-nls --disable-shared --disable-threads \ + --enable-languages=c --with-system-zlib --with-newlib \ + --enable-version-specific-runtime-libs --disable-libssp \ + --with-gnu-as -with-as=/usr/bin/spu-as --with-gnu-ld \ + --with-ld=/usr/bin/spu-ld + PPU + binutils + $ tar xzvf binutils-...tar.gz + $ mkdir binutils_4ps3 + $ cd binutils_4ps3 + $ ../binutils../configure --prefix=$PWD/INSTALL_DIR + > --target=ppc64-yellowdog-linux + $ make install + $ cd .. + cross gcc + $ mkdir gcc_4ps3 + $ PATH=$PWD/../binutils_4ps3/INSTALL_DIR/bin:$PATH + $ ../CbConGCC/configure --prefix=$PWD/INSTALL_DIR + > --enable-language=c --target=ppc64-yellowdog-linux + > --with-newlib --with-included-gettext --enable-shared + > --enable-threads + $ make + + + + * 琉球大学総合情報センターのSolarisサーバでのビルド (sparc) + +なぜかデフォルトのgccが自分のライブラリすら見てくれないのでパスを指定 + export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib/gcc:$HOME/opt/lib + export LIBRARY_PATH=/usr/local/lib:/usr/local/lib/gcc:$HOME/opt/lib +gmpのインストール + ./configure --prefix=$HOME/opt \ + --build=sparc-sun-solaris \ + --host=sparc-sun-solaris + make + make check + make install +libmpfrのインストール + ./configure --prefix=$HOME/opt/ \ + --with-gmp=$HOME/opt + --build=sparc-sun-solaris \ + --host=sparc-sun-solaris + make + make check + make install + # sparc-sun-solaris2.10の方がいいかもしれない +CbCをインストール + ../CbCGCC/configure --prefix=$PWD/INSTALL_DIR --disable-nls \ + --disable-bootstrap --enable-languages=c \ + --with-gmp=$HOME/opt --with-mpfr=$HOME/opt \ + --build=sparc-sun-solaris2.10 --target=sparc-sun-solaris2.10 \ + --host=sparc-sun-solaris2.10 --enable-shared \ + --with-as=/usr/ccs/bin/as --with-ld=/usr/ccs/bin/ld + make + make install +ビルドは可能。 +ただし、実行は不能 goto cs();すら動かない +config/sparc/sparc.cのoutput_sibcall()でエラーが出る +gdbがインストールされてないので詳細は未調査 +もしかしてsibcallってあまり実装されてないんじゃ… + + + + + + diff -r f2ea7e07d030 -r cc07adb17855 CbC-REPOSITORY --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CbC-REPOSITORY Thu Nov 26 13:27:48 2009 +0900 @@ -0,0 +1,57 @@ + + * CbC/GCCのリポジトリ管理方法 + +Continuation based C のGCC実装用には二つのリポジトリを仕様する + + o CbC/GCC + 実際にCbCを実装したGCCの本体 + o CbC/GCC_original + オリジナルのGCC。本家のgcc-core-4.x.yをそのままリポジトリ化。 + +GCC_origのほうはGCCがリリースされる度にバージョンアップさせ、コミットする。 +さらにその変更をCbC用のGCCリポジトリにpushする + + 本家 + release GCC_orig GCC + | | | + | 4.4.0 4.4.0-cbc + 4.4.1 up | | + | --> 4.4.1 push | + | | --> 4.4.1-cbc + | | | + 4.4.2 up | | + | --> 4.4.2 push | + | | --> 4.4.2-cbc + | | | + + + * 本家GCCのニューリリース時の対応 + +GCC_originalをアップデート + $ cd $HOME + $ wget ftp://gcc.gnu.org/pub/gcc/releases/gcc-4.4.1/gcc-core-4.x.y.tar.gz + $ tar xvf gcc-core-4.x.y.tar.gz + $ cd gcc-4.x.y + $ cd ${HG_REPO}/CbC/GCC_original + $ rm -rf * + $ mv ${HOME}/gcc-4.4.1/* ./ + $ hg commit + +GCC_originalが最新のGCCになったら、その変更をGCCにpushする +GCC_originalからGCCへのpush + $ cd ${HOME} + $ mkdir workspace;cd workspace # 作業ディレクトリ作成 + $ hg clone ${HG}/one/CbC/GCC # CbC用のGCCをクローン + $ cd GCC + $ hg incoming ${HG}/one/CbC/GCC_original # チェック + $ hg pull ${HG}/one/CbC/GCC_original # pull + +この時点で、場合によっては衝突が起こる。ほとんどはgcc/calls.cの中だと +思われる。また、expand_call関数が大幅に変更されたならgcc/cbc-goto.hも +同じように書き換える必要があるかもしれない。 +がんばって動くまで修正したら + $ hg commit + $ hg push ${HG}/one/CbC/GCC # push +これで最新版に更新される + + diff -r f2ea7e07d030 -r cc07adb17855 CbC-examples/code_segment_pointer_check/Makefile --- a/CbC-examples/code_segment_pointer_check/Makefile Mon Nov 16 17:22:19 2009 +0900 +++ b/CbC-examples/code_segment_pointer_check/Makefile Thu Nov 26 13:27:48 2009 +0900 @@ -1,8 +1,8 @@ -CbCC=../../../build_gcc/INSTALL_DIR/bin/gcc +CbCC=../../../build_cbc44/INSTALL_DIR/bin/gcc #CC=gcc -CC=../../../build_gcc/INSTALL_DIR/bin/gcc +CC=../../../build_cbc44/INSTALL_DIR/bin/gcc # fastcall版では-O0,-O2は動作確認、-O3以上はだめ diff -r f2ea7e07d030 -r cc07adb17855 CbC-implemantation.ja --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CbC-implemantation.ja Thu Nov 26 13:27:48 2009 +0900 @@ -0,0 +1,115 @@ + + GCC への CbC コンパイル機能の実装について + +BUILD方法 (作業ディレクトリとは別ディレクトリで) + + $ cd ../ + $ mkdir build-test + $ cd build-test + $ CFLAGS=-O0 ../GCC/configure --disable-nls --disable-bootstrap \ + --enable-languages=c --prefix=$PWD/INSTALL-DIR \ + --enable-checking=tree,rtl,assert + $ make + $ make install + installまでしないと環境によってはincludeに問題が出る場合がある + 実際に使用する場合はconfigureには何もオプションはつけないでいい + CFLAGSには "-O0 -gdwarf-2 -g3"をつけると gdbでのmacro表示できる + + $ CFLAGS="-O0 -gdwarf-2 -g3" ../GCC/configure --disable-nls --disable-bootstrap \ + --enable-languages=c --prefix=$PWD/INSTALL-DIR \ + --enable-checking=tree,rtl,assert + + +CVS管理 + GCC new release のインポート + $ wget gcc-core-4.x.y.tar.gz + $ tar xzvf gcc-core-4.x.y.tar.gz + $ cd gcc-core-4.x.y.tar.gz + $ cvs import -ko -m "comment" CbC_project/GCC FSF_GCC REL_4_x_y + + これでimportされる。 + + 現在のローカルでの修正とのマージ + なにもないディレクトリにて + $ cvs checkout -jREL_4_._. -j REL_4_x_y CbC_project/GCC + + もしくは既にある作業ディレクトリにて + $ cvs update -jREL_4_._. -j REL_4_x_y + + 4_._.は前のバージョン + conflictがでたら手作業で修正(運が良ければなにもしないでいい) + + コンパイルして動作確認後、 + $ cvs commit +これであたらしいreleaseにマージ完了 + + +DEBUG手法 + gccコマンドではなくcc1コマンドに対してgdbを起動 + $ ls + GCC/ build-test/ test/ + $ cd test + $ gdb ../build-test/gcc/cc1 + + treeの表示 + (gdb) p browse_tree (exp) <== expはtree構造体 + + rtxの表示 + (gdb) p debug_rtx (exp) <== expはrtx構造体 + + browse_treeはtree, debug_rtxはrtxをconfigureの + --enable-checkingで指定している必要がある + + +ソースコードを読むために + ディレクトリ内でbuild + $ cd CbC_project/GCC + $ cvs release (念のため) + $ CFLAGS='-O0 -gdwarf-2 -g3' ../GCC/configure --disable-nls \ + > --disable-bootstrap --enable-languages=c --prefix=$PWD/INSTALL-DIR \ + > --enable-checking=tree,rtl,assert + $ make + $ gtags + + +GDBでmacroを表示 + 上記のように CFLAGS='-O0 -gdwarf-2 -g3' をつけてbuild + (gdb) macro expand MACRO(a) + (gdb) info macro MACRO + (gdb) help macro + + +for spu on PS3 + $ ../CbConGCC/configure --prefix=/usr/local/spu-cbc + > --build=powerpc --target=spu --program-prefix=spu- + > --disable-bootstrap --enable-checking=tree,rtl,assert + > --disable-nls --disable-shared --disable-threads + > --enable-languages=c --with-system-zlib --with-newlib + > --enable-version-specific-runtime-libs --disable-libssp + > --with-gnu-as -with-as=/usr/bin/spu-as --with-gnu-ld + > --with-ld=/usr/bin/spu-ld + $ make install + $ cd /usr/local/spu-cbc + $ ln -s /usr/spu spu + + +for ppu on PS3 + binutils + $ tar xzvf binutils-...tar.gz + $ mkdir binutils_4ps3 + $ cd binutils_4ps3 + $ ../binutils../configure --prefix=$PWD/INSTALL_DIR + > --target=ppc64-yellowdog-linux + $ make install + $ cd .. + cross gcc + $ mkdir gcc_4ps3 + $ PATH=$PWD/../binutils_4ps3/INSTALL_DIR/bin:$PATH + $ ../CbConGCC/configure --prefix=$PWD/INSTALL_DIR + > --enable-language=c --target=ppc64-yellowdog-linux + > --with-newlib --with-included-gettext --enable-shared + > --enable-threads + $ make + + + diff -r f2ea7e07d030 -r cc07adb17855 CbC-memo.ja --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CbC-memo.ja Thu Nov 26 13:27:48 2009 +0900 @@ -0,0 +1,888 @@ +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 +: diff -r f2ea7e07d030 -r cc07adb17855 gcc/c-parser.c --- a/gcc/c-parser.c Mon Nov 16 17:22:19 2009 +0900 +++ b/gcc/c-parser.c Thu Nov 26 13:27:48 2009 +0900 @@ -3797,17 +3797,10 @@ if (TREE_CODE(expr.value) == CALL_EXPR ) { TREE_TYPE(expr.value) = void_type_node; - tree env = NULL_TREE; -// if (c_parser_next_token_is (parser, CPP_COMMA)) -// env = c_parser_cbc_make_env(parser); - //if (CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl))) - { - CbC_IS_CbC_GOTO (expr.value) = 1; - CALL_EXPR_TAILCALL (expr.value) = 1; - } + //tree env = NULL_TREE; + CbC_IS_CbC_GOTO (expr.value) = 1; + CALL_EXPR_TAILCALL (expr.value) = 1; add_stmt(expr.value); - //CbC_HAVE_CbC_GOTO (current_function_decl) = 1; - // should be match with function type? stmt = c_finish_return (0); } else