(Translated by https://www.hiragana.jp/)
コンパイラ - Wikipedia コンテンツにスキップ

コンパイラ

出典しゅってん: フリー百科ひゃっか事典じてん『ウィキペディア(Wikipedia)』

コンパイラえい: compiler)は、高水準こうすいじゅん言語げんごかれたコンピュータプログラムを、 コンピュータが実行じっこう解釈かいしゃくできる形式けいしきに、一括いっかつして(※[1]変換へんかんするソフトウェア[2]

概説がいせつ

[編集へんしゅう]

コンパイラの技術ぎじゅつしょのバイブルとされるAlfred V.Aho(アルフレッド・エイホちょ Compilers, Principles, Techniques, and Tools通称つうしょう「ドラゴンブック」[注釈ちゅうしゃく 1])のだい1しょう1せつ冒頭ぼうとうに、コンパイラとはそもそもなにかということについて説明せつめい掲載けいさいされており、そこには「簡潔かんけつうと、コンパイラとは、ある言語げんご(プログラミング言語げんご)でかれたプログラム(ソースプログラム)をみ、それをべつ言語げんごかれた等価とうかのプログラム(ターゲットプログラム)へと翻訳ほんやく(translate)するプログラムである。」とかれており、さらにつづけて「コンパイラは、ソースプログラムにふくまれるエラーをユーザに報告ほうこくするという重要じゅうようなことを翻訳ほんやくの1プロセスとしておこなう。」という説明せつめいくわえている[3]

英語えいご動詞どうしで、あるプログラム言語げんごかれたコードをべつ言語げんごかれたコードに変換へんかんすることを"compile"(コンパイル)といい、コンパイラとはその変換へんかん一括いっかつして(※[1]おこなうコンピュータプログラムのことである。インタプリタとよく対比たいひされる。

(なお、うえでは「ソースプログラム」「ターゲットプログラム」という古典こてんてき用語ようごふく説明せつめいぶん紹介しょうかいしたが、最近さいきん技術ぎじゅつ用語ようごでは、変換へんかんされるまえのプログラムを「ソースコード」とび、変換へんかん機械きかいあるいは中間ちゅうかん言語げんごのプログラムなどを「オブジェクトコード」と[4]傾向けいこうがある。また機械きかい進数しんすうかれているので近年きんねんでは「バイナリコード」ということもある。)

よくあるのは、高水準こうすいじゅん言語げんごかれたプログラムを、コンピュータのプロセッサ[5]直接ちょくせつ実行じっこうできる機械きかいあるいはアセンブリ言語げんごのようなてい水準すいじゅん言語げんごあるいはもとのプログラムよりも"ひくいレベル"のコード(たとえばバイトコードなどの仮想かそう機械きかい中間ちゅうかん言語げんごあるいは中間ちゅうかん表現ひょうげん)に変換へんかんするものである。

コンパイラを俯瞰ふかんしてみると、このには圧倒あっとうされるほど種類しゅるいのコンパイラがある[3]。というのは、ソースコード(ソースプログラム)の記述きじゅつ使つかわれるプログラミング言語げんごだけに着目ちゃくもくしても、FORTRANなど歴史れきしふる言語げんごからはじまり近年きんねん勃興ぼっこうしてきている言語げんごまでふくめるとすうせんにもおよぶプログラミング言語げんごがあり、他方たほう、オブジェクトコード(ターゲットプログラム)の記述きじゅつ使つかわれる言語げんごのほうに着目ちゃくもくしても、種類しゅるいがやはり非常ひじょうおおく、ソースコードの言語げんごとはべつ言語げんごであるかもれないし[注釈ちゅうしゃく 2]、(あるいは中間ちゅうかん言語げんごであるかもれないし)、あるいは機械きかいであるかもれないからであり、その機械きかいマイクロプロセッサもちいたコンピュータのものからスーパーコンピュータのものまであり多種たしゅ多様たようだからである[3]

またコンパイラの種類しゅるいには、シングルパス(ワンパスとも。1かい変換へんかん作業さぎょう完了かんりょうできるもの)、マルチパス(en:Multi-pass compilerふくすうかい作業さぎょう必要ひつようだが、しゅ記憶きおくすくなくてもうごくもの)、ロード・アンド・ゴー(変換へんかんしてすぐに実行じっこう開始かいしするもの)、デバッグもちい最適さいてきようなどの種類しゅるいもある[3]。 →#分類ぶんるいふし説明せつめい

またコンパイルを使つかったコンパイル作業さぎょうは、ひとつのプログラムとして動作どうさするすべてのコードをいっぺんにコンパイルするのではなく、モジュールごとなどにけてコンパイルし(「分割ぶんかつコンパイル」)、ライブラリなどはあらかじめコンパイルされているものとわせて実行じっこうするようにすることもおお[6]。この場合ばあい、コンパイラはリロケータブルバイナリ出力しゅつりょくし、実行じっこう可能かのうファイルの生成せいせいにはリンケージエディタ必要ひつようであり、さらに動的どうてきリンク実行じっこうする場合ばあいはダイナミックリンカ/ローダ(ローダ一種いっしゅ)も必要ひつようである。

なお、「コンパイラ(言語げんご) / インタプリタ(言語げんご)」という2ふん法的ほうてき分類ぶんるいは、Java登場とうじょう以前いぜんでは一般いっぱんてき適切てきせつだったが、近年きんねんでは適切てきせつでないこともえている。開発かいはつ環境かんきょうなどでは、コンパイルしたのち実行じっこうするというような手続てつづきを1コマンドでおこなえるものもえている。そして、Java以降いこうはインタプリタでも実行じっこうコンパイラなどの技術ぎじゅつ利用りようがさかんになってきており、古典こてんてき意味いみでの「コンパイラ」と「インタプリタ」のなかあいだてき性質せいしつのツール(プログラム)もえてきているからである。

なお英語えいごの「compile」はもともと「編集へんしゅうする」「編纂へんさんする」という意味いみ英語えいごであり[7][8]、「compiler」というのは「編集へんしゅうしゃ」という意味いみ英語えいごである[9][10][11][12]

歴史れきし

[編集へんしゅう]

1940年代ねんだいまで、コンピュータのプログラミングは機械きかい直接ちょくせつおこなわれていた。プログラムをして「コード」(英語えいごでは暗号あんごう意味いみする)とぶのは、らない人間にんげんには機械きかいまった意味いみのわからない数値すうち羅列られつだからである。しかし、(人間にんげんにとって比較的ひかくてき理解りかいのしやすい)十進法じっしんほう数字すうじかれたアドレスを内部ないぶ表現ひょうげん二進法にしんほう変換へんかんする、といったプログラムならばEDSAC(1940年代ねんだいまつ登場とうじょうした、イギリスのマシン)においてすで存在そんざいしていた。(つまり、この段階だんかいで、アセンブラのごく一部いちぶ機能きのうかぎれば、実現じつげんしていたことになる)

機械きかいでのプログラミングはうにおよばず、アセンブリ言語げんごもちいても、プログラミングというのは面倒めんどう作業さぎょうである。そういったてい水準すいじゅん言語げんごから、人間にんげんがよりあつかいやすい高水準こうすいじゅん言語げんご徐々じょじょもとめられるようになった。また、機械きかい詳細しょうさい抽象ちゅうしょうされることにより、高水準こうすいじゅんなプログラミング言語げんごかれた同一どういつのソースコードをもとに、詳細しょうさい仕様しようことなる機械きかいでもうごくプログラムを生成せいせいできる、という利点りてんもあった。1950年代ねんだいまつまでに、プログラミング言語げんごがいくつか提案ていあんされ、実験じっけんてきなコンパイラがいくつか開発かいはつされた。

世界せかいはつのコンパイラについては、1952ねんグレース・ホッパーいたA-0 Systemだとされることもある。だが一般いっぱんてきには1957ねんIBMジョン・バッカスのチームが開発かいはつしたFORTRANコンパイラ世界せかいはつ完全かんぜんなコンパイラであるとされている。一般いっぱんてきなコンパイラの開発かいはつでは、まずうごくものをつくってから最適さいてき機能きのうくわえられるが、最初さいしょのFORTRANコンパイラでは、コンパイラが実用じつようになることをしめすために、最初さいしょから最適さいてき労力ろうりょくけられた。

1960ねんの、ホッパーらによるCOBOL複数ふくすうアーキテクチャうえでコンパイル可能かのうとなった言語げんご最初さいしょの1つである。

様々さまざまなアプリケーション領域りょういきで、高水準こうすいじゅん言語げんごというアイデアは素早すばや浸透しんとうしていった。機能きのう拡張かくちょうされたプログラミング言語げんご次々つぎつぎ提案ていあんされ、コンピュータのアーキテクチャそのものも複雑ふくざつしていったため、コンパイラはどんどん複雑ふくざつしていった。

初期しょきのコンパイラはアセンブリ言語げんごかれていた。世界せかいはつの「セルフホスティングコンパイラ」は、1962ねんマサチュまさちゅセッツ工科大学せっつこうかだいがくの Hart と Levin が開発かいはつしたLISPである[13]。1970年代ねんだいには、とくPascalC言語げんごなどにおいて、コンパイル対象たいしょう言語げんごでコンパイラをくことが一般いっぱんした。さらにより高水準こうすいじゅん言語げんごのコンパイラは、PascalやC言語げんご実装じっそうすることもおおい。セルフホスティング・コンパイラの構築こうちくには、ブートストラップ問題もんだいがつきまとう。すなわち、コンパイル対象たいしょう言語げんごかれたコンパイラを最初さいしょにコンパイルするには、べつ言語げんごかれたコンパイラが必要ひつようになる。Hart と Levin の LISPコンパイラではコンパイラをインタプリタじょう動作どうささせてコンパイルをおこなった。

分類ぶんるい

[編集へんしゅう]

機械きかいにコンパイルするコンパイラもあれば、そうでないコンパイラ(後述こうじゅつ)もある。機械きかいコードのことを、ハードウェアであるプロセッサせいのコード、というような意味いみでネイティブコードなどとうことがあり、機械きかいにコンパイルするコンパイラのことをネイティブコンパイラとうことがある。

コンパイラにかぎらず、入力にゅうりょく出力しゅつりょくつあらゆる変換へんかんけいは、入力にゅうりょく種類しゅるいがm種類しゅるい出力しゅつりょく種類しゅるいがn種類しゅるいあるとすると、m×n種類しゅるいがあることになる。コンパイラの場合ばあい、プログラミング言語げんごがm種類しゅるい、コード生成せいせい対象たいしょうとなる命令めいれいセットアーキテクチャがn種類しゅるい、といったようなかんじになるわけであり、入力にゅうりょくがわをフロントエンド、出力しゅつりょくがわをバックエンドとうが、中間ちゅうかん表現ひょうげん設計せっけいいかんでは、のこりのなかあいだ処理しょり部分ぶぶんとく重要じゅうよう部分ぶぶんであるコンパイラ最適さいてき共有きょうゆうできるため、1980年代ねんだい以降いこう基本きほん設計せっけいされたGCCやCOINSやLLVMなどでは、そのようにして多言たげんターゲットに対応たいおうしている。

汎用はんようOSなど、開発かいはつ環境かんきょうおな環境かんきょう目的もくてきプログラムも動作どうささせるような開発かいはつを「セルフ開発かいはつ」とい、セルフ開発かいはつのコンパイラを「セルフコンパイラ」という。それにたいし、開発かいはつ環境かんきょうとはべつ環境かんきょう実行じっこうするような開発かいはつを「クロス開発かいはつ」といい、そのためのコンパイラをクロスコンパイラという。OSカーネル自身じしんのコンパイルなどは、カーネル自身じしん実行じっこう環境かんきょうは、そのOSではなくベアメタルであるという意味いみではあるしゅのクロスコンパイルのようなものであるし、あたらしいコンピュータシステムのための環境かんきょう最初さいしょつくるにはクロス開発かいはつ必要ひつようがある。あるいは、みシステムPDAなど、それ自体じたい開発かいはつ環境かんきょう動作どうささせるだけの機能きのう性能せいのうたない場合ばあい、といったものもある。

いわゆるネイティブコードではなく中間ちゅうかんコード生成せいせいし、さらにべつのコンパイラに処理しょりまかせたり、べつのインタプリタによって実行じっこうしたりするものもある。これを中間ちゅうかんコードコンパイラ、バイトコードコンパイラなどとぶ。またそのバイトコードを解釈かいしゃく実行じっこうする処理しょりけいをバイトコードインタプリタなどとぶ。

ワンパスとマルチパス

[編集へんしゅう]

コンパイラは様々さまざま処理しょり集合しゅうごうたいであり、初期しょきのコンピュータではメモリ容量ようりょう不十分ふじゅうぶんであったため、いちすべての処理しょりおこなうことができなかった。このためコンパイラを複数ふくすう分割ぶんかつし、ソースコードやなんらかの中間ちゅうかんてき表現ひょうげんなん処理しょりほどこすことで解析かいせき変換へんかんおこなっていた。

一回いっかいでコンパイルが可能かのうなものをワンパスコンパイラび、一般いっぱんマルチパスコンパイラよりも高速こうそくあつかいやすい。Pascalなど、おおくの言語げんごはワンパスでコンパイルできるよう意図いとして設計せっけいされている。

言語げんご設計せっけいによっては、コンパイラがソースコードをふくすうかい必要ひつようがある。たとえば、20ぎょう出現しゅつげんする宣言せんげんぶんが10ぎょうぶん変換へんかん影響えいきょうあたえる場合ばあいがある。この場合ばあい一回いっかいのパス(み)で影響えいきょうけるぶんのちにある宣言せんげんかんする情報じょうほうあつめ、かいのパスで実際じっさい変換へんかんおこなう。

ワンパスの欠点けってんは、こう品質ひんしつのコードにかせない最適さいてきおこないにくいというてんげられる。最適さいてきコンパイラがなんかいみをおこなうかというのはまっていないが、最適さいてきかくフェーズでおなしきぶんなん解析かいせきすることもあるし、いちかいしか解析かいせきしない箇所かしょもある。

コンパイラをちいさなプログラムに分割ぶんかつする手法しゅほうは、研究けんきゅうレベルでよくおこなわれる。プログラムの正当せいとうせい判定はんていは、対象たいしょうプログラムがちいさいほど簡単かんたんなためである。

ネイティブコンパイラのほかにも以下いかのような、「ネイティブの機械きかい以外いがいをターゲットとするコンパイラ(ないしトランスレータ)がある。

  • なんらかの高水準こうすいじゅん言語げんごから、なんらかの高水準こうすいじゅん言語げんご変換へんかんする「トランスレータ」。「トランスコンパイラ」などというかたりもある。たとえば、OpenMPなどの自動じどう並列へいれつコンパイラは並列へいれつ明示めいじされていないプログラムを、並列へいれつ明示めいじしたプログラムに変換へんかんする。または、FORTRANの DOALL ぶんなどなんらかの言語げんご構文こうぶん変換へんかんする。
  • ステージコンパイラ(Stage Compiler)はなんらかの理論りろんじょうのマシンのアセンブリ言語げんご出力しゅつりょくする。たとえば、一部いちぶPrologでそのような実装じっそうがなされている。[よう出典しゅってん]JavaPython のバイトコードコンパイラもステージコンパイラの一種いっしゅえる。
  • Java や Smalltalk やマイクロソフトの共通きょうつうちゅうあいだ言語げんごシステムで使つかわれているJITコンパイラ。コンパイラはいったん中間ちゅうかん表現ひょうげん生成せいせいし、実行じっこう中間ちゅうかん表現ひょうげんがターゲットの機械きかいにコンパイルされる。

コンパイラ言語げんご

[編集へんしゅう]

もっぱらその言語げんご処理しょりけいがコンパイラとして実装じっそうされる言語げんごを「コンパイラ言語げんご」などとい、インタプリタとして実装じっそうされる言語げんごを「インタプリタ言語げんご」などとうこともあるが、実験じっけんてき実装じっそうまでふくめればどちらもある言語げんごおおい。Microsoft Visual Studio付属ふぞくするF#/C# Interactiveのように、対話たいわ環境かんきょう入力にゅうりょくしたプログラムを、コンパイラで共通きょうつうちゅうあいだ言語げんご中間ちゅうかん表現ひょうげん)にコンパイルし、さらに共通きょうつう言語げんごランタイム仮想かそう機械きかいじょうでネイティブコードにJITコンパイルしてインタプリタてき実行じっこうする、というような処理しょりけいもある。JavaMicrosoft Visual Basicのように、登場とうじょう当初とうしょはインタプリタ方式ほうしきだったが、のちにネイティブコードへのJITコンパイルやAOTコンパイルをサポートするようになった言語げんごもある。

Common Lispなど言語げんごによっては、実装じっそうにコンパイル機能きのうふくむことを義務ぎむとする仕様しようもある(ただし、Common Lisp仕様しよう解釈かいしゃく実行じっこう処理しょりけい禁止きんししているのではない)。また、インタプリタの実装じっそう容易よういでコンパイラの実装じっそう困難こんなん言語げんごもある(APLSNOBOL4など)。メタプログラミングの利用りようとく文字もじれつevalすることは、インタプリタ方式ほうしきでは造作ぞうさくないことだが、コンパイラ方式ほうしきでは実行じっこう環境かんきょうにコンパイラ自体じたい必要ひつようとなる(動的どうてきプログラミング言語げんご参照さんしょう)。

ハードウェア・コンパイラ

[編集へんしゅう]

ハードウェア記述きじゅつ言語げんご処理しょりけい合成ごうせいけい)を、ハードウェアコンパイラとかシリコンコンパイラなどとぶことがある。

コンパイルのタイミング

[編集へんしゅう]

コンパイルをアプリケーションの実行じっこうおこなうか、実行じっこうまえおこなうかで2つにかれる。

教育きょういくようコンパイラ

[編集へんしゅう]

コンパイラ構築こうちくコンパイラ最適さいてきは、大学だいがくでの計算けいさん科学かがく情報じょうほう工学こうがくのカリキュラムの一部いちぶとなっている。そのようなコースでは適当てきとう言語げんごのコンパイラを実際じっさいつくらせることがおおい。文書ぶんしょ豊富ほうふれいとしてはニクラウス・ヴィルトが1970年代ねんだい教育きょういくよう設計せっけいし、教科書きょうかしょちゅうしめした PL/0 がある[14]。PL/0 は単純たんじゅんだが、教育きょういく目的もくてきにかなった基本きほんまなべるようになっている。PL/0 はPascalでかれていた。ヴィルトによる教科書きょうかしょなん改訂かいていされており、1996ねんはんではOberonでOberonのサブセットOberon-0を実装じっそうしている。

  1. 段階だんかいてき改良かいりょうによるプログラム開発かいはつ[リンク]採用さいよう
  2. 再帰さいき下降かこう構文こうぶん解析かいせき採用さいよう
  3. 拡張かくちょうBNF記法きほうによる文法ぶんぽう記述きじゅつ採用さいよう
  4. Pコード採用さいよう
  5. ブートストラップ問題もんだいをT図式ずしきen:Tombstone diagram)で形式けいしきてき記述きじゅつ

インタプリタとのちが

[編集へんしゅう]

もともとは、コンパイラはしばしばインタプリタ対比たいひされてきたものである。コンパイラは、生成せいせいされた機械きかいプログラムなどの実行じっこうおこなわないが、一度いちどコンパイルすればコンパイラを使つかわずになん実行じっこうできるという利点りてんがある。しかし、インタプリタは、バイナリ実行じっこうファイルは生成せいせいせず、実行じっこうするときにつね必要ひつようだが、プログラムつくったらすぐに実行じっこうできるという利点りてんがある[15][16]

しくみと設計せっけい

[編集へんしゅう]

コンパイラは、概念的がいねんてきうと、一般いっぱんつぎのようなフェーズ(phase(s)、段階だんかい)にしたが処理しょりおこな[17] [18]

通常つうじょうつぎのようないれ出力しゅつりょく説明せつめいされる。[17]

ソースプログラム(ソースコード字句じく解析かいせき構文こうぶん解析かいせきセマンティック解析かいせき中間ちゅうかんコード生成せいせいコード最適さいてきコード生成せいせいターゲットプログラム(オブジェクトコード)

太字ふとじ表記ひょうきしたものがコンパイラのなかふくまれている部分ぶぶん(コンパイラの部品ぶひん)である。つまり、まず字句じく解析かいせき字句じく解析かいせき)がソースコードをトークン分解ぶんかいし、つぎ構文こうぶん解析かいせき構文こうぶん解析かいせき)がトークンれつからプログラムの構文こうぶん構築こうちくし、つぎにセマンティック解析かいせき意味いみ解析かいせき)が意味いみろんてき解析かいせきおこない、つぎ中間ちゅうかんコード作成さくせい中間ちゅうかんコードを生成せいせいし、つぎ最適さいてきがコードの最適さいてきおこない、最後さいごコード生成せいせいうつわ最終さいしゅうてきなターゲットプログラム(オブジェクトコード)[注釈ちゅうしゃく 3]生成せいせいする。

なお、コンパイラの作成さくせいかんすることだが、字句じく規則きそくから字句じく解析かいせき生成せいせいするlex[19]構文こうぶん規則きそくから構文こうぶん解析かいせき生成せいせいするパーサジェネレータ[20]というプログラムがあり、ひろ実用じつようてき使つかわれている。つまりコンパイラのプログラムの一部分いちぶぶん自動的じどうてきいてくれるようなプログラムがすでにあり、それのおかげで全部ぜんぶ人力じんりきくようなことはしないでむ。(なお、コンパイラ全体ぜんたい生成せいせいするコンパイラジェネレータ研究けんきゅうされているものの、ひろ実用じつよう使つかわれるにはいたっていない。)

コンパイラ設計せっけい手法しゅほう処理しょり複雑ふくざつさ、設計せっけいしゃ経験けいけん利用りよう可能かのうなリソース(人間にんげんやツール)に影響えいきょうされる。

コンパイル処理しょり分割ぶんかつ採用さいようしたのはカーネギーメロン大学だいがくでの Production Quality Compiler-Compiler Project であった。このプロジェクトでは、「フロントエンド」、「ミドルエンド」(今日きょうでは滅多めった使つかわれない)、「バックエンド」という用語ようごされた。

非常ひじょうちいさなコンパイラ以外いがい今日きょうでは2段階だんかい(2フェーズ)以上いじょう分割ぶんかつされている。しかし、どういったフェーズけをしようとも、それらフェーズはフロントエンドかバックエンドの一部いちぶなすことができる。フロントエンドとバックエンドの分割ぶんかつてんはどこかというのは論争ろんそうたねにもなっている。フロントエンドではおも文法ぶんぽうてき処理しょり意味いみろんてき処理しょりおこなわれ、ソースコードよりもていレベルな表現ひょうげん変換へんかんする処理しょりおこなわれる。

ミドルエンドはソースコードでも機械きかいでもない形式けいしきたいして最適さいてきほどこすフェーズとされる。ソースコードや機械きかい独立どくりつしているため、汎用はんようてき最適さいてき可能かのうとされ、各種かくしゅ言語げんご各種かくしゅプロセッサに共通きょうつう処理しょりおこなう。

バックエンドはミドルエンドの結果けっかけて処理しょりおこなう。ここでさらなる解析かいせき変換へんかん最適さいてき特定とくていのプラットフォームけにおこな場合ばあいもある。そして、特定とくていプロセッサやOSけにコードを生成せいせいする。

このフロントエンド/ミドルエンド/バックエンドという分割ぶんかつほう採用さいようすることにより、ことなるプログラミング言語げんごけのフロントエンドを結合けつごうしたり、ことなるCPUけのバックエンドを結合けつごうしたりできる。この手法しゅほう具体ぐたいれいとしてはGNUコンパイラコレクションAmsterdam Compiler KitLLVM がある。これらは複数ふくすうのフロントエンドと複数ふくすうのバックエンドがあり、解析かいせき共有きょうゆうしている。

フロントエンド

[編集へんしゅう]

フロントエンドはソースコードを分析ぶんせきして、中間ちゅうかん表現ひょうげんまたは IRばれるプログラムの内部ないぶ表現ひょうげん構築こうちくする。また、シンボルテーブル管理かんりし、ソースコードないかくシンボルに対応たいおうしたデータ構造こうぞう位置いち情報じょうほうかた情報じょうほうスコープなどの情報じょうほう格納かくのうする。このような処理しょりはいくつかのフェーズで実施じっしされる。たとえば以下いかのようなフェーズがある。

  1. くだりさい構築こうちく(Line reconstruction) - キーワードにストロッピング英語えいごばんほどこ場合ばあい識別子しきべつし空白くうはく挿入そうにゅう可能かのう場合ばあい字句じく解析かいせきまえ入力にゅうりょく文字もじれつを「正規せいき」する必要ひつようがある。1960年代ねんだい一般いっぱんてきトップダウン再帰さいき下降かこうがたおもて駆動くどう構文こうぶん解析かいせきでは、ソースコードを一度いちどむだけでトークンのフェーズは不要ふようだった。ストロッピングをおこな言語げんごとしては、Atlas Autocode英語えいごばんEdinburgh IMP英語えいごばん一部いちぶALGOL処理しょりけいなどがあり、これらは「こうさい構築こうちく」フェーズをっている。ストロッピングとは、キーワードになんらかの記号きごうをつけることでキーワードとして使つかわれている文字もじれつ予約よやくとせず、おな文字もじれつ変数へんすうめいやサブチン名ちんめい利用りようできるようにしたものである。たとえば、シングルクオートでキーワードをかこむとか、%記号きごう先頭せんとうにつけるなどの記法きほうがある。
  2. 字句じく解析かいせき - ソースコードの文字もじれつを、「トークン」とばれる、言語げんごてき意味いみのある最小さいしょう単位たんい分割ぶんかつする。かくトークンは最小さいしょう構成こうせい要素ようそであり、たとえばキーワード、識別子しきべつし、シンボルめい、「10」や「365」のようなかず、などである[21]。トークンは一般いっぱん正規せいき言語げんごしたがうため、正規せいき表現ひょうげん解釈かいしゃくする有限ゆうげんオートマトン認識にんしきできる[22]字句じく解析かいせきおこなうソフトウェアを字句じく解析かいせき(lexical analyzer)とぶ。
  3. プリプロセッサ - コンパイルまえぜん処理しょりおこなうもの。マクロ実装じっそうや、定数ていすう定義ていぎ、ヘッダファイルのみに使つかわれる。一般いっぱんにこのフェーズは構文こうぶん解析かいせき意味いみ解析かいせきまえおこなわれる。プリプロセッサはトークンを操作そうさするものであって、構文こうぶん考慮こうりょしない[23]。だから、C言語げんごなどでは、プリプロセッサでマクロを実装じっそうできるが、LISPのような言語げんごでは構文こうぶん解析かいせきマクロえる必要ひつようがあり、プリプロセッサは使つかわれない。
  4. 構文こうぶん解析かいせき - トークンれつ解析かいせきし、プログラムの構造こうぞうあきらかにする。このフェーズで構文こうぶん構築こうちくされ、たんなるトークンのれつだったプログラムにその言語げんご文法ぶんぽう定義ていぎした形式けいしき文法ぶんぽう規則きそく適用てきようすることで構造こうぞう生成せいせいする[24][25]構文こうぶんは、こののち工程こうてい解析かいせきされ、強化きょうかされ、変換へんかんされる。
  5. 意味いみ解析かいせき英語えいごばん - 構文こうぶん要素ようそ意味いみ追加ついかし、シンボルテーブルを作成さくせいする。かたチェック(データがたなどを間違まちがっていないかのチェック)や、変数へんすう関数かんすう定義ていぎ参照さんしょう箇所かしょむすびつける処理しょり既定きてい代入だいにゅう自動じどう変数へんすう初期しょき)、意味いみてき不正ふせいなプログラムを検出けんしゅつして通知つうちするなどの処理しょりおこなわれる。[22]意味いみ解析かいせきには完全かんぜん構文こうぶん必要ひつようであり、理論りろんじょう構文こうぶん解析かいせきコード生成せいせいあいだおこなわなければならない。もちろんコンパイラの実装じっそうによってはこれらをいちおこなうこともある。

バックエンド

[編集へんしゅう]

「バックエンド」という用語ようごは「コード生成せいせい」という用語ようご混同こんどうされることがおおい。アセンブリ言語げんごコードを生成せいせいするという意味いみ機能きのうてきにも類似るいじしているためである。書籍しょせきによっては、バックエンドの汎用はんよう解析かいせきフェーズと最適さいてきフェーズを「ミドルエンド」としょうしてマシン依存いぞんのコード生成せいせい区別くべつすることがある。

バックエンドにふくまれるおもなフェーズは以下いかとおりである。

  1. 解析かいせき - 入力にゅうりょくから生成せいせいされたなかあいだ表現ひょうげん使つかって各種かくしゅ情報じょうほう収集しゅうしゅうする。おも解析かいせきとしてUD連鎖れんさ構築こうちくするデータフロー解析かいせき依存いぞん関係かんけい解析かいせき、エイリアス解析かいせき、ポインタ解析かいせき、エスケープ解析かいせきなどがある。正確せいかく解析かいせきによってコンパイラ最適さいてき可能かのうとなる。また、コールグラフ制御せいぎょフローグラフがここでつくられることがおおい。
  2. 最適さいてき - 中間なかま表現ひょうげん機能きのうてきには等価とうかだがより「ベター」な形式けいしき変換へんかんする。おも最適さいてき手法しゅほうとしてインライン展開てんかいデッドコード削除さくじょ定数ていすう伝播でんぱ、ループ変換へんかんレジスタ自動じどう並列へいれつなどがある[26]
  3. コード生成せいせい - 実際じっさい出力しゅつりょくする機械きかいやバイトコードを生成せいせいする。ここでリソースや記憶きおく装置そうちてが決定けっていされる。たとえば、どの変数へんすうをレジスタに格納かくのうし、どの変数へんすうをメモリに格納かくのうするか、どの命令めいれいをどういう順番じゅんばん実行じっこうするかをアドレッシングモードなどをセシィ-ウルマンほうなどをもちいて決定けっていする。

コンパイラ解析かいせきとは、コンパイラ最適さいてきまえおこなわれる処理しょりで、両者りょうしゃ密接みっせつ関係かんけいがある。たとえば依存いぞん関係かんけい解析かいせきはループ変換へんかん実施じっし重要じゅうよう意味いみつ。

さらに、コンパイラ解析かいせき最適さいてき範囲はんい様々さまざまであり、基本きほんてきなブロック単位たんい場合ばあいからプロシージャや関数かんすうレベル、さらにはプロシージャの垣根かきねえてプログラム全体ぜんたい対象たいしょうとすることもある。広範囲こうはんい考慮こうりょするコンパイラほど最適さいてきもちいることができる「ヒント」がえ、結果けっかとしてよりいコードを生成せいせいする可能かのうせいがある。しかし、広範囲こうはんい考慮こうりょする解析かいせき最適さいてきはコンパイル時間じかんやメモリ消費しょうひのコストがおおきい。これはとくにプロシージャあいだ解析かいせき最適さいてきおこな場合ばあい顕著けんちょである。

最近さいきん商用しょうようコンパイラはプロシージャあいだ解析かいせき/最適さいてきそなえているのが普通ふつうである(IBM、SGIインテルマイクロソフトサン・マイクロシステムズなど)。オープンソースのGCCはプロシージャあいだ最適さいてきたないてん弱点じゃくてんだったが、これも改善かいぜんされつつある。のオープンソースのコンパイラで完全かんぜん最適さいてきおこなうものとしてOpen64がある。

コンパイラ解析かいせき最適さいてきには時間じかん空間くうかん必要ひつようとなるため、コンパイラによってはデフォルトでこれらのフェーズを省略しょうりゃくするものもある。この場合ばあい、ユーザーはオプションを指定していして明示めいじてき最適さいてき指示しじしなければならない。

簡単かんたんれい

[編集へんしゅう]

以下いかのプログラムは中置ちゅうち記法きほう入力にゅうりょくされた四則しそく演算えんざんぎゃくポーランド記法きほうて、独自どくじなかあいだ表現ひょうげんにコンパイルするC言語げんごかれた非常ひじょう単純たんじゅんなワンパス・コンパイラである。このコンパイラは中置ちゅうち記法きほうぎゃくポーランド記法きほうにコンパイルするとともに、あるしゅアセンブリ言語げんごにもコンパイルする。再帰さいき下降かこうがた戦略せんりゃく採用さいようしている。このため、かく関数かんすう文法ぶんぽうにおけるかく非終端ひしゅうたん記号きごう対応たいおうしている。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MODE_POSTFIX     0
#define MODE_ASSEMBLY    1

char    lookahead;
int     pos;
int     compile_mode;
char    expression[20+1];

void error()
{
        printf("Syntax error!\n");
}

void match( char t )
{
        if( lookahead == t )
        {
                pos++;
                lookahead = expression[pos];
        }
        else
                error();
}

void digit()
{
        switch( lookahead )
        {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                        if( compile_mode == MODE_POSTFIX )
                                printf("%c", lookahead);
                        else
                                printf("\tPUSH %c\n", lookahead);
                        
                        match( lookahead );
                        break;
                default:
                        error();
                        break;
        }
}

void term()
{
        digit();
        while(1)
        {
                switch( lookahead )
                {
                        case '*':
                                match('*');
                                digit();
                                
                                printf( "%s", compile_mode == MODE_POSTFIX ? "*"
                                        : "\tPOP B\n\tPOP A\n\tMUL A, B\n\tPUSH A\n");
                                
                                break;
                        case '/':
                                match('/');
                                digit();
                                
                                printf( "%s", compile_mode == MODE_POSTFIX ? "/"
                                        : "\tPOP B\n\tPOP A\n\tDIV A, B\n\tPUSH A\n");
                                break;
                        default:
                                return;
                }
        }
}

void expr()
{
        term();
        while(1)
        {
                switch( lookahead )
                {
                        case '+':
                                match('+');
                                term();

                                printf( "%s", compile_mode == MODE_POSTFIX ? "+"
                                        : "\tPOP B\n\tPOP A\n\tADD A, B\n\tPUSH A\n");
                                break;
                        case '-':
                                match('-');
                                term();

                                printf( "%s", compile_mode == MODE_POSTFIX ? "-"
                                        : "\tPOP B\n\tPOP A\n\tSUB A, B\n\tPUSH A\n");
                                break;
                        default:
                                return;
                }
        }
}

int main ( int argc, char** argv )
{
        printf("Please enter an infix-notated expression with single digits:\n\n\t");
        scanf("%20s", expression);
        
        printf("\nCompiling to postfix-notated expression:\n\n\t");
        compile_mode = MODE_POSTFIX;
        pos = 0;
        lookahead = *expression;
        expr();
        
        printf("\n\nCompiling to assembly-notated machine code:\n\n");
        compile_mode = MODE_ASSEMBLY;
        pos = 0;
        lookahead = *expression;
        expr();
        
        return 0;
}

この単純たんじゅんなコンパイラの実行じっこうれい以下いかしめす。

Please enter an infix-notated expression with single digits:

        3-4*2+2

Compiling to postfix-notated expression:

        342*-2+

Compiling to assembly-notated machine code:

        PUSH 3
        PUSH 4
        PUSH 2
        POP B
        POP A
        MUL A, B
        PUSH A
        POP B
        POP A
        SUB A, B
        PUSH A
        PUSH 2
        POP B
        POP A
        ADD A, B
        PUSH A

脚注きゃくちゅう

[編集へんしゅう]

注釈ちゅうしゃく

[編集へんしゅう]
  1. ^ このほん表紙ひょうしにはあかドラゴンえがかれているのでドラゴンブックとばれている。
  2. ^ オブジェクトコードの記述きじゅつ使つかわれる言語げんごは、ようは、その言語げんごから最終さいしゅうてき機械きかい翻訳ほんやくする道筋みちすじが1すじ(1ほん)でもあるものであればよい。理論りろんじょう機械きかいにたどりくまでに途中とちゅうなに種類しゅるいもの言語げんごにコンパイル(翻訳ほんやく)する必要ひつようがあっても、ともかく最終さいしゅうてき機械きかい翻訳ほんやくするまでの道筋みちすじが1ほんあればい。オブジェクトコードの記述きじゅつ使つかわれる言語げんごかならずしもアセンブリ言語げんご機械きかいでなくてもよい。たとえばC++かれたオブジェクトコードを出力しゅつりょくするコンパイラやC言語げんごかれたオブジェクトコードを出力しゅつりょくするコンパイラもある。それぞれ、C++を機械きかいに、あるいはC言語げんご機械きかい変換へんかんするコンパイラを別途べっと用意よういすれば最終さいしゅうてきにCPUが実行じっこうできる機械きかい変換へんかんできる。よくあるのはアセンブリ言語げんごかれたオブジェクトコードを出力しゅつりょくするコンパイラである。アセンブリ言語げんごかれたプログラムも通常つうじょうそのままでは実行じっこうできないが、アセンブラ使つかってやはりCPUが実行じっこうできる機械きかい変換へんかんできる。
  3. ^ 最終さいしゅうてき出力しゅつりょくされるターゲットプログラムは、機械きかいやアセンブリ言語げんご記述きじゅつしたものがおおいが、それらにかぎるわけではなく、中間なかまコードや高級こうきゅう言語げんごのプログラムを出力しゅつりょくするコンパイラもある。

出典しゅってん

[編集へんしゅう]
  1. ^ a b (※)コンパイラの定義ていぎぶんにわざわざ「一括いっかつして」という言葉ことばふくめることがおおいのは、インタプリタ対比たいひするためである。「一括いっかつして」をれないとインタプリタまでふくんでしまい、定義ていぎぶんとしては落第らくだいてんものとなる。Merriam Websterの英文えいぶん定義ていぎぶんでも、やはり「translates an entire set of instructions[1]と、「命令めいれいぐん(の一部分いちぶぶんではなく)全部ぜんぶを」と明記めいきしている。
  2. ^ コンパイラとは - IT用語ようご辞典じてん”. IT用語ようご辞典じてん e-Words. 2023ねん2がつ22にち閲覧えつらん
  3. ^ a b c d Alfred V. Aho, Compilers, Principles, Techniques, and Tools. Reprinted with corrections March, 1988.(Copyright 1986,Bell Telephone Laboratories, Incorporated), pp.1-2. (Chapter 1.1 "COMPILERS"のふし説明せつめい
  4. ^ ASCII.jpデジタル用語ようご辞典じてん,デジタル大辞泉だいじせん,IT用語ようごがわかる辞典じてん. “オブジェクトコード(おぶじぇくとこーど)とは”. コトバンク. 2020ねん4がつ26にち閲覧えつらん
  5. ^ たとえばCPUGPUなど。
  6. ^ 分割ぶんかつコンパイル”. www3.nit.ac.jp. 2020ねん4がつ27にち閲覧えつらん
  7. ^ プログレッシブ英和えいわちゅう辞典じてん「compile」
  8. ^ Oxford Dictionary; Produce (a list or book) by assembling information collected from other sourcesなんらかの情報じょうほうげんからあつめた情報じょうほうもとにして、一覧いちらんほんつくりだす」
  9. ^ プログレッシブ英和えいわちゅう辞典じてん「compiler」
  10. ^ 大辞泉だいじせん「コンパイラ」
  11. ^ Oxford Dictionary; compiler: A person who produces a list or book by assembling information or written material collected from other sources.
  12. ^ bit 編集へんしゅう『bit 単語たんごちょう共立きょうりつ出版しゅっぱん、1990ねん8がつ15にち、82ぺーじISBN 4-320-02526-1 
  13. ^ CSAIL Publications”. publications.csail.mit.edu. 2020ねん6がつ16にち閲覧えつらん
  14. ^ https://www.246.dk/” (デンマーク). 2020ねん6がつ16にち閲覧えつらん
  15. ^ 2020ねん4がつ13にち 8ふん. “コンパイラとインタプリタのちがいは?言語げんごちがいをかりやすく解説かいせつ”. じゃぱざむ. 2020ねん4がつ27にち閲覧えつらん
  16. ^ インタプリタとコンパイラ”. nyumon-info.com. 2020ねん4がつ27にち閲覧えつらん
  17. ^ a b Alfred V. Aho, Compilers, Principles, Techniques, and Tools. 1988., pp.10-15. 「1.3(1しょう3せつ) THE PHASES OF A COMPILER」
  18. ^ コンパイラの構造こうぞう解説かいせつ | Shinta's Site”. www.gadgety.net. 2020ねん4がつ27にち閲覧えつらん
  19. ^ コマンド:lex: UNIX/Linuxの部屋へや”. x68000.q-e-d.net. 2020ねん4がつ27にち閲覧えつらん
  20. ^ パーサジェネレータとは - Weblio辞書じしょ”. www.weblio.jp. 2020ねん4がつ27にち閲覧えつらん
  21. ^ コンパイラのくち、「字句じく解析かいせき」のための文字もじれつ操作そうさ (1/3)”. @IT. 2020ねん4がつ27にち閲覧えつらん
  22. ^ a b コンパイラの構成こうせい最適さいてき. Nakata, Ikuo, 1935-, 中田なかた, 育男いくお, 1935-. Tōkyō: Asakurashoten. (2009). ISBN 978-4-254-12177-3. OCLC 675837876. https://www.worldcat.org/oclc/675837876 
  23. ^ プリプロセッサとは - IT用語ようご辞典じてん”. IT用語ようご辞典じてん e-Words. 2020ねん4がつ27にち閲覧えつらん
  24. ^ 抽象ちゅうしょう構文こうぶん”. home.a00.itscom.net. 2020ねん4がつ27にち閲覧えつらん
  25. ^ VU - exp. - compiler-general”. www.is.s.u-tokyo.ac.jp. 2020ねん4がつ27にち閲覧えつらん
  26. ^ MaryCore. “っておいてそんはない「コンパイラ最適さいてき」の数々かずかず”. MaryCore 言語げんご知能ちのう総合そうごう研究所けんきゅうじょ. 2020ねん4がつ27にち閲覧えつらん

参考さんこう文献ぶんけん

[編集へんしゅう]
  • Compiler textbook references コンパイラ構成こうせいろん教科書きょうかしょ英語えいご)のリスト
  • Compilers: Principles, Techniques and Tools by Alfred V. Aho, Ravi Sethi, and Jeffrey D. Ullman (ISBN 0-201-10088-6)
    • 原田はらだ賢一けんいち やく、『コンパイラ—原理げんり技法ぎほう・ツール<1>』サイエンスしゃ、1990ねんISBN 4781905854
    • 原田はらだ賢一けんいち やく、『コンパイラ—原理げんり技法ぎほう・ツール<2>』サイエンスしゃ、1990ねんISBN 4781905862
  • Advanced Compiler Design and Implementation by Steven Muchnick (ISBN 1-55860-320-4).
  • Engineering a Compiler by Keith D. Cooper and Linda Torczon . Morgan Kaufmann 2004, ISBN 1-55860-699-8.
  • Understanding and Writing Compilers: A Do It Yourself Guide (ISBN 0-333-21732-2) by Richard Bornat - 構文こうぶんからの機械きかい再帰さいきてき生成せいせい説明せつめいしている貴重きちょう書籍しょせきふるいメインフレームやミニコンピュータの経験けいけんもとづいており、最近さいきん書籍しょせき見落みおとしがちな部分ぶぶんもカバーしている。著者ちょしゃのサイトにあるPDFばん
  • An Overview of the Production Quality Compiler-Compiler Project by Leverett, Cattel, Hobbs, Newcomer, Reiner, Schatz and Wulf. Computer 13(8):38-49 (August 1980)
  • Compiler Construction by Niklaus Wirth (ISBN 0-201-40353-6) Addison-Wesley 1996, 176 pages, PDFばん再帰さいき下降かこう構文こうぶん解析かいせき解説かいせつOberon-0という小型こがた言語げんごのコンパイラを題材だいざいにしている。
  • "Programming Language Pragmatics" by Michael Scott (ISBN 0-12-633951-1) Morgan Kaufmann 2005, 2nd edition, 912 pages. 著者ちょしゃのサイト
  • "A History of Language Processor Technology in IBM", by F.E. Allen, IBM Journal of Research and Development, v.25, no.5, September 1981.
  • ニクラウス・ヴィルト(ちょ)、滝沢たきざわとおるわけ)、牧野まきの裕子ゆうこわけ):「ヴィルトのコンパイラ構成こうせいほう」、星雲せいうんしゃISBN 4-7952-9706-1(1997ねん11月28にち)。
  • 中田なかた育男いくお:「コンパイラの構成こうせい最適さいてき」、朝倉書店あさくらしょてんISBN 978-4-254-12177-3(だい2はん)(1999ねん9がつ15にち初版しょはん、2009ねん11月15にちだい2はん)。
  • A.V.エイホ、M.S.ラム、R.セシィ、J.D.ウルマン、原田はらだ賢一けんいちわけ):「コンパイラ[だい2はん]」、サイエンスしゃISBN 978-4-7819-1229-5(2009ねん5がつ25にちだい2はん、1990ねん10がつ10日とおか初版しょはん)。
  • 五月女さおとめ健治けんじ:「JavaCC:コンパイラコンパイラ for Java」、テクノプレス、ISBN 4-924998-64-8(2003ねん10がつ20日はつか)。
  • Andrew W. Appel、神林かんばやしやすし滝本たきもとそうひろしわけ):「最新さいしんコンパイラ構成こうせい技法ぎほう」、しょうおよげしゃISBN 978-4-7981-1468-2(2009ねん10がつ29にち)。
  • 中田なかた育男いくお渡邊わたなべ担、佐々ささ政宏まさひろ:「コンパイラの基盤きばん技術ぎじゅつ実践じっせん」、朝倉書店あさくらしょてんISBN 978-4-254-12173-5(2008ねん6がつ25にち)。
  • 柏木かしわぎもちふうやく:「きつねさんでもわかるLLVM コンパイラを自作じさくするためのガイドブック」、インプレスジャパン、ISBN 978-4-8443-3415-6(2013ねん6がつ21にち)。
  • 中田なかた育男いくお:「コンパイラ づくりながらまなぶ」、ム社むしゃISBN 978-4-274-22116-3(2017ねん10がつ25にち)。

関連かんれん項目こうもく

[編集へんしゅう]

外部がいぶリンク

[編集へんしゅう]