Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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言語には、lencapnewmakepanicrecoverなどの組み込み関数が多数存在します。これらは通常の関数とは異なり、コンパイラによって特別に扱われます。例えば、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 buildgo installなどのコマンドは、内部的にgo toolコマンドを呼び出して、コンパイラ(gc)、アセンブラ(as)、リンカ(ld)などの様々なツールを実行します。

go tool dist envは、Goのディストリビューションビルド環境の変数を設定するためのコマンドです。このコマンドは、GOARCH(ターゲットアーキテクチャ)、GOOS(ターゲットOS)、GOCHAR(ターゲットアーキテクチャの文字コード)などの環境変数を設定し、クロスコンパイルなどのビルドプロセスを容易にします。

技術的詳細

このコミットは、主に以下のファイルに影響を与えています。

  1. src/cmd/dist/build.c:

    • cmdenv関数にxprintf(format, "GOCHAR", gochar);が追加されました。これは、ビルド環境を設定する際にGOCHAR環境変数も設定するように変更されたことを示しています。GOCHARは、Goのツールチェーンがターゲットアーキテクチャを識別するために使用する文字コードです(例: 6はamd64、8は386)。これにより、mkbuiltinのようなツールが正しいターゲットアーキテクチャのビルド環境で実行されるようになります。
  2. 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)に対応する定義がこのファイルから削除されました。
  3. 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.$GOCHARruntime.$GOCHARが追加されました。これは、mkbuiltinの実行中に生成される可能性のあるこれらのファイルも削除されるようにするためです。
  4. 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コードにするための変更です。
    • エラーハンドリング関数sysfatalfatalに置き換えられました。sysfatalはPlan 9のシステムコールエラーを扱うためのものでしたが、fatalは標準Cライブラリのstrerror(errno)を使用してエラーメッセージを生成するようになりました。これにより、エラー報告がより標準的でクロスプラットフォームな方法で行われるようになります。
    • main関数の戻り値がvoidからintに変更され、return 0;が追加されました。これは、Cプログラムの標準的な慣習に従い、成功時に0を返すようにするためです。
  5. 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の進化に伴い、より新しい、または異なるメカニズムに置き換えられたため、不要になったと考えられます。

コアとなるコードの変更箇所

このコミットのコアとなる変更は、以下の2つの側面に見られます。

  1. 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
    
  2. 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のメモリ管理はガベージコレクションによって自動化されており、通常はnewmakeといった組み込み関数を使用します。これらのunsafeな割り当て関数が削除されたのは、Goのメモリモデルが成熟し、より効率的で安全な内部割り当てメカニズムが導入されたためかもしれません。

これらの関数の削除は、Go言語の内部実装がより洗練され、unsafeパッケージへの依存を減らす方向に向かっていることを示唆しています。これにより、コンパイラの複雑性が軽減され、将来的な変更や最適化が容易になります。

builtin.cのエクスポート形式の変更

src/cmd/gc/builtin.cにおける変更は、mkbuiltinツールが生成する組み込み関数の定義形式が変更されたことを示しています。

  • ?プレフィックスの追加: 多くの関数定義の戻り値の型に?が追加されています(例: *anyから? *any)。これはGoコンパイラの内部表現における変更であり、戻り値が特定のコンテキストでオプショナルであるか、または特別な処理が必要であることを示す可能性があります。例えば、エラーを返す可能性のある関数や、複数の戻り値を持つ関数において、コンパイラがその戻り値をどのように扱うべきかをより明確に指示するために使用されるのかもしれません。
  • 名前付き戻り値の明示: 以前は単に型が記述されていた戻り値が、(@\"\\\".ret any)のように名前付きの引数として明示されるようになりました。これは、Goの関数が複数の戻り値を持つことができる特性を反映しており、コンパイラが各戻り値を個別のエンティティとしてより明確に識別し、処理できるようにするための変更です。これにより、コンパイラは型チェック、最適化、およびコード生成の際に、関数のシグネチャをより正確に解析できるようになります。

これらの変更は、Goコンパイラが組み込み関数やランタイム関数の情報をより詳細かつ厳密に解析できるようにするための内部的な改善です。これにより、コンパイラの正確性と堅牢性が向上し、Goプログラムの実行時パフォーマンスや安定性にも寄与する可能性があります。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード(特にsrc/cmd/gcディレクトリ)
  • Go言語の公式ドキュメント
  • Go言語のコミット履歴とGerrit Code Reviewシステム
  • Go言語のビルドシステムに関する一般的な知識
  • C言語の標準ライブラリ関数に関する知識