[インデックス 11856] ファイルの概要
このコミットは、Go言語のコンパイラ(gc
)に関連する変更であり、特にunsafe
パッケージから古い関数を削除し、mkbuiltin
ツールのビルドプロセスを更新することに焦点を当てています。これにより、Go言語の内部構造とビルドシステムが改善され、よりクリーンで効率的な状態に保たれます。
コミット
commit 1f2445d27bfca7d44f90ed9a6dbb799289bdf548
Author: Russ Cox <rsc@golang.org>
Date: Mon Feb 13 15:37:35 2012 -0500
gc: delete old unsafe functions
Also update build to be able to run mkbuiltin again.
The export form has changed a little, so builtin.c has
more diffs than unsafe.go.
In CL 5650069, I just edited the documentation, a rarely
successful method of change.
R=ken2
CC=golang-dev
https://golang.org/cl/5662043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1f2445d27bfca7d44f90ed9a6dbb799289bdf548
元コミット内容
gc: delete old unsafe functions
Also update build to be able to run mkbuiltin again.
The export form has changed a little, so builtin.c has
more diffs than unsafe.go.
In CL 5650069, I just edited the documentation, a rarely
successful method of change.
変更の背景
このコミットの主な目的は、Go言語のunsafe
パッケージから不要になった古い関数を削除し、それに伴いmkbuiltin
ツールのビルドプロセスを更新することです。Go言語は継続的に進化しており、その過程で一部の内部関数やAPIが廃止されたり、より効率的な代替手段に置き換えられたりすることがあります。
unsafe
パッケージは、Go言語の型安全性をバイパスして低レベルのメモリ操作を可能にするためのものであり、通常の使用では推奨されません。しかし、コンパイラやランタイムのようなGo言語のコア部分では、パフォーマンスや特定の機能を実現するためにunsafe
パッケージが利用されることがあります。
このコミットでは、以前の変更(CL 5650069)でドキュメントのみが更新されたものの、実際のコード変更が伴っていなかったunsafe
関連の関数が、今回実際に削除されました。これは、Go言語のコードベースをクリーンに保ち、メンテナンス性を向上させるための一般的なプラクティスです。
また、mkbuiltin
ツールは、Goコンパイラが内部的に使用する組み込み関数(builtin
関数)の定義を生成するためのものです。これらの組み込み関数は、Goのランタイムや標準ライブラリの特定の操作を効率的に実行するためにコンパイラによって特別に扱われます。unsafe
関数の削除やその他の内部的な変更により、mkbuiltin
が生成する組み込み関数のエクスポート形式が変更されたため、このツール自体も更新が必要となりました。
前提知識の解説
Go言語のunsafe
パッケージ
unsafe
パッケージは、Go言語の標準ライブラリの一部ですが、その名の通り「安全ではない」操作を可能にします。具体的には、以下の機能を提供します。
unsafe.Pointer
: 任意の型のポインタを保持できる特殊なポインタ型です。これにより、型システムをバイパスして異なる型のデータとしてメモリを解釈したり、ポインタ演算を行ったりすることが可能になります。unsafe.Sizeof
: 変数や型のメモリ上のサイズ(バイト単位)を返します。unsafe.Offsetof
: 構造体のフィールドが構造体の先頭からどれだけオフセットしているか(バイト単位)を返します。unsafe.Alignof
: 変数や型のメモリ上のアライメント要件を返します。
これらの機能は、通常はGoの型安全性によって禁止されている低レベルの操作を可能にするため、非常に注意して使用する必要があります。誤用すると、メモリ破壊、データ破損、セキュリティ脆弱性など、予測不能な動作を引き起こす可能性があります。そのため、unsafe
パッケージは主にGoのランタイム、コンパイラ、および特定の高性能ライブラリの内部実装で使用されます。
Goコンパイラ(gc
)と組み込み関数(builtin
)
Goコンパイラ(gc
)は、Go言語のソースコードを機械語に変換する主要なツールです。コンパイラは、Goプログラムのビルドプロセスにおいて中心的な役割を果たします。
Go言語には、len
、cap
、new
、make
、panic
、recover
などの組み込み関数が多数存在します。これらは通常の関数とは異なり、コンパイラによって特別に扱われます。例えば、len
関数はスライスや配列の長さを返すために、コンパイラが直接コードを生成します。これらの組み込み関数は、Goのランタイムシステムと密接に連携しており、Goプログラムの基本的な動作を支えています。
mkbuiltin
ツール
mkbuiltin
は、Goコンパイラのビルドプロセスで使用される内部ツールです。このツールは、Goのランタイムパッケージ(runtime
)やunsafe
パッケージに含まれる特定の関数定義を読み込み、それらをC言語のソースコード(builtin.c
)として出力します。このCコードは、Goコンパイラが組み込み関数やunsafe
関数の情報を認識し、適切に処理するために利用されます。
mkbuiltin
は、Goのビルドシステムの一部として自動的に実行され、Goの内部APIの変更に合わせてbuiltin.c
を最新の状態に保つ役割を担っています。
Goのビルドシステムとgo tool
Go言語のビルドシステムは、go
コマンドによって管理されます。go build
やgo install
などのコマンドは、内部的にgo tool
コマンドを呼び出して、コンパイラ(gc
)、アセンブラ(as
)、リンカ(ld
)などの様々なツールを実行します。
go tool dist env
は、Goのディストリビューションビルド環境の変数を設定するためのコマンドです。このコマンドは、GOARCH
(ターゲットアーキテクチャ)、GOOS
(ターゲットOS)、GOCHAR
(ターゲットアーキテクチャの文字コード)などの環境変数を設定し、クロスコンパイルなどのビルドプロセスを容易にします。
技術的詳細
このコミットは、主に以下のファイルに影響を与えています。
-
src/cmd/dist/build.c
:cmdenv
関数にxprintf(format, "GOCHAR", gochar);
が追加されました。これは、ビルド環境を設定する際にGOCHAR
環境変数も設定するように変更されたことを示しています。GOCHAR
は、Goのツールチェーンがターゲットアーキテクチャを識別するために使用する文字コードです(例:6
はamd64、8
は386)。これにより、mkbuiltin
のようなツールが正しいターゲットアーキテクチャのビルド環境で実行されるようになります。
-
src/cmd/gc/builtin.c
:- このファイルは、Goのランタイムと
unsafe
パッケージの組み込み関数の定義をC言語の文字列として保持しています。 - 多くの関数定義において、戻り値の型指定が変更されました。具体的には、
func @\"\\\".new(@\"\\\".typ *byte) *any\\n"
のような形式がfunc @\"\\\".new(@\"\\\".typ *byte) (? *any)\\n"
のように、戻り値の前に?
が追加されています。 - 同様に、
func @\"\\\".convI2E(@\"\\\".elem any) any\\n"
のような形式がfunc @\"\\\".convI2E(@\"\\\".elem any) (@\"\\\".ret any)\\n"
のように、戻り値が名前付きの引数として明示される形式に変更されています。 - これは、
mkbuiltin
が生成する組み込み関数のエクスポート形式が変更されたことを示しており、コンパイラがこれらの関数の戻り値をより厳密に、または異なる方法で処理する必要があることを示唆しています。特に、?
はGoの内部表現において、戻り値がオプショナルであるか、または特定のコンテキストで特別な意味を持つことを示す可能性があります。名前付き戻り値の導入は、コンパイラが関数のシグネチャをより正確に解析し、型チェックやコード生成を行う上で役立ちます。 unsafe
パッケージから削除された関数(Typeof
,Reflect
,Unreflect
,New
,NewArray
)に対応する定義がこのファイルから削除されました。
- このファイルは、Goのランタイムと
-
src/cmd/gc/mkbuiltin
:mkbuiltin
スクリプト自体が変更されました。- 以前は
eval $(go tool make --no-print-directory -f ../../Make.inc go-env)
を使用してビルド環境を設定していましたが、これがeval $(go tool dist env)
に変更されました。これは、Goのビルドシステムが進化し、環境変数の設定方法がより標準化されたことを反映しています。 GC=${GOCHAR}g
という行が追加され、GC
変数がGOCHAR
に基づいて設定されるようになりました。これにより、mkbuiltin
が正しいコンパイラ(例:6g
for amd64)を使用するようになります。gcc -o mkbuiltin1 mkbuiltin1.c
が追加され、mkbuiltin1.c
が直接gcc
でコンパイルされるようになりました。以前はgo tool make mkbuiltin1
を使用していました。これは、mkbuiltin1
がGoのツールチェーンの一部としてではなく、スタンドアロンのCプログラムとしてビルドされるようになったことを意味します。- 一時ファイルのクリーンアップに
unsafe.$GOCHAR
とruntime.$GOCHAR
が追加されました。これは、mkbuiltin
の実行中に生成される可能性のあるこれらのファイルも削除されるようにするためです。
-
src/cmd/gc/mkbuiltin1.c
:- このCソースファイルは、
mkbuiltin
スクリプトによって呼び出され、Goの.6
ファイル(コンパイルされたGoパッケージのメタデータを含むファイル)から組み込み関数の情報を抽出し、C言語の文字列として整形する役割を担っています。 - ヘッダーファイルのインクルードが変更されました。
#include <u.h>
と#include <libc.h>
が削除され、代わりに標準Cライブラリのヘッダー(stdio.h
,stdlib.h
,unistd.h
,string.h
,errno.h
,stdarg.h
)が追加されました。これは、Plan 9の特定のライブラリへの依存を減らし、よりポータブルなCコードにするための変更です。 - エラーハンドリング関数
sysfatal
がfatal
に置き換えられました。sysfatal
はPlan 9のシステムコールエラーを扱うためのものでしたが、fatal
は標準Cライブラリのstrerror(errno)
を使用してエラーメッセージを生成するようになりました。これにより、エラー報告がより標準的でクロスプラットフォームな方法で行われるようになります。 main
関数の戻り値がvoid
からint
に変更され、return 0;
が追加されました。これは、Cプログラムの標準的な慣習に従い、成功時に0を返すようにするためです。
- このCソースファイルは、
-
src/cmd/gc/unsafe.go
:- このファイルは、Goの
unsafe
パッケージのGo言語側の定義を含んでいます。 - 以下の関数定義が削除されました。
func Typeof(i interface{}) (typ interface{})
func Reflect(i interface{}) (typ interface{}, addr Pointer)
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
func New(typ interface{}) Pointer
func NewArray(typ interface{}, n int) Pointer
- これらの関数は、Goの内部的なリフレクションやメモリ割り当てに関連するものでしたが、おそらくGoの進化に伴い、より新しい、または異なるメカニズムに置き換えられたため、不要になったと考えられます。
- このファイルは、Goの
コアとなるコードの変更箇所
このコミットのコアとなる変更は、以下の2つの側面に見られます。
-
src/cmd/gc/unsafe.go
からの古いunsafe
関数の削除:--- a/src/cmd/gc/unsafe.go +++ b/src/cmd/gc/unsafe.go @@ -16,9 +16,3 @@ type Pointer uintptr // not really; filled in by compiler func Offsetof(any) uintptr func Sizeof(any) uintptr func Alignof(any) uintptr - -func Typeof(i interface{}) (typ interface{}) -func Reflect(i interface{}) (typ interface{}, addr Pointer) -func Unreflect(i interface{}) (typ interface{}, addr Pointer) -func New(typ interface{}) Pointer -func NewArray(typ interface{}, n int) Pointer
-
src/cmd/gc/builtin.c
における組み込み関数のエクスポート形式の変更とunsafe
関数の定義削除: 特に、戻り値の型指定に?
が追加されたり、名前付き戻り値が導入されたりした点が重要です。--- a/src/cmd/gc/builtin.c +++ b/src/cmd/gc/builtin.c @@ -1,14 +1,14 @@ char *runtimeimport = "package runtime\\n"\ "import runtime \\\"runtime\\\"\\n"\ -"\t\"func @\\\"\\\".new(@\\\"\\\".typ *byte) *any\\n\"\ +"\t\"func @\\\"\\\".new(@\\\"\\\".typ *byte) (? *any)\\n\"\ "func @\\\"\\\".panicindex()\\n"\ "func @\\\"\\\".panicslice()\\n"\ "func @\\\"\\\".throwreturn()\\n"\ "func @\\\"\\\".throwinit()\\n"\ "func @\\\"\\\".panicwrap(? string, ? string, ? string)\\n"\ "func @\\\"\\\".panic(? interface {})\\n"\ -"\t\"func @\\\"\\\".recover(? *int32) interface {}\\n\"\ +"\t\"func @\\\"\\\".recover(? *int32) (? interface {})\\n\"\ "func @\\\"\\\".printbool(? bool)\\n"\ "func @\\\"\\\".printfloat(? float64)\\n"\ "func @\\\"\\\".printint(? int64)\\n"\ ... (中略) ... -"\t\"func @\\\"\\\".convI2E(@\\\"\\\".elem any) any\\n\"\ -"\t\"func @\\\"\\\".convI2I(@\\\"\\\".typ *byte, @\\\"\\\".elem any) any\\n\"\ -"\t\"func @\\\"\\\".convT2E(@\\\"\\\".typ *byte, @\\\"\\\".elem any) any\\n\"\ -"\t\"func @\\\"\\\".convT2I(@\\\"\\\".typ *byte, @\\\"\\\".typ2 *byte, @\\\"\\\".elem any) any\\n\"\ -"\t\"func @\\\"\\\".assertE2E(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".convI2E(@\\\"\\\".elem any) (@\\\"\\\".ret any)\\n\"\ +"\t\"func @\\\"\\\".convI2I(@\\\"\\\".typ *byte, @\\\"\\\".elem any) (@\\\"\\\".ret any)\\n\"\ +"\t\"func @\\\"\\\".convT2E(@\\\"\\\".typ *byte, @\\\"\\\".elem any) (@\\\"\\\".ret any)\\n\"\ +"\t\"func @\\\"\\\".convT2I(@\\\"\\\".typ *byte, @\\\"\\\".typ2 *byte, @\\\"\\\".elem any) (@\\\"\\\".ret any)\\n\"\ +"\t\"func @\\\"\\\".assertE2E(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertE2E2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".assertE2I(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".assertE2I(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertE2I2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".assertE2T(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".assertE2T(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertE2T2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".assertI2E(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".assertI2E(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertI2E2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".assertI2I(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".assertI2I(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertI2I2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".assertI2T(@\\\"\\\".typ *byte, @\\\"\\\".iface any) any\\n\"\ +"\t\"func @\\\"\\\".assertI2T(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any)\\n\"\ "func @\\\"\\\".assertI2T2(@\\\"\\\".typ *byte, @\\\"\\\".iface any) (@\\\"\\\".ret any, @\\\"\\\".ok bool)\\n\"\ -"\t\"func @\\\"\\\".ifaceeq(@\\\"\\\".i1 any, @\\\"\\\".i2 any) bool\\n\"\ -"\t\"func @\\\"\\\".efaceeq(@\\\"\\\".i1 any, @\\\"\\\".i2 any) bool\\n\"\ -"\t\"func @\\\"\\\".ifacethash(@\\\"\\\".i1 any) uint32\\n\"\ -"\t\"func @\\\"\\\".efacethash(@\\\"\\\".i1 any) uint32\\n\"\ -"\t\"func @\\\"\\\".equal(@\\\"\\\".typ *byte, @\\\"\\\".x1 any, @\\\"\\\".x2 any) bool\\n\"\ -"\t\"func @\\\"\\\".makemap(@\\\"\\\".mapType *byte, @\\\"\\\".hint int64) map[any]any\\n\"\ -"\t\"func @\\\"\\\".mapaccess1(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any) any\\n\"\ +"\t\"func @\\\"\\\".ifaceeq(@\\\"\\\".i1 any, @\\\"\\\".i2 any) (@\\\"\\\".ret bool)\\n\"\ +"\t\"func @\\\"\\\".efaceeq(@\\\"\\\".i1 any, @\\\"\\\".i2 any) (@\\\"\\\".ret bool)\\n\"\ +"\t\"func @\\\"\\\".ifacethash(@\\\"\\\".i1 any) (@\\\"\\\".ret uint32)\\n\"\ +"\t\"func @\\\"\\\".efacethash(@\\\"\\\".i1 any) (@\\\"\\\".ret uint32)\\n\"\ +"\t\"func @\\\"\\\".equal(@\\\"\\\".typ *byte, @\\\"\\\".x1 any, @\\\"\\\".x2 any) (@\\\"\\\".ret bool)\\n\"\ +"\t\"func @\\\"\\\".makemap(@\\\"\\\".mapType *byte, @\\\"\\\".hint int64) (@\\\"\\\".hmap map[any]any)\\n\"\ +"\t\"func @\\\"\\\".mapaccess1(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any) (@\\\"\\\".val any)\\n\"\ "func @\\\"\\\".mapaccess2(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any) (@\\\"\\\".val any, @\\\"\\\".pres bool)\\n"\ "func @\\\"\\\".mapassign1(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any, @\\\"\\\".val any)\\n"\ "func @\\\"\\\".mapassign2(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any, @\\\"\\\".val any, @\\\"\\\".pres bool)\\n"\ "func @\\\"\\\".mapiterinit(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".hiter *any)\\n"\ "func @\\\"\\\".mapdelete(@\\\"\\\".mapType *byte, @\\\"\\\".hmap map[any]any, @\\\"\\\".key any)\\n"\ "func @\\\"\\\".mapiternext(@\\\"\\\".hiter *any)\\n"\ -"\t\"func @\\\"\\\".mapiter1(@\\\"\\\".hiter *any) any\\n\"\ +"\t\"func @\\\"\\\".mapiter1(@\\\"\\\".hiter *any) (@\\\"\\\".key any)\\n\"\ "func @\\\"\\\".mapiter2(@\\\"\\\".hiter *any) (@\\\"\\\".key any, @\\\"\\\".val any)\\n"\ -"\t\"func @\\\"\\\".makechan(@\\\"\\\".chanType *byte, @\\\"\\\".hint int64) chan any\\n\"\ -"\t\"func @\\\"\\\".chanrecv1(@\\\"\\\".chanType *byte, @\\\"\\\".hchan <-chan any) any\\n\"\ +"\t\"func @\\\"\\\".makechan(@\\\"\\\".chanType *byte, @\\\"\\\".hint int64) (@\\\"\\\".hchan chan any)\\n\"\ +"\t\"func @\\\"\\\".chanrecv1(@\\\"\\\".chanType *byte, @\\\"\\\".hchan <-chan any) (@\\\"\\\".elem any)\\n\"\ "func @\\\"\\\".chanrecv2(@\\\"\\\".chanType *byte, @\\\"\\\".hchan <-chan any) (@\\\"\\\".elem any, @\\\"\\\".received bool)\\n"\ "func @\\\"\\\".chansend1(@\\\"\\\".chanType *byte, @\\\"\\\".hchan chan<- any, @\\\"\\\".elem any)\\n"\ "func @\\\"\\\".closechan(@\\\"\\\".hchan any)\\n"\ -"\t\"func @\\\"\\\".selectnbsend(@\\\"\\\".chanType *byte, @\\\"\\\".hchan chan<- any, @\\\"\\\".elem any) bool\\n\"\ -"\t\"func @\\\"\\\".selectnbrecv(@\\\"\\\".chanType *byte, @\\\"\\\".elem *any, @\\\"\\\".hchan <-chan any) bool\\n\"\ -"\t\"func @\\\"\\\".selectnbrecv2(@\\\"\\\".chanType *byte, @\\\"\\\".elem *any, @\\\"\\\".received *bool, @\\\"\\\".hchan <-chan any) bool\\n\"\ -"\t\"func @\\\"\\\".newselect(@\\\"\\\".size int) *byte\\n\"\ -"\t\"func @\\\"\\\".selectsend(@\\\"\\\".sel *byte, @\\\"\\\".hchan chan<- any, @\\\"\\\".elem *any) bool\\n\"\ -"\t\"func @\\\"\\\".selectrecv(@\\\"\\\".sel *byte, @\\\"\\\".hchan <-chan any, @\\\"\\\".elem *any) bool\\n\"\ -"\t\"func @\\\"\\\".selectrecv2(@\\\"\\\".sel *byte, @\\\"\\\".hchan <-chan any, @\\\"\\\".elem *any, @\\\"\\\".received *bool) bool\\n\"\ -"\t\"func @\\\"\\\".selectdefault(@\\\"\\\".sel *byte) bool\\n\"\ +"\t\"func @\\\"\\\".selectnbsend(@\\\"\\\".chanType *byte, @\\\"\\\".hchan chan<- any, @\\\"\\\".elem any) (? bool)\\n\"\ +"\t\"func @\\\"\\\".selectnbrecv(@\\\"\\\".chanType *byte, @\\\"\\\".elem *any, @\\\"\\\".hchan <-chan any) (? bool)\\n\"\ +"\t\"func @\\\"\\\".selectnbrecv2(@\\\"\\\".chanType *byte, @\\\"\\\".elem *any, @\\\"\\\".received *bool, @\\\"\\\".hchan <-chan any) (? bool)\\n\"\ +"\t\"func @\\\"\\\".newselect(@\\\"\\\".size int) (@\\\"\\\".sel *byte)\\n\"\ +"\t\"func @\\\"\\\".selectsend(@\\\"\\\".sel *byte, @\\\"\\\".hchan chan<- any, @\\\"\\\".elem *any) (@\\\"\\\".selected bool)\\n\"\ +"\t\"func @\\\"\\\".selectrecv(@\\\"\\\".sel *byte, @\\\"\\\".hchan <-chan any, @\\\"\\\".elem *any) (@\\\"\\\".selected bool)\\n\"\ +"\t\"func @\\\"\\\".selectrecv2(@\\\"\\\".sel *byte, @\\\"\\\".hchan <-chan any, @\\\"\\\".elem *any, @\\\"\\\".received *bool) (@\\\"\\\".selected bool)\\n\"\ +"\t\"func @\\\"\\\".selectdefault(@\\\"\\\".sel *byte) (@\\\"\\\".selected bool)\\n\"\ "func @\\\"\\\".selectgo(@\\\"\\\".sel *byte)\\n"\ "func @\\\"\\\".block()\\n"\ -"\t\"func @\\\"\\\".makeslice(@\\\"\\\".typ *byte, @\\\"\\\".nel int64, @\\\"\\\".cap int64) []any\\n\"\ -"\t\"func @\\\"\\\".growslice(@\\\"\\\".typ *byte, @\\\"\\\".old []any, @\\\"\\\".n int64) []any\\n\"\ -"\t\"func @\\\"\\\".sliceslice1(@\\\"\\\".old []any, @\\\"\\\".lb uint64, @\\\"\\\".width uint64) []any\\n\"\ -"\t\"func @\\\"\\\".sliceslice(@\\\"\\\".old []any, @\\\"\\\".lb uint64, @\\\"\\\".hb uint64, @\\\"\\\".width uint64) []any\\n\"\ -"\t\"func @\\\"\\\".slicearray(@\\\"\\\".old *any, @\\\"\\\".nel uint64, @\\\"\\\".lb uint64, @\\\"\\\".hb uint64, @\\\"\\\".width uint64) []any\\n\"\ +"\t\"func @\\\"\\\".makeslice(@\\\"\\\".typ *byte, @\\\"\\\".nel int64, @\\\"\\\".cap int64) (@\\\"\\\".ary []any)\\n\"\ +"\t\"func @\\\"\\\".growslice(@\\\"\\\".typ *byte, @\\\"\\\".old []any, @\\\"\\\".n int64) (@\\\"\\\".ary []any)\\n\"\ +"\t\"func @\\\"\\\".sliceslice1(@\\\"\\\".old []any, @\\\"\\\".lb uint64, @\\\"\\\".width uint64) (@\\\"\\\".ary []any)\\n\"\ +"\t\"func @\\\"\\\".sliceslice(@\\\"\\\".old []any, @\\\"\\\".lb uint64, @\\\"\\\".hb uint64, @\\\"\\\".width uint64) (@\\\"\\\".ary []any)\\n\"\ +"\t\"func @\\\"\\\".slicearray(@\\\"\\\".old *any, @\\\"\\\".nel uint64, @\\\"\\\".lb uint64, @\\\"\\\".hb uint64, @\\\"\\\".width uint64) (@\\\"\\\".ary []any)\\n\"\ "func @\\\"\\\".closure()\\n"\ "func @\\\"\\\".memequal(@\\\"\\\".eq *bool, @\\\"\\\".size uintptr, @\\\"\\\".x *any, @\\\"\\\".y *any)\\n"\ "func @\\\"\\\".memequal8(@\\\"\\\".eq *bool, @\\\"\\\".size uintptr, @\\\"\\\".x *any, @\\\"\\\".y *any)\\n"\ @@ -96,28 +96,23 @@ char *runtimeimport =\ "func @\\\"\\\".memequal32(@\\\"\\\".eq *bool, @\\\"\\\".size uintptr, @\\\"\\\".x *any, @\\\"\\\".y *any)\\n"\ "func @\\\"\\\".memequal64(@\\\"\\\".eq *bool, @\\\"\\\".size uintptr, @\\\"\\\".x *any, @\\\"\\\".y *any)\\n"\ "func @\\\"\\\".memequal128(@\\\"\\\".eq *bool, @\\\"\\\".size uintptr, @\\\"\\\".x *any, @\\\"\\\".y *any)\\n"\ -"\t\"func @\\\"\\\".int64div(? int64, ? int64) int64\\n\"\ -"\t\"func @\\\"\\\".uint64div(? uint64, ? uint64) uint64\\n\"\ -"\t\"func @\\\"\\\".int64mod(? int64, ? int64) int64\\n\"\ -"\t\"func @\\\"\\\".uint64mod(? uint64, ? uint64) uint64\\n\"\ -"\t\"func @\\\"\\\".float64toint64(? float64) int64\\n\"\ -"\t\"func @\\\"\\\".float64touint64(? float64) uint64\\n\"\ -"\t\"func @\\\"\\\".int64tofloat64(? int64) float64\\n\"\ -"\t\"func @\\\"\\\".uint64tofloat64(? uint64) float64\\n\"\ -"\t\"func @\\\"\\\".complex128div(@\\\"\\\".num complex128, @\\\"\\\".den complex128) complex128\\n\"\ +"\t\"func @\\\"\\\".int64div(? int64, ? int64) (? int64)\\n\"\ +"\t\"func @\\\"\\\".uint64div(? uint64, ? uint64) (? uint64)\\n\"\ +"\t\"func @\\\"\\\".int64mod(? int64, ? int64) (? int64)\\n\"\ +"\t\"func @\\\"\\\".uint64mod(? uint64, ? uint64) (? uint64)\\n\"\ +"\t\"func @\\\"\\\".float64toint64(? float64) (? int64)\\n\"\ +"\t\"func @\\\"\\\".float64touint64(? float64) (? uint64)\\n\"\ +"\t\"func @\\\"\\\".int64tofloat64(? int64) (? float64)\\n\"\ +"\t\"func @\\\"\\\".uint64tofloat64(? uint64) (? float64)\\n\"\ +"\t\"func @\\\"\\\".complex128div(@\\\"\\\".num complex128, @\\\"\\\".den complex128) (@\\\"\\\".quo complex128)\\n\"\ "\\n"\ "$$\\n"\ ";\n"\ " char *unsafeimport =\n"\ " \t\"package unsafe\\n\"\n"\ " \t\"import runtime \\\"runtime\\\"\\n\"\ " \t\"type @\\\"\\\".Pointer uintptr\\n\"\ -"\t\"func @\\\"\\\".Offsetof(? any) uintptr\\n\"\ -"\t\"func @\\\"\\\".Sizeof(? any) uintptr\\n\"\ -"\t\"func @\\\"\\\".Alignof(? any) uintptr\\n\"\ -"\t\"func @\\\"\\\".Typeof(@\\\"\\\".i interface {}) interface {}\\n\"\ -"\t\"func @\\\"\\\".Reflect(@\\\"\\\".i interface {}) (@\\\"\\\".typ interface {}, @\\\"\\\".addr @\\\"\\\".Pointer)\\n\"\ -"\t\"func @\\\"\\\".Unreflect(@\\\"\\\".typ interface {}, @\\\"\\\".addr @\\\"\\\".Pointer) interface {}\\n\"\ -"\t\"func @\\\"\\\".New(@\\\"\\\".typ interface {}) @\\\"\\\".Pointer\\n\"\ -"\t\"func @\\\"\\\".NewArray(@\\\"\\\".typ interface {}, @\\\"\\\".n int) @\\\"\\\".Pointer\\n\"\ +"\t\"func @\\\"\\\".Offsetof(? any) (? uintptr)\\n\"\ +"\t\"func @\\\"\\\".Sizeof(? any) (? uintptr)\\n\"\ +"\t\"func @\\\"\\\".Alignof(? any) (? uintptr)\\n\"\ "\\n"\ "$$\\n"\ ";\n
コアとなるコードの解説
unsafe
関数の削除
src/cmd/gc/unsafe.go
から削除された関数は、Goの内部的なリフレクションやメモリ管理に関連するものです。
Typeof
,Reflect
,Unreflect
: これらの関数は、Goの型システムを動的に操作したり、インターフェース値から型情報や基盤となるデータへのポインタを取得したりするために使用されていた可能性があります。Goのリフレクション機能は進化しており、これらの低レベルなunsafe
関数がより安全で抽象化されたreflect
パッケージの機能に置き換えられたか、あるいはコンパイラ内部で異なる最適化が導入されたため不要になったと考えられます。New
,NewArray
: これらの関数は、指定された型に基づいて新しいメモリ領域を割り当て、そのポインタを返すために使用されていた可能性があります。Goのメモリ管理はガベージコレクションによって自動化されており、通常はnew
やmake
といった組み込み関数を使用します。これらのunsafe
な割り当て関数が削除されたのは、Goのメモリモデルが成熟し、より効率的で安全な内部割り当てメカニズムが導入されたためかもしれません。
これらの関数の削除は、Go言語の内部実装がより洗練され、unsafe
パッケージへの依存を減らす方向に向かっていることを示唆しています。これにより、コンパイラの複雑性が軽減され、将来的な変更や最適化が容易になります。
builtin.c
のエクスポート形式の変更
src/cmd/gc/builtin.c
における変更は、mkbuiltin
ツールが生成する組み込み関数の定義形式が変更されたことを示しています。
?
プレフィックスの追加: 多くの関数定義の戻り値の型に?
が追加されています(例:*any
から? *any
)。これはGoコンパイラの内部表現における変更であり、戻り値が特定のコンテキストでオプショナルであるか、または特別な処理が必要であることを示す可能性があります。例えば、エラーを返す可能性のある関数や、複数の戻り値を持つ関数において、コンパイラがその戻り値をどのように扱うべきかをより明確に指示するために使用されるのかもしれません。- 名前付き戻り値の明示: 以前は単に型が記述されていた戻り値が、
(@\"\\\".ret any)
のように名前付きの引数として明示されるようになりました。これは、Goの関数が複数の戻り値を持つことができる特性を反映しており、コンパイラが各戻り値を個別のエンティティとしてより明確に識別し、処理できるようにするための変更です。これにより、コンパイラは型チェック、最適化、およびコード生成の際に、関数のシグネチャをより正確に解析できるようになります。
これらの変更は、Goコンパイラが組み込み関数やランタイム関数の情報をより詳細かつ厳密に解析できるようにするための内部的な改善です。これにより、コンパイラの正確性と堅牢性が向上し、Goプログラムの実行時パフォーマンスや安定性にも寄与する可能性があります。
関連リンク
- Go言語の
unsafe
パッケージに関する公式ドキュメント: https://pkg.go.dev/unsafe - Go言語の組み込み関数に関する公式ドキュメント: https://go.dev/ref/spec#Predeclared_identifiers
- このコミットのGo Gerrit Code Reviewリンク: https://golang.org/cl/5662043
参考にした情報源リンク
- Go言語のソースコード(特に
src/cmd/gc
ディレクトリ) - Go言語の公式ドキュメント
- Go言語のコミット履歴とGerrit Code Reviewシステム
- Go言語のビルドシステムに関する一般的な知識
- C言語の標準ライブラリ関数に関する知識