2. コンパイラ・ドライバ
コンパイラ・ドライバはコンパイラの部品をつなぎ合わせてコンパイラを構成する
ためにものである。COINSには標準のコンパイラ・ドライバとして
coins.driver.Driver
というクラスが用意されている。このDriverはCコンパイラを構成するものであるが、
COINSの標準ドライバという意味でCOINS コンパイラ・ドライバとも呼ばれる。
新しい言語のコンパイラ・ドライバを得るためには、この
Driverのサブクラスを作って、フロントエンドの呼び出し部分だけをオーバライドして
その言語のフロントエンドを呼び出すようにすればよい。実際に、COINSのFortranコンパイラ
(5. フロントエンドの5.2)、
PL0コンパイラ、
Simpleコンパイラなど
のフロントエンドはそのようにして作られている。
したがって、これらのコンパイラでは標準のDriverで使える各種のオプション機能が
ほとんどそのまま使える。
以下では、COINS コンパイラ・インフラストラクチャに興味があるが、ま
だ使用したことはないという方に向けて、 COINS のドライバ部分の設計方針、
構成、使い方などを解説している。
COINS コンパイラ・インフラストラクチャは、主に、新しいコンパイラを作
りたい人が簡単にそれをできるように支援するためのフレームワークであるの
で、ドライバ部分もそれを支援することを主目的としている。このため、ドラ
イバ部分は、コンパイラ・ドライバを作成するための Java 言語 API と、そ
れを利用して作られたコンパイラ・ドライバから成っている。
現在
のリリースには、コマンド・ライン・インタフェース(CLI)を利用した、オー
ソドックスなスタイルのコンパイラ・ドライバ(CLI ドライバ)が含まれてい
る。それを以下では、たんにコンパイラ・ドライバと呼んでいる。
2.1 コンパイラ・ドライバの設計
2.1.1 設計方針
COINS のユーザは、次の2種類に分かれると想定した。
- COINS を使って新しいコンパイラを作ろうとするユーザ
- COINS から提供されているデフォルトのコンパイラ実装か、または、前項の
ユーザによって作られた新しいコンパイラを使ってソース・コードをコンパ
イルしようとするユーザ
前者のユーザは、次のような目的を持っているかもしれない。
- 新しいプログラミング言語を開発したので、そのコンパイラを作りたい
- 新しいチップを作ったので、そのためのコンパイラを作りたい
- 新しい最適化処理を作ったので、それをコンパイラに組み込みたい
- 新しいコンパイラ・インタフェースを考えたので、それを実現してみたい
これらを可能とするために、「新しいコンパイラ」は、「新しいコンパイラ・
ドライバ」を必要とするであろう。 COINS は、コンパイラ・ドライバを簡単
にプログラミングするためのドライバ API を提供している。
後者のユーザを、以下では「オペレータ」と呼ぶ。また、断りなく「ユーザ」
と書かれている場合、それはオペレータ以外のユーザを指す。
オペレータはコンパイラを使うために複雑な手順を踏むことはしたくなかろ
う。可能ならば Makefile の CC 変数を変更するだけで済ませたいに違いない。
このため、 COINS は、上記のドライバ API を使用して、コマンド・ライン・
インタフェース(CLI)を利用したオーソドックスなスタイルのコンパイラ・
ドライバ(CLI ドライバ)を提供している。 CLI ドライバは、コマンド文法
や基本的なオプションの意味について、 gcc と多くの共通点を持っている。
2.1.2 構成
COINS コンパイラ・ドライバが提供するフレームワークの全体構成を図1に
示す。
ユーザ ┏━━━━━━┓┏━━━━━━━┓┏━━━━━━━┓
記述層 ┃ドライバ実装┃┃ドライバU/I┃┃サフィクス規則┃
┗━━━━━━┛┗━━━━━━━┛┗━━━━━━━┛
┏━━━━━━━━━┓ ┏━━━━━━━━━━━━┓
API層┃ トレースAPI ┃ ┃ コンパイル仕様API ┃
┃ 警告API ┃ ┃ ┃
┗━━━━━━━━━┛ ┗━━━━━━━━━━━━┛
┏━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ エンジン ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━┛
図1 COINS コンパイラ・ドライバのフレームワーク
ユーザは、次の3種類のものを(必要ならば)準備する。
- ドライバ・ユーザ・インタフェース(ドライバ U/I)
- ドライバ U/I とは、次のことを行うものである。
- オペレータからの指定を元に、「コンパイル仕様オブ
ジェクト」を生成する
- コンパイル仕様オブジェクトと、ドライバ実装をエン
ジンに引き渡して、エンジンを起動する
コンパイル仕様オブジェクトとは、その提供する方法にした
がってオペレータが明示的または暗黙に指定した、コンパイ
ル対象のファイル名やコンパイル・オプションを保持するオ
ブジェクトである。「方法」とは、 CLI かもしれないし、
GUI かもしれない。
- ドライバ実装
- ドライバ実装は、エンジンから呼び出される次のサービスを
実装するものである。
ドライバ実装には、エンジンからコンパイル仕様オブジェク
トが引き渡されるので、上記の実現のためにこれを参照する。
- サフィクス規則
- サフィクス規則とは、「どのサフィクスを持つファイルに対
してどの処理を行なうとどのサフィクスを持つファイルが生
成されるか」を記述した規則である。
COINS は、 C, Fortran, Java に対応しているデフォルトの
サフィクス規則ファイルを提供している。ユーザはこれを変
更することで、異なるサフィクス規則を実現して良い。
各 API およびエンジンは次の機能を提供している。
- エンジン
- ドライバ U/I から受けとったコンパイル仕様を元に、サフィ
クス規則を解釈して、ドライバ実装の対応するサービスを、
順に呼び出す。生成されたファイルは、サフィクス規則に従っ
て命名される。
- コンパイル仕様 API
- コンパイル仕様の作成と参照のための API である。コンパ
イル対象のファイル名、およびオプションの指定/解除/参照
が可能である。
ユーザが自由にオプションを定義できるように、「COINS オ
プション」と呼ばれるオプション体系が用意されている。
ドライバ U/I は、自由に COINS オプションを定義して値を
設定することができ、ドライバ実装は、それを参照すること
ができる。
- トレース API
- オペレータが指定したトレース・オプションを解釈し、特定
のトレース・メッセージを出力をするかどうかを判断し、出
力する機能を持つ。
- 警告 API
- オペレータが指定した警告オプションを解釈し、特定の警告
メッセージを出力するかどうかを判断し、出力する機能を持
つ。
2.2 コンパイラ・ドライバの使い方
COINS のリリースで提供されているクラス coins.driver.Driver は、ドラ
イバ API を使用して作られた、 CLI ベースのコンパイラ・ドライバである。
gcc と多くの点で共通のインタフェースになるように注意して作られている。
クラス coins.driver.Driver は、図1で言うところの「ドライバ実装」で
あり、クラス coins.driver.CommandLine が「ドライバ U/I」である。
2.2.1 コマンド文法
java [java-option ...] coins.driver.Driver [option | filename]...
コマンド名の「java」は、環境によっては、「jre」などの別の名前かもし
れない。
java-option には、 java 実行環境に対する適切なオプションを指定できる。
COINS を使用するためには、 COINS をビルドしたディレクトリに対して
java のクラスパスが通っている必要がある。 CLASSPATH 環境変数か、または、
-cp オプションを適切に設定しなければならない。
例えば、 /usr/local/coins にビルドしたのであれば、
java -cp /usr/local/coins coins.driver.Driver [option | filename]
と指定すれば良い。
2.2.2 基本オプション
次のオプションを指定できる。
- -E
- プリプロセスのみ。例えば C プログラムの場合であれば、 foo.c
をプリプロセスして foo.i を生成する。出力ファイルは、入力ファ
イル (上の例で言えば foo.c) があったディレクトリに生成される。
(gcc では標準出力に出力される。)
- -S
- 狭義のコンパイル(アセンブリ言語出力)まで。例えば C プログ
ラムの場合であれば、 foo.c をプリプロセスし、コンパイルして
foo.s を生成する。出力ファイルは、入力ファイル (上の例で言え
ば foo.c) があったディレクトリに生成される。
(gcc では、カレント・ワーキング・ディレクトリに出力される。)
- -c
- リンクしない。例えば C プログラムの場合であれば、 foo.c をプ
リプロセス、コンパイル、アセンブルして foo.o を生成する。出
力ファイルは、入力ファイル (上の例で言えば foo.c) があったディ
レクトリに生成される。
(gcc では、カレント・ワーキング・ディレクトリに出力される。)
- -help
- ヘルプ・メッセージを出力する。
- -o file
- 出力ファイルを指定する。出力ファイルとは、 -E オプションが指
定されている状況ではプリプロセス後のファイルを、 -S オプショ
ンが指定されている状況ではアセンブリ言語ファイルを、 -c オプ
ションが指定されている状況ではオブジェクトファイルを、それら
が指定されていない状況では実行形式ファイルを指す。
- -barch または -b arch
- ターゲットアーキテクチャを指定する。 -coins:target=arch を指
定するのと完全に同等である (-coins:target=arch の項を参照)。
- -pipe
- 一時ファイルの代わりにパイプラインを使う。
- -Wcategory
- 警告カテゴリが category である警告メッセージを出力させる。
- -Wno-category
- 警告カテゴリが category である警告メッセージを出力させない。
- -C
- プリプロセスによってコメントを削除しない。
- -Dmacro[=definition]
- プリプロセッサ・マクロ macroを定義する。 definition が指定
された場合、それをmacro の値とする。
- -Ipath
- インクルード・パスを定義する。
- -P
- #line ディレクティブを出力しない。
- -Umacro
- プリプロセッサ・マクロ macro の定義を取り消す。
- -O
- -O1 に等しい。
- -Olevel
- 最適化レベルを level に設定する。 level は非負整数。各レベル
で実施される最適化は以下の通り。
- -O0
- 何もしない(-coins:hirOpt=noSimplify に等しく、HIRの単純化もしない)。
- -O1
- -coins:hirOpt=cf,ssa-opt=prun/cpyp/cstp/dce/ebe/srd3,loopinversion
に等しい。
- -O2
- -coins:hirOpt=cf,ssa-opt=
prun/divex/cse/cstp/hli/osr/hli/cstp/cpyp/preqp/cstp/rpe/dce/srd3,loopinversion
に等しい。ただし,coins-1.4.4.3より後のバージョンでは,これに
-coins:regpromote,schedule-after
が加わる。
- -O3
- -coins:hirOpt=inline/cf/pre,ssa-opt=
prun/divex/cse/cstp/hli/osr/hli/cstp/cpyp/preqp/cstp/rpe/dce/srd3,loopinversion
に等しい。ただし,coins-1.4.5.2より後のバージョンでは,これに
-coins:regpromote-ex,schedule,pipelining
が加わる。
- -O4
- -coins:hirOpt=inline/loopexp/cf/cpf/pre,ssa-opt=
prun/divex/cse/cstp/hli/osr/hli/cstp/cpyp/preqp/cstp/rpe/dce/srd3,loopinversion
に等しい。ただし,coins-1.4.5.2より後のバージョンでは,これに
-coins:regpromote-ex,schedule,pipelining
が加わる。
- -g
- 実行形式ファイル中にデバッグ情報を残す。
- -v
- サブプロセスを起動するごとに、その起動形式を表示する。
- -Lpath
- path を、 -l オプションで指定されるアーカイヴ・ファイルの検
索パスに追加する。
- -dynamic
- 共有ライブラリを使用する。
- -static
- 静的リンクする。
- -larchive
- libarchive.a ファイルをリンクする。
- -coins:options
- COINS オプション。この詳細は次節に述べる。
2.2.3 COINS オプション
COINSオプションはCOINS特有のオプションである。それは次の形で指定する。
-coins:options
options にはコンマ記号 (`,') を含まない任
意の文字列を指定できる。
複数の COINS オプションは、コンマ記号 (`,') で区切って連続し
て与えることができる。例えば、
-coins:debug,trace=Driver.8,suffix=/tmp/mysuffixes
は、下記と同等である。
-coins:debug -coins:trace=Driver.8 -coins:suffix=/tmp/mysuffixes
COINSオプションには、上記の例の"debug"のように名前だけからなるものと、
"trace=Driver.8"のように"name=spec"の
形のものがある。後者の形で複数個のspecを指定する場合は、
name=spec1/spec2/spec3
のようにそれらを"/"で区切って並べる必要がある。なお、上記の"suffix"オプションの"/"は
これとは違ってディレクトリの区切りを示すものである。
たとえば、"/"で区切らずに
-coins:trace=HIR.1,trace=Driver.8
のようにすると、最後の"trace=Driver.8"だけが有効になる。両方を有効にするためには
-coins:trace=HIR.1/Driver.8
のように指定しなければならない。
標準的な(CLI ドライバまたはドライバ API によって解釈される)
COINS オプションには下記のものがある。
ターゲットアーキテクチャ指定
ターゲットアーキテクチャを指定するオプションは次の形である。
-coins:target=arch
または
-coins:target=arch-convention
このオプションは、
-b archまたは、-b arch-conventionを指定するのと完全に同等である。
最初の形の指定は
-coins:target=arch-standard
を指定するのに等しい。また2番目の指定は
-coins:target-arch=arch,target-convention=convention
を指定するのに等しい。
ターゲットアーキテクチャの種別を指定するオプションは次の形である。
-coins:target-arch=arch
現在は、arch には、次のいずれかを指定できる。
- sparc ...... SUN SPARC アーキテクチャ(乗除算はサブルーチン・コールになる)
- sparc-v8 ... SUN SPARC アーキテクチャ(乗除算は機械語命令になる)
- x86 ........ インテル i386 アーキテクチャ
- x86sse2 ... インテル i386 アーキテクチャ (浮動小数演算に SSE/SSE2 命令を使用する)(coins-1.4.4.2より後)
- x86_64 ..... インテル 64 アーキテクチャ(AMD64 ABI Draft 0.98に従う)(coins-1.4.3以降)
- x86_64-mac . インテルマック 64 アーキテクチャ(AMD64 ABI Draft 0.98に従う)(coins-1.4.3以降)
- arm ........ ARM社のARM アーキテクチャ
- mips ....... MIPS アーキテクチャ
- sh4 ........ 日立のSH-4 アーキテクチャ
- ppc ........ IBMのPowerPC アーキテクチャ
- alpha ...... Alpha アーキテクチャ
- thumb ...... Thumb (16ビットARMアーキテクチャ)
- mb ......... Xilinx MicroBlaze アーキテクチャ
いずれも、多くのテストプログラム(COINSのソース・アーカイブのcoins/test/c 以下の約700個、現在は約1000個ある)で動くことを確認している。
さらに、sparcとx86については、約8,000個のテストプログラムと、SPEC2000が通ることを
確認している。
その他のマシンのうち、armとx86_64についてはかなりテストが行われており、
SPEC2000の多くのテストが動くことを確認している。
sparcとx86, x86sse2, x86_64, x86_64-macでは、C言語の"long long"型をサポートしているが、
その他のマシンのコード生成系ではそれをサポートしていない。
x86_64-macでは、fprintfなどの、引数にFILE*を指定する関数の呼出しをサポートしていない。
target-arch オプションが指定されると、標準ドライバは、プリプロ
セッサに与えるオプションとして -D__arch__ を追加し、
LIR モジュールを起動する際のターゲットアーキテクチャ名
として arch を指定する。このオプションが指定されない場
合、 LIR モジュールにはアーキテクチャ名として sparc が
与えられる。
ターゲットアーキテクチャのコンベンションを指定するオプションは次の形である。
-coins:target-convention=convention
現在は、 target-arch=arch の値に応じて、次のいずれかを指定できる。
- arch: sparcまたはsparc-v8 の場合
- standard ... 標準 SPARC コンベンション
- arch: x86 の場合
- standard ... Linux ELF
- cygwin ... cygwin
- arch: x86_64 の場合
- standard ... Linux ELF
- mac ... インテルマック
- arch: mips の場合
- standard ... PS2 Linux
- spim ... spim シミュレータ
- linux ... Linux ELF ※アセンブル時に要 -KPIC オプション
(coins-1.4.4.1より後のバージョンで使用できる)
このオプションが指定されると、標準ドライバは、 LIR モジュー
ルを起動する際のターゲットコンベンション名として
convention を指定する。このオプションが指定されない場合、
LIR モジュールにはコンベンション名として文字列
"standard" が与えられる。
プレプロセサとアセンブラとの指定
プレプロセサを指定するオプションは次の形である。
-coins:preprocessor=prep
アセンブラを指定するオプションは次の形である。
-coins:assembler=asm
リンカーを指定するオプションは次の形である。
-coins:linker=link
デフォルトでは,プレプロセサは"cpp",アセンブラは"as",リンカーは"gcc"である.
(coins-1.4.4.4まではアセンブラのデフォルトは"gas"であったが,それより後の
バージョンでは,アセンブラのデフォルトは"as"になる.)
アーキテクチャの指定によって,これらのデフォルトの名前と違う名前のプレプロセサやアセンブラが使われる場合は,
上記のオプション指定でその名前を指定する必要がある.
クロスコンパイルの場合は,オプションで"-S"を指定して,
アセンブラコードを出力し,それを実機でアセンブルして実行するか,
クロスアセンブラを指定してオブジェクトコードを生成すればよい.
いずれにしても,COINS のコンパイラではアーキテクチャの指定によってアセンブラを決めて,
そのアセンブラ用のコードを生成するから,実機ではそれに合ったコマンドを使う必要がある.
以下では,デフォルトの名前と違う場合,あるいはプレプロセサやアセンブラに対して
オプション指定をする必要がある場合,および実機でのコマンドなどを列挙する.
- x86_64-mac の場合
-coins:assembler="as -arch x86_64",linker="gcc -arch x86_64"
- alpha(linux マシン)を指定して,クロスコンパイルする場合
COINS のコマンドでは -S と preprocessor=alpha-linux-cpp
を指定し,linux マシンで gcc コマンドを使えばよい
- arm, thumb, mb を指定して,クロスコンパイル,クロスアセンブルする場合
-coins:preprocessor=XXX-linux-cpp,assembler=XXX-linux-as
ここで,XXX は "arm", "thumb", "mb"のいずれかである.
ただし XXX-linux- の部分は、クロスアセンブラを
ビルドする時の設定で変更できるため他のパターンの場合もある.
- mips-linux を指定して,クロスコンパイル,クロスアセンブルする場合
-coins:preprocessor=mips-linux-cpp,assembler="mips-linux-as -KPIC"
- MicroBlaze で EDK8.1 に含まれている gcc を使っている場合
-coins:preprocessor=mb-cpp,assembler=mb-as
以下のような場合はヘッダファイルを指定する必要がある.
- stdarg.h
-
COINSで,引数の個数不定の関数を使うプログラムをコンパイル
する場合は,COINSの
lang/c/include/stdarg.h
をヘッダファイルとして使う必要がある.そのためには
-coins:preprocessor="cpp -I../lang/c/include"
などとすればよい.
ただし,これが使えるのは,アーキテクチャが
sparc, x86, x86_64, arm
の場合だけである.
- ヘッダファイルによるエラーの回避
-
たとえば,x86_64-macのマシンで,
#include <stdio.h>
を含むプログラムをコンパイルするとstdio.hで
使われている拡張機能のためにシンッタクスエラーとなって
コンパイルできない.
そのような場合には,簡素化したstdio.hを使う必要がある.
COINSの
lang/c/include/samples/
にはいくつかの簡素化したヘッダファイルが置いてある.
HIRでの最適化
HIRでの最適化を指定するオプションは次の形である。
-coins:hirOpt=hiroptspec
-coins:hirOpt=hiroptspec/hiroptspec/...
hiroptspec は、次のいずれかである。
- noSimplify HIRの単純化変換なし
- cf 定数畳み込み
- cpf 定数伝播と畳み込み
- cse 共通部分式削除
- dce 非到達命令削除
- fromc C 言語プログラムパーザでの簡単な最適化
- gt 基本ブロック内での大域変数の局所変数化
- pre 部分冗長性除去
- loopexp ループ展開
- presrhir SSAでのスカラ置換と連携したループ展開
- inline インライン展開
- inlinedepth 再帰的なインライン展開の深さ指定
- globalReform 大域的パタン照合
- complexityAllowance プログラムの大きさによる最適化制御
- alias=opt 楽観的な別名解析
(aliasについては、hirOpt=の項目としてではなく、coinsオプションの1つとして
-coins:alias=opt
のように指定する。)
これらの最適化の意味については、
6. HIRでの最適化を参照されたい。
粗粒度並列化
HIRから粗粒度並列化モジュールを生成する粗粒度並列化コンパイラCoCoを呼び出すことを指定するオプションは次の形である。
-coins:coarseGrainParallel
または
-coins:cgParallel
詳しくは、7.2 粗粒度並列化コンパイラCoCo
を参照されたい。
ループ並列化
HIRでループ並列化したものをopenMPのソースとして出力することを指定するオプションは次の形である。
-coins:parallelDoAll=OpenMP
これによって、OpenMP指示文を付加したCファイルが生成される。
forループを解析して並列化の条件に合うものに対して
並列実行用のアセンブリ言語プログラムを生成することを指定するオプションは次の形である。
-coins:parallelDoAll=n -S
ここで n は並列度を表す整定数である。
openMPコンパイラが使える環境で、openMPのソースとして出力したものを直ちに
コンパイルしてしまうためには、
次のように、それ用のドライバを起動すればよい。
java coins.lparallel.LoopPara -coins:hir2c foo.c
詳しくは、 英語のドキュメントの
6. Parallelization for HIRを参照。
SSA最適化
LIRでのSSA最適化を指定するオプションは次の形である。
-coins:ssa-opt=ssa_opt
-coins:ssa-opt=ssa_opt/..
ssa_opt は、次のいずれかである。
- SSA 形式への変換
- mini Minimal SSA 形式への変換
- semi Semi-Pruned SSA 形式への変換
- prun Pruned SSA 形式への変換
- SSA 形式からの逆変換
- brig Briggsの方法による逆変換
- srd1 Sreedharの方法Iによる逆変換
- srd2 Sreedharの方法IIによる逆変換
- srd3 Sreedharの方法IIIによる逆変換
- SSA 最適化
- cbb 基本ブロックの連結
- cpyp コピー伝播
- cse 共通部分式削除
- cstp 条件分岐を考慮した定数畳み込みと定数伝播
- dce 無用命令削除
- divex 式を3アドレス方式に変換(代入の右辺の演算子はたかだか1つ)
- ebe 空ブロック削除
- esplt 危険辺の分割
- gra 大域的再結合(Global Reassociation)
- hli ループ不変コードの巻き上げ
- lir2c LIRからCプログラムを生成する
- osr ループの帰納変数に関わる演算の強さの軽減と判定の置き換え
- preqp 質問伝播の方法による大域的番号付けと部分冗長性除去
- rpe 冗長なPhi関数の除去
- ssag SSAグラフの作成
- glia 大域ロード命令集約
coins-1.4.4.2より後のバージョンでは,SSA形式ではない,通常形式LIRに対する最適化も
ssa-optの中のオプションとして指定できる(詳細は「8.1.2.1 SSA最適化部の使い方」参照)。
その最適化機能には次のものがある。
- 通常形式最適化
- pdeqp 要求駆動型無用コード除去
- divex2 式を3アドレス方式に変換(divex と同様だが通常形式プログラムに対して適用)
- esplt 危険辺の分割(SSA形式最適化に対するものと同じだが、それは通常形式プログラムに対しても適用可能)
- expde 部分無用コード除去の反復適用
- ddpde 要求駆動型部分無用コード除去
coins-1.5以降のバージョンでは,通常形式最適化の一種として、SSAのスカラ置換(変数のレジスタ化を進める)最適化向けに次のオプションが使える。(詳細は「8.1.2.1 SSA最適化部の使い方」参照)。
- 大域値番号付けに基づく要求駆動型部分冗長除去におけるスカラ置換
- divex3 式の3アドレス形式変換(スカラ置換むけ)
- eqp コピー伝播を伴わない要求駆動型部分冗長除去(レジスタ要求低減型)
- presr 要求駆動型部分冗長除去によるスカラ置換
LIR最適化
coins-1.4.4.2より後のバージョンでは,SSA形式ではない通常形式LIRに対する最適化も指定できるように
なったので,SSA形式最適化と通常形式最適化を合わせて「LIR最適化」として書けるようにした(coins-1.4.4.3より後)。
それを指定するオプションは次の形である。
-coins:lir-opt=lir_opt/..
-coins:lirOpt=lir_opt/..
lir_opt に書けるものは,いまのところssa_opt に書けるものと同じである。
LIRでのその他の最適化機能には次のものがある。
- loopinversion 無条件ジャンプで終るループを条件ジャンプで終るように上下を入れ換える
- regpromote レジスタプロモーション(「9.2.5 レジスタ・プロモーション」参照)
- regpromote-ex ポインタ解析に基づく拡張レジスタプロモーション(「9.2.5 レジスタ・プロモーション」参照)
- schedule レジスタ割付けの前と後で命令スケジュール(「9.2.3 命令スケジューラ」参照)
- schedule-after レジスタ割付けの後で命令スケジュール(「9.2.3 命令スケジューラ」参照)
- pipelining ソフトウェアパイプライニング(「9.2.4 ソフトウェア・パイプライニング」参照)
これらを指定するには,たとえば次のように書けばよい。
-coins:loopinversion,schedule
いままでは
-coins:loopinversion,schedule,attach=coins.backend.sched.Schedule
のように指定していたが,coins-1.4.4.3より後ではattachを指定する必要がない.
なお,pipeliningを指定すると,scheduleも指定したものと見なされる.
SIMD並列化
LIRでSIMD並列化を指定するオプションは次の形である。
-coins:target=x86simd,simd
詳しくは、 8.2 SIMD並列化を参照されたい。
バックエンドの拡張最適化
バックエンドの拡張最適化機能を指定するオプションには次のものがある。
-coins:schedule,attach=coins.backend.sched.Schedule
命令スケジューラをマシン命令選択後のレジスタ割り付け前とレジスタ割り付け後の
2ヶ所で起動する。
より詳しくは、9.2 バックエンドの付加機能
の「9.2.3. 命令スケジューラ」を参照されたい。
-coins:regpromote
大域変数は通常メモリに割り付けられるが、それをレジスタに割り付けようとするレジスタプロモーションの基本版を起動する。
-coins:regpromote-ex
大域変数は通常メモリに割り付けられるが、それをレジスタに割り付けようとするレジスタプロモーションの拡張版を起動する。
コンパイル過程の情報出力
デバッグ用、またはコンパイル過程の情報を出力するオプションには
次のものがある。まず最初に、分かりやすい形で表示する、いわゆる
可視化ツールをあげる。
可視化ツールCoVis
これは、ソースプログラム、HIR、HIRの制御フローグラフ、LIR、 LIRの制御フローグラフなどの対応をグラフィカルに表示するものである。
この表示をするためには、コンパイル時に
-coins:snapshot
というオプション指定をする必要がある。その結果、xmlファイルが生成されるので、
それをCoVisで開けば良い。なお、CoVisでのグラフ表示にはATTの研究所で開発されたgraphviz
というソフトを使っている。詳しくはCoVisUsersGuide.pdfを参照されたい。
コード生成過程のトレース情報表示ツール
バックエンドでのコード生成過程をソースプログラムやバックエンドの
各フェーズと対応させながら見るためには、
-coins:debuginfo,trace=xxx
のようなオプション指定をする必要がある。その出力結果を
java coins.driver.Driver -coins:debuginfo,... > trace.java
perl trace2html.pl -o trace -c trace.java
のようにperlのファイルtrace2html.plで処理すればtrace.htmlファイルが
作成されるので、それをブラウザで表示すれば良い。
traceオプションの指定の仕方は以後の記述の中にあるが、バックエンドに関係する
ものには以下のものがある。
- -coins:trace=LIR[.number]
- バックエンドの入口と出口で、LIRの内部状態を標準出力に表示する。
「.number」はなくても良い。numberは数値であり、その意味は以後の記述で説明される。
- -coins:trace=TMD[.number]
- コード生成部のトレース情報を標準出力に表示する。
- -coins:trace=phasename[.number]
- 変換ステップの名前phasenameを指定して、その変換作業の前後のLIRの状態を表示する。
phasenameとしては、以下のものが指定出来る。
ToCFG, ToLinear, ToMachineCode, EarlyRewriting, LateRewriting, Restruct, InstSel, AggregateByReference, ConvToAsm, NamingFloatConst, ReplaceFloatConst, RewriteConvUF, AugmentCFG, IntroVirReg, JumpCanon, JumpOpt, LoopInversion, PreHeaders, SimpleOpt, Ssa(pruned), Ssa(minimal), LiveRange, RegisterAllocation
コンパイル過程のトレース情報表示
上記の2つの可視化ツールの他に、コンパイル過程のトレース情報を
出力するための以下のオプション指定がある。
- -coins:debug
- コンパイラそのもののデバッグをしていることを示す。
-coins:preserveFiles,testHir,testSym に等しい。
- -coins:preserveFiles
- 一時ファイルを削除しない。
- -coins:trace=tracespec
- -coins:trace=tracespec/tracespec/..
- トレース・オプション。
トレース・メッセージには、メッセージ・カテゴリつきトレー
ス・メッセージと、メッセージ・カテゴリのないトレース・
メッセージの2種類が存在する。
トレース・メッセージには、メッセージ・レベルを指定して
良い。メッセージ・レベルは非負整数である。メッセージ・
レベルが指定されていないトレース・メッセージは、 0 が指
定されているものとして扱われる。
上記の形式の中で、 tracespec は、次のいずれかである。
level
category.level
level にはトレース・レベルを非負整数で、 category には
トレース・カテゴリを英数字列で指定する。
前者の形式は、
メッセージ・カテゴリのないトレース・メッセージのトレー
ス・レベルを指定する。指定されたトレース・レベル以下の
メッセージ・レベルを持つ、メッセージ・カテゴリのないト
レース・メッセージが出力される。
後者の形式は、メッセー
ジ・カテゴリがcategory であるトレース・メッセージのト
レース・レベルを指定する。指定されたトレース・レベル以
下のメッセージ・レベルを持つメッセージ・カテゴリが
category であるトレース・メッセージが出力される。例えば、
-coins:trace=2
は、メッセージ・レベルが 2 以下であるメッセージ・カテゴ
リなしトレース・メッセージを出力する。
-coins:trace=HIR.4
は、メッセージ・レベルが 4 以下であるメッセージ・カテゴ
リが HIR のトレース・メッセージを出力する。
出力先は標準出力である。
COINS が提供している各コンパイラ部品に対して有効なトレー
ス・カテゴリの種類には、
- Control -- 実行されたフェーズとモジュール
- HIR -- 高水準中間表現HIRの情報
- Sym -- 記号表Sym(シンボルテーブル)の情報
- Flow -- 制御フローとデータフローの情報
- Alias -- 別名解析の情報
- Parse -- C Parserの情報
- ToHir -- C-AST (Cの抽象構文木) からHIRへの変換の情報
- Opt1 -- HIR最適化の情報
- Para1 -- ループ並列化の情報
- TMD -- コード生成過程の情報
- LIR -- 低水準中間表現LIRの情報
などがある。
これらを利用すると、コンパイラで行っている内容を容易に理解できる
とともに、コンパイル結果に不審な点がある場合にその原因をつきとめる
ことができる。
異なるカテゴリーのトレースを / で区切って指定すると、指定された各カテゴリーの
トレース情報が出力される。たとえば、
-coins:trace=Sym.1/HIR.1
と指定すると、バックエンドに渡される直前の記号情報とHIRがトレース出力される。
-O3 -coins:trace=Sym.1/HIR.2/Flow.1/Opt1.4
のように、最適化レベルを指定してFlow, Opt1カテゴリーのトレース指定をすると、
記号やHIRのほかに、制御フロー解析、データフロー解析の情報とHIR最適化の
コンパイル過程の情報が出力される。
複数のトレース・カテゴリのないトレース・レベルが指定さ
れた場合、および、同じトレース・カテゴリに対して複数の
トレース・レベルが指定された場合、後から指定された方が
優先される。例えば、
-coins:trace=4/8
は、メッセージ・レベルが 8 以下のメッセージ・カテゴリな
しトレース・メッセージを表示する。 4 以下ではない。
-coins:trace=HIR.6/HIR.3
の例では、メッセージ・レベルが 3 以下の、メッセージ・カ
テゴリが HIR のトレース・メッセージを表示する。 6 以
下ではない。
特別なトレース・カテゴリ default は、他の tracespec で
明示的にトレース・レベルを指定されていないすべてのトレー
ス・カテゴリのトレース・レベルを指定するための
ものである。例えば、
-coins:trace=default.2/HIR.4
は、メッセージ・カテゴリがHIRのものについてはレベルが 4
以下、それ以外のカテゴリのものについては
レベルが 2 以下のトレース情報を表示する。
大きなトレース・レベル(例えば 7, 8, 9 など)を指定する
と、膨大な量のトレース・メッセージが出力されるかもしれ
ないので注意が必要である。
その他
その他のオプションには、以下のものがある。
- -coins:libdir=path
- ライブラリ・ディレクトリのパス名を path に変更する。
ライブラリ・ディレクトリの詳細については、 4.6 節を参照。
複数の -coins:libdir オプションが指定された場合、最後に
指定されたものが有効である。
- -coins:property=path
- プロパティ・ファイルのパス名を path に変更する。デフォ
ルトでは、ライブラリ・ディレクトリにある `properties'
とういファイルがプロパティ・ファイルであるが、このオプ
ションを指定して変更できる。
プロパティ・ファイルは、 COINS オプションを指定するため
の方法の一つである。詳細については、
2.3.7 節を参照。
複数の -coins:property オプションが指定された場合、最後
に指定されたものが有効である。
- -coins:suffix=path
- サフィクス規則ファイルのパスを path に変更する。デフォ
ルトでは、ライブラリ・ディレクトリにある `suffixes' と
いう名前のファイルがサフィクス規則ファイルであるが、こ
のオプションを指定して変更できる。
サフィクス規則ファイルの詳細については、 2.3.8 節を参照。
複数の -coins:suffix オプションが指定された場合、最後に
指定されたものが有効である。
- -coins:suffixoption=option
- サフィクス・オプションを指定する。
サフィクス・オプションの詳細については、 2.3.8 節を参照。
複数の -coins:suffixoption オプションが指定され、それら
が矛盾する場合、より後に指定されたものが有効となる。
- -coins:hir2c=t1
- -coins:hir2c=t1/t2/.../tn
- 指定されたタイミングで、 HIR を C 言語ソースに変換して
ファイルに出力する。 t1, t2, ..., tn には、次の 3 種類
のタイミング指定子のうちのいずれかを指定できる。
- new ... HIR を生成した直後
- flo ... HIR 上でデータ・フロー解析を行った直後
- opt ... HIR→LIR 変換の直前
複数のタイミング指定子が指定されると、指定されたすべて
のタイミングで変換と出力が行われる。
生成された C 言語ソース・ファイルは、r-hir-t.c という
ファイル名を持つ。ここで、 r はコンパイル対象のソース・
ファイルのファイル名 (拡張子より前の部分) であり、 t は、
指定されたタイミング指定子である。例えば、
java coins.driver.Driver -coins:hir2c=new foo.c
は、 foo-hir-new.c というファイルを生成する。不正なタイ
ミング指定子は無視され、ファイルは生成されない。
- -coins:lir2c=t1
- -coins:lir2c=t1/t2/.../tn
- 指定されたタイミングで、 LIR を C 言語ソースに変換して
ファイルに出力する。 t1, t2, ..., tn には、次の 2 種類
のタイミング指定子のうちのいずれかを指定できる。
- new ... LIR を生成した直後
- opt ... LIR 上でのすべての最適化の終了後
生成された C 言語ソース・ファイルは、 r-lir-t.c という
ファイル名を持つ。ここで、r はコンパイル対象のソース・
ファイルのファイル名 (拡張子より前の部分) であり、 t は、
指定されたタイミング指定子である。例えば、
java coins.driver.Driver -coins:lir2c=new foo.c
は、 foo-lir-new.c というファイルを生成する。不正なタイ
ミング指定子は無視され、ファイルは生成されない。
- -coins:stopafterhir2c
- -coins:stopafterlir2c
- 各コンパイル単位のコンパイルを、 hir2c/lir2c オプション
で指定されたすべてのタイミングで C 言語ソース・ファイル
を生成した時点で終了する。コード生成、アセンブルおよび
リンクは行われない。ただし、 hir2c/lir2c オプションに不
正なタイミング指定子が指定された場合の動作は不定である。
- -coins:testHir
- HIR 上での最適化が終了し、 HIR to LIR 変換を行う直前に、
HIR の一貫性を検査する。
- -coins:testSym
- HIR 上での最適化が終了し、 HIR to LIR 変換を行う直前に、
シンボル・テーブルの一貫性を検査する。
- -coins:preprocessor=preprocessor-command
- -coins:assembler=assembler-command
- -coins:linker=linker-command
- プリプロセッサ、アセンブラ、リンカの代替コマンドを指定
する。
COINS の CLI ドライバは、プリプロセッサ、アセンブラ、リ
ンカとして、それぞれ、 cpp, gas, gcc を起動するが、別の
コマンドを使用したい場合にこのオプションを使用する。次
の例では、アセンブラとして `as' を使用する。
-coins:assembler=as
コマンド名の中に空白文字が現れる場合、それは単語の区切
りとして扱われる。例えば、次のオプションは、プリプロセッ
サとして gcc を -E オプションつきで起動することを指定す
る。
-coins:preprocessor=gcc -E
このとき、コマンド・インタプリタから空白文字をエスケー
プすることを忘れてはならない。多くの Unix のシェルでは、
引用符を使って空白文字をエスケープできる。例えば下記は
その例である。このうち、二重引用符を使う方法は Windows
でも使用可能であろう。
-coins:preprocessor="gcc -E"
-coins:preprocessor='gcc -E'
'-coins:preprocessor=gcc -E'
CLI ドライバは、コマンド名の中に引用符記号 (' および ")
が現れる場合、その引用符記号と、その次に現れる同じ引用
符記号を文字列から取り除き、その間の文字列を、次のよう
に解釈する。
- 空白を単語の区切りとして解釈しない。
- 異なる引用符記号は、その文字そのものとして扱う。
この規則は、上述の、空白文字を単語の区切りとして認識す
る規則から逃れるために使用できる。例えば、ファイルやディ
レクトリ名に空白文字を含むことができる環境の場合、次の
ようにしてそれらをエスケープできる。
-coins:preprocessor='my cc' -E
この例では、プリプロセッサとして、プログラム `my cc' が、
`-E' というオプションつきで起動される。このとき、コマン
ド・インタプリタから引用符記号や空白をエスケープするの
を忘れてはならない。例えば、 Windows であれば、下記のよ
うに二重引用符を使用する必要があろう。
-coins:preprocessor="'my cc' -E"
CLI ドライバは、コマンド名の中に現れるバックスラッシュ
記号 (`\') に続く文字を、その文字そのものとして扱う。バッ
クスラッシュ記号自身も、バックスラッシュ記号に続けて記
述することで、バックスラッシュ記号そのものとして記述で
きる。引用符も、バックシュラッシュ記号に続けて記述する
と、上述の意味を失い、引用符そのものとして解釈される。
このエスケープ規則も、上述の、空白文字を単語の区切りと
して認識する規則から逃れるために使用できる。例えば、ファ
イルやディレクトリ名に空白文字を含むことができる環境の
場合、次のようにしてそれらをエスケープできる。
-coins:linker=c:\\Program\ Files\\bin_utils\\ld
この例では、 `c:\Program Files\bin_utils\ld' がリンカと
して使用される。ここで、もし必要なら、 `\' と空白を、コ
マンド・インタプリタからエスケープするのを忘れないよう
に。例えば、 Windows であれば、下記のように二重引用符を
使用する必要があろう。
-coins:linker="c:\\Program\ Files\\bin_utils\\ld"
- -coins:max-recovered-errors=n
- ひとつのコンパイル単位の、ひとつのコンパイル・ステップ
におけるリカヴァード・コンパイル・エラーの数がnを越え
た場合、コンパイル・エラーとして扱われる。または、n が
0 の場合、リカヴァード・コンパイル・エラーの数がいくつ
になってもコンパイル・エラーとして扱わない。ここで、コ
ンパイル・ステップとは、プリプロセス、コンパイル、アセ
ンブル、リンクのことである。
- -coins:max-warnings=n
- ひとつのコンパイル単位の、ひとつのコンパイル・ステップ
における警告の数がn を越えた場合、コンパイル・エラーと
して扱われる。または、 n が 0 の場合、警告の数がいくつ
になってもコンパイル・エラーとして扱わない。ここで、コ
ンパイル・ステップとは、プリプロセス、コンパイル、アセ
ンブル、リンクのことである。
- -coins:compile-parallel
- 各コンパイル単位のコンパイルを並行して実行する。スレッ
ド・セーフに実装されていないコンパイラ部品を使用する場
合、このオプションを指定してはならない。
- -coins:gprof
- gprofによるプロファイルを可能にするオプション(coins-1.4.3.3より後のバージョンで使える)。現在、sparc,x86x,86sse2のみ対応している。
-coins:linker='gcc -pg'と共に用いる必要がある(x86sse2の場合はそれを指定しなくてもよい)。testdriver_gprof.sh、testdriverw_gprof.sh
を用いることで、テストとまとめてプロファイル作業を行うことができる。
gccと同様に、コンパイルした実行ファイルを実行すると、gmon.outが出力されるので、「gprof 実行ファイル」でプロファイルできる。
参考
gprofのマニュアル
'gprof: A Call Graph Execution Profiler' by S. Graham, P. Kessler, M. McKusick
新しいオプションの追加
COINSオプションを新たに追加するには、次のようにすれば良い。
オプションの名前は任意につけることが出来る。たとえば、その名前を"newOption"
としたとすれば、それを指定するには、
-coins:newOption
とすればよい。
そのオプションがコンパイル時に指定されているかどうか調べるには、
if (ioRoot.getCompileSpecification().getCoinsOptions().isSet("newOption")) {
// newOptionの処理
}
とすればよい。
ここで、ioRootはクラスIoRoot(入出力情報のルート)のインスタンス・オブジェクトであり、
いろいろなところでアクセス出来るようになっている。たとえば、
coins.driver.Driverやそれを継承しているドライバではアクセス出来るようになっている。
また、クラスSymRoot(シンボル情報のルート)やクラスHirRoot(HIR情報のルート)
のインスタンスからもioRootにアクセス出来る。
バックエンドの情報のルートはクラスcoins.backend.Rootのインスタンスから得られるが、
そのインスタンスはioRoot.getCompileSpecification()で得られるCompileSpecificationクラスのオブジェクトを持っている。
これらの情報を使えば、いろいろなところで、オプションが指定されていたかどうかを調べることが出来る。その例が、
5. フロントエンド
の「5.2.2 Fortranフロントエンドの使い方」にある。
なお、IoRootのインスタンスが簡単に得られるようになっていない場合にも、
((coins.driver.CompileThread)Thread.currentThread()).getIoRoot()
でそれを得ることが出来る。
2.2.4 入力ファイル
オプションに混じって、入力ファイルを記述することができる。エンジンは、
サフィクス規則を参照しながら、どのファイルにどの処理を行うかを決定し、
ドライバ実装の対応するメソッドを起動する。サフィクス規則の詳細について
は、 2.1.4.8 節を参照。
各出力ファイルは、 -o オプションが指定されない限り、ソース・ファイル
があるディレクトリに作られる。
2.2.5 終了ステータス
CLI ドライバは、下記の方針で終了ステータスを返す。
異常終了には、入出力エラーやコンパイル・エラーなどが含まれる。
2.2.6 ターゲットアーキテクチャの指定
ドライバは、ターゲットアーキテクチャを指定する方法として、下記の
3 種類の方法を用意している。
- -b arch-convention または -barch-convention
- -coins:target=arch-convention
- -coins:target-arch=arch,target-convention=convention
これらはすべて等価であり、ひとつを指定することは他のすべてを指定する
ことと等しい。
conventionが省略されると、 "standard" が指定されたものとみなす。
ターゲットアーキテクチャが指定されない場合のデフォルトは"sparc" である。
cygwin 上でコンパイルするユーザは、 -b x86-cygwin を指定するとともに、
(通常の場合は、)次を指定する必要がある。
-coins:assembler=as
その他、 cygwin のインストールの状況によって、下記を必要とするケースも
あるようである。
-coins:preprocessor="cpp-3 -I/usr/include"
(-coins:preprocessor="cpp -I/usr/include" -- java 1.6より前のバージョンの場合)
2.2.7 使い方の例
下記の例すべてについて、 CLASSPATH 環境変数が適切に設定されているも
のとする。
java coins.driver.Driver foo.c
は、 foo.c をコンパイルして a.out を生成する。
java coins.driver.Driver -o foo foo.c
は、 foo.c をコンパイルして、実行形式ファイル foo を生成する。
java coins.driver.Driver -c foo.c
は、 foo.c をコンパイルして、オブジェクト・ファイル foo.o を生成する。
java coins.driver.Driver -E foo/bar.c baz/boo.c
は、 foo/bar.c と baz/foo.c をプリプロセスして、 foo/bar.i と
baz/boo.i を生成する。ここで、 `.i' は、プリプロセスされた C プログラ
ムのサフィクスとして、デフォルトのサフィクス規則に記述されている。
java coins.driver.Driver -S foo.c bar.i
は、 foo.c と bar.i をコンパイルして、アセンブリ言語ファイル foo.s と
bar.s を生成する
いくつかの例外的なケースを除き、 `java coins.driver.Driver' を `cc' に
alias することで、 COINS C コンパイラを普通の C コンパイラと同様に使用
できる。例外的なケースとは、例えば、 `cc -E' は cpp とまったく同様には
使えない、などである。
2.3 ドライバ API の使い方
ドライバ API の使い方については、対応するクラスの JavaDoc に詳しい。
本文書では、どのクラスの JavaDoc を読めば良いかが分かる程度の概要の
みを説明する。
2.3.1 ドライバ U/I
ドライバ U/I とは、次のことを行うものである。
- オペレータからの指定を元に、「コンパイル仕様オブジェクト」を生成
する
- コンパイル仕様オブジェクトと、ドライバ実装をエンジンに引き渡して、
エンジンを起動する
「コンパイル仕様オブジェクト」は、 coins.driver.CompileSpecification
インタフェースを実現するように作らなければならない。
CLI ドライバにおいては、 coins.driver.Driver クラスの main メソッド
および go メソッドがドライバ U/I に相当する。これは次のように記述され
ている。
protected void go(String[] args) {
CompileSpecification spec = new CommandLine(args);
int status = new CompilerDriver(spec).go(this);
System.exit(status);
}
public static void main(String[] args) {
new Driver().go(args);
}
coins.driver.CommandLine クラスは、 CLI ドライバのためのコンパイル仕様
クラスである。 coins.driver.CompilerDriver クラスが、エンジンである。
coins.driver.Driver クラスはドライバ実装も兼ねているので、自分自身をイ
ンスタンシエートしてエンジンに与えている。
もしも CLI ドライバと同じユーザ・インタフェースを持つドライバを作る
のであれば、この部分はそのまま使用できる。
2.3.2 ドライバの実装
ドライバ実装は、エンジンから呼び出される次のサービスを実装するもので
ある。
coins.driver.CompilerImplementation クラスが、ドライバ実装が実装すべ
きインタフェースを定義している。
CLI ドライバの場合は、 coins.driver.Driver クラスがドライバ実装の役
割を担っている。 CLI ドライバは上記の 4 種類のメソッドを提供しているが、
プリプロセス、アセンブル、リンクについては、外部プロセスを呼び出すだけ
である。
2.3.3 コンパイル仕様
コンパイル仕様は、 coins.driver.CompileSpecification インタフェース
を実装しなければならない。
CLI ドライバでは、 coins.driver.CommandLine クラスがこれに当たる。
2.3.4 トレース API
オペレータが指定したトレース・オプションを解釈し、特定のトレース・メッ
セージを出力をするかどうかを判断し、出力する機能を持つ。
ドライバ実装、および、そこから呼び出されるコンパイラ部品は、メッセー
ジ・カテゴリ(文字列)と、メッセージ・レベル(非負整数)を指定して、ト
レース・メッセージを出力する API を呼び出す。メッセージ・カテゴリは、
英数字列でありさえすれば、ユーザが任意に指定できる。
トレース・オプションには、トレース・カテゴリとトレース・レベルの対の
集合を指定できる。トレース API は、指定されたトレース・オプションに照
らして、いずれかのトレース・カテゴリと同じメッセージ・カテゴリを持ち、
そのトレース・レベル以下のメッセージ・レベルを持つトレース・メッセージ
だけを出力する。
オペレータが指定したトレース・オプションを格納した
coins.driver.Trace クラスのオブジェクトを取得するには、
CompileSpecification#getTrace() メソッドを使用する。
2.3.5 警告 API
オペレータが指定した警告オプションを解釈し、特定の警告メッセージを出
力するかどうかを判断し、出力する機能を持つ。
ドライバ実装、および、そこから呼び出されるコンパイラ部品は、警告カテ
ゴリ(文字列)を指定して、警告メッセージを出力する API を呼び出す。警
告カテゴリは、ユーザが任意に指定できる。
警告オプションには、出力すべき警告カテゴリ、および出力すべきでない警
告カテゴリを指定できる。警告 API は、指定された警告オプションに照らし
て、出力すべきと指定された警告メッセージだけを出力する。
CompileSpecification#getWarning() メソッドで、 coins.driver.Warning
クラスのオブジェクトを取得できる。ここに、オペレータが指定した警告オプ
ションが格納されている。
2.3.6 ライブラリ・ディレクトリ
コンパイラ部品の動作をカスタマイズ可能にする場合、オペレータにコンフィ
ギュレーション・ファイルを用意させる方法を採ることがあり得る。例えば、
ドライバ API は、オペレータが次の 2 種類のファイルを準備することができ
るように設計されている。
- プロパティ・ファイル (2.3.7 節参照)
- サフィクス規則ファイル (2.3.8 節参照)
ライブラリ・ディレクトリは、このようなコンフィギュレーション・ファイ
ルを置くためのディレクトリである。
COINS ドライバ API は、コンパイラ部品に対して、ライブラリ・ディレク
トリのパス名を提供する機能がある。すなわち、
CompileSpecification#getCoinsOptions() メソッドによって得られる
coins.driver.CoinsOptions オブジェクトの CoinsOptions#getLibDir() メソッ
ドを呼び出すことで得ることができる。 COINS のユーザは、オペレータに対
して、コンフィギュレーション・ファイルをライブラリ・ディレクトリに置く
ように指示しておいて、上記 API を使ってディレクトリのパス名を得て、必
要なファイルを読み込むことができる。
COINS オプションである -coins:libdir=path が指定された場合、ドライバ
API は、ライブラリ・ディレクトリのパス名として path を返す。このオプショ
ンが指定されていない場合、オペレータのホーム・ディレクトリ (Java 実行
環境が返す、 user.home プロパティの値) に `coins' という名前のディレク
トリがあれば、そのパス名を返す。それもない場合、カレント・ワーキング・
ディレクトリを示す相対パス名を返す。
2.3.7 プロパティ・ファイル
コンパイラの開発のために COINS を使用する場合、トレースや警告の設定、
オリジナルのオプションなどの指定などで、長い COINS オプションを毎回指
定する状況になることが考えられる。この状況を改善する目的で、 COINS オ
プションをファイルに入れ、それを参照させることができるようになっている。
このファイルが「プロパティ・ファイル」である。
デフォルトでは、ライブラリ・ディレクトリの下の `properties' というファ
イルがプロパティ・ファイルとして参照される。
プロパティ・ファイルの位置は、オペレータが指定したいこともあるかもし
れないので、コンパイル仕様を生成するときに設定できるようになっている。
プロパティ・ファイルの解釈と反映は、コンパイル仕様の生成の際に、
coins.driver.CoinsOptions クラスが行う。
properties ファイルの書式は、 java.utils.Properties#load() メソッド
が読み込めるものであれば良い。下記に記述例を示す。
debug:
trace: Driver.8
suffix: /tmp/mysuffixes
上記は、コマンドラインから次のように指定したのと同等である。
-coins:debug,trace=Driver.8,suffix=/tmp/mysuffixes
プロパティ・ファイルとコマンドラインの両方にオプション指定があった場合は、
前者のオプション指定の後ろに後者のオプション指定があった場合と同じことになる。
たとえば、両方にtraceオプション指定がある場合は、後者だけが有効になる。
2.3.8 サフィクス規則
サフィクス規則とは、「どのサフィクスを持つファイルに対してどの処理を
行なうとどのサフィクスを持つファイルが生成されるか」を記述した規則であ
る。 COINS は、 C, Fortran, Java に対応しているデフォルトのサフィクス
規則ファイルを提供している。
デフォルトでは、ライブラリ・ディレクトリの下の `suffixes' というファ
イルがサフィクス規則ファイルとして参照される。サフィクス規則ファイルが
見つからない場合は、下記の内容がデフォルトとして使用される。
#SRD, 2, Suffix rule DB file, format version 2
c, C, C source, i,s,o
c(out-newlir), C, C source, i,lir,-
i, C, preprocessed C source, -,s,o
cc/cpp/cxx/C, C++, C++ source, ii,s,o
ii, C++, preprocessed C++ source, -,s,o
java, Java, Java source, -,class,-
java(native), Java, Java source (native compile), -,s,o
f, FORTRAN, FORTRAN source, -,s,o
f(out-newlir), FORTRAN, FORTRAN source, -,lir,o
lir, LIR, new LIR, -,s,o
S, Assembler, assembly source (need preprocess), s,-,o
s, Assembler, assembly source, -,-,o
このファイルの文法の詳細は、 coins.driver.SuffixFactory.java に記述
されているが、おおむね、
サフィクス, 言語名, 意味, プリプロセス後/コンパイル後/アセンブル後のサフィクス
という構造になっている。
同じサフィクスを持つファイルであっても、コンパイラの動作モードに応じ
て、異なるサフィクスのファイルに変換したい場合があり得る(例えば、ある
Java コンパイラは、バイト・コードにコンパイルする場合は .class ファイ
ルを、ネイティブ・コンパイルする場合は、 .o ファイルを生成するかもしれ
ない)。このように、適用するサフィクス規則をコンパイラの動作時に変更し
たい場合、サフィクス・オプションを使用できる。
サフィクス規則ファイルには、同じサフィクスに対して、複数の規則を定義
することができるが、その場合、そのうちのひとつを除いた残りの規則には、
それぞれに異なるサフィクス・オプションを与えなければならない。
コンパイル仕様にサフィクス・オプションが指定されなかった場合は、サフィ
クス・オプションのないサフィクス規則が使用され、サフィクス・オプション
が与えられた場合は、そのサフィクス・オプションと一致するサフィクス・オ
プションを持つサフィクス規則が使用される。
サフィクス規則ファイルの位置は、オペレータが指定したいこともあるかも
しれないので、コンパイル仕様を生成するときに設定できるようになっている。
サフィクス規則ファイルの解釈と反映は、コンパイル仕様の生成の際に、
coins.driver.SuffixFactory クラスが行う。
2.3.9 settings ファイル
コンパイルは複雑な処理であり、その過程ではいろいろの情報が参照される。
それらの中には、必ずしもすべてのユーザが同じ情報を指定するとは限らない
ものがあり、その場合にはサイト独自の設定が必要となる。この例には、例え
ば、コンパイラがリンクするライブラリファイルの置き場所、 OS の名称や版
番号などが考えられる。settings ファイルは、そのような、サイト独自の設
定を記述するべきファイルとして設計されたものである。
ライブラリディレクトリに settings という名前のファイルがあると、
coins.driver.Driver はこれを読み込み、 defaultSettings という Driver
オブジェクトのメンバ変数に格納する。
settings ファイルの書式は、 java.utils.Propertis#load() メソッドが読
み込めるものであれば良い。
coins.driver.Driver にとって、 settings に記述して有効なのは、次のプ
ロパティである。
- defaultLinkerOptions
常にリンカに与えるオプション。何らかの事情で、毎回 -L オプショ
ンや -B オプションを与えなければならない場合などに使用できる。
- systemIncludePath
常に与えるインクルードパスを指定するオプション。 COINS 固有の
stdarg.h のパスを指定する場合などに使用できる。
COINS を利用して作るコンパイラ部品や、 coins.driver.Driver 以外のド
ライバも、サイト独自の設定を読み込むのに settings ファイルを利用して良
い。
2.4 既知の障害と制限事項
リリース 1.0 における既知の障害と制限事項は下記の通り。
2.4.1 既知の障害
なし。
2.4.2 制限事項
- リンカオプションに -b arch が追加されない。
COINS コンパイラインフラストラクチャが取り扱うターゲットアーキテクチャ
名と、リンカとして使用している gcc が取り扱うターゲットアーキテクチャ
名は異なるポリシーで命名されているので、正しく取り扱うには両者を変換
する必要があるが、現在その機能は実装されていない。 gcc コマンドのデ
フォルトとは異なるアーキテクチャをターゲットとしようとするユーザは、
-coins:linker=linker-command オプションを用いて、リンカとして適切な
オプションつきの gcc を起動するようにするなど、工夫する必要がある。
- -coins:lir2c オプションには下記の制限がある。
- 関数ポインタ
関数ポインタの宣言は、正しい C プログラムに変換できない.
- ポインタ変数
lir2c は、ソースプログラム上ではポインタ型であった変数を int 型
であると宣言する。
- 符号付き/符号なし
lir2c は、ソースプログラム上では符号なし (unsigned) であった変数
も、符号つき (signed) であると宣言する。
また、いくつかの LIR の演算には、符号付きと符号なしの 2 種類があ
るが、 lir2c はこれらを区別せずに変換する。
- グローバル変数の初期化
lir2c は、 char* 型の変数を文字列定数で初期化する場合を除き、関
数の外部で定義されている変数の宣言および初期化のコードを生成しない。
- φ関数
lir2c は、 -coins:ssa-opt オプションで起動される SSA 最適化の結
果 LIR 中に生じる「φ 関数」を変換しない。
2.5 コンパイラ・ドライバの実現
コンパイラ制御部の実現(pdf)を参照されたい。