フロントエンド

- 既存のフロントエンド

- Cフロントエンド

- C言語仕様
- Cフロントエンドの使い方

- 必要なソフト

- Cフロントエンドの構成

- Fortranフロントエンド

- Fortran言語仕様
- Fortranフロントエンドの使い方

- 必要なソフト

- Fortranフロントエンドの構成

- Javaフロントエンド

- 新しいフロントエンドの作り方

- JavaCC（LLパーサ生成系）を使った例
- jay（LRパーサ生成系）を使った例

## 5. フロントエンド

フロントエンドはソースプログラムを解析して、それをHIRのツリーに変換するものである。

### 5.1. 既存のフロントエンド

COINSのリリースに入っているフロントエンドには以下のものがある。

#### 5.1.1. Cフロントエンド

##### 5.1.1.1. C言語仕様

言語仕様はISO規格の
ISO/IEC 9899:1990 Programming Language C
に従っている。これは、1990年版ANSI Cと呼ばれているものと同じである。
ただし、以下のものはサポートしていない。

- 前処理（preprocessing）
- ライブラリ
- wchar_t型とL"xx"定数

なお、long double型はdouble型と同じサイズである。 また、前処理とライブラリはgccのものが使われることを仮定している。

##### 5.1.1.2. Cフロントエンドの使い方

Cフロントエンドは次の形のコマンドによって呼び出すことが出来る。

    　　　java coins.driver.Driver オプション指定　　ソースファイル名

「オプション指定」については 2.2. コンパイラ・ドライバの使い方 を参照されたい。

「ソースファイル名」は".c"で終わるものでなければならない。

###### 必要なソフトウェア

以下のコマンドが実行出来るようになっていなければならない。

- cpp（プレプロセサ）
- gas（アセンブラ）
- gcc（リンカとして）

それらが使えず、代わりにものがある場合、たとえば、 アセンブラとして"gas"でなく"as"が使える場合は

    　　　-coins:assembler=as

というオプション指定をすればよい。より詳しくは ここの

    　　　-coins:preprocessor/assembler/linker

の記述を参照されたい。

##### 5.1.1.3. Cフロントエンドの構成

C言語には演算と代入の機能を併せ持つ複合代入演算子などがあるので、そのようなC言語の演算子をそのまま表現できる機能をHIRに追加したHIR-Cを定め、HIR-Cを経由してHIRに変換する方式とした。また、HIRを作成する際に無駄を省くため、簡単な効率化機能も組み込んだ。したがって、HIRへの変換過程は次のようになっている。

1. Ｃプログラムを抽象構文木ASTに変換
このモジュールはcoins.cfrontとcoins.astパッケージにある。
2. ASTをHIR-Cに変換
このモジュールはcoins.casttohirパッケージにある。
3. HIR-CをHIRに変換
このモジュールはcoins.casttohirパッケージにある。
4. HIRに対する最適化化変換

Cの前処理系にはgccの前処理系cppを利用する。また、実行時ライブラリもgccのものを利用することにし、インタフェースをgccに合わせている。

    -coins:hirOpt=fromc

というオプション指定をすると、HIR生成時に次のような最適化を行う。
ただし、この指定がなくても、同様な最適化がHIRの基本最適化や バックエンドの最適化で行われるので、生成されるコードに対する効果は あまりないが、生成されるHIRが多少短くなる。

1. 打ち消しあう演算の削除

       *&v    -->  v
        -(-v)  -->  v、　他

2. 特定の定数に対する演算

       v +  0  -->  v		  v -  0  -->  v
       v *  0  -->  0		  v *  1  -->  v, 他

3. 条件式の効率化

        !(a<b)  -->  a>=b
       定数A 比較演算子 定数B  -->  true または false, 他
       e1 && e2  でe1がtrue  -->  e1の副作用,e2
       r = (a=1)>0 ? 1 : 0;  -->  r = (a=1) , 1;   他

4. 無駄な文の削除

       到達不能の式文/return/goto  -->  削除
       ジャンプ距離が0のgoto       -->  削除
       参照されないラベル          -->  削除
       連続するラベル              -->  ラベルの統合
       空のブロック                -->  削除
       式文                    -->  副作用だけ残して他の部分を削除

5. 条件式が定数(trueまたはfalse)の場合のif文の展開

       if(true) THEN部; else ELSE部; --> { THEN部; goto LABEL_END; ELSE部; LABEL_END:; }, 他

6. 条件式が定数(trueまたはfalse)の場合のループ文の展開

       while(false) BODY部;
    	--> { goto LABEL_BREAK; BODY部; LABEL_BREAK:; }
       for(INIT部;false;STEP部) BODY部;
    	--> { INIT部; goto LABEL_BREAK; BODY部; STEP部; LABEL_BREAK:; }
       do BODY部; while(false);             --> BODY部;
       他

詳しくは、COINSのソース・アーカイブのdoc-en/CfrontOpt.txtを参照されたい。

#### 5.1.2. Fortranフロントエンド

##### 5.1.2.1. Fortran言語仕様

言語仕様はFortran 77にしたがっている。Fortran 77の規格文書としては以下のものが あるが、内容的にはすべて同じである。

- アメリカ規格: ANSI X3.9-1978 Programming Language FORTRAN
- 国際規格: IS 1539 Programming Languages -- FORTRAN
- 日本工業規格: JIS C 6201 電子計算機プログラム言語 FORTRAN

ただし、以下の制限がある。

- BLOCK文で宣言されている変数はEQUIVALENCE文で使ってはならない
- 文字型のサブストリングはEQUIVALENCE文で使ってはならない
- ENTRY文のサポートが不完全である
- READ文のサポートが不完全である

以下のものはFortran 77の規格の仕様には入っていないが、ベンチマークプログラム などでもよく使われているので、サポートしている。

- DO ... END DOが使える
- 識別子の2文字目以降に"_"が使える
- 型として、complex * 16 、integer * 8 、real * 8 などを許す

##### 5.1.2.2. Fortranフロントエンドの使い方

Fortranフロントエンドは次の形のコマンドによって呼び出すことが出来る。

    　　　java coins.driver.F77Driver オプション指定　　ソースファイル名

「オプション指定」については 2.2. コンパイラ・ドライバの使い方 を参照されたい。

「ソースファイル名」は".f"で終わるものでなければならない。ソースファイル名は "foo.f bar.f ..."のようにいくつか並べても良い。

なお、

       -coins:printhir

というオプションを指定すると、FortranプログラムをHIRに変換した後で、HIRの木と シンボルテーブルを出力する。

これは、coins.driver.F77Driverの中に、次のような記述があるからである。 このようにして、任意のオプションを追加することが出来る。

       if (io.getCompileSpecification().getCoinsOptions().isSet("printhir")) {
          hirRoot.programRoot.print(0);
          io.printOut.print("¥n");
          symRoot.symTable.printSymTableAllDetail(symRoot.symTableRoot);
          symRoot.symTableConst.printSymTableDetail();
          io.printOut.print("¥n");
        }

###### 必要なソフトウェア

Cで必要なソフトウェアはFortranでも必要である。

その他に、実行時ライブラリとして"libf2c"が必要である。このライブラリは http://www.netlib.org/f2c/libf2c.zip をダウンロードして、その中にあるREADMEにしたがってインストールすれば良い。

UNIX系のOSの場合、解凍したlibf2cのディレクトリで

    % cp makefile.u Makefile
    % make

を実行して得られる"libf2c.a"を適当なところにおいて、その置き場所を Fortran Driverに認識させれば良い。そのためには

    libf2cLocation	  /directory/path/where/libf2c.a/exists

のように、"libf2c.a"の置き場所を指定する行を含んだファイルを"settings"という名前で ライブラリ・ディレクトリに置けば良い。

ライブラリ・ディレクトリは、特に指定しない場合は、

    ~/coins/

となっているので、そこに"settings"ファイルを置けば良い。

なお、cygwinの場合は、上記の手続きに少し修正が必要である。まず、上記のMakefileの中にある"a.out" を"a.exe"に変更する必要がある（2ヶ所）。また、cygwinでは、上記のライブラリ・ディレクトリを認識せず、 現在作業中のディレクトリを探すようであるので、"settings"ファイルは作業中のディレクトリに置いておく必要がある。

##### 5.1.2.3. Fortranフロントエンドの構成

coins.driver.F77Driverはcoins.driver.Driverのサブクラスであり、 フロントエンド呼び出しのメソッドをオーバライドしているだけである。 したがって、coins.driver.Driverのほとんどの機能はそのまま使うことが出来る。

Fortran言語には、ENTRY文、assigned GOTO文など、最近の言語にはない ものとしてHIRには用意されてない機能がいくつかある。それらについては プログラム変換をしている。おおまかには、それと等値な働きをするCプログラムを 考えて、それのHIRに相当するものに変換している。

HIRへの変換過程は次のようになっている。

1. FortranプログラムをFortran用中間表現Firに変換
2. FirをHIRに変換

これらのモジュールはcoins.ffrontパッケージにある。そのディレクトリ内にある

- 手書きのF77Scannerクラス
- f77k.lexからJFlexによって生成されたScannerクラス
- f77k.jayからjayによって生成されたParserクラス

によって字句解析と構文解析が行われる。

詳しくは Fortran特有の機能に対する考慮、 Fortranコンパイラの設計、を参照されたい。

#### 5.1.3. Javaフロントエンド

Javaのフロントエンドは以下の方針で開発しているが、デバッグ中であるので、リリース版にはまだ入っていない。

Javaではプログラムがソースプログラムとしてではなく、クラスファイルとして提供されることが多い。Javaソースプログラムを入力とする言語処理系を作ったとしても、クラスファイルを入力とするものも必要となる。そこで、COINSではJava言語を入力とするのではなく、それから作られたクラスファイルを入力としてHIRを生成する。JavaプログラムはHIRとLIRを経て機械語に変換されるが、それを実行する時には通常のJava仮想機械が持つ機能も必要になる。それらの機能を少ない人数で短期間に作ることは困難なので、gnu gcjの実行時ライブラリを利用することにし、インタフェースをそれにあわせた。

Javaの実現にあたっては、オブジェクトの生成と例外処理が大きい課題となる。オブジェクトのデータ構造はgcjにあわせる。例外処理の方法としては、表引き法、２返戻値法などがあるが。gcjは表引き法を採用している。これをHIRで表現するには、HIRに例外処理の機構を組み込む必要があり、それはHIRだけでなく、バックエンドなど、COINSのほぼ全体に対する改造が必要となる。そこで、Javaの例外処理の実現にあたっては、２返戻値法を使うことにして、メソッド呼び出し時にgcjの表引き法が必要とする情報を付加するつなぎの処理を挿入することにした。

### 5.2. 新しいフロントエンドの作り方

COINSで新しいフロントエンドを作った例としては、C0コンパイラ、PL0コンパイラ、Simpleコンパイラ、 Fortranコンパイラなどがある。
最初のC0コンパイラについては、情報処理学会誌のVol.47のNo.4とNo.5に連載された 「21世紀のコンパイラ道しるべ　・・COINSをベースにして」に説明がある。 後ろの3つのコンパイラについては、それらの説明が下記のページにあるので、 それを参照されたい。 http://www.coins-project.org/advanceduse/compilerDevelop.html

#### 5.2.1. JavaCC（LLパーサ生成系）を使った例

C0コンパイラのフロントエンドのJavaCCによる記述は http://www.coins-project.org/IPSJ-mitisirube/ のc0frontを参照されたい。

PL0コンパイラのフロントエンドのJavaCCによる記述は http://www.coins-project.org/advanceduse/ll/coinsCompilerPL0.html を参照されたい。

#### 5.2.2. LRパーサ生成系を使った例

C0コンパイラのフロントエンドのnotavaccによる記述は http://www.coins-project.org/IPSJ-mitisirube/ のc0front2を参照されたい。

Simpleコンパイラのフロントエンドのjayによる記述は http://www.coins-project.org/advanceduse/simple/coinsCompiler.html を参照されたい。