[インデックス 16608] ファイルの概要
このコミットは、Go言語のGCCフロントエンドであるgccgoに関するドキュメント(doc/gccgo_contribute.html
とdoc/gccgo_install.html
)の更新を目的としています。主な変更点は、gccgoのインストール手順、Goのバージョン互換性、C言語との連携に関する技術的詳細、および開発者向けの追加リソースへのリンクの更新です。
コミット
commit ffde4970d06fd0b03a3e06893ae916894f2cce8f
Author: Ian Lance Taylor <iant@golang.org>
Date: Thu Jun 20 14:49:15 2013 -0700
doc: update gccgo docs
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/10401046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/ffde4970d06fd0b03a3e06893ae916894f2cce8f
元コミット内容
このコミットは、Goプロジェクトのドキュメントを更新するものです。具体的には、doc/gccgo_contribute.html
とdoc/gccgo_install.html
の2つのファイルが変更されています。
doc/gccgo_contribute.html
: gccgoフロントエンドでの開発プロセスに関する詳細な情報を提供するHACKING
ファイルへのリンクが追加されました。doc/gccgo_install.html
:- GCCのバージョンとGoのバージョン(Go 1およびGo 1.1)の互換性に関する記述が更新されました。
- GCCの前提条件ライブラリをダウンロードするためのスクリプト
contrib/download_prerequisites
に関する情報が追加されました。 - UbuntuとGCCのシステムライブラリパスに関する不一致の問題に対する注意書きが更新され、古いGCCバージョンに限定されることが明記されました。
- gccgoコンパイラがインポートされたパッケージのファイル名をオブジェクトファイルに記録しないという記述の日付が2012-03-20から2013-06-20に更新されました。
- Go関数がC言語からアクセスされる際の型表現に関する説明が大幅に修正されました。特に、複数の戻り値を持つGo関数がC関数からどのように見えるか、およびその表現が「変更される可能性がある」という注意書きが追加されました。
- C関数がブロックする可能性がある場合に、Goプログラム全体をブロックする可能性があるという重要な警告が追加され、cgoまたはSWIGの使用が推奨されました。
変更の背景
このコミットが行われた2013年6月は、Go言語がGo 1.0(2012年3月リリース)を経て、Go 1.1(2013年5月リリース)が登場した直後の時期にあたります。Go言語は急速に進化しており、それに伴い、異なるコンパイラ実装であるgccgoもGo言語の仕様変更や改善に追従する必要がありました。
gccgoは、Go言語のコードをGCCのバックエンドを通じてコンパイルするプロジェクトであり、標準のGoコンパイラ(gc
)とは異なるアプローチを取っています。そのため、Go言語の新しいバージョンがリリースされるたびに、gccgoもその変更を反映し、ドキュメントも最新の状態に保つ必要がありました。
このコミットの背景には、以下の点が挙げられます。
- Go言語の進化への追従: Go 1.1のリリースに伴い、gccgoがGo 1.1の仕様にどの程度対応しているか、また今後の対応予定についてユーザーに明確に伝える必要がありました。
- 開発者体験の向上: gccgoの開発に貢献したい、あるいはより深く理解したい開発者向けに、
gofrontend
リポジトリ内のHACKING
ファイルという詳細な開発ガイドへのリンクを提供することで、情報へのアクセスを容易にしました。 - ビルドプロセスの改善: GCCのビルドは複雑であり、前提条件のライブラリの準備は特に手間がかかる作業でした。
contrib/download_prerequisites
スクリプトの存在を明記することで、ユーザーのビルド体験を向上させようとしました。 - C言語との相互運用性の明確化: GoとCの相互運用は、特にパフォーマンスが要求される場面や既存のCライブラリを利用する際に重要です。gccgoにおけるGo関数のC言語からの呼び出し規約(ABI)は、
gc
コンパイラとは異なる可能性があり、その詳細を明確にすることで、開発者がより安全かつ効率的にコードを書けるようにしました。特に、複数の戻り値を持つGo関数のC言語での表現や、ブロッキングC関数の呼び出しに関する注意は、潜在的なバグやパフォーマンス問題を防ぐ上で非常に重要です。 - ドキュメントの鮮度維持: ドキュメント内の日付情報や、特定の技術的制約に関する記述を最新の状態に保つことで、ユーザーが誤解するのを防ぎ、正確な情報を提供することを目的としています。
前提知識の解説
Go言語のコンパイラとgccgo
Go言語には主に2つの公式コンパイラ実装が存在します。
-
gc
(Go Compiler):- Goプロジェクトが公式に開発・メンテナンスしている標準のコンパイラです。
- Go言語で書かれており、Goのソースコードを直接機械語にコンパイルします。
- Goのリリースサイクルに合わせて迅速に更新され、最新の言語機能や最適化が最も早く取り込まれます。
- クロスコンパイルに優れており、単一のバイナリを生成します。
-
gccgo
:- GCC (GNU Compiler Collection) のフロントエンドとして実装されたGoコンパイラです。
- GoのソースコードをGCCの中間表現(GIMPLEなど)に変換し、その後GCCの既存の最適化パスとバックエンドを利用して機械語を生成します。
- GCCの広範な最適化技術や、様々なアーキテクチャへの対応といった恩恵を受けることができます。
- C/C++など他のGCCがサポートする言語との連携が比較的容易です。
gc
コンパイラと比較して、Go言語の最新機能への対応が遅れる傾向があります。これは、GCCのリリースサイクルがGoのそれよりも長いためです。
このコミットは、主にgccgo
に関するドキュメントの更新であり、gccgo
のユーザーや開発者にとって重要な情報を提供しています。
Go 1とGo 1.1
- Go 1 (2012年3月リリース): Go言語の最初の安定版リリースであり、言語仕様の互換性が保証されました。これにより、Go言語は実用的なプログラミング言語としての地位を確立しました。
- Go 1.1 (2013年5月リリース): Go 1のリリース後、初めてのマイナーバージョンアップです。パフォーマンスの改善、標準ライブラリの拡張、一部の言語機能の微調整などが行われました。このコミットが行われたのはGo 1.1リリース直後であり、gccgoがGo 1.1にどの程度対応しているかが重要な関心事でした。
C言語との相互運用性 (cgo)
Go言語は、C言語のコードをGoプログラムから呼び出すためのcgo
というメカニズムを提供しています。cgo
は、GoとCの間のデータ型変換や関数呼び出し規約(ABI)の調整を自動的に行い、異なる言語間の連携を容易にします。
gccgo
の場合も、C言語との相互運用は可能ですが、gc
コンパイラとは異なるABIを持つ可能性があります。特に、Goの関数がC言語からどのように見えるか、Goのデータ型がC言語でどのように表現されるかといった点は、コンパイラの実装に依存します。このコミットでは、Go関数のC言語からの呼び出し規約に関する詳細が更新されており、これはcgo
を使用する開発者にとって非常に重要な情報です。
ブロッキングC関数
C言語の関数の中には、I/O操作(ファイル読み書き、ネットワーク通信など)や同期プリミティブ(ロック、セマフォなど)のように、処理が完了するまで実行を一時停止(ブロック)するものがあります。Go言語は軽量なゴルーチンと非同期I/Oを特徴としていますが、GoのゴルーチンからブロッキングC関数を直接呼び出すと、そのゴルーチンだけでなく、場合によってはGoランタイム全体がブロックされ、他のゴルーチンの実行に影響を与える可能性があります。このため、GoからC関数を呼び出す際には、ブロッキングの可能性を考慮し、適切なメカニズム(例えば、cgo
が提供するスレッド管理など)を通じて呼び出すことが推奨されます。
技術的詳細
gccgoのバージョン互換性に関する更新
コミットでは、doc/gccgo_install.html
において、GCCのバージョンとGoのバージョン(Go 1およびGo 1.1)の互換性に関する記述が更新されています。
- GCC 4.7.1以降の4.7リリース: Go 1のコンパイラとライブラリを完全に含んでいると明記されました。以前はGCC 4.7.0がGo 1に非常に近いが完全ではない、GCC 4.7.1で完全になるだろう、という記述でした。
- GCC 4.8.0および4.8.1: Go 1.1に「近いが同一ではない」と記述されました。これは、GCCのリリースタイミングとGoのリリースタイミングのずれによるものです。
- GCC 4.8.2: Go 1.1.1の実装を完全に含むことが期待される、と記述されました。
この情報は、ユーザーが特定のGoバージョンに対応するgccgoをビルドまたは使用する際に、どのGCCバージョンを選択すべきかの指針となります。
GCCビルドの前提条件スクリプト
GCCをソースからビルドする際には、GMP (GNU Multiple Precision Arithmetic Library)、MPFR (Multiple-Precision Floating-point Reliable), MPC (Multiple-Precision Complex) といった複数のライブラリが前提条件として必要になります。これらを個別にダウンロードして設定するのは手間がかかります。
コミットでは、contrib/download_prerequisites
というスクリプトがGCCのソースツリー内に存在し、これらの前提条件ライブラリを便利にダウンロードできることが明記されました。これは、gccgoを含むGCCのビルドプロセスを簡素化し、ユーザーの負担を軽減するための重要な情報です。
UbuntuとGCCのライブラリパス問題
古いバージョンのUbuntuとGCC(特にGCC 4.8より前)の間で、システムライブラリやヘッダーファイルの検索パスに関する不一致が存在することがありました。これはgccgo固有の問題ではなく、GCC全体のビルドに関する問題です。
コミットでは、この問題が「GCC 4.8より前のバージョン」に限定されることが明確にされました。そして、古いバージョンのGCCをビルドする際に、特定の環境変数を設定することでこの問題を回避できる可能性があることが示されています。これは、過去の互換性問題に関する重要な注意点です。
Go関数のC言語からの型表現の変更
このコミットの最も技術的に重要な変更点の一つは、Go関数がC言語からアクセスされる際の型表現に関する説明の更新です。
変更前:
Go関数(レシーバなし)の型は、対応するC関数の型と等価であるとされていました。複数の戻り値を持つGo関数は、C関数では構造体を返す、と説明されていました。
例: func GoFunction(int) (int, float64)
は struct { int i; float64 f; } CFunction(int)
と等価。
また、Go関数へのポインタは、対応するC関数へのポインタと等価であるとされていましたが、これは「変更される可能性がある」と注意書きがありました。
変更後:
Go関数の型は、「構造体へのポインタ」であると説明が変更されました。この構造体の最初のフィールドは関数のコードへのポインタ(C関数へのポインタと等価)であり、追加の末尾パラメータとして「クロージャ」が渡されると説明されました。このクロージャの引数には、Go関数構造体へのポインタを渡す、とされています。
複数の戻り値を持つGo関数は、C関数では構造体を返すという点は変わりませんが、C関数のシグネチャにvoid*
型の追加パラメータが加わっています。
例: func GoFunction(int) (int, float64)
は struct { int i; float64 f; } CFunction(int, void*)
と「おおよそ等価」と説明されました。
以前の「Go関数へのポインタはC関数へのポインタと等価」という記述は削除されました。
この変更は、gccgoがGo関数の内部表現、特にクロージャやメソッドの扱いをどのようにC言語のABIにマッピングするかに関する、より正確な(そして当時の実装に即した)説明を提供しています。subject to change
という注意書きが残っていることから、このABIがまだ安定しておらず、将来的に変更される可能性があったことが伺えます。これは、GoとCの相互運用を行う開発者にとって、ABIの安定性が重要であることを示唆しています。
ブロッキングC関数呼び出しに関する警告
GoプログラムからC関数を呼び出す際に、そのC関数がブロックする可能性がある場合(例: read
システムコールなど)、Goプログラム全体がブロックされる可能性があるという重要な警告が追加されました。そして、このような状況を避けるために、gc
コンパイラと同様に、cgo
またはSWIGを通じてC関数を呼び出すことが推奨されています。
これは、Goの並行性モデル(ゴルーチンとスケジューラ)とC言語の同期的なI/Oモデルとの間の重要な相互作用に関する注意喚起です。Goのランタイムは、ブロッキングシステムコールを検出すると、そのゴルーチンをブロックし、他のゴルーチンを同じOSスレッド上で実行し続けることができます。しかし、C言語のライブラリ関数がGoランタイムに認識されない形でブロッキングを行う場合、Goのスケジューラが適切に動作せず、プログラム全体のパフォーマンスや応答性に悪影響を与える可能性があります。cgo
は、このようなブロッキングC関数呼び出しを専用のOSスレッドにディスパッチするなどのメカニズムを提供することで、Goランタイムの健全性を保ちます。
コアとなるコードの変更箇所
このコミットはドキュメントの変更のみであり、Go言語のソースコードやgccgoコンパイラ自体のコード変更は含まれていません。変更されたファイルは以下の2つです。
doc/gccgo_contribute.html
doc/gccgo_install.html
doc/gccgo_contribute.html
の変更
--- a/doc/gccgo_contribute.html
+++ b/doc/gccgo_contribute.html
@@ -10,6 +10,10 @@ For information on contributing to parts of Go other than gccgo,
see <a href="/doc/contribute.html">Contributing to the Go project</a>. For
information on building gccgo for yourself,
see <a href="/doc/gccgo_install.html">Setting up and using gccgo</a>.
+For more of the gritty details on the process of doing development
+with the gccgo frontend,
+see <a href="https://code.google.com/p/gofrontend/source/browse/HACKING">the
+file HACKING</a> in the gofrontend repository.
</p>
<h2>Legal Prerequisites</h2>
doc/gccgo_install.html
の変更
--- a/doc/gccgo_install.html
+++ b/doc/gccgo_install.html
@@ -32,10 +32,14 @@ will include Go support.
</p>
<p>
-The GCC 4.7.0 release includes Go support that is very close to
-<a href="/doc/go1.html">Go 1</a>. Due to release timing it will not
-include the last few changes to the Go 1 libraries. The GCC 4.7.1
-release should include a complete Go 1 compiler and libraries.
+The GCC 4.7.1 release and all later 4.7 releases include a complete
+<a href="/doc/go1.html">Go 1</a> compiler and libraries.
+</p>
+
+<p>
+Due to timing, the GCC 4.8.0 and 4.8.1 releases are close to but not
+identical to Go 1.1. The GCC 4.8.2 release is expected to include a
+complete Go 1.1.1 implementation.
</p>
<h2 id=\"Source_code\">Source code\">Source code</h2>
@@ -125,6 +129,8 @@ described on
the <a href=\"http://gcc.gnu.org/install/prerequisites.html\">gcc web
site</a>. It is important to install all the prerequisites before
running the gcc <code>configure</code> script.
+The prerequisite libraries can be conveniently downloaded using the
+script <code>contrib/download_prerequisites</code> in the GCC sources.
<h3 id=\"Build_commands\">Build commands</h3>
@@ -147,11 +153,11 @@ make install
<h3 id=\"Ubuntu\">A note on Ubuntu</h3>
<p>
-Current versions of Ubuntu and current versions of gcc disagree on
+Current versions of Ubuntu and versions of GCC before 4.8 disagree on
where system libraries and header files are found. This is not a
-gccgo issue, and we hope this will be resolved soon. Until it is,\n-setting these environment variables while configuring and building
-gccgo may fix the problem.
+gccgo issue. When building older versions of GCC, setting these
+environment variables while configuring and building gccgo may fix the
+problem.
</p>
<pre>
@@ -309,7 +315,7 @@ gccgo. Both options take directories to search. The
</p>
<p>
-The gccgo compiler does not currently (2012-03-20) record
+The gccgo compiler does not currently (2013-06-20) record
the file name of imported packages in the object file. You must
arrange for the imported data to be linked into the program.
</p>
@@ -385,23 +391,23 @@ struct __go_slice {\n </pre>\n \n <p>\n-The type of a Go function with no receiver is equivalent to a C function\n-whose parameter types are equivalent. When a Go function returns more\n-than one value, the C function returns a struct. For example, these\n-functions have equivalent types:\n+The type of a Go function is a pointer to a struct (this is\n+<b style=\"color: red;\">subject to change</b>). The first field in the\n+struct points to the code of the function, which will be equivalent to\n+a pointer to a C function whose parameter types are equivalent, with\n+an additional trailing parameter. The trailing parameter is the\n+closure, and the argument to pass is a pointer to the Go function\n+struct.\n+\n+When a Go function returns more than one value, the C function returns\n+a struct. For example, these functions are roughly equivalent:\n </p>\n \n <pre>\n func GoFunction(int) (int, float64)\n-struct { int i; float64 f; } CFunction(int)\n+struct { int i; float64 f; } CFunction(int, void*)\n </pre>\n \n-<p>\n-A pointer to a Go function is equivalent to a pointer to a C function\n-when the functions have equivalent types (this is\n-<b style=\"color: red;\">subject to change</b>).\n-</p>\n-\n <p>\n Go <code>interface</code>, <code>channel</code>, and <code>map</code>\n types have no corresponding C type (<code>interface</code> is a\n@@ -457,6 +463,14 @@ i := c_open(&name[0], syscall.O_RDONLY, 0);\n <code>os.Open</code> function instead).\n </p>\n \n+<p>\n+Note that if the C function can block, such as in a call\n+to <code>read</code>, calling the C function may block the Go program.\n+Unless you have a clear understanding of what you are doing, all calls\n+between C and Go should be implemented through cgo or SWIG, as for\n+the <code>gc</code> compiler.\n+</p>\n+\n <p>\n The name of Go functions accessed from C is subject to change. At present\n the name of a Go function that does not have a receiver is\n```
## コアとなるコードの解説
このコミットはドキュメントの更新であるため、Go言語のランタイムやコンパイラの「コアとなるコード」そのものに変更はありません。しかし、変更されたドキュメントの内容は、gccgoの内部動作、特にGoとCの相互運用性に関する重要な側面を説明しています。
特に注目すべきは、Go関数のC言語からの型表現に関する説明の変更です。これは、gccgoがGoの関数(特にクロージャや複数の戻り値を持つ関数)をどのようにコンパイルし、C言語の呼び出し規約にマッピングしているかを示唆しています。
* **Go関数の型が「構造体へのポインタ」として表現される**: これは、Goの関数が単なるコードエントリポイントだけでなく、関連する環境(クロージャのキャプチャ変数など)を持つ可能性があることを示唆しています。この構造体には、関数のコードへのポインタと、クロージャのデータへのポインタが含まれると考えられます。C言語からGo関数を呼び出す際には、この構造体へのポインタを渡すことで、Goランタイムが正しく関数を実行し、クロージャのコンテキストにアクセスできるようになります。
* **複数の戻り値を持つGo関数のC言語での表現**: 以前は単に構造体を返すC関数とされていましたが、変更後は`void*`型の追加パラメータがC関数のシグネチャに加わっています。これは、Goランタイムが戻り値を格納するためのメモリ領域をC関数に渡すためのメカニズムである可能性があります。
* **`subject to change`の継続**: Go関数のC言語からの型表現が「変更される可能性がある」という注意書きが残っていることは、当時のgccgoのABIがまだ流動的であり、将来のバージョンで互換性のない変更が行われる可能性があったことを示しています。これは、gccgoを使用してGoとCの相互運用を行う開発者にとって、ABIに直接依存するコードを書くことのリスクを警告するものです。
これらのドキュメントの変更は、gccgoの内部実装の詳細を外部に公開し、開発者がより正確な知識を持ってgccgoを使用できるようにするためのものです。特に、C言語との連携は低レベルな部分であり、ABIの理解はパフォーマンスや正確性に直結するため、これらの情報は非常に価値があります。
## 関連リンク
* Go言語公式サイト: [https://golang.org/](https://golang.org/)
* Go 1 Release Notes: [https://golang.org/doc/go1](https://golang.org/doc/go1)
* Go 1.1 Release Notes: [https://golang.org/doc/go1.1](https://golang.org/doc/go1.1)
* GCC公式サイト: [https://gcc.gnu.org/](https://gcc.gnu.org/)
* gofrontendリポジトリ (当時のGoogle Code): [https://code.google.com/p/gofrontend/](https://code.google.com/p/gofrontend/) (現在はGitHubに移行している可能性が高い)
## 参考にした情報源リンク
* Go言語の公式ドキュメント(コミットで参照されているもの)
* GCCの公式ドキュメント(ビルドに関する情報)
* Go言語のリリースノート(Go 1, Go 1.1のリリース時期と内容確認のため)
* `gccgo`に関する一般的な情報源(`gc`との比較など)
* `cgo`に関する一般的な情報源(GoとCの相互運用性、ブロッキングC関数の扱いなど)
* 当時のGoogle Codeの`gofrontend`リポジトリの`HACKING`ファイルの内容(直接参照はしていないが、その存在と目的を理解するため)
* UbuntuとGCCのライブラリパス問題に関する一般的な情報(当時のフォーラムやメーリングリストの議論など)