[インデックス 1911] ファイルの概要
このコミットは、Goコンパイラの内部構造における重要な変更、具体的にはbits.cファイルの移動と関連する定義の再配置を扱っています。これは、Goコンパイラの最適化フェーズで使用されるビット操作関連のコードが、より汎用的なコンパイラバックエンドのコンポーネントとして再編成されたことを示唆しています。
コミット
commit 531f242f5dfce8fb592533c872b8e0452789040a
Author: Russ Cox <rsc@golang.org>
Date: Mon Mar 30 16:13:11 2009 -0700
move bits.c from 6g to gc
R=ken
OCL=26909
CL=26909
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/531f242f5dfce8fb592533c872b8e0452789040a
元コミット内容
bits.cを6gからgcへ移動。
変更の背景
この変更の背景には、Goコンパイラのアーキテクチャの進化があります。初期のGoコンパイラは、ターゲットアーキテクチャごとに異なるフロントエンド(例: 6gはamd64用、8gはarm用など)を持っていました。しかし、コンパイラの共通部分(型チェック、AST処理、最適化など)はアーキテクチャに依存しないはずです。
bits.cは、コンパイラの最適化フェーズ、特にデータフロー解析やレジスタ割り当てなどで使用されるビット集合操作(bitset operations)を実装していると考えられます。これらの操作は、特定のCPUアーキテクチャに特化したものではなく、コンパイラのバックエンドにおける一般的なユーティリティ機能です。
コミットメッセージにある「move bits.c from 6g to gc」は、6g(amd64アーキテクチャ向けのGoコンパイラ)に特化していたbits.cの機能を、より汎用的なgc(Go Compilerの共通部分、またはGoコンパイラ全体を指す)ディレクトリに移動することで、コードの再利用性を高め、コンパイラ全体の構造を整理しようとする意図を示しています。これにより、将来的に他のアーキテクチャ向けのコンパイラでも同じビット操作ロジックを共有できるようになります。
前提知識の解説
- Goコンパイラ (
gc): Go言語の公式コンパイラです。初期のGoコンパイラは、6g(amd64),8g(arm),5g(386) のように、ターゲットアーキテクチャごとに異なる名前の実行ファイルを持っていました。しかし、これらは共通のコードベースを共有しており、最終的にはgo tool compileという単一のコマンドに統合されていきました。このコミットが行われた2009年時点では、まだアーキテクチャごとのコンパイラが明確に分かれていた時期の名残が見られます。 6g: amd64 (x86-64) アーキテクチャ向けのGoコンパイラを指します。gcディレクトリ: Goコンパイラの共通部分、またはコンパイラ全体を構成するソースコードが配置されるディレクトリです。- ビット集合 (Bitset): ビットの配列を用いて集合を表現するデータ構造です。各ビットが特定の要素の存在(1)または不在(0)を示します。コンパイラにおいては、データフロー解析(例: どの変数が特定の時点で「生きている」か、どの式が「利用可能」か)やレジスタ割り当て(例: どのレジスタが使用中か)などの最適化アルゴリズムで頻繁に利用されます。ビット操作は非常に高速であるため、コンパイラのパフォーマンスに寄与します。
- コンパイラの最適化: コンパイラが生成する機械語コードの効率(実行速度、メモリ使用量など)を向上させるための処理です。データフロー解析、レジスタ割り当て、定数伝播、デッドコード削除など、様々な手法があります。ビット集合はこれらの最適化の基盤となるデータ構造として使われます。
技術的詳細
このコミットの主要な技術的変更は、bits.cとその関連定義の移動です。
-
bits.cの移動:src/cmd/6g/bits.cからsrc/cmd/gc/bits.cへファイルが物理的に移動しました。- これに伴い、
bits.c内部のインクルードパスが変更されました。以前は"gg.h"と"opt.h"をインクルードしていましたが、移動後は"go.h"をインクルードするように変更されています。これは、go.hがgcディレクトリ内の共通ヘッダファイルであり、必要な定義をすべて提供しているためです。
-
ヘッダファイルの変更:
src/cmd/6g/opt.hから、Bits構造体、Var構造体、およびそれらに関連するマクロ(BITS,NVAR)と外部変数宣言(zbits,var)が削除されました。また、bits.cで定義されている関数(bor,band,bnotなど)のプロトタイプ宣言も削除されました。- これらの削除された定義と宣言は、
src/cmd/gc/go.hに移動されました。これにより、bits.cがgcディレクトリの共通コンポーネントとして機能するために必要な型定義や関数プロトタイプが、go.hを通じて他のgcコンポーネントから利用可能になります。
-
Makefileの変更:
src/cmd/6g/Makefileからbits.$O(bits.cのコンパイル済みオブジェクトファイル)が削除されました。src/cmd/gc/Makefileにbits.$Oが追加されました。これにより、bits.cがgcコンポーネントの一部としてビルドされるようになります。
-
src/cmd/make8.bashの追加:- このコミットでは、
src/cmd/make8.bashという新しいシェルスクリプトが追加されています。これは、Goコンパイラおよび関連ツール(8l,8a,8c,gcなど)をビルドするためのスクリプトです。このスクリプト自体はbits.cの移動とは直接関係ありませんが、当時のGoのビルドシステムの一部として同時にコミットされたものです。clean.bashを実行し、8lをビルドした後、各コンポーネントディレクトリに移動してmake installを実行する手順が記述されています。
- このコミットでは、
これらの変更は、Goコンパイラのコードベースをよりモジュール化し、アーキテクチャ固有のコードと共通コードを分離するという、長期的な目標の一環として行われたものです。bits.cのような汎用的なユーティリティを共通のgcディレクトリに移動することで、コードの重複を避け、メンテナンス性を向上させることができます。
コアとなるコードの変更箇所
このコミットのコアとなるコードの変更は、主に以下のファイルに集中しています。
-
src/cmd/6g/Makefile:--- a/src/cmd/6g/Makefile +++ b/src/cmd/6g/Makefile @@ -22,7 +22,6 @@ OFILES=\ obj.$O\ peep.$O\ reg.$O\ - bits.$O\ ../6l/enam.$O\ LIB=\bits.$OがOFILESリストから削除されています。 -
src/cmd/6g/opt.h:Bits構造体、Var構造体、関連マクロ、およびbits.c関数のプロトタイプが削除されています。 -
src/cmd/gc/Makefile:--- a/src/cmd/gc/Makefile +++ b/src/cmd/gc/Makefile @@ -28,6 +28,7 @@ OFILES=\ mparith3.$O\ builtin.$O\ compat.$O\ + bits.$O\ $(LIB): $(OFILES)\ ar rsc $(LIB) $(OFILES)\bits.$OがOFILESリストに追加されています。 -
src/cmd/{6g => gc}/bits.c: ファイルがリネーム(移動)され、インクルードパスが変更されています。--- a/src/cmd/6g/bits.c +++ b/src/cmd/gc/bits.c @@ -28,8 +28,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "gg.h" -#include "opt.h" +#include "go.h" Bits bor(Bits a, Bits b) -
src/cmd/gc/go.h:Bits構造体、Var構造体、関連マクロ、およびbits.c関数のプロトタイプが追加されています。--- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -11,7 +11,7 @@ #include "compat.h" #ifndef EXTERN -#define EXTERN extern +#define EXTERN extern #endif enum { @@ -420,6 +420,29 @@ enum Erv, // evaluated in rvalue context }; +#define BITS 5 +#define NVAR (BITS*sizeof(uint32)*8) + +typedef struct Bits Bits; +struct Bits +{ + uint32 b[BITS]; +}; + +EXTERN Bits zbits; + +typedef struct Var Var; +struct Var +{ + vlong offset; + Sym* sym; + char name; + char etype; +}; + +EXTERN Var var[NVAR]; + + typedef struct Io Io; struct Io { @@ -871,3 +894,17 @@ Node* nodarg(Type*, int);\n void nodconst(Node*, Type*, vlong);\n Type* deep(Type*);\n Type* shallow(Type*);\n+\n+/*\n+ * bits.c\n+ */\n+Bits bor(Bits, Bits);\n+Bits band(Bits, Bits);\n+Bits bnot(Bits);\n+int bany(Bits*);\n+int bnum(Bits);\n+Bits blsh(uint);\n+int beq(Bits, Bits);\n+int bset(Bits, uint);\n+int Qconv(Fmt *fp);\n+int bitno(int32);\
コアとなるコードの解説
このコミットの核心は、bits.cファイルとその関連するデータ構造および関数の定義を、6g(amd64アーキテクチャ固有のコンパイラ部分)からgc(Goコンパイラの共通部分)へ移動した点にあります。
bits.c: このファイルには、ビット集合を操作するための基本的な関数群が含まれています。例えば、bor(ビットOR)、band(ビットAND)、bnot(ビットNOT)、bany(任意のビットがセットされているか)、bnum(セットされているビットの数)、blsh(左シフト)、beq(等価性チェック)、bset(ビットセット)などです。これらの関数は、コンパイラの最適化フェーズで、変数やレジスタの状態、データフロー情報などを効率的に管理するために使用されます。Bits構造体:uint32 b[BITS];という配列を持つ構造体で、ビット集合の実体を表します。BITSマクロは、この配列のサイズを定義しており、ビット集合がカバーできるビット数を決定します。Var構造体: 変数に関する情報を保持する構造体です。offset,sym(シンボル)、name,etype(要素型)などのフィールドを持ちます。コンパイラが変数を追跡し、最適化を行う際に使用されます。- ヘッダファイルの再編成:
opt.hからこれらの定義が削除され、go.hに移動されたことは、これらのビット操作機能がもはや特定のアーキテクチャ(amd64)の最適化に限定されるものではなく、Goコンパイラ全体の共通ユーティリティとして位置づけられたことを明確に示しています。go.hはgcディレクトリ内の他の多くのソースファイルからインクルードされるため、この移動により、bits.cの機能がコンパイラのより広範な部分で利用可能になります。 - Makefileの変更: ビルドシステムにおける変更は、この論理的な再編成を物理的に反映したものです。
6gのビルドからbits.oが除外され、gcのビルドに含まれることで、bits.cがgcコンポーネントの一部としてコンパイル・リンクされるようになります。
この変更は、Goコンパイラの設計が初期段階から成熟していく過程で、共通の基盤コードを抽出し、アーキテクチャ固有のコードから分離していくという、一般的なソフトウェアエンジニアリングのプラクティスに沿ったものです。これにより、コードの保守性、拡張性、および再利用性が向上します。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Goコンパイラの歴史に関する情報(非公式): Goコンパイラの進化について深く掘り下げた記事やプレゼンテーションが参考になる場合があります。例えば、Goの初期のコンパイラ設計に関するRuss Cox氏やRob Pike氏の講演資料など。
参考にした情報源リンク
- Go言語のソースコード(特に
src/cmd/gcおよびsrc/cmd/6gディレクトリの初期のコミット履歴) - コンパイラ設計に関する一般的な書籍やオンラインリソース(ビット集合、データフロー解析、レジスタ割り当てなど)
- Go言語の公式ドキュメントやブログ(コンパイラの内部構造に関する記事があれば)
- GitHubのコミット履歴とdiffビューア
- Goコンパイラの開発者メーリングリストのアーカイブ(当時の議論があれば)
(注: 上記の「関連リンク」と「参考にした情報源リンク」は、一般的な情報源の例であり、この特定のコミットに関する詳細な外部資料が直接見つからない場合でも、関連する概念を理解するために役立つものです。)