1

私が取り組んでいるツールは、コンパイラによって生成された中間形式を取得し、それにいくつかのコードを追加してから、その変更された中間コードをコンパイラのバックエンドに渡して最終的なコードを生成する必要があります。

gcc について少し調べたところ、GIMPLE 形式は理解しやすいことがわかりましたが、GIMPLE コードを変更する複雑さについてはよくわかりません。また、プラグインを使用する以外に、そこからコンパイルを再開する方法もわかりません。独自のパスを追加します。また、ドキュメンテーションが不足しており、gcc での作業に行き詰まると大変なことになると警告されました。

別のオプションは、LLVM バイトコードを使用することです。しかし、私は LLVM を使ったことがないので、LLVM での作業がどれほど複雑になるかわかりません。私が気付いていないより良いオプションがあるかもしれません。したがって、私は最善の選択肢を知りたいだけです。私の好みは次のとおりです。

  • プラットフォーム非依存
  • 使いやすい
  • 十分に文書化されています
  • より多くの人が利用できるため、より多くのヘルプを利用できます
4

3 に答える 3

1

あなたの説明によると、LLVMは法案に完全に適合しています。その主な目的の 1 つは、IR コードを操作するための柔軟なライブラリおよびフレームワークとして機能することです。付属の無数の最適化、変換、および分析の「パス」は、証拠としても優れた例としても役立ちます。IMO LLVM は、質問に記載されている 4 つのポイントにも非常によく答えます。

  • プラットフォームの非依存性: LLVM は主要なプラットフォーム (Linux、Mac、および Windows) で実行され、多くの CPU タイプのコードを生成する方法を知っています。
  • 使いやすい: IR とコンパイラのバックエンドはハッキングするのが難しい分野ですが、LLVM は比較的新しいプロジェクトであり、十分に文書化されており、非常にクリーンなコード ベースであるため、適切な候補です。
  • 十分に文書化されています:自分をノックアウトしてください
  • 利用者の増加: 非常に活発な開発と利用が行われており、一部の企業 (特に Apple と Google) はすでに多額の投資を行っています。
于 2012-02-06T17:42:09.317 に答える
1

ご存知かもしれませんが、MELTは GCC を拡張する高レベルのドメイン固有言語です。Gimple(など...)で非常に簡単に作業できます(また、Gccの内部表現を変更します)

ただし、Gimple(およびツリー)の表現(エッジなどの他の表現)は複雑であるため、GCCの拡張にはいくつかの作業が必要です...

于 2012-02-02T17:57:39.553 に答える
0

これはまったく役に立たないかもしれませんが、 の処理パスについて疑問に思いましたgcc。からの要約された (主に exec/fork 呼び出しに切り詰められた) 出力strace -f -o gcc.strace gcc -c tstamp.c:

7141  execve("/usr/bin/gcc", ["gcc", "-c", "tstamp.c"], [/* 52 vars */]) = 0
7141  open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 3
7141  close(3)                          = 0
7141  vfork( <unfinished ...>
7142  execve("/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1", ["/usr/libexec/gcc/i686-redhat-lin"..., "-quiet", "tstamp.c", "-quiet", "-dumpbase", "tstamp.c", "-mtune=generic", "-march=i686", "-auxbase", "tstamp", "-o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141  <... vfork resumed> )             = 7142
7141  waitpid(7142,  <unfinished ...>
7142  <... execve resumed> )            = 0
7142  open("tstamp.c", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 3
7142  close(3)                          = 0
7142  open("/tmp/ccqzaCI4.s", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7142  open("/usr/include/stdio.h", O_RDONLY|O_NOCTTY|O_LARGEFILE) = 4
... (opens and closes every include file)
7142  close(4)                          = 0
7142  close(3)                          = 0
7142  exit_group(0)                     = ?
7141  <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7142
7141  vfork( <unfinished ...>
7143  execve("/usr/bin/as", ["as", "--32", "-o", "tstamp.o", "/tmp/ccqzaCI4.s"], [/* 55 vars */] <unfinished ...>
7141  <... vfork resumed> )             = 7143
7141  waitpid(7143,  <unfinished ...>
7143  <... execve resumed> )            = 0
7143  unlink("tstamp.o")                = 0
7143  open("tstamp.o", O_RDWR|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
7143  open("/tmp/ccqzaCI4.s", O_RDONLY|O_LARGEFILE) = 4
7143  close(4)                          = 0
7143  close(3)                          = 0
7143  exit_group(0)                     = ?
7141  <... waitpid resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0) = 7143
7141  unlink("/tmp/ccqzaCI4.s")         = 0
7141  exit_group(0)                     = ?

cc1該当するすべてのロジックがあります。特に次のように入力した後は、複雑なプログラムだと思います。

/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help

/usr/libexec/gcc/i686-redhat-linux/4.6.1/cc1 --help=C
于 2012-02-02T18:27:08.560 に答える