[インデックス 15416] ファイルの概要
このコミットは、Goコンパイラ(cmd/gc)におけるmkbuiltinツールの挙動を修正し、gc -Aフラグが常にすべてのシンボルをエクスポートセクションに書き出すように変更するものです。具体的には、src/cmd/gc/builtin.cとsrc/cmd/gc/export.cの2つのファイルが変更されています。
コミット
commit 1a01ffd386add6c1e11642c44c4009bd8ffcdd3d
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Feb 26 03:14:59 2013 +0800
cmd/gc: fix mkbuiltin (gc -A always write all symbols to export section)
Regenerate cmd/gc/builtin.c.
Fixes #4908.
R=rsc
CC=golang-dev
https://golang.org/cl/7383053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1a01ffd386add6c1e11642c44c4009bd8ffcdd3d
元コミット内容
cmd/gc: fix mkbuiltin (gc -A always write all symbols to export section)
Regenerate cmd/gc/builtin.c.
Fixes #4908.
変更の背景
このコミットは、Goコンパイラ(cmd/gc)のmkbuiltinツールに関連するバグ、具体的にはGo Issue #4908を修正するために行われました。mkbuiltinは、Goの組み込み関数や型に関する情報をbuiltin.cというC言語のソースファイルとして生成するツールです。このツールは、GoコンパイラがGo言語の組み込み要素を認識し、適切に処理するために不可欠です。
問題は、gc -Aフラグが使用された際に、コンパイラがすべてのシンボルをエクスポートセクションに正しく書き出さないことにありました。エクスポートセクションは、コンパイルされたGoパッケージが他のパッケージから利用できるように、そのパッケージが提供するシンボル(関数、変数、型など)の情報を格納する領域です。gc -Aフラグは、通常、デバッグやコンパイラの内部動作の検証のために使用され、すべてのシンボルがエクスポートされることを期待されます。しかし、このバグにより、mkbuiltinが生成するbuiltin.cが、この期待に反する挙動を示していました。
この不整合は、コンパイラのビルドプロセスや、Go言語の組み込み機能の正確な動作に影響を与える可能性がありました。そのため、gc -Aフラグが意図通りにすべてのシンボルをエクスポートセクションに含めるように修正する必要がありました。
前提知識の解説
- Goコンパイラ (
cmd/gc): Go言語の公式コンパイラであり、Goソースコードを機械語に変換する役割を担います。gcはGoコンパイラのコマンド名です。 mkbuiltin: Goコンパイラのビルドプロセスで使用される内部ツールの一つです。Go言語の組み込み関数(例:len,cap,new,makeなど)や組み込み型(例:int,string,boolなど)に関する情報を、コンパイラが利用できるC言語のソースファイル(builtin.c)として生成します。これにより、コンパイラはこれらの組み込み要素を特別扱いし、効率的に処理することができます。gc -Aフラグ: Goコンパイラgcに渡されるオプションの一つです。このフラグは、コンパイラが生成するオブジェクトファイル(またはエクスポート情報)に、通常はエクスポートされない内部シンボルも含めて、すべてのシンボルをエクスポートセクションに含めるように指示します。これは主に、コンパイラのデバッグ、プロファイリング、または内部構造の解析のために使用されます。- シンボル (Symbol): プログラミング言語において、変数、関数、型、定数など、プログラム内で名前を持つエンティティを指します。コンパイラはこれらのシンボルを管理し、それらの定義と参照を解決します。
- エクスポートセクション (Export Section): コンパイルされたプログラムやライブラリにおいて、外部からアクセス可能なシンボル(関数、変数、型など)の情報を格納する領域です。Go言語では、パッケージの外部に公開される(大文字で始まる)シンボルがエクスポートされます。コンパイラは、このエクスポート情報を用いて、異なるパッケージ間でのリンクを可能にします。
- Go Issue #4908: GoプロジェクトのIssueトラッカーで報告された特定のバグを指します。このコミットの変更は、このIssueで記述された問題の解決を目的としています。
技術的詳細
このコミットの技術的詳細は、Goコンパイラの内部構造、特にシンボル管理とエクスポートメカニズムに深く関わっています。
Goコンパイラは、ソースコードを解析し、抽象構文木(AST)を構築した後、型チェックや最適化などの様々なフェーズを経て、最終的に機械語コードを生成します。この過程で、コンパイラはプログラム内のすべてのシンボルを追跡し、それらの属性(型、スコープ、アドレスなど)を管理します。
mkbuiltinツールは、Goの組み込み関数や型を、コンパイラがC言語のコードとして直接扱えるようにするためのものです。builtin.cファイルは、これらの組み込み要素の定義をC言語の構造体や関数として記述し、コンパイラが内部的に参照できるようにします。
問題となっていたのは、gc -Aフラグが指定された際に、autoexport関数(src/cmd/gc/export.cに定義されている)が期待通りにすべてのシンボルをエクスポートセクションに含めないことでした。autoexport関数は、コンパイラがシンボルを処理する際に、そのシンボルがエクスポートされるべきかどうかを判断するロジックを含んでいます。
元のコードでは、autoexport関数は以下の条件でシンボルをエクスポートしていました。
if(exportname(n->sym->name) || initname(n->sym->name))
これは、シンボル名がGoのエクスポート規則(大文字で始まる)に従っているか、またはinit関数のような特殊な名前である場合にのみエクスポートするという意味です。
しかし、gc -Aフラグが指定された場合、コンパイラはすべてのシンボルをエクスポートすべきです。このコミットでは、autoexport関数にdebug['A']という条件が追加されました。debug['A']は、gc -Aフラグが設定されているかどうかを示す内部フラグです。
変更後のコードは以下のようになります。
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
この変更により、gc -Aフラグが有効な場合(debug['A']が真の場合)は、exportnameやinitnameの条件に関わらず、常にexportsym(n)が呼び出され、現在のシンボルnがエクスポートセクションに書き込まれるようになります。これにより、gc -Aの意図通りの挙動が実現され、すべてのシンボルがエクスポートされるようになります。
また、src/cmd/gc/builtin.cの変更は、この修正に伴いmkbuiltinツールによって再生成された結果です。具体的には、runtimeimportとunsafeimportの文字列リテラル内で定義されている組み込み関数の引数名に、·と数字が追加されています(例: @\"\\\".typが@\"\\\".typ·2に)。これは、コンパイラの内部的なシンボル管理や名前解決のメカニズムが更新されたことを示唆しており、引数名の一意性を保証するための変更であると考えられます。このような変更は、コンパイラの内部的な表現がより堅牢になることを意味します。
コアとなるコードの変更箇所
src/cmd/gc/builtin.c
このファイルは、mkbuiltinツールによって生成されるGoの組み込み関数や型の定義を含むC言語のソースファイルです。このコミットでは、このファイル全体が再生成されています。
主な変更点は、runtimeimportとunsafeimportというC言語の文字列リテラル内で定義されているGoの組み込み関数のシグネチャです。具体的には、関数の引数名に·と数字が追加されています。
変更前(例):
"func @\"\\\".new(@\"\\\".typ *byte) (? *any)\\n"
"func @\"\\\".appendslice(@\"\\\".typ *byte, @\"\\\".x any, @\"\\\".y []any) (? any)\\n"
変更後(例):
"func @\"\\\".new (@\"\\\".typ·2 *byte) (? *any)\\n"
"func @\"\\\".appendslice (@\"\\\".typ·2 *byte, @\"\\\".x·3 any, @\"\\\".y·4 []any) (? any)\\n"
この変更は、mkbuiltinツールが生成するコードのフォーマットが更新された結果であり、コンパイラの内部的なシンボル管理の改善を反映しています。
src/cmd/gc/export.c
このファイルは、Goコンパイラがシンボルをエクスポートするロジックを定義しています。
変更前:
if(exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
変更後:
// -A is for cmd/gc/mkbuiltin script, so export everything
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
この変更により、debug['A']フラグ(gc -Aオプションが有効な場合に設定される)が真であれば、exportnameやinitnameの条件に関わらず、すべてのシンボルがエクスポートされるようになりました。
コアとなるコードの解説
src/cmd/gc/builtin.cの変更
builtin.cの変更は、直接的なバグ修正というよりも、バグ修正に伴うmkbuiltinの再実行によって生成された結果です。引数名に付与された·と数字は、コンパイラの内部的な名前解決メカニズムが、引数名の一意性をより厳密に管理するように変更されたことを示唆しています。これは、コンパイラが内部的にシンボルを識別し、処理する際の堅牢性を高めるための改善と考えられます。例えば、異なるスコープで同じ名前の引数が存在する場合でも、一意に識別できるようにするための措置かもしれません。
src/cmd/gc/export.cの変更
この変更がこのコミットの核心です。autoexport関数は、コンパイラがシンボルを処理する際に、そのシンボルが最終的にコンパイルされたバイナリのエクスポートテーブルに含まれるべきかどうかを決定します。
exportname(n->sym->name): シンボル名がGoのエクスポート規則(大文字で始まる)に従っているかどうかをチェックします。initname(n->sym->name): シンボル名がinit関数のような特殊な名前であるかどうかをチェックします。init関数はGoプログラムの初期化時に自動的に実行されるため、エクスポートされる必要があります。debug['A']: これはGoコンパイラの内部的なデバッグフラグで、gc -Aコマンドラインオプションが指定された場合に真となります。
変更前は、Goのエクスポート規則に従うシンボルか、init関数のみがエクスポートされていました。しかし、gc -Aフラグの目的は、デバッグや解析のために「すべての」シンボルをエクスポートすることです。
変更後のコードでは、debug['A']が||(論理OR)演算子で追加されています。これにより、gc -Aフラグが有効な場合、exportnameやinitnameの条件が偽であっても、debug['A']が真であるため、if文の条件全体が真となり、exportsym(n)が実行されます。結果として、gc -Aが指定された際には、Goのエクスポート規則に関わらず、すべてのシンボルが強制的にエクスポートセクションに書き込まれるようになります。これは、gc -Aの本来の意図に合致する修正であり、Go Issue #4908で報告された問題を解決します。
関連リンク
- Go Issue #4908: https://code.google.com/p/go/issues/detail?id=4908 (古いGoogle Codeのリンクですが、当時のIssueトラッカーです)
- Go CL 7383053: https://golang.org/cl/7383053 (Gerrit Code Reviewのリンク)
参考にした情報源リンク
- Go言語の公式ドキュメント (Goコンパイラの内部構造に関する詳細なドキュメントは公開されていませんが、一般的なコンパイラの概念やGo言語の仕様が理解の助けとなります)
- Goコンパイラのソースコード (特に
src/cmd/gcディレクトリ内のファイル) - Go Issueトラッカー (Go Issue #4908の議論内容)
- Gerrit Code Review (CL 7383053のレビューコメント)
- 一般的なコンパイラ設計と実装に関する文献
- Go言語の組み込み関数とパッケージに関する情報
[インデックス 15416] ファイルの概要
このコミットは、Goコンパイラ(cmd/gc)におけるmkbuiltinツールの挙動を修正し、gc -Aフラグが常にすべてのシンボルをエクスポートセクションに書き出すように変更するものです。具体的には、src/cmd/gc/builtin.cとsrc/cmd/gc/export.cの2つのファイルが変更されています。
コミット
commit 1a01ffd386add6c1e11642c44c4009bd8ffcdd3d
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Tue Feb 26 03:14:59 2013 +0800
cmd/gc: fix mkbuiltin (gc -A always write all symbols to export section)
Regenerate cmd/gc/builtin.c.
Fixes #4908.
R=rsc
CC=golang-dev
https://golang.org/cl/7383053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1a01ffd386add6c1e11642c44c4009bd8ffcdd3d
元コミット内容
cmd/gc: fix mkbuiltin (gc -A always write all symbols to export section)
Regenerate cmd/gc/builtin.c.
Fixes #4908.
変更の背景
このコミットは、Goコンパイラ(cmd/gc)のmkbuiltinツールに関連するバグ、具体的にはGo Issue #4908を修正するために行われました。mkbuiltinは、Goの組み込み関数や型に関する情報をbuiltin.cというC言語のソースファイルとして生成するツールです。このツールは、GoコンパイラがGo言語の組み込み要素を認識し、適切に処理するために不可欠です。
問題は、gc -Aフラグが使用された際に、コンパイラがすべてのシンボルをエクスポートセクションに正しく書き出さないことにありました。エクスポートセクションは、コンパイルされたGoパッケージが他のパッケージから利用できるように、そのパッケージが提供するシンボル(関数、変数、型など)の情報を格納する領域です。gc -Aフラグは、通常、デバッグやコンパイラの内部動作の検証のために使用され、すべてのシンボルがエクスポートされることを期待されます。しかし、このバグにより、mkbuiltinが生成するbuiltin.cが、この期待に反する挙動を示していました。
この不整合は、コンパイラのビルドプロセスや、Go言語の組み込み機能の正確な動作に影響を与える可能性がありました。そのため、gc -Aフラグが意図通りにすべてのシンボルをエクスポートセクションに含めるように修正する必要がありました。
前提知識の解説
- Goコンパイラ (
cmd/gc): Go言語の公式コンパイラであり、Goソースコードを機械語に変換する役割を担います。gcはGoコンパイラのコマンド名です。 mkbuiltin: Goコンパイラのビルドプロセスで使用される内部ツールの一つです。Go言語の組み込み関数(例:len,cap,new,makeなど)や組み込み型(例:int,string,boolなど)に関する情報を、コンパイラが利用できるC言語のソースファイル(builtin.c)として生成します。これにより、コンパイラはこれらの組み込み要素を特別扱いし、効率的に処理することができます。gc -Aフラグ: Goコンパイラgcに渡されるオプションの一つです。このフラグは、コンパイラが生成するオブジェクトファイル(またはエクスポート情報)に、通常はエクスポートされない内部シンボルも含めて、すべてのシンボルをエクスポートセクションに含めるように指示します。これは主に、コンパイラのデバッグ、プロファイリング、または内部構造の解析のために使用されます。- シンボル (Symbol): プログラミング言語において、変数、関数、型、定数など、プログラム内で名前を持つエンティティを指します。コンパイラはこれらのシンボルを管理し、それらの定義と参照を解決します。
- エクスポートセクション (Export Section): コンパイルされたプログラムやライブラリにおいて、外部からアクセス可能なシンボル(関数、変数、型など)の情報を格納する領域です。Go言語では、パッケージの外部に公開される(大文字で始まる)シンボルがエクスポートされます。コンパイラは、このエクスポート情報を用いて、異なるパッケージ間でのリンクを可能にします。
- Go Issue #4908: GoプロジェクトのIssueトラッカーで報告された特定のバグを指します。このコミットの変更は、このIssueで記述された問題の解決を目的としています。
技術的詳細
このコミットの技術的詳細は、Goコンパイラの内部構造、特にシンボル管理とエクスポートメカニズムに深く関わっています。
Goコンパイラは、ソースコードを解析し、抽象構文木(AST)を構築した後、型チェックや最適化などの様々なフェーズを経て、最終的に機械語コードを生成します。この過程で、コンパイラはプログラム内のすべてのシンボルを追跡し、それらの属性(型、スコープ、アドレスなど)を管理します。
mkbuiltinツールは、Goの組み込み関数や型を、コンパイラがC言語のコードとして直接扱えるようにするためのものです。builtin.cファイルは、これらの組み込み要素の定義をC言語の構造体や関数として記述し、コンパイラが内部的に参照できるようにします。
問題となっていたのは、gc -Aフラグが指定された際に、autoexport関数(src/cmd/gc/export.cに定義されている)が期待通りにすべてのシンボルをエクスポートセクションに含めないことでした。autoexport関数は、コンパイラがシンボルを処理する際に、そのシンボルがエクスポートされるべきかどうかを判断するロジックを含んでいます。
元のコードでは、autoexport関数は以下の条件でシンボルをエクスポートしていました。
if(exportname(n->sym->name) || initname(n->sym->name))
これは、シンボル名がGoのエクスポート規則(大文字で始まる)に従っているか、またはinit関数のような特殊な名前である場合にのみエクスポートするという意味です。
しかし、gc -Aフラグが指定された場合、コンパイラはすべてのシンボルをエクスポートすべきです。このコミットでは、autoexport関数にdebug['A']という条件が追加されました。debug['A']は、gc -Aフラグが設定されているかどうかを示す内部フラグです。
変更後のコードは以下のようになります。
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
この変更により、gc -Aフラグが有効な場合(debug['A']が真の場合)は、exportnameやinitnameの条件に関わらず、常にexportsym(n)が呼び出され、現在のシンボルnがエクスポートセクションに書き込まれるようになります。これにより、gc -Aの意図通りの挙動が実現され、すべてのシンボルがエクスポートされるようになります。
また、src/cmd/gc/builtin.cの変更は、この修正に伴いmkbuiltinツールによって再生成された結果です。具体的には、runtimeimportとunsafeimportの文字列リテラル内で定義されている組み込み関数の引数名に、·と数字が追加されています(例: @\"\\\".typが@\"\\\".typ·2に)。これは、コンパイラの内部的なシンボル管理や名前解決のメカニズムが更新されたことを示唆しており、引数名の一意性を保証するための変更であると考えられます。このような変更は、コンパイラの内部的な表現がより堅牢になることを意味します。
コアとなるコードの変更箇所
src/cmd/gc/builtin.c
このファイルは、mkbuiltinツールによって生成されるGoの組み込み関数や型の定義を含むC言語のソースファイルです。このコミットでは、このファイル全体が再生成されています。
主な変更点は、runtimeimportとunsafeimportというC言語の文字列リテラル内で定義されているGoの組み込み関数のシグネチャです。具体的には、関数の引数名に·と数字が追加されています。
変更前(例):
"func @\"\\\".new(@\"\\\".typ *byte) (? *any)\\n"
"func @\"\\\".appendslice(@\"\\\".typ *byte, @\"\\\".x any, @\"\\\".y []any) (? any)\\n"
変更後(例):
"func @\"\\\".new (@\"\\\".typ·2 *byte) (? *any)\\n"
"func @\"\\\".appendslice (@\"\\\".typ·2 *byte, @\"\\\".x·3 any, @\"\\\".y·4 []any) (? any)\\n"
この変更は、mkbuiltinツールが生成するコードのフォーマットが更新された結果であり、コンパイラの内部的なシンボル管理の改善を反映しています。
src/cmd/gc/export.c
このファイルは、Goコンパイラがシンボルをエクスポートするロジックを定義しています。
変更前:
if(exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
変更後:
// -A is for cmd/gc/mkbuiltin script, so export everything
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
この変更により、debug['A']フラグ(gc -Aオプションが有効な場合に設定される)が真であれば、exportnameやinitnameの条件に関わらず、すべてのシンボルがエクスポートされるようになりました。
コアとなるコードの解説
src/cmd/gc/builtin.cの変更
builtin.cの変更は、直接的なバグ修正というよりも、バグ修正に伴うmkbuiltinの再実行によって生成された結果です。引数名に付与された·と数字は、コンパイラの内部的な名前解決メカニズムが、引数名の一意性をより厳密に管理するように変更されたことを示唆しています。これは、コンパイラが内部的にシンボルを識別し、処理する際の堅牢性を高めるための改善と考えられます。例えば、異なるスコープで同じ名前の引数が存在する場合でも、一意に識別できるようにするための措置かもしれません。
src/cmd/gc/export.cの変更
この変更がこのコミットの核心です。autoexport関数は、コンパイラがシンボルを処理する際に、そのシンボルが最終的にコンパイルされたバイナリのエクスポートテーブルに含まれるべきかどうかを決定します。
exportname(n->sym->name): シンボル名がGoのエクスポート規則(大文字で始まる)に従っているかどうかをチェックします。initname(n->sym->name): シンボル名がinit関数のような特殊な名前であるかどうかをチェックします。init関数はGoプログラムの初期化時に自動的に実行されるため、エクスポートされる必要があります。debug['A']: これはGoコンパイラの内部的なデバッグフラグで、gc -Aコマンドラインオプションが指定された場合に真となります。
変更前は、Goのエクスポート規則に従うシンボルか、init関数のみがエクスポートされていました。しかし、gc -Aフラグの目的は、デバッグや解析のために「すべての」シンボルをエクスポートすることです。
変更後のコードでは、debug['A']が||(論理OR)演算子で追加されています。これにより、gc -Aフラグが有効な場合、exportnameやinitnameの条件が偽であっても、debug['A']が真であるため、if文の条件全体が真となり、exportsym(n)が実行されます。結果として、gc -Aが指定された際には、Goのエクスポート規則に関わらず、すべてのシンボルが強制的にエクスポートセクションに書き込まれるようになります。これは、gc -Aの本来の意図に合致する修正であり、Go Issue #4908で報告された問題を解決します。
関連リンク
- Go Issue #4908: https://code.google.com/p/go/issues/detail?id=4908 (古いGoogle Codeのリンクですが、当時のIssueトラッカーです)
- Go CL 7383053: https://golang.org/cl/7383053 (Gerrit Code Reviewのリンク)
参考にした情報源リンク
- Go言語の公式ドキュメント (Goコンパイラの内部構造に関する詳細なドキュメントは公開されていませんが、一般的なコンパイラの概念やGo言語の仕様が理解の助けとなります)
- Goコンパイラのソースコード (特に
src/cmd/gcディレクトリ内のファイル) - Go Issueトラッカー (Go Issue #4908の議論内容)
- Gerrit Code Review (CL 7383053のレビューコメント)
- 一般的なコンパイラ設計と実装に関する文献
- Go言語の組み込み関数とパッケージに関する情報