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

[インデックス 15934] ファイルの概要

このコミットは、Go言語のランタイムパッケージからmkasmh.shというシェルスクリプトを削除するものです。このスクリプトの機能はGo 1.0のリリースに伴いcmd/distツールに統合されたため、もはや不要となり、削除されました。

コミット

commit cb807e7b4a3c6291f16507ee9a31a303f411ddba
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 25 17:46:11 2013 -0400

    runtime: delete mkasmh.sh
    
    This functionality moved into cmd/dist for Go 1.0.
    Changes to this script have no effect.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/8020043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/cb807e7b4a3c6291f16507ee9a31a303f411ddba

元コミット内容

このコミットは、Go言語のランタイム(src/pkg/runtime)ディレクトリからmkasmh.shというシェルスクリプトを削除することを目的としています。コミットメッセージによると、このスクリプトが提供していた機能はGo 1.0のリリース時にcmd/distツールへと移行されており、そのためmkasmh.shに対する変更はもはやシステムに影響を与えない状態になっていました。つまり、このスクリプトは陳腐化しており、コードベースから除去されるべきであるという判断がなされたものです。

変更の背景

Go言語の初期開発段階では、ビルドプロセスは現在よりも分散しており、特定のタスクを処理するために個別のスクリプトが使用されていました。mkasmh.shもその一つで、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成する役割を担っていました。

Go 1.0のリリースは、Go言語にとって非常に重要なマイルストーンでした。このバージョンでは、言語仕様、標準ライブラリ、およびツールチェインの安定化が図られ、後方互換性が保証されるようになりました。この安定化の一環として、ビルドシステムの整理と効率化も進められました。

cmd/distは、Go 1.0で導入されたGo自身のビルドを管理するためのツールです。Goのソースコードからコンパイラ、リンカ、アセンブラなどのツールチェイン全体をビルドし、Goの標準ライブラリをコンパイルする役割を担っています。cmd/distの導入により、Goのビルドプロセスはより一元化され、堅牢になりました。

mkasmh.shの機能がcmd/distに統合されたのは、このようなビルドシステムの一元化と整理の流れの一環です。これにより、ビルドスクリプトの重複が解消され、メンテナンス性が向上し、Goのビルドプロセス全体がよりクリーンで効率的なものになりました。このコミットは、その移行が完了し、古いスクリプトが安全に削除できるようになったことを示しています。

前提知識の解説

Go言語のビルドプロセス

Go言語のビルドプロセスは、ソースコードから実行可能なバイナリを生成する一連のステップです。

  1. コンパイル: Goのソースコード(.goファイル)は、Goコンパイラ(go tool compile)によってオブジェクトファイル(.oファイル)にコンパイルされます。
  2. アセンブル: アセンブリ言語で書かれたファイル(.sファイル)は、Goアセンブラ(go tool asm)によってオブジェクトファイルにアセンブルされます。Goのランタイムや特定のパフォーマンスが要求される部分はアセンブリで書かれることがあります。
  3. リンク: コンパイルおよびアセンブルされたオブジェクトファイルと、必要な標準ライブラリのアーカイブファイルが、Goリンカ(go tool link)によって結合され、最終的な実行可能バイナリが生成されます。
  4. ビルドツール: これらのステップは通常、go buildコマンドによって自動的に調整されます。しかし、Go自身のツールチェインをビルドする際には、より低レベルなcmd/distのようなツールが使用されます。

Goのランタイムとアセンブリ

Goのランタイム(runtimeパッケージ)は、ガベージコレクション、スケジューラ、メモリ管理、システムコールインターフェースなど、Goプログラムの実行を支える低レベルな機能を提供します。これらの機能の一部は、パフォーマンスやOSとの直接的なインタラクションのために、Go言語ではなくアセンブリ言語で実装されています。

アセンブリコードは、特定のCPUアーキテクチャ(例: x86, ARM)とOS(例: Linux, Windows, macOS)に依存するため、プラットフォームごとに異なる実装が必要になることがあります。アセンブリコードとGoコード間のインターフェースを定義するために、アセンブリヘッダーファイルが使用されます。これには、Goコードからアセンブリ関数を呼び出すための定数やオフセットなどが含まれます。

mkasmh.shの役割(削除前)

mkasmh.shは "make assembly header" の略であり、その名の通り、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成するシェルスクリプトでした。具体的には、以下の機能を持っていたと考えられます。

  • プラットフォーム固有の定数定義: OS(GOOS)とアーキテクチャ(GOARCH)に基づいて、アセンブリコード内で使用されるマクロや定数(例: get_tls, g, m)を定義していました。これらは、スレッドローカルストレージ(TLS)へのアクセスや、Goのgoroutine構造体(g)やマシン構造体(m)のフィールドへのオフセットを定義するために重要です。
  • Cコンパイラ(Goツールチェインの一部)の利用: スクリプト内では、8c(386用)、6c(amd64用)、5c(ARM用)といったGoのツールチェインに含まれるCコンパイラ(実際にはGoのフロントエンドを持つコンパイラ)を使用して、proc.cのようなファイルをコンパイルし、その出力から構造体のオフセット情報を抽出していました。これは、Goのランタイム構造体(例: G, M, Gobuf)のメモリレイアウトがアセンブリコードから正しく参照されるようにするために必要でした。
  • 自動生成: スクリプトのコメントには「AUTO-GENERATED by autogen.sh; DO NOT EDIT」とあり、このスクリプト自体がさらに上位の自動生成プロセスの一部であったことを示唆しています。

cmd/distの役割

cmd/distは、GoのソースコードからGoのツールチェイン全体(コンパイラ、リンカ、アセンブラなど)と標準ライブラリをビルドするためのGo自身のビルドツールです。Go 1.0で導入され、Goのビルドプロセスを自動化し、クロスコンパイルなどの複雑なシナリオを管理する中心的な役割を担っています。mkasmh.shが担っていたような、アセンブリヘッダーの生成といった低レベルなビルドタスクも、このcmd/distの内部機能として吸収されました。これにより、Goのビルドシステムはより統合され、外部スクリプトへの依存が減りました。

Go 1.0の意義

Go 1.0は、Go言語の歴史において極めて重要なリリースです。このバージョンで、Go言語の仕様、標準ライブラリ、およびツールチェインが「安定」と宣言され、後方互換性が保証されるようになりました。これは、Go言語が実用的なプログラミング言語として広く採用されるための基盤を築きました。ビルドシステムの整理と効率化も、この安定化の重要な側面でした。

技術的詳細

mkasmh.shの削除は、Goのビルドシステムが成熟し、より洗練された内部ツールに移行したことを意味します。

削除されたmkasmh.shスクリプトの内容を見ると、その主な機能は以下の2点でした。

  1. アセンブリマクロの生成:

    • get_tls, g, mといったマクロを、ターゲットとなるOS(GOOS)とアーキテクチャ(GOARCH)に応じて定義していました。
    • 特に386アーキテクチャでは、Windows、Plan 9、LinuxといったOSごとにTLS(Thread Local Storage)へのアクセス方法が異なるため、それに対応するアセンブリ命令(例: MOVL 0x14(FS), r for Windows, MOVL _tos(SB), r for Plan 9, MOVL 8(GS), r for Linux)を生成していました。これは、GoのランタイムがgoroutineやM(OSスレッド)の情報を効率的に取得するために不可欠な部分です。
    • amd64アーキテクチャでも同様に、Windowsとその他のOSでTLSアクセスが異なっていました。
    • ARMアーキテクチャでは、gmを特定のレジスタ(R10, R9)に割り当てる定義がありました。
  2. Goランタイム構造体のオフセット定義:

    • Goのツールチェインに含まれるCコンパイラ(8c, 6c, 5c)を使用して、proc.cのようなGoランタイムのCソースファイルをコンパイルし、その出力からGoランタイムの主要な構造体(G (goroutine), M (machine), Gobuf (goroutineのコンテキスト保存用バッファ), WinCall (Windows固有の呼び出しコンテキスト))のフィールドオフセットを抽出していました。
    • このオフセット情報は、アセンブリコードがこれらの構造体の特定のフィールドにアクセスする際に必要となります(例: g_stack0, m_sched, gobuf_spなど)。アセンブリコードは、これらのオフセットを使ってメモリ上の正しい位置にアクセスします。

これらの機能は、Goのランタイムが低レベルでOSやハードウェアと連携するために不可欠なものでした。cmd/distへの統合により、これらの生成プロセスはGoのビルドシステム内部でより堅牢かつ効率的に管理されるようになりました。例えば、cmd/distはGoのソースコードを解析して構造体のレイアウト情報を取得し、それに基づいてアセンブリヘッダーを生成する機能を内包するようになったと考えられます。これにより、シェルスクリプトの実行環境に依存することなく、Goのビルドプロセス全体がGo言語自身でより制御されるようになりました。

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

このコミットによる変更は、単一ファイルの削除です。

  • src/pkg/runtime/mkasmh.sh が完全に削除されました。
    • 変更行数: 138行の削除

コアとなるコードの解説

削除されたmkasmh.shスクリプトは、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成する役割を担っていました。スクリプトの冒頭には、一時ファイルのクリーンアップのためのtrapコマンドや、エラー時に終了するset -eが設定されています。

スクリプトは、引数からターゲットシステム(例: linux_amd64)を解析し、GOOSGOARCH環境変数を設定します。そして、対応するGoのCコンパイラ(8c, 6c, 5c)のパスを設定していました。

主要な処理は以下の通りです。

  1. プラットフォーム固有のアセンブリマクロ定義: case "$GOARCH"ブロック内で、386, amd64, armといったアーキテクチャごとに、さらにGOOSwindows, plan9, linuxなど)に応じて、アセンブリコードで使用するマクロ(get_tls, g, m, LR)を#defineとして出力していました。

    • get_tls(r): スレッドローカルストレージ(TLS)のベースアドレスをレジスタrにロードする命令を定義します。OSやアーキテクチャによってTLSのアクセス方法が異なるため、ここで抽象化されていました。
    • g(r): goroutine構造体へのポインタをレジスタrから取得するオフセットを定義します。
    • m(r): M(OSスレッド)構造体へのポインタをレジスタrから取得するオフセットを定義します。 これらのマクロは、Goのランタイムが現在のgoroutineやMのコンテキストに素早くアクセスするために不可欠です。
  2. ランタイム構造体オフセットの抽出: スクリプトの後半では、GoのCコンパイラ($CC)を使ってproc.cをコンパイルし、その出力をawkコマンドで処理していました。 awkスクリプトは、コンパイラの出力からaggr G, aggr M, aggr Gobuf, aggr WinCallといったパターンを検出し、これらの構造体のフィールド名とそのオフセットを抽出していました。 例えば、Gobuf 24 sched;のような行から、#define gobuf_sched 24のような形式でマクロを生成していました。 これらのマクロは、アセンブリコードがGoのランタイム構造体の特定のフィールド(例: gobuf_schedGobuf構造体内のschedフィールドのオフセット)に直接アクセスするために使用されます。

このスクリプトが削除されたということは、これらのアセンブリヘッダーの生成ロジックが、より統合されたcmd/distツール内部で、Go言語のコードとして、またはより洗練された方法で再実装されたことを意味します。これにより、ビルドプロセスの堅牢性と移植性が向上しました。

関連リンク

参考にした情報源リンク

  • Go 1.0 Release Notes: https://go.dev/doc/go1
  • Goのビルドシステムに関する一般的な情報 (Goの公式ドキュメントやブログ記事など)
  • Goのランタイムとアセンブリに関する情報 (Goのソースコードや関連する技術記事など)
  • cmd/distの役割に関する情報 (Goのソースコードや関連する技術記事など)
  • Goのツールチェインに関する情報 (Goの公式ドキュメントなど)
  • スレッドローカルストレージ (TLS) に関する一般的な情報
  • Goのruntimeパッケージのソースコード (特にproc.cやアセンブリファイル)# [インデックス 15934] ファイルの概要

このコミットは、Go言語のランタイムパッケージからmkasmh.shというシェルスクリプトを削除するものです。このスクリプトの機能はGo 1.0のリリースに伴いcmd/distツールに統合されたため、もはや不要となり、削除されました。

コミット

commit cb807e7b4a3c6291f16507ee9a31a303f411ddba
Author: Russ Cox <rsc@golang.org>
Date:   Mon Mar 25 17:46:11 2013 -0400

    runtime: delete mkasmh.sh
    
    This functionality moved into cmd/dist for Go 1.0.
    Changes to this script have no effect.
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/8020043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/cb807e7b4a3c6291f16507ee9a31a303f411ddba

元コミット内容

このコミットは、Go言語のランタイム(src/pkg/runtime)ディレクトリからmkasmh.shというシェルスクリプトを削除することを目的としています。コミットメッセージによると、このスクリプトが提供していた機能はGo 1.0のリリース時にcmd/distツールへと移行されており、そのためmkasmh.shに対する変更はもはやシステムに影響を与えない状態になっていました。つまり、このスクリプトは陳腐化しており、コードベースから除去されるべきであるという判断がなされたものです。

変更の背景

Go言語の初期開発段階では、ビルドプロセスは現在よりも分散しており、特定のタスクを処理するために個別のスクリプトが使用されていました。mkasmh.shもその一つで、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成する役割を担っていました。

Go 1.0のリリースは、Go言語にとって非常に重要なマイルストーンでした。このバージョンでは、言語仕様、標準ライブラリ、およびツールチェインの安定化が図られ、後方互換性が保証されるようになりました。この安定化の一環として、ビルドシステムの整理と効率化も進められました。

cmd/distは、Go 1.0で導入されたGo自身のビルドを管理するためのツールです。Goのソースコードからコンパイラ、リンカ、アセンブラなどのツールチェイン全体をビルドし、Goの標準ライブラリをコンパイルする役割を担っています。cmd/distの導入により、Goのビルドプロセスはより一元化され、堅牢になりました。

mkasmh.shの機能がcmd/distに統合されたのは、このようなビルドシステムの一元化と整理の流れの一環です。これにより、ビルドスクリプトの重複が解消され、メンテナンス性が向上し、Goのビルドプロセス全体がよりクリーンで効率的なものになりました。このコミットは、その移行が完了し、古いスクリプトが安全に削除できるようになったことを示しています。

前提知識の解説

Go言語のビルドプロセス

Go言語のビルドプロセスは、ソースコードから実行可能なバイナリを生成する一連のステップです。

  1. コンパイル: Goのソースコード(.goファイル)は、Goコンパイラ(go tool compile)によってオブジェクトファイル(.oファイル)にコンパイルされます。
  2. アセンブル: アセンブリ言語で書かれたファイル(.sファイル)は、Goアセンブラ(go tool asm)によってオブジェクトファイルにアセンブルされます。Goのランタイムや特定のパフォーマンスが要求される部分はアセンブリで書かれることがあります。
  3. リンク: コンパイルおよびアセンブルされたオブジェクトファイルと、必要な標準ライブラリのアーカイブファイルが、Goリンカ(go tool link)によって結合され、最終的な実行可能バイナリが生成されます。
  4. ビルドツール: これらのステップは通常、go buildコマンドによって自動的に調整されます。しかし、Go自身のツールチェインをビルドする際には、より低レベルなcmd/distのようなツールが使用されます。

Goのランタイムとアセンブリ

Goのランタイム(runtimeパッケージ)は、ガベージコレクション、スケジューラ、メモリ管理、システムコールインターフェースなど、Goプログラムの実行を支える低レベルな機能を提供します。これらの機能の一部は、パフォーマンスやOSとの直接的なインタラクションのために、Go言語ではなくアセンブリ言語で実装されています。

アセンブリコードは、特定のCPUアーキテクチャ(例: x86, ARM)とOS(例: Linux, Windows, macOS)に依存するため、プラットフォームごとに異なる実装が必要になることがあります。アセンブリコードとGoコード間のインターフェースを定義するために、アセンブリヘッダーファイルが使用されます。これには、Goコードからアセンブリ関数を呼び出すための定数やオフセットなどが含まれます。

mkasmh.shの役割(削除前)

mkasmh.shは "make assembly header" の略であり、その名の通り、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成するシェルスクリプトでした。具体的には、以下の機能を持っていたと考えられます。

  • プラットフォーム固有の定数定義: OS(GOOS)とアーキテクチャ(GOARCH)に基づいて、アセンブリコード内で使用されるマクロや定数(例: get_tls, g, m)を定義していました。これらは、スレッドローカルストレージ(TLS)へのアクセスや、Goのgoroutine構造体(g)やマシン構造体(m)のフィールドへのオフセットを定義するために重要ですす。
  • Cコンパイラ(Goツールチェインの一部)の利用: スクリプト内では、8c(386用)、6c(amd64用)、5c(ARM用)といったGoのツールチェインに含まれるCコンパイラ(実際にはGoのフロントエンドを持つコンパイラ)を使用して、proc.cのようなファイルをコンパイルし、その出力から構造体のオフセット情報を抽出していました。これは、Goのランタイム構造体(例: G, M, Gobuf)のメモリレイアウトがアセンブリコードから正しく参照されるようにするために必要でした。
  • 自動生成: スクリプトのコメントには「AUTO-GENERATED by autogen.sh; DO NOT EDIT」とあり、このスクリプト自体がさらに上位の自動生成プロセスの一部であったことを示唆しています。

cmd/distの役割

cmd/distは、GoのソースコードからGoのツールチェイン全体(コンパイラ、リンカ、アセンブラなど)と標準ライブラリをビルドするためのGo自身のビルドツールです。Go 1.0で導入され、Goのビルドプロセスを自動化し、クロスコンパイルなどの複雑なシナリオを管理する中心的な役割を担っています。mkasmh.shが担っていたような、アセンブリヘッダーの生成といった低レベルなビルドタスクも、このcmd/distの内部機能として吸収されました。これにより、Goのビルドシステムはより統合され、外部スクリプトへの依存が減りました。

Go 1.0の意義

Go 1.0は、Go言語の歴史において極めて重要なリリースです。このバージョンで、Go言語の仕様、標準ライブラリ、およびツールチェインが「安定」と宣言され、後方互換性が保証されるようになりました。これは、Go言語が実用的なプログラミング言語として広く採用されるための基盤を築きました。ビルドシステムの整理と効率化も、この安定化の重要な側面でした。

技術的詳細

mkasmh.shの削除は、Goのビルドシステムが成熟し、より洗練された内部ツールに移行したことを意味します。

削除されたmkasmh.shスクリプトの内容を見ると、その主な機能は以下の2点でした。

  1. アセンブリマクロの生成:

    • get_tls, g, mといったマクロを、ターゲットとなるOS(GOOS)とアーキテクチャ(GOARCH)に応じて定義していました。
    • 特に386アーキテクチャでは、Windows、Plan 9、LinuxといったOSごとにTLS(Thread Local Storage)へのアクセス方法が異なるため、それに対応するアセンブリ命令(例: MOVL 0x14(FS), r for Windows, MOVL _tos(SB), r for Plan 9, MOVL 8(GS), r for Linux)を生成していました。これは、GoのランタイムがgoroutineやM(OSスレッド)の情報を効率的に取得するために不可欠な部分です。
    • amd64アーキテクチャでも同様に、Windowsとその他のOSでTLSアクセスが異なっていました。
    • ARMアーキテクチャでは、gmを特定のレジスタ(R10, R9)に割り当てる定義がありました。
  2. Goランタイム構造体のオフセット定義:

    • Goのツールチェインに含まれるCコンパイラ(8c, 6c, 5c)を使用して、proc.cのようなGoランタイムのCソースファイルをコンパイルし、その出力をawkコマンドで処理していました。
    • このawkスクリプトは、コンパイラの出力からaggr G, aggr M, aggr Gobuf, aggr WinCallといったパターンを検出し、これらの構造体のフィールド名とそのオフセットを抽出していました。
    • 例えば、Gobuf 24 sched;のような行から、#define gobuf_sched 24のような形式でマクロを生成していました。
    • これらのマクロは、アセンブリコードがGoのランタイム構造体の特定のフィールド(例: gobuf_schedGobuf構造体内のschedフィールドのオフセット)に直接アクセスするために使用されます。

これらの機能は、Goのランタイムが低レベルでOSやハードウェアと連携するために不可欠なものでした。cmd/distへの統合により、これらの生成プロセスはGoのビルドシステム内部でより堅牢かつ効率的に管理されるようになりました。例えば、cmd/distはGoのソースコードを解析して構造体のレイアウト情報を取得し、それに基づいてアセンブリヘッダーを生成する機能を内包するようになったと考えられます。これにより、シェルスクリプトの実行環境に依存することなく、Goのビルドプロセス全体がGo言語自身でより制御されるようになりました。

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

このコミットによる変更は、単一ファイルの削除です。

  • src/pkg/runtime/mkasmh.sh が完全に削除されました。
    • 変更行数: 138行の削除

コアとなるコードの解説

削除されたmkasmh.shスクリプトは、Goのランタイムが使用するアセンブリコードのためのヘッダーファイルを生成する役割を担っていました。スクリプトの冒頭には、一時ファイルのクリーンアップのためのtrapコマンドや、エラー時に終了するset -eが設定されています。

スクリプトは、引数からターゲットシステム(例: linux_amd64)を解析し、GOOSGOARCH環境変数を設定します。そして、対応するGoのCコンパイラ(8c, 6c, 5c)のパスを設定していました。

主要な処理は以下の通りです。

  1. プラットフォーム固有のアセンブリマクロ定義: case "$GOARCH"ブロック内で、386, amd64, armといったアーキテクチャごとに、さらにGOOSwindows, plan9, linuxなど)に応じて、アセンブリコードで使用するマクロ(get_tls, g, m, LR)を#defineとして出力していました。

    • get_tls(r): スレッドローカルストレージ(TLS)のベースアドレスをレジスタrにロードする命令を定義します。OSやアーキテクチャによってTLSのアクセス方法が異なるため、ここで抽象化されていました。
    • g(r): goroutine構造体へのポインタをレジスタrから取得するオフセットを定義します。
    • m(r): M(OSスレッド)構造体へのポインタをレジスタrから取得するオフセットを定義します。 これらのマクロは、Goのランタイムが現在のgoroutineやMのコンテキストに素早くアクセスするために不可欠です。
  2. ランタイム構造体オフセットの抽出: スクリプトの後半では、GoのCコンパイラ($CC)を使ってproc.cをコンパイルし、その出力をawkコマンドで処理していました。 awkスクリプトは、コンパイラの出力からaggr G, aggr M, aggr Gobuf, aggr WinCallといったパターンを検出し、これらの構造体のフィールド名とそのオフセットを抽出していました。 例えば、Gobuf 24 sched;のような行から、#define gobuf_sched 24のような形式でマクロを生成していました。 これらのマクロは、アセンブリコードがGoのランタイム構造体の特定のフィールド(例: gobuf_schedGobuf構造体内のschedフィールドのオフセット)に直接アクセスするために使用されます。

このスクリプトが削除されたということは、これらのアセンブリヘッダーの生成ロジックが、より統合されたcmd/distツール内部で、Go言語のコードとして、またはより洗練された方法で再実装されたことを意味します。これにより、ビルドプロセスの堅牢性と移植性が向上しました。

関連リンク

参考にした情報源リンク

  • Go 1.0 Release Notes: https://go.dev/doc/go1
  • Goのビルドシステムに関する一般的な情報 (Goの公式ドキュメントやブログ記事など)
  • Goのランタイムとアセンブリに関する情報 (Goのソースコードや関連する技術記事など)
  • cmd/distの役割に関する情報 (Goのソースコードや関連する技術記事など)
  • Goのツールチェインに関する情報 (Goの公式ドキュメントなど)
  • スレッドローカルストレージ (TLS) に関する一般的な情報
  • Goのruntimeパッケージのソースコード (特にproc.cやアセンブリファイル)