かつては、forthはforthで構築されているものが多かった。しかし、現在は、forthといえども、中核部分はC言語などの、様々なプラットフォームで利用できるマシン語コンパイル型の言語環境を用いて構築されている例が多いようである。そんな中でMopsは全体がforthで構築されており、現在では特異な存在となっている。その場合、自分自身を自分自身でコンパイルする、ということになる。
自己コンパイルに際しては、ややこんがらがる事態が発生することがある。その混乱の原因は、今コンパイラとして稼働している環境のワード(=関数)と同名のワードを新たに構築しているコンパイラの中にもコンパイルしなければならないことに由来する。特に、現在稼働中の環境の中にあるワードを、コンパイルされているワードの側から呼び出したりしないように注意しなければならない。これをしてしまうと、コンパイル後の関数が、もはや実行ファイル内に実在しない関数を呼び出してしまうことになり、実行すれば、当然、クラッシュするからである。
この点、C言語などの、ソースコードは文字列でしかなく、それを解析した結果にマシンコードを割り当てて保存すれば良いようなコンパイラ型言語(普通はそういう仕組みである)では発生しにくい問題である。
Forth系言語に関しては、コンパイラ構築の練習のために手を出す人が多いようであるので、その種のテクニカルな問題についても説明しておきたいと思う。あまり考えすぎると何だかわけがわからなくなったりするが、実際にはそれほど難しい話ではない。
以下、forth系環境を用いてforth系言語のコンパイラを構築することを話題の中心とし、一般的なC言語系のコンパイラを用いてforthコンパイラを構築することに関しては、付随的に述べる(その上、実際にC言語系でforthを書いた経験はないので、常識的推測に留まる)。
クロスコンパイルとは?
クロスは交差ということで、コンパイルを実行する環境とは別の環境で動くようなコードをコンパイルすること、である。「別の環境」といっても、機械丸ごとマシン語から違うという場合と、OSだけが違うという場合とがある。コンパイラといえども、現在では、何かのOSが動いている状態で動作し、そのサービス関数(ライブラリ関数)を利用するというのは普通なので、CPUのタイプが同じでもOSが違うだけで、かなり違う内容にしなければならない。ポートしようとすると、機械まで違う場合と、OSだけが違う場合とで、かかる時間に大差はないともいわれる。
クロスコンパイルに関して気をつけるべきことは、現在走行中の環境のためのコードを、コンパイルされるコードに混ぜないように注意することである。これに関しては、コンパイルされたマシンコードを保存する場所を考えることで対策を立てるのが一番簡単だが、後で説明する。
機械命令の違いのみならず、保存される数値に関しても、エンディアンの問題がある。iMopsの場合も、初めの環境はビッグエンディアンでRISCマシンであるPowerPC上のコード(PowerMops)を用いて、リトルエンディアンのCISCマシンであるx86-64のコードを出力する形だったので、メモリー上のバイト順を入れ替えるワードを用いた。
なお、自分は全く知識がなかったので初めは混乱したが、機械命令の記録順序は、エンディアンとは関係ないことに留意しておくと良い。機械命令は、通常、最初に演算の種類の指定の記号があり、続いて演算項になるレジスタやメモリー参照の指定の記号があるが、その順番は、数値を表す即値部分(イミディエット)の内部を除けば、エンディアンにかかわらず、メモリーの低いほうが初めという順序である。つまり、機械命令に関しては、全部で4バイトあっても、リトルエンディアンであるからといって小さいほうの桁から格納していく必要はない、というか、そんなことはしてはならない。
最終更新:2016年06月14日 10:16