view CbC-implemantation.ja @ 92:689bf9141c8c

add conv1/benchmark.sh
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Wed, 04 Jan 2012 02:15:01 +0900
parents e62c90c8e699
children
line wrap: on
line source



	GCC への CbC コンパイル機能の実装について


___________________________________________________________
    Code Segmentの実装
-----------------------------------------------------------

Code SegmentをC言語に組み込む。
コンパイラとしては単なるvoidの関数として扱い、parse treeにcode
segmentであることのフラグを追加する。

 * 予約語''__code``の追加
  c-common.cで定義されているc_common_reswords配列に追加
  { "__code", RID_CbC_CODE, 0}  # D_CONLYも入れるか?

 * treeの生成関数
  関数の型を表すtreeはbuild_funciton_type関数で生成されるが、code
  segmentではこれを使えない。build_function_typeはhash管理でまったく同
  じ引数型、返り値型を持つものは同じオブジェクトを使うから。
  なのでbuild_code_segment_typeでこの代わりを行う。
    # 本当はbuild_function_typeのhashにcbcフラグも含める方がいいかもし
    # れない。
  この関数は主にgrokdeclaratorから呼ばれる

 * cbc_set_codesegment関数
   Undocumented.
   でも今は意味なかったような…



___________________________________________________________
    goto文の実装
-----------------------------------------------------------

CbCについて重要な構文''goto cs(a, b, c);``を実装する。
c-parser.c内の c_parser_statement_after_labels()関数における巨大なスイ
ッチ文のcase RID_GOTOのコードを修正する。

 * アイデア
  全てのgoto文を単なる関数呼び出しとその後のリターン文と解釈することで
  tail callを可能にする。
  次のgoto文は
      goto cs(a);
  このparse treeでもこの様に解釈される
      cs(a);
      return;

 * Parser側での修正

  オリジナルC言語のパース方法
  1. gotoに続くトークンがCPP_NAME
     通常のgoto文として処理
  2. gotoに続くトークンが'*`
     computed gotoとして処理
     see "GCC Manual" Sec 6.3.  (not internals Manual)
  これを以下の様に変更する

  CbCでのパース方法
  1. gotoに続くトークンがCPP_NAME && CPP_NAMEに次ぐトークンが';`
     通常のgoto文として処理
  2. gotoに続くトークンが'*`
     computed gotoとして処理
  3. それ以外
     CbCのgotoとして処理
    
  処理内容
  1. gotoトークンに続く文を関数呼び出しとみて
     c_parser_expr_no_commas()関数を使ってパース、treeを取得
     # これで(*csp)(a)などにも対応できる
  2. 取得したtreeがCALL_EXPRでなければエラー
  3. treeにCbC_GOTOのフラグを立てる
  4. treeにTAILCALLのフラグを立てる
  5. add_stmt
  6. return文のtreeを生成

 * RTL expansion

  通常のCALL_EXPRを解析するexpand_callを一部修正する。この関数の途中か
  らでexpand_cbc_goto関数に切り替えてRTLの生成はそこで全てを請け負う。
  本来expand_callではtreeにsibcallフラグが立っていても、生成の過程で不
  可能と検知するとsibcallを中断して通常のcallになるが、cbc_expand_call
  では無理やりsibcallにする。

  expand_callでの修正内容
    Undocumented.
  expand_cbc_gotoの処理内容
    Undocumented.

___________________________________________________________
    goto文における並列代入の実装  Nov 26, 2009
-----------------------------------------------------------

c-parser.c: c_parser_statement_after_labels()における goto文のパースの
段階で全ての引数を一時変数に代入する形に変更する。
もちろんこれだけで並列代入ができる分けではないが、おそらくGCCの最適化
機構でできると考える。

  1. c_parser_expr_no_commasでCALL_EXPRを取得
  2. 全ての引数に対して一時変数を作成
  3. それぞれを代入
  4. CALL_EXPRの引数を一時変数に置き換え
  2-4の処理をcbc_replace_argumentsで行う。



___________________________________________________________
    return擬似変数の実装
-----------------------------------------------------------

___________________________________________________________
    environmentの実装
-----------------------------------------------------------

















___________________________________________
 * goto文における並列代入実装について考える
-------------------------------------------

Nov 26, 2009
c-parser.c: c_parser_statement_after_labels()における goto文のパースの
段階で全ての引数を一時変数に代入する形に変更する。
もちろんこれだけで並列代入ができる分けではないが、おそらくGCCの最適化
機構でできると考える。

  1. c_parser_expr_no_commasでCALL_EXPRを取得
  2. 全ての引数に対して一時変数を作成 build_decl?
     名前なしでできるか?
  3. それぞれを代入
  4. CALL_EXPRの引数を一時変数に置き換え
  5. expand_callでの実装を元に戻す?
     現状のままでも動きはするはず
引数のタイプ
  関数
    o ADDR_EXPR
    o PARM_DECL, VAR_DECL, 
  other
    o *_EXPR
    o PARM_DECL, VAR_DECL,

実装の準備
  o CALL_EXPRから引数リストを取得
    DECL_ARGUMENTS(fundecl)
      tree args = DECL_ARGUMENTS (fndecl);
      for (; args; args = TREE_CHAIN (args))
        {
          tree type = TREE_TYPE (args);
          if (INTEGRAL_TYPE_P (type)
              && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
            DECL_ARG_TYPE (args) = integer_type_node;
        }
  o 名前なしの変数作成
    var = build_decl(VAR_DECL, NULL_TREE, TYPE);
    DECL_ARTIFICIAL (val) = 1;
  o 代入文
    build_modify_expr (loc, TO_EXPR, NOP_EXPR, FROM_EXPR)
  o Constantなら一時変数いらない
    もしくはcallerの引数と同じ場合にのみ一時変数を使うか
  o CALL_EXPRは取得後に引数を変えても大丈夫なのか?
  o expand_callでのstore_one_arg, check_sibcall_argument_overlapの動作

<del>実装に邪魔ないくつかの関数の解析</del>
  o mem_overlaps_already_clobbered_arg_p(addr, size)
    指定したメモリ[addr,addr+size]範囲がすでに前の引数格納によって上書
    きされていないかをチェックする。
    引数範囲を1byte毎にbitmapの1bitに表し、上書きされた場所は1がセット
    されている。それにかぶるとNG.
    また、addrが動的(esp+eaxなど)ならNG.
  o sotre_one_args()
この実装ではexpand_cbc_gotoをいじらない事にした



 * 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で指定している必要がある